//////////////////////////////////////////////////////////////////////////////// // // 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 GetPciPort( out PciPortHandle pciPortHandle ) { return PciPortHandle.Create(out pciPortHandle); } [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; } } }