singrdk/base/Kernel/Singularity/V1/Services/DeviceService.cs

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;
}
}
}