singrdk/base/Kernel/Singularity/Io/IoConfig.cs

318 lines
13 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// 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
{
/// <summary>
/// Instances of this class represent a set of I/O resources that have been assigned
/// to a specific device driver instance.
/// </summary>
[CLSCompliant(false)]
public abstract class IoConfig
{
/// <summary>
/// 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.
/// </summary>
public String[] Ids;
public IoRange[] DynamicRanges;
public IoRange[] FixedRanges;
/// <summary>
/// This property exists for compatibility with drivers that assume a single device ID.
/// It returns the first device ID in the list.
/// </summary>
// [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];
}
}
/// <summary>
/// Builds a description of this IoConfig instance.
/// </summary>
/// <returns>The description text.</returns>
public virtual string ToPrint()
{
StringBuilder text = new StringBuilder();
ToPrint(text);
return text.ToString();
}
/// <summary>
/// Builds a description of this IoConfig instance.
/// </summary>
/// <param name="text">The text buffer in which to write the description.</param>
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)
{
for (int i = 0; i < DynamicRanges.Length; i++)
{
if (DynamicRanges[i] != null)
{
text.Append(" range[");
text.Append(i);
text.Append("]: ");
text.Append(DynamicRanges[i]);
text.Append("\n");
}
}
}
/// <summary>
/// Prints a description of this I/O configuration to the debug port.
/// </summary>
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
ushort pciAddressPort;
ushort pciDataPort;
ushort pciIdentifier;
if (DeviceService.GetPciConfig(out pciAddressPort,
out pciDataPort,
out pciIdentifier))
{
Tracing.Log(Tracing.Debug, "PCI Config: addr={0:x4} port=" +
"{1:x4} id={2:x4}", pciAddressPort, pciDataPort,
pciIdentifier);
IoPort addrPort = new IoPort(pciAddressPort, 4,
Access.ReadWrite);
IoPort dataPort = new IoPort(pciDataPort, 4, Access.ReadWrite);
PciPort port = new PciPort(addrPort, dataPort, pciIdentifier);
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
// 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
}
}