140 lines
5.7 KiB
C#
140 lines
5.7 KiB
C#
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
using Microsoft.Singularity.Channels;
|
|
using Microsoft.Singularity.Io;
|
|
using Microsoft.Singularity.Configuration;
|
|
using Microsoft.Singularity.Hal.Acpi;
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Text;
|
|
|
|
namespace Microsoft.Singularity.Drivers
|
|
{
|
|
[CLSCompliant(false)]
|
|
public class AcpiBus : IBusDevice
|
|
{
|
|
[DriverCategory]
|
|
[Signature("/root/acpi0")]
|
|
[EnumeratesDevice("/acpi/...")]
|
|
class MyConfig : DriverCategoryDeclaration
|
|
{
|
|
}
|
|
|
|
private AcpiDevice[]! deviceInfoEntries;
|
|
delegate IoRange IoRangeTransformer(IoRange);
|
|
|
|
public AcpiBus(AcpiDevice[]! deviceInfoEntries)
|
|
{
|
|
this.deviceInfoEntries = deviceInfoEntries;
|
|
}
|
|
|
|
private static IoRange ProcessExceptions(string deviceId, IoRange resource) {
|
|
// Some Dells like the Dell Precision 490 make the HPET range
|
|
// read-only - but it needs to be read-write.
|
|
if (deviceId == "/pnp/PNP0103" && resource is IoMemoryRange &&
|
|
!((IoMemoryRange)resource).Writable) {
|
|
IoMemoryRange resourceMemoryRange = (IoMemoryRange)resource;
|
|
return new IoMemoryRange(resourceMemoryRange.RangeBase, resourceMemoryRange.RangeLength,
|
|
true/*readable*/, true/*writable*/);
|
|
}
|
|
else {
|
|
return resource;
|
|
}
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
}
|
|
|
|
public void Finalize()
|
|
{
|
|
}
|
|
|
|
public PnpConfig! ReportConfig()
|
|
{
|
|
// TODO: What resources does the root ACPI "bus" have? Any?
|
|
return new PnpConfig(new string[] { "" }, new ArrayList());
|
|
}
|
|
|
|
private IoConfig! ResourceDescriptorsToIoConfig(string deviceId, ResourceDescriptor[] resourceDescriptors)
|
|
{
|
|
ArrayList resourceList = new ArrayList();
|
|
string[]! ids = new string[1];
|
|
ids[0] = deviceId;
|
|
|
|
foreach (ResourceDescriptor resourceDescriptor in resourceDescriptors) {
|
|
if (resourceDescriptor is MemoryRangeDescriptor) {
|
|
MemoryRangeDescriptor descriptor = (MemoryRangeDescriptor)resourceDescriptor;
|
|
if (descriptor.ConsumerProducer == ConsumerProducer.Consumes) {
|
|
// The resource can take on any base address in the range descriptor.Minimum -
|
|
// descriptor.Maximum. Just use the minimum for now.
|
|
resourceList.Add(new IoMemoryRange(descriptor.Minimum, descriptor.Length,
|
|
true/*readable*/, descriptor.Writable));
|
|
}
|
|
}
|
|
else if (resourceDescriptor is IoRangeDescriptor) {
|
|
IoRangeDescriptor descriptor = (IoRangeDescriptor)resourceDescriptor;
|
|
if (descriptor.ConsumerProducer == ConsumerProducer.Consumes) {
|
|
// The resource can take on any base address in the range descriptor.Minimum -
|
|
// descriptor.Maximum. Just use the minimum for now. We use Access.ReadWrite
|
|
// since ACPI supplies no information about whether it's writable.
|
|
resourceList.Add(new IoPortRange((ushort)descriptor.Minimum, (ushort)descriptor.Length,
|
|
Access.ReadWrite));
|
|
}
|
|
}
|
|
else if (resourceDescriptor is IrqDescriptor) {
|
|
IrqDescriptor descriptor = (IrqDescriptor)resourceDescriptor;
|
|
foreach (int interruptNumber in descriptor.InterruptNumbers) {
|
|
resourceList.Add(new IoIrqRange((byte)interruptNumber, 1));
|
|
}
|
|
}
|
|
else if (resourceDescriptor is DmaDescriptor) {
|
|
DmaDescriptor descriptor = (DmaDescriptor)resourceDescriptor;
|
|
foreach (int dmaChannelNumber in descriptor.DmaChannelNumbers) {
|
|
resourceList.Add(new IoDmaRange((byte)dmaChannelNumber, 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
ArrayList processedResourceList = new ArrayList();
|
|
foreach (object obj in resourceList) {
|
|
IoRange newResource = (IoRange)ProcessExceptions(deviceId, (IoRange)obj);
|
|
if (newResource != null) {
|
|
processedResourceList.Add(newResource);
|
|
}
|
|
}
|
|
|
|
return new PnpConfig(ids, processedResourceList);
|
|
}
|
|
|
|
public SortedList Enumerate()
|
|
{
|
|
SortedList found = new SortedList();
|
|
|
|
int node = 0x100;
|
|
|
|
foreach (AcpiDevice! deviceInfo in deviceInfoEntries) {
|
|
IoConfig! ioConfig = ResourceDescriptorsToIoConfig(deviceInfo.DeviceId,
|
|
(!)deviceInfo.ResourceDescriptors);
|
|
|
|
DebugStub.Write("Detected ACPI device ");
|
|
DebugStub.WriteLine(ioConfig.Id);
|
|
System.Text.StringBuilder descriptionBuilder = new System.Text.StringBuilder();
|
|
ioConfig.DumpRanges(descriptionBuilder);
|
|
DebugStub.WriteLine(descriptionBuilder.ToString());
|
|
|
|
found.Add(String.Format("/{0,3:x3}", node++), ioConfig);
|
|
}
|
|
|
|
return found;
|
|
}
|
|
}
|
|
}
|