2008-03-05 09:52:00 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Microsoft Research Singularity
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// File: IoApic.cs
|
|
|
|
//
|
|
|
|
// Note:
|
|
|
|
// Intel MP Specification 1.4
|
|
|
|
// 82093AA I/O Advanced Programmable Interrupt Controller
|
|
|
|
|
|
|
|
namespace Microsoft.Singularity.Hal
|
|
|
|
{
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
using Microsoft.Singularity.Io;
|
|
|
|
using Microsoft.Singularity.Hal.Acpi;
|
|
|
|
|
|
|
|
public enum IoBits : ushort
|
|
|
|
{
|
|
|
|
IrqMask = 0x0100,
|
|
|
|
TriggerModeMask = 0x0080,
|
|
|
|
TriggerModeLevel = TriggerModeMask,
|
|
|
|
TriggerModeEdge = 0,
|
|
|
|
RemoteIRR = 0x0040,
|
|
|
|
IntPolMask = 0x0020,
|
|
|
|
IntPolActiveLow = IntPolMask,
|
|
|
|
IntPolActiveHigh = 0,
|
|
|
|
DeliveryStatus = 0x0010,
|
|
|
|
DstMask = 0x0008, // Destination Mask
|
|
|
|
DstLogical = DstMask,
|
|
|
|
DstPhysical = 0,
|
|
|
|
DelModMask = 0x0007, // Delivery Mode Mask
|
|
|
|
DelModFixed = 0x0000,
|
|
|
|
DelModLowest = 0x0001,
|
|
|
|
DelModSMI = 0x0002,
|
|
|
|
DelModReserved1 = 0x0003,
|
|
|
|
DelModNMI = 0x0004,
|
|
|
|
DelModINIT = 0x0005,
|
|
|
|
DelModReserved2 = 0x0006,
|
|
|
|
DelModExtINT = 0x0007,
|
|
|
|
};
|
|
|
|
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public struct RedirectionEntry
|
|
|
|
{
|
|
|
|
public byte Destination;
|
|
|
|
public IoBits IoBits;
|
|
|
|
public byte InterruptVector;
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
|
|
|
public RedirectionEntry(byte destination,
|
|
|
|
IoBits ioBits,
|
|
|
|
byte interruptVector)
|
|
|
|
{
|
|
|
|
this.Destination = destination;
|
|
|
|
this.IoBits = ioBits;
|
|
|
|
this.InterruptVector = interruptVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
|
|
|
public RedirectionEntry(byte destination,
|
|
|
|
ushort ioBits,
|
|
|
|
byte interruptVector)
|
|
|
|
{
|
|
|
|
this.Destination = destination;
|
|
|
|
this.IoBits = (IoBits)ioBits;
|
|
|
|
this.InterruptVector = interruptVector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public class IoApic
|
|
|
|
{
|
|
|
|
private const uint MaskBit = 1 << 16;
|
|
|
|
private const uint RedHiBase = 0x11;
|
|
|
|
private const uint RedLoBase = 0x10;
|
2008-11-17 18:29:00 -05:00
|
|
|
private const uint IdLimit = 0x0f;
|
|
|
|
private const uint IndexLimit = 24;
|
|
|
|
private const uint RegisterLimit = 0x3f;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
IoMemory ioRegSel;
|
|
|
|
IoMemory ioWin;
|
|
|
|
uint entries;
|
2008-11-17 18:29:00 -05:00
|
|
|
uint interruptBase;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
SpinLock ioLock;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public IoApic(UIntPtr memoryBase, uint interruptBase)
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
|
|
|
ioRegSel = IoMemory.MapPhysicalMemory(memoryBase,
|
|
|
|
new UIntPtr(4u), true, true);
|
|
|
|
ioWin = IoMemory.MapPhysicalMemory(memoryBase + new UIntPtr(0x10u),
|
|
|
|
new UIntPtr(4u), true, true);
|
|
|
|
entries = ((ReadRegister(1) & 0xff0000u) >> 16) + 1;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (uint i = 0; i < entries; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
SetEntryMask(i, true);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
ioLock = new SpinLock(SpinLock.Types.IoApic);
|
|
|
|
|
|
|
|
this.interruptBase = interruptBase;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
2008-11-17 18:29:00 -05:00
|
|
|
private bool AcquireLock()
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool irqRestore = Processor.DisableInterrupts();
|
2008-03-05 09:52:00 -05:00
|
|
|
#if SINGULARITY_MP
|
2008-11-17 18:29:00 -05:00
|
|
|
this.ioLock.Acquire();
|
2008-03-05 09:52:00 -05:00
|
|
|
#endif // SINGULARITY_MP
|
2008-11-17 18:29:00 -05:00
|
|
|
return irqRestore;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
2008-11-17 18:29:00 -05:00
|
|
|
private void ReleaseLock(bool irqRestore)
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
|
|
|
#if SINGULARITY_MP
|
2008-11-17 18:29:00 -05:00
|
|
|
this.ioLock.Release();
|
2008-03-05 09:52:00 -05:00
|
|
|
#endif // SINGULARITY_MP
|
|
|
|
Processor.RestoreInterrupts(irqRestore);
|
|
|
|
}
|
|
|
|
|
|
|
|
[ Conditional("DEBUG_APIC") ]
|
|
|
|
[NoHeapAllocation]
|
2008-11-17 18:29:00 -05:00
|
|
|
[HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
internal void DumpRedirectionEntries()
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
|
|
|
for (uint i = 0; i < entries; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
uint hi = ReadRegister(RedHiBase + i * 2);
|
|
|
|
uint lo = ReadRegister(RedLoBase + i * 2);
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
|
|
"IoApic Entry {0:x2} {1:x8} {2:x8}",
|
|
|
|
i, hi, lo);
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
[NoHeapAllocation]
|
|
|
|
private void RangeCheck(uint value, uint max, string name)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
if (value > max) {
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugStub.Break();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
|
|
|
private uint ReadRegister(uint offset)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
RangeCheck(offset, RegisterLimit, "offset");
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugStub.Assert(Processor.InterruptsDisabled());
|
|
|
|
|
|
|
|
IoResult result = ioRegSel.Write32NoThrow(0, offset);
|
|
|
|
DebugStub.Assert(IoResult.Success == result);
|
|
|
|
|
|
|
|
uint outValue;
|
|
|
|
result = ioWin.Read32NoThrow((byte)0, out outValue);
|
|
|
|
DebugStub.Assert(IoResult.Success == result);
|
|
|
|
return outValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation]
|
|
|
|
private void WriteRegister(uint offset, uint value)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
RangeCheck(offset, RegisterLimit, "offset");
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugStub.Assert(Processor.InterruptsDisabled());
|
|
|
|
|
|
|
|
IoResult result = ioRegSel.Write32NoThrow(0, offset);
|
|
|
|
DebugStub.Assert(IoResult.Success == result);
|
|
|
|
|
|
|
|
result = ioWin.Write32NoThrow((byte)0, value);
|
|
|
|
DebugStub.Assert(IoResult.Success == result);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public byte GetId()
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
return (byte)((ReadRegister(0) & 0x0f000000u) >> 24);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public void SetId(byte id)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
|
|
|
RangeCheck(id, IdLimit, "id");
|
2008-03-05 09:52:00 -05:00
|
|
|
uint reserved = ReadRegister(0) & 0xf0ffffffu;
|
|
|
|
WriteRegister(0, reserved | ((uint)id << 24));
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public byte GetVersion()
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
return (byte)ReadRegister(1);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public byte GetArbitrationId()
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
return (byte)((ReadRegister(2) & 0x0f000000u) >> 24);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public void SetArbitrationId(byte id)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
RangeCheck(id, IdLimit, "id");
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
uint reserved = ReadRegister(0) & 0xf0ffffffu;
|
|
|
|
WriteRegister(2, reserved | ((uint)id << 24));
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public uint RedirectionEntryCount
|
|
|
|
{
|
|
|
|
[NoHeapAllocation]
|
|
|
|
get { return entries; }
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public uint InterruptBase
|
|
|
|
{
|
|
|
|
[NoHeapAllocation]
|
|
|
|
get { return interruptBase; }
|
|
|
|
}
|
|
|
|
|
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public RedirectionEntry GetRedirectionEntry(uint index)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
|
|
|
RangeCheck(index, IndexLimit, "offset");
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
uint hi = ReadRegister(RedHiBase + index * 2);
|
|
|
|
uint lo = ReadRegister(RedLoBase + index * 2);
|
|
|
|
|
|
|
|
return new RedirectionEntry((byte) (hi >> 24),
|
|
|
|
(ushort) ((lo >> 8) & 0x1ff),
|
|
|
|
(byte) (lo & 0xff));
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public void SetRedirectionEntry(uint index, ref RedirectionEntry entry)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
|
|
|
RangeCheck(index, IndexLimit, "offset");
|
2008-03-05 09:52:00 -05:00
|
|
|
WriteRegister(RedLoBase + index * 2, MaskBit);
|
|
|
|
|
|
|
|
uint hi = ReadRegister(RedHiBase + index * 2) & 0xffffffu;
|
|
|
|
hi |= ((uint)entry.Destination) << 24;
|
|
|
|
WriteRegister(RedHiBase + index * 2, hi);
|
|
|
|
|
|
|
|
uint lo = ReadRegister(RedLoBase + index * 2) & 0x1ffffu;
|
|
|
|
lo |= ((uint)entry.IoBits) << 8;
|
|
|
|
lo |= (uint)entry.InterruptVector;
|
|
|
|
WriteRegister(RedLoBase + index * 2, lo);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public void SetEntryMask(uint index, bool masked)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
uint lo = ReadRegister(RedLoBase + index * 2) & ~MaskBit;
|
2008-11-17 18:29:00 -05:00
|
|
|
if (masked) {
|
2008-03-05 09:52:00 -05:00
|
|
|
lo |= MaskBit;
|
|
|
|
}
|
|
|
|
WriteRegister(RedLoBase + index * 2, lo);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation][HalLock]
|
2008-03-05 09:52:00 -05:00
|
|
|
public bool GetEntryMask(uint index)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
bool enabled = AcquireLock();
|
|
|
|
try {
|
2008-03-05 09:52:00 -05:00
|
|
|
uint lo = ReadRegister(RedLoBase + index * 2) & MaskBit;
|
|
|
|
return lo == MaskBit;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
finally {
|
|
|
|
ReleaseLock(enabled);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static IoApic [] CreateIOApics()
|
|
|
|
{
|
|
|
|
// Prefer to get the list of IoApics from the MADT
|
|
|
|
Madt madt = AcpiTables.GetMadt();
|
2008-11-17 18:29:00 -05:00
|
|
|
if (madt != null) {
|
2008-03-05 09:52:00 -05:00
|
|
|
ArrayList alist = madt.GetIoApics();
|
2008-11-17 18:29:00 -05:00
|
|
|
if (alist.Count > 0) {
|
2008-03-05 09:52:00 -05:00
|
|
|
IoApic [] apics = new IoApic[alist.Count];
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < alist.Count; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
// Have to convert from a ...Hal.Acpi.IoApic into a Hal.IoApic:
|
|
|
|
Microsoft.Singularity.Hal.Acpi.IoApic sourceEntry = (Microsoft.Singularity.Hal.Acpi.IoApic) alist[i];
|
2008-11-17 18:29:00 -05:00
|
|
|
IoApic destEntry = new IoApic(sourceEntry.Address, sourceEntry.InterruptBase);
|
2008-03-05 09:52:00 -05:00
|
|
|
destEntry.SetId(sourceEntry.Id);
|
|
|
|
apics[i] = destEntry;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
DebugStub.Print("Created IoApics from MADT table\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
return apics;
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
DebugStub.Print("Created IoApics from MpResources table table\n");
|
2008-03-05 09:52:00 -05:00
|
|
|
// Otherwise, create from Mp tables
|
|
|
|
return CreateFromMpResources();
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static IoApic [] CreateFromMpResources()
|
|
|
|
{
|
|
|
|
ArrayList ioApicEntries = MpResources.IoApicEntries;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
if (ioApicEntries == null) {
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugStub.Print("No I/O APICs found\n");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Scan IoApic entries and remove those that are marked unusable
|
|
|
|
int usable = ioApicEntries.Count;
|
2008-11-17 18:29:00 -05:00
|
|
|
foreach (MpIoApicEntry entry in ioApicEntries) {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (((int)entry.Flags & 0x1) != 0x1) usable--;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
if (usable == 0) {
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugStub.Print("No usable I/O APICs found\n");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
IoApic [] apics = new IoApic[usable];
|
|
|
|
int i = 0;
|
2008-11-17 18:29:00 -05:00
|
|
|
foreach (MpIoApicEntry entry in ioApicEntries) {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (((int)entry.Flags & 0x1) != 0x1)
|
|
|
|
continue;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
apics[i] = new IoApic(new UIntPtr(entry.BaseAddress), 0);
|
2008-03-05 09:52:00 -05:00
|
|
|
apics[i].SetId(entry.Id);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return apics;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class IoApicInspector
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation]
|
2008-03-05 09:52:00 -05:00
|
|
|
public static void DescribeModMask(IoBits ioBits)
|
|
|
|
{
|
|
|
|
ioBits = (IoBits) ((ushort)ioBits & (ushort)IoBits.DelModMask);
|
2008-11-17 18:29:00 -05:00
|
|
|
switch (ioBits) {
|
2008-03-05 09:52:00 -05:00
|
|
|
case IoBits.DelModFixed:
|
|
|
|
DebugStub.Print("Fixed\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModLowest:
|
|
|
|
DebugStub.Print("Lowest\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModSMI:
|
|
|
|
DebugStub.Print("SMI\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModReserved1:
|
|
|
|
DebugStub.Print("Reserved1\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModNMI:
|
|
|
|
DebugStub.Print("NMI\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModINIT:
|
|
|
|
DebugStub.Print("INIT\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModReserved2:
|
|
|
|
DebugStub.Print("Reserved2\n");
|
|
|
|
return;
|
|
|
|
case IoBits.DelModExtINT:
|
|
|
|
DebugStub.Print("ExtINT\n");
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
DebugStub.Print("ERROR\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
[NoHeapAllocation]
|
2008-03-05 09:52:00 -05:00
|
|
|
public static void PrintApic(IoApic ioApic)
|
|
|
|
{
|
|
|
|
DebugStub.Print("Io Apic\n");
|
|
|
|
DebugStub.Print(" Id: {0:x2} Version: {1:x4} ArbitrationId: {2:x2}\n",
|
|
|
|
__arglist(
|
|
|
|
ioApic.GetId(),
|
|
|
|
ioApic.GetVersion(),
|
|
|
|
ioApic.GetArbitrationId()));
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (uint i = 0; i < ioApic.RedirectionEntryCount; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
RedirectionEntry e = ioApic.GetRedirectionEntry(i);
|
|
|
|
IoBits ib = (IoBits) ((int)e.IoBits & ~(int)IoBits.DelModMask);
|
|
|
|
|
|
|
|
DebugStub.Print(" IoRedTbl[{0:x2}]" +
|
|
|
|
"Dst: {1:x2} IntVec: {2:x2} Control: {3} {4} {5} {6} {7} {8}" +
|
|
|
|
"Delivery Mode ",
|
|
|
|
__arglist(
|
|
|
|
i,
|
|
|
|
e.Destination,
|
|
|
|
e.InterruptVector,
|
|
|
|
((ib & IoBits.DstLogical) != 0) ? "Logical" : "Physical",
|
|
|
|
((ib & IoBits.IrqMask) != 0) ? "Masked" : "Unmasked",
|
|
|
|
((ib & IoBits.TriggerModeMask) != 0) ? "Level" : "Edge",
|
|
|
|
((ib & IoBits.RemoteIRR) != 0) ? "Accept" : "Recv",
|
|
|
|
((ib & IoBits.IntPolMask) != 0) ? "Hi active" : "Lo active",
|
|
|
|
((ib & IoBits.DeliveryStatus) != 0) ? "Pending" : "Idle"));
|
|
|
|
DescribeModMask(e.IoBits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|