507 lines
18 KiB
C#
507 lines
18 KiB
C#
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity - Singularity ABI
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: DeviceService.cs
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using Microsoft.Singularity;
|
|
using Microsoft.Singularity.Io;
|
|
using Microsoft.Singularity.Memory;
|
|
|
|
namespace Microsoft.Singularity.V1.Services
|
|
{
|
|
[CLSCompliant(false)]
|
|
public struct DeviceService
|
|
{
|
|
[ExternalEntryPoint]
|
|
public static unsafe uint GetPnpSignature(int index, /*[out]*/ char * output, uint maxout)
|
|
{
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
|
|
Tracing.Log(Tracing.Debug, "DeviceService.GetPnpSignature({0:x8}, {1})",
|
|
(UIntPtr)output, maxout);
|
|
if (config == null || config.Ids == null || config.Ids.Length == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (index < 0)
|
|
return 0;
|
|
if (index >= config.Ids.Length)
|
|
return 0;
|
|
string id = config.Ids[index];
|
|
|
|
Tracing.Log(Tracing.Debug, " {0}", config.ToString());
|
|
if (output == null) {
|
|
return (uint)id.Length + 1;
|
|
}
|
|
return (uint)id.InternalGetChars(output, (int)maxout);
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetPciConfigImpl(
|
|
ushort * addrPort,
|
|
ushort * dataPort,
|
|
ushort * identifier)
|
|
{
|
|
return GetPciConfig(out *addrPort, out *dataPort, out *identifier);
|
|
}
|
|
|
|
public static bool GetPciConfig(out ushort addrPort,
|
|
out ushort dataPort,
|
|
out ushort identifier)
|
|
{
|
|
bool ret = false;
|
|
|
|
|
|
addrPort = 0;
|
|
dataPort = 0;
|
|
identifier = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
|
|
PciConfig pci = config as PciConfig;
|
|
if (pci != null) {
|
|
addrPort = pci.AddressPort;
|
|
dataPort = pci.DataPort;
|
|
identifier = pci.Identifier;
|
|
ret = true;
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetPciConfig(out addr={0:x4}, out data={1:x4}, out id={2:x8})",
|
|
addrPort, dataPort, identifier);
|
|
Tracing.Log(Tracing.Debug, " {0}", config.ToString());
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static uint GetDynamicIoRangeCount()
|
|
{
|
|
uint ret = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null) {
|
|
ret = (uint)config.DynamicRanges.Length;
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug, "DeviceService.GetDynamicIoRangeCount() = {0}", ret);
|
|
Tracing.Log(Tracing.Debug, " {0}", config.ToString());
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetDynamicIoPortRangeImpl(
|
|
uint range,
|
|
ushort * port,
|
|
ushort * size,
|
|
bool * readable,
|
|
bool * writable)
|
|
{
|
|
return GetDynamicIoPortRange(range, out *port, out *size,
|
|
out *readable, out *writable);
|
|
}
|
|
|
|
public static bool GetDynamicIoPortRange(uint range,
|
|
out ushort port,
|
|
out ushort size,
|
|
out bool readable,
|
|
out bool writable)
|
|
{
|
|
bool ret = false;
|
|
|
|
port = 0;
|
|
size = 0;
|
|
readable = false;
|
|
writable = false;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.DynamicRanges.Length > range) {
|
|
IoPortRange ipr = config.DynamicRanges[range] as IoPortRange;
|
|
if (ipr != null) {
|
|
port = ipr.Port;
|
|
size = ipr.Size;
|
|
readable = ipr.Readable;
|
|
writable = ipr.Writable;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetDynamicIoPortRange(range={0}, out port={1:x4}, out size={2})",
|
|
range, port, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetDynamicIoMemoryRangeImpl(
|
|
uint range,
|
|
byte * * data,
|
|
uint * size,
|
|
bool * readable,
|
|
bool * writable)
|
|
{
|
|
return GetDynamicIoMemoryRange(range, out *data, out *size,
|
|
out *readable, out *writable);
|
|
}
|
|
|
|
public static unsafe bool GetDynamicIoMemoryRange(uint range,
|
|
out byte * data,
|
|
out uint size,
|
|
out bool readable,
|
|
out bool writable)
|
|
{
|
|
bool ret = false;
|
|
|
|
data = null;
|
|
size = 0;
|
|
readable = false;
|
|
writable = false;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.DynamicRanges.Length > range) {
|
|
IoMemoryRange imr = config.DynamicRanges[range] as IoMemoryRange;
|
|
if (imr != null) {
|
|
data = (byte *)imr.PhysicalAddress.Value;
|
|
size = (uint)imr.Length;
|
|
readable = imr.Readable;
|
|
writable = imr.Writable;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetDynamicIoMemoryRange(range={0}, out data={1:x8}, out size={2})",
|
|
range, (UIntPtr)data, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static int GetIrqCount(byte irq)
|
|
{
|
|
int count = Processor.CurrentProcessor.GetIrqCount(irq);
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetIrqCount(irq={0:x}, count={1:x8})",(UIntPtr) irq, (UIntPtr) count);
|
|
return count;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetDynamicIoIrqRangeImpl(
|
|
uint range,
|
|
byte * line,
|
|
byte * size)
|
|
{
|
|
return GetDynamicIoIrqRange(range, out *line, out *size);
|
|
}
|
|
|
|
public static bool GetDynamicIoIrqRange(uint range,
|
|
out byte line,
|
|
out byte size)
|
|
{
|
|
bool ret = false;
|
|
|
|
line = 0;
|
|
size = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.DynamicRanges.Length > range) {
|
|
IoIrqRange iir = config.DynamicRanges[range] as IoIrqRange;
|
|
if (iir != null) {
|
|
line = iir.Line;
|
|
size = iir.Size;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetDynamicIoIrqRange(range={0}, out line={1:x2}, out size={2:x2})",
|
|
range, line, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetDynamicIoDmaRangeImpl(
|
|
uint range,
|
|
byte * channel,
|
|
byte * size)
|
|
{
|
|
return GetDynamicIoDmaRange(range, out *channel, out *size);
|
|
}
|
|
|
|
public static bool GetDynamicIoDmaRange(uint range,
|
|
out byte channel,
|
|
out byte size)
|
|
{
|
|
bool ret = false;
|
|
|
|
channel = 0;
|
|
size = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.DynamicRanges.Length > range) {
|
|
IoDmaRange idr = config.DynamicRanges[range] as IoDmaRange;
|
|
if (idr != null) {
|
|
channel = idr.Channel;
|
|
size = idr.Size;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetDynamicIoDmaRange(range={0}, out channel={1:x2}, out size={2:x2})",
|
|
range, channel, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
[ExternalEntryPoint]
|
|
public static uint GetFixedIoRangeCount()
|
|
{
|
|
uint ret = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null) {
|
|
if (config.FixedRanges != null) {
|
|
ret = (uint)config.FixedRanges.Length;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug, "DeviceService.GetFixedIoRangeCount() = {0}", ret);
|
|
Tracing.Log(Tracing.Debug, " {0}", config.ToString());
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetFixedIoPortRangeImpl(
|
|
uint range,
|
|
ushort * port,
|
|
ushort * size,
|
|
bool * readable,
|
|
bool * writable)
|
|
{
|
|
return GetFixedIoPortRange(range, out *port, out *size,
|
|
out *readable, out *writable);
|
|
}
|
|
|
|
public static bool GetFixedIoPortRange(uint range,
|
|
out ushort port,
|
|
out ushort size,
|
|
out bool readable,
|
|
out bool writable)
|
|
{
|
|
bool ret = false;
|
|
|
|
port = 0;
|
|
size = 0;
|
|
readable = false;
|
|
writable = false;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.FixedRanges.Length > range) {
|
|
IoPortRange ipr = config.FixedRanges[range] as IoPortRange;
|
|
if (ipr != null) {
|
|
port = ipr.Port;
|
|
size = ipr.Size;
|
|
readable = ipr.Readable;
|
|
writable = ipr.Writable;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetFixedIoPortRange(range={0}, out port={1:x4}, out size={2})",
|
|
range, port, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetFixedIoMemoryRangeImpl(
|
|
uint range,
|
|
byte * * data,
|
|
uint * size,
|
|
bool * readable,
|
|
bool * writable)
|
|
{
|
|
return GetFixedIoMemoryRange(range, out *data, out *size,
|
|
out *readable, out *writable);
|
|
}
|
|
|
|
public static unsafe bool GetFixedIoMemoryRange(uint range,
|
|
out byte * data,
|
|
out uint size,
|
|
out bool readable,
|
|
out bool writable)
|
|
{
|
|
bool ret = false;
|
|
|
|
data = null;
|
|
size = 0;
|
|
readable = false;
|
|
writable = false;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.FixedRanges.Length > range) {
|
|
IoMemoryRange imr = config.FixedRanges[range] as IoMemoryRange;
|
|
if (imr != null) {
|
|
data = (byte *)imr.PhysicalAddress.Value;
|
|
DebugStub.Assert(data != null);
|
|
size = (uint)imr.Length;
|
|
readable = imr.Readable;
|
|
writable = imr.Writable;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetFixedIoMemoryRange(range={0}, out data={1:x8}, out size={2})",
|
|
range, (UIntPtr)data, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetFixedIoIrqRangeImpl(
|
|
uint range,
|
|
byte * line,
|
|
byte * size)
|
|
{
|
|
return GetFixedIoIrqRange(range, out *line, out *size);
|
|
}
|
|
|
|
public static bool GetFixedIoIrqRange(uint range,
|
|
out byte line,
|
|
out byte size)
|
|
{
|
|
bool ret = false;
|
|
|
|
line = 0;
|
|
size = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.FixedRanges.Length > range) {
|
|
IoIrqRange iir = config.FixedRanges[range] as IoIrqRange;
|
|
if (iir != null) {
|
|
line = iir.Line;
|
|
size = iir.Size;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetFixedIoIrqRange(range={0}, out line={1:x2}, out size={2:x2})",
|
|
range, line, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetFixedIoDmaRangeImpl(
|
|
uint range,
|
|
byte * channel,
|
|
byte * size)
|
|
{
|
|
return GetFixedIoDmaRange(range, out *channel, out *size);
|
|
}
|
|
|
|
public static bool GetFixedIoDmaRange(uint range,
|
|
out byte channel,
|
|
out byte size)
|
|
{
|
|
bool ret = false;
|
|
|
|
channel = 0;
|
|
size = 0;
|
|
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
if (config != null && config.FixedRanges.Length > range) {
|
|
IoDmaRange idr = config.FixedRanges[range] as IoDmaRange;
|
|
if (idr != null) {
|
|
channel = idr.Channel;
|
|
size = idr.Size;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"DeviceService.GetFixedIoDmaRange(range={0}, out channel={1:x2}, out size={2:x2})",
|
|
range, channel, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static UIntPtr MapPhysicalRange(UIntPtr physStart,
|
|
UIntPtr numBytes,
|
|
bool readable,
|
|
bool writable)
|
|
{
|
|
return MemoryManager.UserMapPhysicalMemory(
|
|
new PhysicalAddress(physStart), numBytes
|
|
);
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static void UnmapPhysicalRange(UIntPtr startAddr,
|
|
UIntPtr limitAddr)
|
|
{
|
|
MemoryManager.UserUnmapPhysicalMemory(startAddr, limitAddr);
|
|
}
|
|
|
|
// Resolve a 32-bit virtual address (virtualAddr) to a
|
|
// 32-bit physical address (physAddr). If the lookup
|
|
// succeeds, return true, and set physRemaining to be
|
|
// the number of bytes on physAddr's physical page whose
|
|
// address is greater than or equal to physAddr. For
|
|
// example, if physAddr is the very last address on the
|
|
// page, physRemaining will be 1. TODO: if needed, add
|
|
// some notion of pinned memory
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool GetDmaPhysicalAddressImpl(
|
|
UIntPtr virtualAddr,
|
|
UIntPtr * physAddr,
|
|
UIntPtr * physRemaining)
|
|
{
|
|
return GetDmaPhysicalAddress(virtualAddr,
|
|
out *physAddr,
|
|
out *physRemaining);
|
|
}
|
|
|
|
private static bool GetDmaPhysicalAddress(UIntPtr virtualAddr,
|
|
out UIntPtr physAddr,
|
|
out UIntPtr physRemaining)
|
|
{
|
|
UIntPtr alignedAddr = MemoryManager.PageAlign(virtualAddr);
|
|
#if PAGING
|
|
PhysicalAddress phys = VMManager.GetPageMapping(alignedAddr);
|
|
if (phys != PhysicalAddress.Null) {
|
|
physAddr = (UIntPtr)phys.Value + (virtualAddr - alignedAddr);
|
|
physRemaining = MemoryManager.PagePad(physAddr + 1) - physAddr;
|
|
return true;
|
|
}
|
|
#else
|
|
if (virtualAddr != UIntPtr.Zero) {
|
|
physAddr = virtualAddr;
|
|
physRemaining = MemoryManager.PagePad(physAddr + 1) - physAddr;
|
|
return true;
|
|
}
|
|
#endif // PAGING
|
|
physAddr = UIntPtr.Zero;
|
|
physRemaining = UIntPtr.Zero;
|
|
return false;
|
|
}
|
|
}
|
|
}
|