2008-03-05 09:52:00 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Microsoft Research Singularity
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// File: PciConfig.cs
|
|
|
|
//
|
|
|
|
// Note:
|
|
|
|
//
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
#define DEBUG_PCI
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
using System;
|
|
|
|
using StringBuilder = System.Text.StringBuilder;
|
|
|
|
using System.Collections;
|
|
|
|
using Microsoft.Singularity;
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
#if !SINGULARITY_PROCESS
|
|
|
|
using Microsoft.Singularity.Hal;
|
|
|
|
#endif
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
namespace Microsoft.Singularity.Io
|
|
|
|
{
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public class PciConfig : IoConfig
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Bit encodings for PCI_COMMON_CONFIG.HeaderType
|
|
|
|
//
|
|
|
|
public const uint PCI_MULTIFUNCTION = 0x800000; // full dword
|
|
|
|
public const uint PCI_TYPE_MASK = 0x7f0000; // full dword
|
|
|
|
public const uint PCI_DEVICE_TYPE = 0x000000; // full dword
|
|
|
|
public const uint PCI_BRIDGE_TYPE = 0x010000; // full dword
|
|
|
|
public const uint PCI_CARDBUS_TYPE = 0x020000; // full dword
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
private const int PCI_CONTROL_OFFSET = 0x0004;
|
|
|
|
private const int PCI_STATUS_OFFSET = 0x0006;
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
|
|
|
// Bit encodings for PCI_COMMON_CONFIG.Control
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
public const uint PCI_ENABLE_IO_SPACE = 0x0001;
|
|
|
|
public const uint PCI_ENABLE_MEMORY_SPACE = 0x0002;
|
|
|
|
public const uint PCI_ENABLE_BUS_MASTER = 0x0004;
|
|
|
|
public const uint PCI_ENABLE_SPECIAL_CYCLES = 0x0008;
|
|
|
|
public const uint PCI_ENABLE_WRITE_AND_INVALIDATE = 0x0010;
|
|
|
|
public const uint PCI_ENABLE_VGA_COMPATIBLE_PALETTE = 0x0020;
|
|
|
|
public const uint PCI_ENABLE_PARITY = 0x0040; // (ro+)
|
|
|
|
public const uint PCI_ENABLE_WAIT_CYCLE = 0x0080; // (ro+)
|
|
|
|
public const uint PCI_ENABLE_SERR = 0x0100; // (ro+)
|
|
|
|
public const uint PCI_ENABLE_FAST_BACK_TO_BACK = 0x0200; // (ro)
|
|
|
|
public const uint PCI_DISABLE_INTERRUPTS = 0x0400;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
//
|
|
|
|
// Bit encodings for PCI_COMMON_CONFIG.Status
|
|
|
|
//
|
|
|
|
const uint PCI_STATUS_FAST_BACK_TO_BACK = 0x0080; // (ro)
|
|
|
|
const uint PCI_STATUS_DATA_PARITY_DETECTED = 0x0100;
|
|
|
|
const uint PCI_STATUS_DEVSEL = 0x0600; // 2 bits wide
|
|
|
|
const uint PCI_STATUS_SIGNALED_TARGET_ABORT = 0x0800;
|
|
|
|
const uint PCI_STATUS_RECEIVED_TARGET_ABORT = 0x1000;
|
|
|
|
const uint PCI_STATUS_RECEIVED_MASTER_ABORT = 0x2000;
|
|
|
|
const uint PCI_STATUS_SIGNALED_SYSTEM_ERROR = 0x4000;
|
|
|
|
const uint PCI_STATUS_DETECTED_PARITY_ERROR = 0x8000;
|
|
|
|
|
|
|
|
// Bit encodes for PCI_COMMON_CONFIG.u.type0.BaseAddresses
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
const uint PCI_BAR_TYPE_MASK = 0xf;
|
|
|
|
const uint PCI_BAR_TYPE_IO = 0x1;
|
|
|
|
const uint PCI_BAR_TYPE_MEM20 = 0x2;
|
|
|
|
const uint PCI_BAR_TYPE_MEM32 = 0x0;
|
|
|
|
const uint PCI_BAR_TYPE_MEM64 = 0x4;
|
|
|
|
const uint PCI_BAR_TYPE_MEMMASK = 0x6;
|
|
|
|
const uint PCI_BAR_TYPE_PREFETCH = 0x8;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
const uint PCI_ROMADDRESS_ENABLED = 0x00000001;
|
|
|
|
|
|
|
|
const uint PCI_ENABLE_BRIDGE_PARITY_ERROR = 0x0001;
|
|
|
|
const uint PCI_ENABLE_BRIDGE_SERR = 0x0002;
|
|
|
|
const uint PCI_ENABLE_BRIDGE_ISA = 0x0004;
|
|
|
|
const uint PCI_ENABLE_BRIDGE_VGA = 0x0008;
|
|
|
|
const uint PCI_ENABLE_BRIDGE_MASTER_ABORT_SERR = 0x0020;
|
|
|
|
const uint PCI_ASSERT_BRIDGE_RESET = 0x0040;
|
|
|
|
const uint PCI_ENABLE_BRIDGE_FAST_BACK_TO_BACK = 0x0080;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_STORAGE = 0x01;
|
|
|
|
const byte PCI_CLASS_NETWORK = 0x02;
|
|
|
|
const byte PCI_CLASS_DISPLAY = 0x03;
|
|
|
|
const byte PCI_CLASS_MULTIMEDIA = 0x04;
|
|
|
|
const byte PCI_CLASS_MEMORY = 0x05;
|
|
|
|
const byte PCI_CLASS_BRIDGE = 0x06;
|
|
|
|
const byte PCI_CLASS_COMMUNICATION = 0x07;
|
|
|
|
const byte PCI_CLASS_SYSTEM = 0x08;
|
|
|
|
const byte PCI_CLASS_INPUT = 0x09;
|
|
|
|
const byte PCI_CLASS_DOCKING = 0x0a;
|
|
|
|
const byte PCI_CLASS_PROCESSOR = 0x0b;
|
|
|
|
const byte PCI_CLASS_SERIAL = 0x0c;
|
|
|
|
const byte PCI_CLASS_WIRELESS = 0x0d;
|
|
|
|
const byte PCI_CLASS_I2O = 0x0e;
|
|
|
|
const byte PCI_CLASS_SATELLITE = 0x0f;
|
|
|
|
const byte PCI_CLASS_ENCRYPTION = 0x10;
|
|
|
|
const byte PCI_CLASS_ACQUISITION = 0x11;
|
|
|
|
const byte PCI_CLASS_OTHERS = 0xff;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_STORAGE_SCSI = 0x00;
|
|
|
|
const byte PCI_CLASS_STORAGE_IDE = 0x01; // NB: Interface
|
|
|
|
const byte PCI_CLASS_STORAGE_FLOPPY = 0x02;
|
|
|
|
const byte PCI_CLASS_STORAGE_IPI = 0x03;
|
|
|
|
const byte PCI_CLASS_STORAGE_RAID = 0x04;
|
|
|
|
const byte PCI_CLASS_STORAGE_ATA = 0x05; // NB: Interface
|
|
|
|
const byte PCI_CLASS_STORAGE_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_NETWORK_ETHERNET = 0x00;
|
|
|
|
const byte PCI_CLASS_NETWORK_RING = 0x01;
|
|
|
|
const byte PCI_CLASS_NETWORK_FDDI = 0x02;
|
|
|
|
const byte PCI_CLASS_NETWORK_ATM = 0x03;
|
|
|
|
const byte PCI_CLASS_NETWORK_ISDN = 0x04;
|
|
|
|
const byte PCI_CLASS_NETWORK_FIP = 0x05;
|
|
|
|
const byte PCI_CLASS_NETWORK_PICMG = 0x06; // NB: Interface
|
|
|
|
const byte PCI_CLASS_NETWORK_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_DISPLAY_VGA = 0x00; // NB: Interface
|
|
|
|
const byte PCI_CLASS_DISPLAY_XGA = 0x01;
|
|
|
|
const byte PCI_CLASS_DISPLAY_3D = 0x02;
|
|
|
|
const byte PCI_CLASS_DISPLAY_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_MULTIMEDIA_VIDEO = 0x00;
|
|
|
|
const byte PCI_CLASS_MULTIMEDIA_AUDIO = 0x01;
|
|
|
|
const byte PCI_CLASS_MULTIMEDIA_TELEPHONY = 0x02;
|
|
|
|
const byte PCI_CLASS_MULTIMEDIA_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_MEMORY_RAM = 0x00;
|
|
|
|
const byte PCI_CLASS_MEMORY_FLASH = 0x01;
|
|
|
|
const byte PCI_CLASS_MEMORY_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_BRIDGE_HOST = 0x00;
|
|
|
|
const byte PCI_CLASS_BRIDGE_ISA = 0x01;
|
|
|
|
const byte PCI_CLASS_BRIDGE_EISA = 0x02;
|
|
|
|
const byte PCI_CLASS_BRIDGE_MC = 0x03;
|
|
|
|
const byte PCI_CLASS_BRIDGE_PCI = 0x04; // NB: Interface
|
|
|
|
const byte PCI_CLASS_BRIDGE_PCMCIA = 0x05;
|
|
|
|
const byte PCI_CLASS_BRIDGE_NUBUS = 0x06;
|
|
|
|
const byte PCI_CLASS_BRIDGE_CARDBUS = 0x07;
|
|
|
|
const byte PCI_CLASS_BRIDGE_RACEWAY = 0x08; // NB: Interface
|
|
|
|
const byte PCI_CLASS_BRIDGE_SEMIPCI = 0x09; // NB: Interface
|
|
|
|
const byte PCI_CLASS_BRIDGE_INFINIBAND = 0x0a;
|
|
|
|
const byte PCI_CLASS_BRIDGE_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_SERIAL = 0x00; // NB: Interface
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_PARALLEL = 0x01; // NB: Interface
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_MULTIPORT = 0x02;
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_MODEM = 0x03; // NB: Interface
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_GPIB = 0x04;
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_SMARTCARD = 0x05;
|
|
|
|
const byte PCI_CLASS_COMMUNICATION_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_SYSTEM_PIC = 0x00; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SYSTEM_DMA = 0x01; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SYSTEM_TIMER = 0x02; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SYSTEM_RTC = 0x03; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SYSTEM_PCIHP = 0x04;
|
|
|
|
const byte PCI_CLASS_SYSTEM_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_INPUT_KEYBOARD = 0x00;
|
|
|
|
const byte PCI_CLASS_INPUT_PEN = 0x01;
|
|
|
|
const byte PCI_CLASS_INPUT_MOUSE = 0x02;
|
|
|
|
const byte PCI_CLASS_INPUT_SCANNER = 0x03;
|
|
|
|
const byte PCI_CLASS_INPUT_GAMEPORT = 0x04; // NB: Interface
|
|
|
|
const byte PCI_CLASS_INPUT_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_SERIAL_FIREWIRE = 0x00; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SERIAL_ACCESS = 0x01;
|
|
|
|
const byte PCI_CLASS_SERIAL_SSA = 0x02;
|
|
|
|
const byte PCI_CLASS_SERIAL_USB = 0x03; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SERIAL_FIBRE = 0x04;
|
|
|
|
const byte PCI_CLASS_SERIAL_SMBUS = 0x05;
|
|
|
|
const byte PCI_CLASS_SERIAL_INFINIBAND = 0x06;
|
|
|
|
const byte PCI_CLASS_SERIAL_IPMI = 0x07; // NB: Interface
|
|
|
|
const byte PCI_CLASS_SERIAL_SERCOS = 0x08;
|
|
|
|
const byte PCI_CLASS_SERIAL_CANBUS = 0x09;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_WIRELESS_IRDA = 0x00;
|
|
|
|
const byte PCI_CLASS_WIRELESS_IR = 0x01;
|
|
|
|
const byte PCI_CLASS_WIRELESS_RF = 0x10;
|
|
|
|
const byte PCI_CLASS_WIRELESS_BLUETOOTH = 0x11;
|
|
|
|
const byte PCI_CLASS_WIRELESS_BROADBAND = 0x12;
|
|
|
|
const byte PCI_CLASS_WIRELESS_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_I2O_I2O = 0x00; // NB: Interface
|
|
|
|
|
|
|
|
const byte PCI_CLASS_SATELLITE_TV = 0x01;
|
|
|
|
const byte PCI_CLASS_SATELLITE_AUDIO = 0x02;
|
|
|
|
const byte PCI_CLASS_SATELLITE_VOICE = 0x03;
|
|
|
|
const byte PCI_CLASS_SATELLITE_DATA = 0x04;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_ENCRYPTION_NETWORK = 0x00;
|
|
|
|
const byte PCI_CLASS_ENCRYPTION_ENTERTAINMENT = 0x10;
|
|
|
|
const byte PCI_CLASS_ENCRYPTION_OTHER = 0x80;
|
|
|
|
|
|
|
|
const byte PCI_CLASS_ACQUISITION_DPIO = 0x00;
|
|
|
|
const byte PCI_CLASS_ACQUISITION_PERF = 0x01;
|
|
|
|
const byte PCI_CLASS_ACQUISITION_COMM = 0x10;
|
|
|
|
const byte PCI_CLASS_ACQUISITION_MGMT = 0x20;
|
|
|
|
const byte PCI_CLASS_ACQUISITION_OTHER = 0x80;
|
|
|
|
|
|
|
|
const int PCI_INTERRUPT_LINE = 0x3c;
|
|
|
|
|
|
|
|
const int PCI_INTERRUPT_PIN = 0x3d;
|
|
|
|
const byte PCI_INTERRUPT_PIN_A = 1;
|
|
|
|
const byte PCI_INTERRUPT_PIN_B = 2;
|
|
|
|
const byte PCI_INTERRUPT_PIN_C = 3;
|
|
|
|
const byte PCI_INTERRUPT_PIN_D = 4;
|
|
|
|
|
|
|
|
protected PciPort port;
|
|
|
|
|
|
|
|
public ushort VendorId; // 00..01 (ro)
|
|
|
|
public ushort DeviceId; // 02..03 (ro)
|
2008-11-17 18:29:00 -05:00
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
protected byte RevisionId; // 08..08 (ro)
|
|
|
|
public byte Interface; // 09..09 (ro)
|
|
|
|
protected byte SubClassId; // 0a..0a (ro)
|
|
|
|
protected byte ClassId; // 0b..0b (ro)
|
|
|
|
public byte CacheLineSize; // 0c..0c (ro+)
|
|
|
|
protected byte LatencyTimer; // 0d..0d (ro+)
|
|
|
|
protected byte HeaderType; // 0e..0e (ro)
|
|
|
|
protected byte BIST; // 0f..0f Built in self test
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
protected ulong[] BaseAddresses; // 10..17 or ..27 [2 or 6]
|
|
|
|
protected ulong[] BaseAddrSizes;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
protected ushort SubsystemVendorId; // 2c..2d (devices only)
|
|
|
|
protected ushort SubsystemDeviceId; // 2e..2f (devices only)
|
|
|
|
|
|
|
|
protected uint ROMBaseAddress; // 38..3b or 30.33
|
|
|
|
protected byte InterruptPin; // 3d..3d
|
|
|
|
|
|
|
|
public static PciConfig Create(String[] ids, PciPort port,
|
|
|
|
IoRange [] fixedRanges)
|
|
|
|
{
|
|
|
|
uint u = port.Read32(0);
|
|
|
|
if (u == ~0u || u == 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
PciConfig config = null;
|
|
|
|
|
|
|
|
u = port.Read32(0x0c);
|
|
|
|
switch (u & PciConfig.PCI_TYPE_MASK) {
|
|
|
|
case PciConfig.PCI_DEVICE_TYPE:
|
|
|
|
config = new PciDeviceConfig(port);
|
|
|
|
break;
|
|
|
|
case PciConfig.PCI_BRIDGE_TYPE:
|
|
|
|
config = new PciBridgeConfig(port);
|
|
|
|
break;
|
|
|
|
case PciConfig.PCI_CARDBUS_TYPE:
|
|
|
|
config = new PciCardbusConfig(port);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (config != null) {
|
|
|
|
config.FixedRanges = fixedRanges;
|
|
|
|
}
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal PciConfig(String[] ids, PciPort port)
|
|
|
|
{
|
|
|
|
this.port = port;
|
|
|
|
this.Read();
|
|
|
|
this.Ids = ids;
|
|
|
|
}
|
|
|
|
|
|
|
|
public PciConfig(PciPort port)
|
|
|
|
{
|
|
|
|
this.port = port;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public PciPort PciPort
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
get { return this.port; }
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public IoIrqRange GetIrq()
|
|
|
|
{
|
|
|
|
return new IoIrqRange(InterruptLine, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetInterrupt(byte irq)
|
|
|
|
{
|
|
|
|
Write8(PCI_INTERRUPT_LINE, irq);
|
|
|
|
}
|
|
|
|
|
|
|
|
public byte InterruptLine
|
|
|
|
{
|
|
|
|
get { return Read8(PCI_INTERRUPT_LINE); }
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public ushort Control
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
get { return Read16(PCI_CONTROL_OFFSET); }
|
|
|
|
set { Write16(PCI_CONTROL_OFFSET, value); }
|
|
|
|
}
|
|
|
|
|
|
|
|
public ushort Status
|
|
|
|
{
|
|
|
|
get { return Read16(PCI_STATUS_OFFSET); }
|
|
|
|
set { Write16(PCI_STATUS_OFFSET, value); }
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IoSpaceEnabled
|
|
|
|
{
|
|
|
|
get { return ((uint)Control & PCI_ENABLE_IO_SPACE) != 0; }
|
|
|
|
set {
|
|
|
|
uint tmp = (uint)Control & ~PCI_ENABLE_IO_SPACE;
|
|
|
|
if (value) {
|
|
|
|
tmp |= PCI_ENABLE_IO_SPACE;
|
|
|
|
}
|
|
|
|
Control = (ushort)(tmp & 0xffff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool MemorySpaceEnabled
|
|
|
|
{
|
|
|
|
get { return ((uint)Control & PCI_ENABLE_MEMORY_SPACE) != 0; }
|
|
|
|
set {
|
|
|
|
uint tmp = (uint)Control & ~PCI_ENABLE_MEMORY_SPACE;
|
|
|
|
if (value) {
|
|
|
|
tmp |= PCI_ENABLE_MEMORY_SPACE;
|
|
|
|
}
|
|
|
|
Control = (ushort)(tmp & 0xffff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool InterruptsEnabled
|
|
|
|
{
|
|
|
|
get { return ((uint)Control & PCI_DISABLE_INTERRUPTS) == 0; }
|
|
|
|
set {
|
|
|
|
uint tmp = (uint)Control & ~PCI_DISABLE_INTERRUPTS;
|
|
|
|
if (!value) {
|
|
|
|
tmp |= PCI_ENABLE_MEMORY_SPACE;
|
|
|
|
}
|
|
|
|
Control = (ushort)(tmp & 0xffff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Port operations
|
|
|
|
//
|
|
|
|
|
|
|
|
public ulong Read64(int offset)
|
|
|
|
{
|
|
|
|
ulong hi = Read32(offset + 4);
|
|
|
|
return (hi << 32) | (ulong)Read32(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Write64(int offset, ulong value)
|
|
|
|
{
|
|
|
|
Write32(offset + 4, (uint)(value >> 32));
|
|
|
|
Write32(offset, (uint)(value & 0xffffffff));
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public uint Read32(int offset) {
|
|
|
|
return port.Read32(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Write32(int offset, uint value) {
|
|
|
|
port.Write32(offset, value);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public ushort Read16(int offset) {
|
2008-03-05 09:52:00 -05:00
|
|
|
return port.Read16(offset);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public void Write16(int offset, ushort value) {
|
2008-03-05 09:52:00 -05:00
|
|
|
port.Write16(offset, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public byte Read8(int offset) {
|
|
|
|
return port.Read8(offset);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public void Write8(int offset, byte value) {
|
2008-03-05 09:52:00 -05:00
|
|
|
port.Write8(offset, value);
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
protected virtual void Read()
|
|
|
|
{
|
|
|
|
uint u;
|
|
|
|
|
|
|
|
u = Read32(0x00);
|
|
|
|
VendorId = (ushort)(u & 0xffff);
|
|
|
|
DeviceId = (ushort)((u >> 16) & 0xffff);
|
|
|
|
|
|
|
|
u = Read32(0x08);
|
|
|
|
RevisionId = (byte)(u & 0xff);
|
|
|
|
Interface = (byte)((u >> 8) & 0xff);
|
|
|
|
SubClassId = (byte)((u >> 16) & 0xff);
|
|
|
|
ClassId = (byte)((u >> 24) & 0xff);
|
|
|
|
|
|
|
|
u = Read32(0x0c);
|
|
|
|
CacheLineSize = (byte)(u & 0xff);
|
|
|
|
LatencyTimer = (byte)((u >> 8) & 0xff);
|
|
|
|
HeaderType = (byte)((u >> 16) & 0xff);
|
|
|
|
BIST = (byte)((u >> 24) & 0xff);
|
|
|
|
|
|
|
|
this.Ids = GetIds();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <para>
|
2008-11-17 18:29:00 -05:00
|
|
|
/// Builds the list of device IDs for this PCI device. We generate the same
|
2008-03-05 09:52:00 -05:00
|
|
|
/// strings that Windows uses for its hardware IDs and compatible IDs.
|
|
|
|
/// The order is significant; the PNP manager will search the device IDs,
|
|
|
|
/// one by one, for a device driver that matches. The list is ordered from
|
|
|
|
/// most specific to least specific.
|
|
|
|
/// </para>
|
|
|
|
///
|
|
|
|
/// <para>
|
|
|
|
/// WDM "hardware IDs":
|
|
|
|
/// PCI\VEN_xxxy&DEV_yyyy&SUBSYS_zzzzzzzz&REV_rr
|
|
|
|
/// PCI\VEN_xxxy&DEV_yyyy&SUBSYS_zzzzzzzz
|
|
|
|
/// PCI\VEN_xxxy&DEV_yyyy&CC_ccssii
|
|
|
|
/// PCI\VEN_xxxy&DEV_yyyy&CC_ccss
|
|
|
|
/// PCI\VEN_xxxy
|
|
|
|
/// </para>
|
|
|
|
///
|
|
|
|
/// <para>
|
|
|
|
/// WDM "compatible IDs":
|
|
|
|
/// PCI\VEN_xxxy&DEV_yyyy&REV_rr
|
|
|
|
/// PCI\VEN_xxxy&DEV_yyyy
|
|
|
|
/// PCI\VEN_xxxx&CC_ccssii
|
|
|
|
/// PCI\VEN_xxxx&CC_ccss
|
|
|
|
/// PCI\CC_ccssii
|
|
|
|
/// PCI\CC_ccss
|
|
|
|
/// </para>
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>
|
|
|
|
/// An array containing the device IDs. The list is ordered from most specific
|
|
|
|
/// to least specific.
|
|
|
|
/// </returns>
|
|
|
|
public string[] GetIds()
|
|
|
|
{
|
|
|
|
const string pci_prefix = @"PCI/";
|
|
|
|
const string and = "&";
|
|
|
|
|
|
|
|
string id_classcode = "CC_" + ByteToHex(this.ClassId) + ByteToHex(this.SubClassId);
|
|
|
|
string id_classcode_interface = id_classcode + ByteToHex(this.Interface);
|
|
|
|
string id_vendor = "VEN_" + UInt16ToHex(this.VendorId);
|
|
|
|
string id_device = "DEV_" + UInt16ToHex(this.DeviceId);
|
|
|
|
string id_vendor_device = id_vendor + and + id_device;
|
|
|
|
string id_revision = "REV_" + ByteToHex(this.RevisionId);
|
|
|
|
string id_subsys = "SUBSYS_" + UInt16ToHex(this.SubsystemVendorId) + UInt16ToHex(this.SubsystemDeviceId);
|
|
|
|
|
|
|
|
#if ENABLE_OLD_SIGNATURE
|
|
|
|
string sing_id = String.Format("/pci/{0,2:x2}/{1,2:x2}/{2,4:x4}/{3,4:x4}/" +
|
|
|
|
"{4,2:x2}",
|
|
|
|
ClassId,
|
|
|
|
SubClassId,
|
|
|
|
VendorId,
|
|
|
|
DeviceId,
|
|
|
|
RevisionId);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
string[] ids = {
|
|
|
|
#if ENABLE_OLD_SIGNATURE
|
|
|
|
sing_id,
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Hardware IDs
|
2008-11-17 18:29:00 -05:00
|
|
|
pci_prefix + id_vendor_device + and + id_classcode
|
|
|
|
+ and + id_subsys + and + id_revision,
|
2008-03-05 09:52:00 -05:00
|
|
|
pci_prefix + id_vendor_device + and + id_subsys + and + id_revision,
|
|
|
|
pci_prefix + id_vendor_device + and + id_subsys,
|
|
|
|
pci_prefix + id_vendor_device + and + id_classcode_interface,
|
|
|
|
pci_prefix + id_vendor_device + and + id_classcode,
|
|
|
|
pci_prefix + id_vendor,
|
|
|
|
|
|
|
|
// Compatible IDs
|
|
|
|
pci_prefix + id_vendor_device + and + id_revision,
|
|
|
|
pci_prefix + id_vendor_device,
|
|
|
|
pci_prefix + id_vendor + and + id_classcode_interface,
|
|
|
|
pci_prefix + id_vendor + and + id_classcode,
|
|
|
|
pci_prefix + id_classcode_interface,
|
|
|
|
pci_prefix + id_classcode,
|
|
|
|
};
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < ids.Length; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
string id = ids[i];
|
|
|
|
id = id.Replace('\\', '/').ToLower();
|
|
|
|
ids[i] = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ids;
|
|
|
|
}
|
|
|
|
|
|
|
|
static string ByteToHex(byte value)
|
|
|
|
{
|
|
|
|
StringBuilder sb = new StringBuilder(2);
|
|
|
|
sb.Append(HexDigits[value >> 4]);
|
|
|
|
sb.Append(HexDigits[value & 0xf]);
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
static string UInt16ToHex(ushort value)
|
|
|
|
{
|
|
|
|
StringBuilder sb = new StringBuilder(4);
|
|
|
|
sb.Append(HexDigits[(value >> 12) & 0xf]);
|
|
|
|
sb.Append(HexDigits[(value >> 8) & 0xf]);
|
|
|
|
sb.Append(HexDigits[(value >> 4) & 0xf]);
|
|
|
|
sb.Append(HexDigits[value & 0xf]);
|
|
|
|
return sb.ToString();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const string HexDigits = "0123456789ABCDEF";
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
private void ProbeIoRange(int offset,
|
|
|
|
out ushort start,
|
|
|
|
out ushort length)
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
uint start32 = port.Read32(offset);
|
|
|
|
|
|
|
|
DebugStub.Assert((start32 & PCI_BAR_TYPE_IO) == PCI_BAR_TYPE_IO);
|
|
|
|
|
|
|
|
Write32(offset, ~0u);
|
|
|
|
uint length32 = Read32(offset);
|
|
|
|
length32 &= ~PCI_BAR_TYPE_IO;
|
|
|
|
length32 |= 0xffff0000;
|
|
|
|
length32 = ~length32 + 1;
|
|
|
|
|
|
|
|
Write32(offset, start32);
|
|
|
|
|
|
|
|
if (start32 <= 0xffff && length32 <= 0xffff) {
|
|
|
|
start = (ushort)start32;
|
|
|
|
length = (ushort)length32;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else {
|
|
|
|
start = 0;
|
|
|
|
length = 0;
|
|
|
|
#if DEBUG_PCI
|
|
|
|
DebugStub.Break();
|
|
|
|
#endif // DEBUG_PCI
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
private void ProbeMemoryRange64(int offset,
|
|
|
|
out ulong start,
|
|
|
|
out ulong length)
|
|
|
|
{
|
|
|
|
start = Read64(offset);
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
DebugStub.Assert((start & PCI_BAR_TYPE_MEMMASK) ==
|
|
|
|
PCI_BAR_TYPE_MEM64);
|
|
|
|
|
|
|
|
Write64(offset, UInt64.MaxValue);
|
|
|
|
length = Read64(offset);
|
2008-03-05 09:52:00 -05:00
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
length &= ~((ulong)PCI_BAR_TYPE_MASK);
|
|
|
|
length = ~length + 1;
|
|
|
|
|
|
|
|
Write64(offset, start);
|
|
|
|
|
|
|
|
if (UIntPtr.Size == 4 &&
|
|
|
|
(start > (ulong)UInt32.MaxValue ||
|
|
|
|
(start + length) > (ulong)UInt32.MaxValue)) {
|
|
|
|
start = 0;
|
|
|
|
length = 0;
|
2008-03-05 09:52:00 -05:00
|
|
|
#if DEBUG_PCI
|
2008-11-17 18:29:00 -05:00
|
|
|
DebugStub.Break();
|
|
|
|
#endif // DEBUG_PCI
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ProbeMemoryRange32(int offset,
|
|
|
|
out uint start,
|
|
|
|
out uint length)
|
|
|
|
{
|
|
|
|
start = Read32(offset);
|
|
|
|
|
|
|
|
DebugStub.Assert(
|
|
|
|
(start & PCI_BAR_TYPE_MEMMASK) == PCI_BAR_TYPE_MEM32 ||
|
|
|
|
(start & PCI_BAR_TYPE_MEMMASK) == PCI_BAR_TYPE_MEM20
|
|
|
|
);
|
|
|
|
|
|
|
|
Write32(offset, UInt32.MaxValue);
|
|
|
|
length = port.Read32(offset) & ~PCI_BAR_TYPE_MASK;
|
|
|
|
if ((start & PCI_BAR_TYPE_MASK) == PCI_BAR_TYPE_MEM20) {
|
|
|
|
length |= 0xfff00000;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
length = ~length + 1;
|
|
|
|
|
|
|
|
Write32(offset, start);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void ReadBaseAddresses(int n)
|
|
|
|
{
|
|
|
|
InterruptPin = Read8(PCI_INTERRUPT_PIN);
|
|
|
|
|
|
|
|
if (InterruptPin != 0) {
|
|
|
|
|
|
|
|
// Add interrupt resource to list of ranges if present
|
|
|
|
DynamicRanges = new IoRange [n + 1];
|
|
|
|
|
|
|
|
DynamicRanges[n] = new IoIrqRange(Read8(PCI_INTERRUPT_LINE), 1);
|
|
|
|
byte currentInterruptLine = InterruptLine;
|
|
|
|
|
|
|
|
#if !SINGULARITY_PROCESS
|
|
|
|
byte newInterruptLine = Platform.TranslatePciInterrupt(currentInterruptLine,
|
|
|
|
InterruptPin,
|
|
|
|
port);
|
|
|
|
if (newInterruptLine != currentInterruptLine)
|
|
|
|
{
|
|
|
|
SetInterrupt(newInterruptLine);
|
|
|
|
currentInterruptLine = newInterruptLine;
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
#endif
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
IoIrqRange range = new IoIrqRange(currentInterruptLine, 1);
|
|
|
|
|
|
|
|
DynamicRanges[n] = range;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DynamicRanges = new IoRange [n];
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseAddresses = new ulong [n];
|
|
|
|
BaseAddrSizes = new ulong [n];
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
uint control = Read32(0x04);
|
|
|
|
uint send = (control & (~(PCI_ENABLE_IO_SPACE|PCI_ENABLE_MEMORY_SPACE)))
|
|
|
|
& 0xffff;
|
|
|
|
if (control == 0x02b00003) {
|
|
|
|
send = (control & (~(PCI_ENABLE_IO_SPACE))) & 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DONT_SKIP_NVIDIA
|
|
|
|
if (control == 0x02b00003) {
|
|
|
|
send = control & 0xffff;
|
|
|
|
|
|
|
|
send &= ~PCI_ENABLE_IO_SPACE;
|
|
|
|
port.Write32(0x04, send);
|
|
|
|
Tracing.Log(Tracing.Debug, "NVIDIA Read[{0}]: ctrl={1:x8} send={2:x8}", n, control, send);
|
|
|
|
uint x = Read32(0x04);
|
|
|
|
Tracing.Log(Tracing.Debug, "NVIDIA Read[{0}]: finl={1:x8}", n, x);
|
|
|
|
|
|
|
|
port.Write32(0x04, control & 0xffff);
|
|
|
|
x = Read32(0x04);
|
|
|
|
Tracing.Log(Tracing.Debug, "NVIDIA Read[{0}]: last={1:x8}", n, x);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
port.Write32(0x04, send);
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0, bar = 0; i < n; i++, bar++) {
|
|
|
|
int offset = 0x10 + i * 4;
|
|
|
|
uint type = Read32(offset) & PCI_BAR_TYPE_MASK;
|
|
|
|
|
|
|
|
if ((type & PCI_BAR_TYPE_IO) == PCI_BAR_TYPE_IO) {
|
|
|
|
ushort addr16, size16;
|
|
|
|
ProbeIoRange(offset, out addr16, out size16);
|
|
|
|
if (size16 != 0) {
|
|
|
|
DynamicRanges[bar] =
|
|
|
|
new IoPortRange(
|
|
|
|
(ushort)((uint)addr16 & ~PCI_BAR_TYPE_IO),
|
|
|
|
size16,
|
|
|
|
Access.ReadWrite
|
|
|
|
);
|
|
|
|
BaseAddresses[bar] = addr16;
|
|
|
|
BaseAddrSizes[bar] = size16;
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((type & PCI_BAR_TYPE_MEMMASK) == PCI_BAR_TYPE_MEM64) {
|
|
|
|
ulong addr64, size64;
|
|
|
|
ProbeMemoryRange64(offset, out addr64, out size64);
|
|
|
|
if (size64 != 0) {
|
|
|
|
DynamicRanges[bar] =
|
|
|
|
new IoMemoryRange(
|
|
|
|
addr64 & ~PCI_BAR_TYPE_MASK,
|
|
|
|
size64,
|
|
|
|
Access.ReadWrite
|
|
|
|
);
|
|
|
|
BaseAddresses[bar] = addr64;
|
|
|
|
BaseAddrSizes[bar] = size64;
|
|
|
|
i += 1;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else if ((type & PCI_BAR_TYPE_MEMMASK) == PCI_BAR_TYPE_MEM32 ||
|
|
|
|
(type & PCI_BAR_TYPE_MEMMASK) == PCI_BAR_TYPE_MEM20) {
|
|
|
|
uint addr32, size32;
|
|
|
|
ProbeMemoryRange32(offset, out addr32, out size32);
|
|
|
|
if (size32 != 0) {
|
|
|
|
DynamicRanges[bar] =
|
|
|
|
new IoMemoryRange(
|
|
|
|
addr32 & ~PCI_BAR_TYPE_MASK,
|
|
|
|
size32,
|
|
|
|
Access.ReadWrite
|
|
|
|
);
|
|
|
|
BaseAddresses[bar] = addr32;
|
|
|
|
BaseAddrSizes[bar] = size32;
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
port.Write32(0x04, control & 0xffff);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
{
|
|
|
|
return String.Format("[PCI: VEN_{0:x4} DEV_{1:x4} CLASS {2:x2}.{3:x2}.{4:x2} BASE {5:x8}]",
|
|
|
|
this.VendorId,
|
|
|
|
this.DeviceId,
|
|
|
|
this.ClassId,
|
|
|
|
this.SubClassId,
|
|
|
|
this.Interface,
|
|
|
|
this.Base);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string ToPrint()
|
|
|
|
{
|
|
|
|
StringBuilder text = new StringBuilder();
|
|
|
|
base.DumpRanges(text);
|
|
|
|
text.AppendFormat(" PCI Vendor/Device: {0:x4}.{1:x4} rev {2:x2} {3} {4}\n",
|
|
|
|
this.VendorId,
|
|
|
|
this.DeviceId,
|
|
|
|
this.RevisionId,
|
|
|
|
this.Vendor,
|
|
|
|
this.Device);
|
|
|
|
text.AppendFormat(" PCI Class/Subclass: {0:x2}.{1:x2}.{2:x2}\n",
|
|
|
|
this.ClassId,
|
|
|
|
this.SubClassId,
|
|
|
|
this.Interface,
|
|
|
|
this.Class);
|
|
|
|
return text.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected string PrintAddresses()
|
|
|
|
{
|
|
|
|
String s;
|
|
|
|
|
|
|
|
bool print = false;
|
|
|
|
for (int i = 0; i < BaseAddresses.Length; i++) {
|
|
|
|
if (BaseAddresses[i] != 0 || BaseAddrSizes[i] != 0) {
|
|
|
|
print = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!print &&
|
|
|
|
ROMBaseAddress == 0 && InterruptLine == 0 && InterruptPin == 0) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
s = String.Format(" RM={0:x8} IL={1,2:x2} IP={2,2:x2} ",
|
|
|
|
ROMBaseAddress,
|
|
|
|
InterruptLine,
|
|
|
|
InterruptPin);
|
|
|
|
|
|
|
|
int printed = 0;
|
|
|
|
for (int i = 0; i < BaseAddresses.Length; i++) {
|
|
|
|
if (DynamicRanges[i] != null) {
|
|
|
|
s += String.Format("A{0}={1} ", i, DynamicRanges[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DONT_PRINT_RAW_ADDRESSS_BUT_ONLY_RANGES
|
|
|
|
if (BaseAddresses[i] == 0 && BaseAddrSizes[i] == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
if ((BaseAddresses[i] & PCI_BAR_TYPE_IO) != 0) {
|
2008-03-05 09:52:00 -05:00
|
|
|
s += String.Format("A{0}=IO:{1:x8}[{2:x}] ",
|
|
|
|
i, BaseAddresses[i], BaseAddrSizes[i]);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if ((BaseAddresses[i] & PCI_BAR_TYPE_MEM64) != 0) {
|
|
|
|
s += String.Format("A{0}=64:{1:x8}[{2:x}] ",
|
|
|
|
i, BaseAddresses[i], BaseAddrSizes[i]);
|
|
|
|
}
|
|
|
|
else if ((BaseAddresses[i] & PCI_BAR_TYPE_MEM20) != 0) {
|
|
|
|
s += String.Format("A{0}=20:{1:x8}[{2:x}] ",
|
|
|
|
i, BaseAddresses[i], BaseAddrSizes[i]);
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
else {
|
2008-11-17 18:29:00 -05:00
|
|
|
s += String.Format("A{0}=32:{1:x8}[{2:x}] ",
|
|
|
|
i, BaseAddresses[i], BaseAddrSizes[i]);
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
printed++;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected string Vendor {
|
|
|
|
get {
|
|
|
|
switch (VendorId) {
|
|
|
|
case 0x1011:
|
|
|
|
return "DEC";
|
|
|
|
case 0x104c:
|
|
|
|
return "TI";
|
|
|
|
case 0x5333:
|
|
|
|
return "S3";
|
|
|
|
case 0x8086:
|
|
|
|
return "Intel";
|
|
|
|
case 0x10de:
|
|
|
|
return "nVidia";
|
|
|
|
case 0x1106:
|
|
|
|
return "VIA Technologies";
|
|
|
|
default:
|
|
|
|
return String.Format("{0,4:x4}", VendorId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected string Device {
|
|
|
|
get {
|
|
|
|
switch (VendorId) {
|
|
|
|
case 0x8086:
|
|
|
|
switch (DeviceId) {
|
|
|
|
case 0x0484: return "82379AB";
|
|
|
|
case 0x1229: return "82559nic";
|
|
|
|
case 0x122E: return "82371FB";
|
|
|
|
case 0x1234: return "82371MX";
|
|
|
|
case 0x2410: return "82801AA";
|
|
|
|
case 0x7000: return "82371SB";
|
|
|
|
case 0x7110: return "82371AB";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x10de:
|
|
|
|
// NVIDIA
|
2008-11-17 18:29:00 -05:00
|
|
|
switch (DeviceId) {
|
2008-03-05 09:52:00 -05:00
|
|
|
case 0x0050: return "PCI-to-ISA bridge";
|
|
|
|
case 0x0052: return "nForce PCI System Management Module";
|
|
|
|
case 0x0057: return "nForce Network Interface";
|
|
|
|
case 0x0059: return "Realtek AC'97 Audio";
|
|
|
|
case 0x005a: return "USB OHCI";
|
|
|
|
case 0x005d: return "PCI-to-PCI bridge";
|
|
|
|
case 0x005e: return "nForce4 HyperTransport Bridge";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x1106:
|
|
|
|
// VIA
|
2008-11-17 18:29:00 -05:00
|
|
|
switch (DeviceId) {
|
2008-03-05 09:52:00 -05:00
|
|
|
case 0x3044: return "OHCI Compliant IEEE 1394 Host Controller";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return String.Format("{0,4:x4}", DeviceId);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected string Class {
|
|
|
|
get {
|
|
|
|
switch (ClassId) {
|
|
|
|
case PCI_CLASS_STORAGE:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_STORAGE_SCSI: return "Scsi";
|
|
|
|
case PCI_CLASS_STORAGE_IDE: return "Ide";
|
|
|
|
case PCI_CLASS_STORAGE_FLOPPY: return "Floppy";
|
|
|
|
case PCI_CLASS_STORAGE_IPI: return "Ipi";
|
|
|
|
case PCI_CLASS_STORAGE_RAID: return "Raid";
|
|
|
|
case PCI_CLASS_STORAGE_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_NETWORK:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_NETWORK_ETHERNET: return "Ethernet";
|
|
|
|
case PCI_CLASS_NETWORK_RING: return "Ring";
|
|
|
|
case PCI_CLASS_NETWORK_FDDI: return "Fddi";
|
|
|
|
case PCI_CLASS_NETWORK_ATM: return "Atm";
|
|
|
|
case PCI_CLASS_NETWORK_OTHER: return "Other";
|
|
|
|
case PCI_CLASS_NETWORK_FIP: return "FIP";
|
|
|
|
case PCI_CLASS_NETWORK_PICMG: return "PICMG";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_DISPLAY:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_DISPLAY_VGA: return "Vga";
|
|
|
|
case PCI_CLASS_DISPLAY_XGA: return "Xga";
|
|
|
|
case PCI_CLASS_DISPLAY_3D: return "3D";
|
|
|
|
case PCI_CLASS_DISPLAY_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_MULTIMEDIA:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_MULTIMEDIA_VIDEO: return "Video";
|
|
|
|
case PCI_CLASS_MULTIMEDIA_AUDIO: return "Audio";
|
|
|
|
case PCI_CLASS_MULTIMEDIA_TELEPHONY: return "Telephony";
|
|
|
|
case PCI_CLASS_MULTIMEDIA_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_MEMORY:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_MEMORY_RAM: return "Ram";
|
|
|
|
case PCI_CLASS_MEMORY_FLASH: return "Flash";
|
|
|
|
case PCI_CLASS_MEMORY_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_BRIDGE:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_BRIDGE_HOST: return "Host";
|
|
|
|
case PCI_CLASS_BRIDGE_ISA: return "Isa";
|
|
|
|
case PCI_CLASS_BRIDGE_EISA: return "Eisa";
|
|
|
|
case PCI_CLASS_BRIDGE_MC: return "Mc";
|
|
|
|
case PCI_CLASS_BRIDGE_PCI: return "Pci";
|
|
|
|
case PCI_CLASS_BRIDGE_PCMCIA: return "Pcmcia";
|
|
|
|
case PCI_CLASS_BRIDGE_NUBUS: return "Nubus";
|
|
|
|
case PCI_CLASS_BRIDGE_CARDBUS: return "Cardbus";
|
|
|
|
case PCI_CLASS_BRIDGE_RACEWAY: return "Raceway";
|
|
|
|
case PCI_CLASS_BRIDGE_SEMIPCI: return "Semipci";
|
|
|
|
case PCI_CLASS_BRIDGE_INFINIBAND: return "Infiniband";
|
|
|
|
case PCI_CLASS_BRIDGE_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_COMMUNICATION:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_COMMUNICATION_SERIAL: return "Serial";
|
|
|
|
case PCI_CLASS_COMMUNICATION_PARALLEL: return "Parallel";
|
|
|
|
case PCI_CLASS_COMMUNICATION_MULTIPORT: return "Multiport";
|
|
|
|
case PCI_CLASS_COMMUNICATION_MODEM: return "Modem";
|
|
|
|
case PCI_CLASS_COMMUNICATION_GPIB: return "Gpib";
|
|
|
|
case PCI_CLASS_COMMUNICATION_SMARTCARD: return "Smartcard";
|
|
|
|
case PCI_CLASS_COMMUNICATION_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_SYSTEM:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_SYSTEM_PIC: return "Pic";
|
|
|
|
case PCI_CLASS_SYSTEM_DMA: return "Dma";
|
|
|
|
case PCI_CLASS_SYSTEM_TIMER: return "Timer";
|
|
|
|
case PCI_CLASS_SYSTEM_RTC: return "Rtc";
|
|
|
|
case PCI_CLASS_SYSTEM_PCIHP: return "Pcihp";
|
|
|
|
case PCI_CLASS_SYSTEM_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_INPUT:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_INPUT_KEYBOARD: return "Keyboard";
|
|
|
|
case PCI_CLASS_INPUT_PEN: return "Pen";
|
|
|
|
case PCI_CLASS_INPUT_MOUSE: return "Mouse";
|
|
|
|
case PCI_CLASS_INPUT_SCANNER: return "Scanner";
|
|
|
|
case PCI_CLASS_INPUT_GAMEPORT: return "Gameport";
|
|
|
|
case PCI_CLASS_INPUT_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_SERIAL:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_SERIAL_FIREWIRE: return "Firewire";
|
|
|
|
case PCI_CLASS_SERIAL_ACCESS: return "Access";
|
|
|
|
case PCI_CLASS_SERIAL_SSA: return "Ssa";
|
|
|
|
case PCI_CLASS_SERIAL_USB:
|
2008-11-17 18:29:00 -05:00
|
|
|
switch (this.Interface) {
|
2008-03-05 09:52:00 -05:00
|
|
|
case 0x00: return "USB1.1 UHCI";
|
|
|
|
case 0x10: return "USB1.1 OHCI";
|
|
|
|
case 0x20: return "USB2.0 EHCI";
|
|
|
|
default:
|
|
|
|
return "Usb";
|
|
|
|
}
|
|
|
|
case PCI_CLASS_SERIAL_FIBRE: return "Fibre";
|
|
|
|
case PCI_CLASS_SERIAL_SMBUS: return "Smbus";
|
|
|
|
case PCI_CLASS_SERIAL_INFINIBAND: return "Infiniband";
|
|
|
|
case PCI_CLASS_SERIAL_IPMI: return "Ipmi";
|
|
|
|
case PCI_CLASS_SERIAL_SERCOS: return "Sercos";
|
|
|
|
case PCI_CLASS_SERIAL_CANBUS: return "Canbus";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
case PCI_CLASS_WIRELESS:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_WIRELESS_IRDA: return "Irda";
|
|
|
|
case PCI_CLASS_WIRELESS_IR: return "Ir";
|
|
|
|
case PCI_CLASS_WIRELESS_RF: return "Rf";
|
|
|
|
case PCI_CLASS_WIRELESS_BLUETOOTH: return "Bluetooth";
|
|
|
|
case PCI_CLASS_WIRELESS_BROADBAND: return "Broadband";
|
|
|
|
case PCI_CLASS_WIRELESS_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_I2O:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_I2O_I2O: return "I2O";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_SATELLITE:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_SATELLITE_TV: return "Tv";
|
|
|
|
case PCI_CLASS_SATELLITE_AUDIO: return "Audio";
|
|
|
|
case PCI_CLASS_SATELLITE_VOICE: return "Voice";
|
|
|
|
case PCI_CLASS_SATELLITE_DATA: return "Data";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_ENCRYPTION:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_ENCRYPTION_NETWORK: return "Network";
|
|
|
|
case PCI_CLASS_ENCRYPTION_ENTERTAINMENT:return "Entertainment";
|
|
|
|
case PCI_CLASS_ENCRYPTION_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
|
|
|
|
case PCI_CLASS_ACQUISITION:
|
|
|
|
switch (SubClassId) {
|
|
|
|
case PCI_CLASS_ACQUISITION_DPIO: return "Dpio";
|
|
|
|
case PCI_CLASS_ACQUISITION_PERF: return "Perf";
|
|
|
|
case PCI_CLASS_ACQUISITION_COMM: return "Comm";
|
|
|
|
case PCI_CLASS_ACQUISITION_MGMT: return "Mgmt";
|
|
|
|
case PCI_CLASS_ACQUISITION_OTHER: return "Other";
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
default: return String.Format("{0,2:x2}", SubClassId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected string Base {
|
|
|
|
get {
|
|
|
|
switch (ClassId) {
|
|
|
|
case PCI_CLASS_STORAGE: return "Storage";
|
|
|
|
case PCI_CLASS_NETWORK: return "Network";
|
|
|
|
case PCI_CLASS_DISPLAY: return "Display";
|
|
|
|
case PCI_CLASS_MULTIMEDIA: return "Multimedia";
|
|
|
|
case PCI_CLASS_MEMORY: return "Memory";
|
|
|
|
case PCI_CLASS_BRIDGE: return "Bridge";
|
|
|
|
case PCI_CLASS_COMMUNICATION: return "Communication";
|
|
|
|
case PCI_CLASS_SYSTEM: return "System";
|
|
|
|
case PCI_CLASS_INPUT: return "Input";
|
|
|
|
case PCI_CLASS_DOCKING: return "Docking";
|
|
|
|
case PCI_CLASS_PROCESSOR: return "Processor";
|
|
|
|
case PCI_CLASS_SERIAL: return "Serial";
|
|
|
|
case PCI_CLASS_OTHERS: return "Others";
|
|
|
|
case PCI_CLASS_WIRELESS: return "Wireless";
|
|
|
|
case PCI_CLASS_I2O: return "I2O";
|
|
|
|
case PCI_CLASS_SATELLITE: return "Satellite";
|
|
|
|
case PCI_CLASS_ENCRYPTION: return "Encryption";
|
|
|
|
case PCI_CLASS_ACQUISITION: return "Acquisition";
|
|
|
|
default: return String.Format("{0,2:x2}", ClassId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public class PciBridgeConfig : PciConfig
|
|
|
|
{
|
|
|
|
// Bridges: (HeaderType & ~PCI_MULTIFUNCTION) == PCI_BRIDGE_TYPE
|
|
|
|
// public uint BaseAddresses[2]; // 10..17
|
|
|
|
protected byte PrimaryBus; // 18..18
|
|
|
|
protected byte SecondaryBus; // 19..19
|
|
|
|
protected byte SubordinateBus; // 1a..1a
|
|
|
|
protected byte SecondaryLatency; // 1b..1b
|
|
|
|
protected byte IOBase; // 1c..1c
|
|
|
|
protected byte IOLimit; // 1d..1d
|
|
|
|
protected ushort SecondaryStatus; // 1e..1f
|
|
|
|
protected ushort MemoryBase; // 20..21
|
|
|
|
protected ushort MemoryLimit; // 22..23
|
|
|
|
protected ushort PrefetchBase; // 24..25
|
|
|
|
protected ushort PrefetchLimit; // 26..27
|
|
|
|
protected uint PrefetchBaseUpper32; // 28..2b
|
|
|
|
protected uint PrefetchLimitUpper32; // 2c..2f
|
|
|
|
protected ushort IOBaseUpper16; // 30..31
|
|
|
|
protected ushort IOLimitUpper16; // 32..33
|
|
|
|
// protected uint Reserved; // 34..37
|
|
|
|
// protected uint ROMBaseAddress; // 38..3b
|
|
|
|
#if DISABLED
|
|
|
|
// protected byte InterruptLine; // 3c..3c
|
|
|
|
#endif
|
|
|
|
// protected byte InterruptPin; // 3d..3d
|
|
|
|
protected ushort BridgeControl; // 3e..3f
|
|
|
|
|
|
|
|
public PciBridgeConfig(PciPort port)
|
|
|
|
: base(port)
|
|
|
|
{
|
|
|
|
Read();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void Read()
|
|
|
|
{
|
|
|
|
base.Read();
|
|
|
|
base.ReadBaseAddresses(2);
|
|
|
|
|
|
|
|
uint u;
|
|
|
|
|
|
|
|
u = port.Read32(0x18);
|
|
|
|
PrimaryBus = (byte)(u & 0xff);
|
|
|
|
SecondaryBus = (byte)((u >> 8) & 0xff);
|
|
|
|
SubordinateBus = (byte)((u >> 16) & 0xff);
|
|
|
|
SecondaryLatency = (byte)((u >> 24) & 0xff);
|
|
|
|
|
|
|
|
u = port.Read32(0x1c);
|
|
|
|
IOBase = (byte)(u & 0xff);
|
|
|
|
IOLimit = (byte)((u >> 8) & 0xff);
|
|
|
|
SecondaryStatus = (ushort)((u >> 16) & 0xffff);
|
|
|
|
|
|
|
|
u = port.Read32(0x20);
|
|
|
|
MemoryBase = (ushort)(u & 0xffff);
|
|
|
|
MemoryLimit = (ushort)((u >> 16) & 0xffff);
|
|
|
|
|
|
|
|
u = port.Read32(0x24);
|
|
|
|
PrefetchBase = (ushort)(u & 0xffff);
|
|
|
|
PrefetchLimit = (ushort)((u >> 16) & 0xffff);
|
|
|
|
|
|
|
|
u = port.Read32(0x28);
|
|
|
|
PrefetchBaseUpper32 = u;
|
|
|
|
|
|
|
|
u = port.Read32(0x2c);
|
|
|
|
PrefetchLimitUpper32 = u;
|
|
|
|
|
|
|
|
u = port.Read32(0x30);
|
|
|
|
IOBaseUpper16 = (ushort)(u & 0xffff);
|
|
|
|
IOLimitUpper16 = (ushort)((u >> 16) & 0xffff);
|
|
|
|
|
|
|
|
u = port.Read32(0x38);
|
|
|
|
ROMBaseAddress = u;
|
|
|
|
|
|
|
|
u = port.Read32(0x3c);
|
|
|
|
#if DISABLED
|
|
|
|
InterruptLine = (byte)(u & 0xff);
|
|
|
|
#endif
|
|
|
|
InterruptPin = (byte)((u >> 8) & 0xff);
|
|
|
|
BridgeControl = (ushort)((u >> 16) & 0xffff);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string ToPrint()
|
|
|
|
{
|
|
|
|
return base.ToPrint() +
|
|
|
|
String.Format("BUS={0,2:x2}.{1,2:x2}.{2,2:x2} IO={3,4:x4}..{4,4:x4}",
|
|
|
|
PrimaryBus, SecondaryBus, SubordinateBus,
|
|
|
|
IOBase, IOLimit) +
|
|
|
|
"" +
|
|
|
|
base.PrintAddresses() + "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public class PciDeviceConfig : PciConfig
|
|
|
|
{
|
|
|
|
// Devices: (HeaderType & ~PCI_MULTIFUNCTION) == PCI_DEVICE_TYPE
|
|
|
|
// public uint BaseAddresses[6]; // 10..27
|
|
|
|
protected uint CardbusCisPtr; // 28..2b
|
|
|
|
// protected ushort SubsystemVendorId; // 2c..2d
|
|
|
|
// protected ushort SubsystemDeviceId; // 2e..2f
|
|
|
|
// protected uint ROMBaseAddress; // 30..33
|
2008-11-17 18:29:00 -05:00
|
|
|
protected byte capabilities; // 34..34
|
2008-03-05 09:52:00 -05:00
|
|
|
// protected byte Reserved[7]; // 35..38
|
|
|
|
#if DISABLED
|
|
|
|
// protected byte InterruptLine; // 3c..3c
|
|
|
|
#endif
|
|
|
|
// protected byte InterruptPin; // 3d..3d (ro)
|
|
|
|
protected byte MinimumGrant; // 3e..3e (ro)
|
|
|
|
protected byte MaximumLatency; // 3f..3f (ro)
|
|
|
|
|
|
|
|
public PciDeviceConfig(PciPort port)
|
|
|
|
: base(port)
|
|
|
|
{
|
|
|
|
Read();
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
public byte Capabilities
|
|
|
|
{
|
|
|
|
get { return this.capabilities; }
|
|
|
|
}
|
|
|
|
|
2008-03-05 09:52:00 -05:00
|
|
|
protected override void Read()
|
|
|
|
{
|
|
|
|
base.Read();
|
|
|
|
base.ReadBaseAddresses(6);
|
|
|
|
|
|
|
|
uint u;
|
|
|
|
|
|
|
|
u = port.Read32(0x28);
|
|
|
|
CardbusCisPtr = u;
|
|
|
|
|
|
|
|
u = port.Read32(0x2c);
|
|
|
|
SubsystemVendorId = (ushort)(u & 0xffff);
|
|
|
|
SubsystemDeviceId = (ushort)((u >> 16) & 0xffff);
|
|
|
|
|
|
|
|
u = port.Read32(0x30);
|
|
|
|
ROMBaseAddress = u;
|
|
|
|
|
|
|
|
u = port.Read32(0x34);
|
2008-11-17 18:29:00 -05:00
|
|
|
this.capabilities = (byte)(u & 0xff);
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
u = port.Read32(0x3c);
|
|
|
|
if ((u & 0xff) == 0) {
|
|
|
|
port.Write32(0x3c, u | 0x7);
|
|
|
|
u = port.Read32(0x3c);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DISABLED
|
|
|
|
InterruptLine = (byte)(u & 0xff);
|
|
|
|
#endif
|
|
|
|
InterruptPin = (byte)((u >> 8) & 0xff);
|
|
|
|
MinimumGrant = (byte)((u >> 16) & 0xff);
|
|
|
|
MaximumLatency = (byte)((u >> 24) & 0xff);
|
|
|
|
|
|
|
|
Ids = GetIds();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string ToPrint()
|
|
|
|
{
|
|
|
|
String s = base.ToPrint() + "\n " + base.PrintAddresses();
|
|
|
|
|
|
|
|
if (CardbusCisPtr != 0 ||
|
|
|
|
Capabilities != 0 ||
|
|
|
|
MinimumGrant != 0 ||
|
|
|
|
MaximumLatency != 0) {
|
|
|
|
|
|
|
|
s += String.Format(" cis={0:x8} cap={1,2:x2} mg={2,2:x2} ml={3,2:x2}",
|
|
|
|
CardbusCisPtr,
|
|
|
|
Capabilities,
|
|
|
|
MinimumGrant,
|
|
|
|
MaximumLatency);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[CLSCompliant(false)]
|
|
|
|
public class PciCardbusConfig : PciConfig
|
|
|
|
{
|
|
|
|
public PciCardbusConfig(PciPort port)
|
|
|
|
: base(port)
|
|
|
|
{
|
2008-11-17 18:29:00 -05:00
|
|
|
BaseAddresses = new ulong [0];
|
2008-03-05 09:52:00 -05:00
|
|
|
Read();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void Read()
|
|
|
|
{
|
|
|
|
base.Read();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string ToPrint()
|
|
|
|
{
|
|
|
|
return base.ToPrint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // end namespace Microsoft.Singularity.Io
|