194 lines
5.9 KiB
C#
194 lines
5.9 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 PicResources : DriverCategoryDeclaration
|
|
{
|
|
[IoPortRange(0, Default = 0x0020, Length = 0x02)]
|
|
public IoPortRange port1;
|
|
|
|
[IoPortRange(1, Default = 0x00a0, Length = 0x02)]
|
|
public IoPortRange port2;
|
|
}
|
|
|
|
[ CLSCompliant(false) ]
|
|
public sealed class Pic
|
|
{
|
|
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 Pic(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 Finalize()
|
|
{
|
|
}
|
|
|
|
private void MaskAll()
|
|
{
|
|
pic1MaskPort.Write8(0xff);
|
|
pic0MaskPort.Write8(0xff);
|
|
}
|
|
}
|
|
}
|