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

315 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>
2008-11-17 18:29:00 -05:00
public String[] Ids;
public IoRange[] DynamicRanges;
public IoRange[] FixedRanges;
2008-03-05 09:52:00 -05:00
/// <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)
{
2008-11-17 18:29:00 -05:00
foreach (string id in this.Ids) {
2008-03-05 09:52:00 -05:00
text.Append(" device id: ");
text.Append(id);
text.Append("\n");
}
}
public void DumpRanges(StringBuilder text)
{
2008-11-17 18:29:00 -05:00
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");
}
2008-03-05 09:52:00 -05:00
}
}
}
/// <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
2008-11-17 18:29:00 -05:00
PciPortHandle pciPortHandle = new PciPortHandle();
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
if (DeviceService.GetPciPort(out pciPortHandle))
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
PciPort port = new PciPort(pciPortHandle);
2008-03-05 09:52:00 -05:00
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
2008-11-17 18:29:00 -05:00
// TODO: We should really copy all of the ranges, so that
2008-03-05 09:52:00 -05:00
// 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
}
}