/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: IoConfig.cs // using System; using StringBuilder = System.Text.StringBuilder; using ArrayList = System.Collections.ArrayList; #if SINGULARITY_PROCESS using Microsoft.Singularity; using Microsoft.Singularity.V1.Services; #endif // SINGULARITY_PROCESS namespace Microsoft.Singularity.Io { /// /// Instances of this class represent a set of I/O resources that have been assigned /// to a specific device driver instance. /// [CLSCompliant(false)] public abstract class IoConfig { /// /// Contains the list of device IDs for this device. These IDs are created (assigned) /// by the bus driver that enumerated this device. The bus driver may assign any /// number of IDs. The first ID should always be the Singularity-compatible ID, /// which uses a path-like syntax, e.g. /pnp/PNP0303 for devices enumerated by the /// PNP BIOS / ISAPNP bus device, or /pci/02/00/8086/... for devices enumerated by /// the PCI bus enumerator. /// public String[] Ids; public IoRange[] DynamicRanges; public IoRange[] FixedRanges; /// /// This property exists for compatibility with drivers that assume a single device ID. /// It returns the first device ID in the list. /// // [Obsolete("Fix code to use Ids (list of ids)")] public String Id { get { if (Ids == null || Ids.Length == 0 || Ids[0] == null) return ""; else return Ids[0]; } } /// /// Builds a description of this IoConfig instance. /// /// The description text. public virtual string ToPrint() { StringBuilder text = new StringBuilder(); ToPrint(text); return text.ToString(); } /// /// Builds a description of this IoConfig instance. /// /// The text buffer in which to write the description. protected void ToPrint(StringBuilder text) { text.Append("IoConfig: type="); text.Append(this.GetType().Name); text.Append("\n"); DumpIds(text); DumpRanges(text); } public void DumpIds(StringBuilder text) { foreach (string id in this.Ids) { text.Append(" device id: "); text.Append(id); text.Append("\n"); } } public void DumpRanges(StringBuilder text) { if (FixedRanges != null) { for (int i = 0; i < FixedRanges.Length; i++) { if (FixedRanges[i] != null) { text.Append(" frange["); text.Append(i); text.Append("]: "); text.Append(FixedRanges[i]); text.Append("\n"); } } } if (DynamicRanges != null) { for (int i = 0; i < DynamicRanges.Length; i++) { if (DynamicRanges[i] != null) { text.Append(" drange["); text.Append(i); text.Append("]: "); text.Append(DynamicRanges[i]); text.Append("\n"); } } } } /// /// Prints a description of this I/O configuration to the debug port. /// public void Print() { DebugStub.WriteLine(ToPrint()); } #if SINGULARITY_PROCESS public static unsafe IoConfig GetConfig() { // first get the device signature ArrayList idlist = new ArrayList(); char[] idbuffer = new char[0x80]; for (int i = 0;; i++) { int len = (int)DeviceService.GetPnpSignature(i, null, 0); if (len == 0) break; if (len > idbuffer.Length) idbuffer = new char[len]; fixed (char* idbuffer_pinned = &idbuffer[0]) { len = (int)DeviceService.GetPnpSignature(i, idbuffer_pinned, (uint)idbuffer.Length); } if (len == 0) break; string id = new String(idbuffer, 0, len); idlist.Add(id); Tracing.Log(Tracing.Debug, "PNP Signature: [{0}]", id); } string[] ids = (string[])idlist.ToArray(typeof(string)); #if false string id = null; char[] sigArray = new char[DeviceService.GetPnpSignature(null, 0)]; fixed (char *sigPtr = &sigArray[0]) { int len = (int)DeviceService.GetPnpSignature( sigPtr, (uint)sigArray.Length); id = String.StringCTOR(sigPtr, 0, len); } #endif // now get the fixed resources IoRange[] fixedRanges = GetFixedIoResources(); // now determine if this is a PCI bus, and if so, configure it as // such PciPortHandle pciPortHandle = new PciPortHandle(); if (DeviceService.GetPciPort(out pciPortHandle)) { PciPort port = new PciPort(pciPortHandle); return PciConfig.Create(ids, port, fixedRanges); } else { Tracing.Log(Tracing.Debug, "PCI Config: None."); } // it isn't a PCI device, so create a PnpConfig object // TODO: We should really copy all of the ranges, so that // we can augment even PCI devices (like VGA cards). uint rangeCount = DeviceService.GetDynamicIoRangeCount(); Tracing.Log(Tracing.Debug, "I/O Ranges: {0}", rangeCount); IoRange[] dynamicRanges = new IoRange[rangeCount]; for (uint range = 0; range < rangeCount; range++) { ushort port; ushort size; bool readable; bool writable; byte * dataAddr; uint dataSize; byte irq; byte irqSize; byte dma; byte dmaSize; if (DeviceService.GetDynamicIoPortRange(range, out port, out size, out readable, out writable)) { Tracing.Log(Tracing.Debug, "{0:d4}. I/O Port: port={1:x4}" + "[{2:x}] read={3} write={4}", range, port, size, (UIntPtr)(readable ? 1 : 0), (UIntPtr)(writable ? 1 : 0)); dynamicRanges[range] = new IoPortRange(port, size, readable, writable); } else if (DeviceService.GetDynamicIoMemoryRange(range, out dataAddr, out dataSize, out readable, out writable)) { UIntPtr addr = (UIntPtr)dataAddr; Tracing.Log(Tracing.Debug, "{0:d4}. Memory: addr={1:x8}" + "[2:x] read={3} write={4}", range, addr, dataSize, (UIntPtr)(readable ? 1 : 0), (UIntPtr)(writable ? 1 : 0)); dynamicRanges[range] = new IoMemoryRange(addr, dataSize, readable, writable); } else if (DeviceService.GetDynamicIoIrqRange(range, out irq, out irqSize)) { Tracing.Log(Tracing.Debug, "{0:d4}. Irq: irq={1:x2}" + "[{2:x}]", range, irq, irqSize); dynamicRanges[range] = new IoIrqRange(irq, irqSize); } else if (DeviceService.GetDynamicIoDmaRange(range, out dma, out dmaSize)) { Tracing.Log(Tracing.Debug, "{0:d4}. Dma: dma={1:x2}" + "[{2:x}]", range, dma, dmaSize); dynamicRanges[range] = new IoDmaRange(dma, dmaSize); } else { Tracing.Log(Tracing.Debug, "{0:d4}. Empty", range); } } return new PnpConfig(ids, dynamicRanges, fixedRanges); } // return an IoRange array filled with all of the fixed resources that // this assembly requested in its manifest private unsafe static IoRange[] GetFixedIoResources() { uint rangeCount = DeviceService.GetFixedIoRangeCount(); Tracing.Log(Tracing.Debug, "I/O Ranges: {0}", rangeCount); IoRange[] ranges = new IoRange[rangeCount]; for (uint range = 0; range < rangeCount; range++) { ushort port, size; bool readable, writable; byte * dataAddr; uint dataSize; byte irq, irqSize; byte dma, dmaSize; if (DeviceService.GetFixedIoPortRange(range, out port, out size, out readable, out writable)) { Tracing.Log(Tracing.Debug, "{0:d4}. I/O Port: port={1:x4}" + "[{2:x}] read={3} write={4}", range, port, size, (UIntPtr)(readable ? 1 : 0), (UIntPtr)(writable ? 1 : 0)); ranges[range] = new IoPortRange(port, size, readable, writable); } else if (DeviceService.GetFixedIoMemoryRange(range, out dataAddr, out dataSize, out readable, out writable)) { UIntPtr addr = (UIntPtr)dataAddr; Tracing.Log(Tracing.Debug, "{0:d4}. Memory: addr={1:x8}" + "[2:x] read={3} write={4}", range, addr, dataSize, (UIntPtr)(readable ? 1 : 0), (UIntPtr)(writable ? 1 : 0)); ranges[range] = new IoMemoryRange(addr, dataSize, readable, writable); } else if (DeviceService.GetFixedIoIrqRange(range, out irq, out irqSize)) { Tracing.Log(Tracing.Debug, "{0:d4}. Irq: irq={1:x2}[{2:x}]", range, irq, irqSize); ranges[range] = new IoIrqRange(irq, irqSize); } else if (DeviceService.GetFixedIoDmaRange(range, out dma, out dmaSize)) { Tracing.Log(Tracing.Debug, "{0:d4}. Dma: dma={1:x2}[{2:x}]", range, dma, dmaSize); ranges[range] = new IoDmaRange(dma, dmaSize); } else { Tracing.Log(Tracing.Debug, "{0:d4}. Empty", range); } } return ranges; } #endif // SINGULARITY_PROCESS } }