/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: Pic.cs // // Note: // http://home.ozonline.com.au/davmac/davpage/PIC.html // using Microsoft.Singularity.Io; using System; using System.Diagnostics; using System.Runtime.CompilerServices; using Microsoft.Singularity.Configuration; namespace Microsoft.Singularity.Hal { [DriverCategory] [Signature("/pnp/PNP0000")] public sealed class PicStubResources : DriverCategoryDeclaration { [IoPortRange(0, Default = 0x0020, Length = 0x02)] public IoPortRange port1; [IoPortRange(1, Default = 0x00a0, Length = 0x02)] public IoPortRange port2; } [ CLSCompliant(false) ] public sealed class PicStub { public const byte PIC_VECTORS = 16; private IoPort pic0CtrlPort; private IoPort pic0MaskPort; private IoPort pic1CtrlPort; private IoPort pic1MaskPort; private byte baseVector; // Constants for PIC interrupt vectors. internal PicStub(PnpConfig config) { // /pnp/08/00/01/PNP0000 0003 cfg dis // I/O Port inf=01 min=0020 max=0020 aln=01 len=02 0020..0021 // I/O Port inf=01 min=00a0 max=00a0 aln=01 len=02 00a0..00a1 // IRQ mask=0004 type=79 // Range[0]: 0x20; // PIC0 // Range[1]: 0xA0; // PIC1 pic0CtrlPort = ((IoPortRange)config.DynamicRanges[0]) .PortAtOffset(0, 1, Access.ReadWrite); pic0MaskPort = ((IoPortRange)config.DynamicRanges[0]) .PortAtOffset(1, 1, Access.ReadWrite); pic1CtrlPort = ((IoPortRange)config.DynamicRanges[1]) .PortAtOffset(0, 1, Access.ReadWrite); pic1MaskPort = ((IoPortRange)config.DynamicRanges[1]) .PortAtOffset(1, 1, Access.ReadWrite); } public byte Initialize(byte baseVector) { this.baseVector = baseVector; // Set ICW1 (must be followed by ICW2, ICW3, and ICW4). // 00010001b - 8-byte,cascaded,triggered,w/ICW4 pic1CtrlPort.Write8(0x11); pic0CtrlPort.Write8(0x11); // ICW2 pic1MaskPort.Write8((byte)(baseVector + 8)); pic0MaskPort.Write8(baseVector); // ICW3 pic1MaskPort.Write8(0x02); // Cascaded interrupt number pic0MaskPort.Write8(0x04); // Cascaded interrupt bit. // ICW4 pic1MaskPort.Write8(1); pic0MaskPort.Write8(1); // OCW2 - EOI pic1CtrlPort.Write8(0x20); pic0CtrlPort.Write8(0x20); MaskAll(); DumpRegisters(); pic1CtrlPort.Write8(0x20); pic0CtrlPort.Write8(0x20); MaskAll(); DumpRegisters(); MaskAll(); // OCW2 - EOI pic1CtrlPort.Write8(0x20); pic0CtrlPort.Write8(0x20); return PIC_VECTORS; } public void Initialize() { this.Initialize(0x60); DumpRegisters(); } [NoHeapAllocation] public void AckIrq(byte irq) { DumpRegisters(); #if DEBUG_INTERRUPTS DebugStub.Print("Int{0:x2} Acked, Mask={1:x8}\n", __arglist(irq + baseVector, irqMask)); #endif // Quiet the interrupt controller. IoResult result; if (irq >= 8) { result = pic1CtrlPort.Write8NoThrow(0x20); DebugStub.Assert(IoResult.Success == result); } result = pic0CtrlPort.Write8NoThrow(0x20); DebugStub.Assert(IoResult.Success == result); DumpRegisters(); } [ Conditional("DEBUG_INTERRUPTS") ] [NoHeapAllocation] public void DumpRegisters() { byte irr0, isr0, irr1, isr1; IoResult result; // OCW3 - read IRR result = pic0CtrlPort.Write8NoThrow(0x04 | 0x02); DebugStub.Assert(IoResult.Success == result); result = pic0CtrlPort.Read8NoThrow(out irr0); DebugStub.Assert(IoResult.Success == result); // OCW3 - read ISR result = pic0CtrlPort.Write8NoThrow(0x04 | 0x03); DebugStub.Assert(IoResult.Success == result); result = pic0CtrlPort.Read8NoThrow(out isr0); DebugStub.Assert(IoResult.Success == result); // OCW3 - read IRR result = pic1CtrlPort.Write8NoThrow(0x04 | 0x02); DebugStub.Assert(IoResult.Success == result); result = pic1CtrlPort.Read8NoThrow(out irr1); DebugStub.Assert(IoResult.Success == result); // OCW3 - read ISR result = pic1CtrlPort.Write8NoThrow(0x04 | 0x03); DebugStub.Assert(IoResult.Success == result); result = pic1CtrlPort.Read8NoThrow(out isr1); DebugStub.Assert(IoResult.Success == result); // Get mask state byte mask0, mask1; result = pic0MaskPort.Read8NoThrow(out mask0); DebugStub.Assert(IoResult.Success == result); result = pic1MaskPort.Read8NoThrow(out mask1); DebugStub.Assert(IoResult.Success == result); DebugStub.Print("PIC IRR: {0:x2}/{1:x2} ISR: {2:x2}/{3:x2} Mask {4:x2}/{5:x2}\n", __arglist(irr0, irr1, isr0, isr1, mask0, mask1)); } public void ReleaseResources() { } private void MaskAll() { pic1MaskPort.Write8(0xff); pic0MaskPort.Write8(0xff); } } }