/base/Kernel/Singularity/Io/PciConfig.cs
C# | 1262 lines | 1015 code | 170 blank | 77 comment | 106 complexity | df31910d9466772e741fa98277c06e71 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Microsoft Research Singularity
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // File: PciConfig.cs
- //
- // Note:
- //
-
- #define DEBUG_PCI
-
- using System;
- using StringBuilder = System.Text.StringBuilder;
- using System.Collections;
- using Microsoft.Singularity;
-
- #if !SINGULARITY_PROCESS
- using Microsoft.Singularity.Hal;
- #endif
-
- 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
-
- private const int PCI_CONTROL_OFFSET = 0x0004;
- private const int PCI_STATUS_OFFSET = 0x0006;
-
- //
- // Bit encodings for PCI_COMMON_CONFIG.Control
- //
- 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;
-
- //
- // 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
- //
- 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;
-
- 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)
-
- 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
-
- protected ulong[] BaseAddresses; // 10..17 or ..27 [2 or 6]
- protected ulong[] BaseAddrSizes;
-
- 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;
- }
-
- public PciPort PciPort
- {
- get { return this.port; }
- }
-
- 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); }
- }
-
- public ushort Control
- {
- 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));
- }
-
- public uint Read32(int offset) {
- return port.Read32(offset);
- }
-
- public void Write32(int offset, uint value) {
- port.Write32(offset, value);
- }
-
- public ushort Read16(int offset) {
- return port.Read16(offset);
- }
-
- public void Write16(int offset, ushort value) {
- port.Write16(offset, value);
- }
-
- public byte Read8(int offset) {
- return port.Read8(offset);
- }
-
- public void Write8(int offset, byte value) {
- port.Write8(offset, value);
- }
-
- ///////////////////////////////////////////////////////////////////////
-
- 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>
- /// Builds the list of device IDs for this PCI device. We generate the same
- /// 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
- pci_prefix + id_vendor_device + and + id_classcode
- + and + id_subsys + and + id_revision,
- 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,
- };
-
- for (int i = 0; i < ids.Length; i++) {
- 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";
-
- private void ProbeIoRange(int offset,
- out ushort start,
- out ushort length)
- {
- 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;
- }
- else {
- start = 0;
- length = 0;
- #if DEBUG_PCI
- DebugStub.Break();
- #endif // DEBUG_PCI
- }
- }
-
- private void ProbeMemoryRange64(int offset,
- out ulong start,
- out ulong length)
- {
- start = Read64(offset);
-
- DebugStub.Assert((start & PCI_BAR_TYPE_MEMMASK) ==
- PCI_BAR_TYPE_MEM64);
-
- Write64(offset, UInt64.MaxValue);
- length = Read64(offset);
-
- 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;
- #if DEBUG_PCI
- 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;
- }
- 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;
- }
- #endif
-
- IoIrqRange range = new IoIrqRange(currentInterruptLine, 1);
-
- DynamicRanges[n] = range;
- }
- else {
- DynamicRanges = new IoRange [n];
- }
-
- BaseAddresses = new ulong [n];
- BaseAddrSizes = new ulong [n];
-
- 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);
-
- 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;
- }
- }
- 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;
- }
- }
- 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;
- }
- }
- }
-
- port.Write32(0x04, control & 0xffff);
- }
-
- 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;
- }
-
- if ((BaseAddresses[i] & PCI_BAR_TYPE_IO) != 0) {
- s += String.Format("A{0}=IO:{1:x8}[{2:x}] ",
- i, BaseAddresses[i], BaseAddrSizes[i]);
- }
- 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]);
- }
- else {
- s += String.Format("A{0}=32:{1:x8}[{2:x}] ",
- i, BaseAddresses[i], BaseAddrSizes[i]);
- }
- #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
- switch (DeviceId) {
- 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
- switch (DeviceId) {
- 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:
- switch (this.Interface) {
- 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
- protected byte capabilities; // 34..34
- // 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 …
Large files files are truncated, but you can click here to view the full file