149 lines
4.8 KiB
C#
149 lines
4.8 KiB
C#
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity - Singularity ABI
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: InterruptHandle.cs
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using Microsoft.Singularity;
|
|
using Microsoft.Singularity.Io;
|
|
using Microsoft.Singularity.Memory;
|
|
using Microsoft.Singularity.V1.Services;
|
|
|
|
namespace Microsoft.Singularity.V1.Threads
|
|
{
|
|
[CLSCompliant(false)]
|
|
public struct InterruptHandle // : public SyncHandle
|
|
{
|
|
|
|
public readonly UIntPtr id; // could be moved to SyncHandle
|
|
public static readonly InterruptHandle Zero = new InterruptHandle();
|
|
|
|
internal InterruptHandle(UIntPtr id)
|
|
{
|
|
this.id = id;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static unsafe bool CreateImpl(
|
|
byte irqNum,
|
|
InterruptHandle* handle)
|
|
{
|
|
return Create(irqNum, out *handle);
|
|
}
|
|
|
|
public static bool Create(byte irqNum,
|
|
out InterruptHandle handle)
|
|
{
|
|
bool ret = false;
|
|
handle = new InterruptHandle();
|
|
|
|
//
|
|
// Create an IoIrq, and a handle in the current process to hold it.
|
|
//
|
|
IoConfig config = Thread.CurrentProcess.IoConfig;
|
|
for (int i = 0; i < config.DynamicRanges.Length; i++) {
|
|
IoIrqRange iir = config.DynamicRanges[i] as IoIrqRange;
|
|
if (iir != null && iir.Irq <= irqNum && irqNum < iir.Irq + iir.Size) {
|
|
IoIrq irq = iir.IrqAtOffset((byte)(irqNum - iir.Irq));
|
|
|
|
handle = new InterruptHandle(
|
|
Thread.CurrentProcess.AllocateHandle(irq));
|
|
irq.RegisterInterrupt();
|
|
ret = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Tracing.Log(Tracing.Debug,
|
|
"InterruptHandle.Create(irq={0:x2}, out id={0:x8})",
|
|
irqNum, handle.id);
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static bool Dispose(InterruptHandle handle)
|
|
{
|
|
Tracing.Log(Tracing.Debug, "InterruptHandle.Dispose(id={0:x8})",
|
|
handle.id);
|
|
|
|
bool ret = false;
|
|
if (handle.id != UIntPtr.Zero) {
|
|
//
|
|
// Releasing the handle will allow the IoIrq event to be
|
|
// garbage-collected.
|
|
//
|
|
IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq;
|
|
ret = irq.ReleaseInterrupt();
|
|
Thread.CurrentProcess.ReleaseHandle(handle.id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static bool Wait(InterruptHandle handle)
|
|
{
|
|
if (handle.id == UIntPtr.Zero) {
|
|
Tracing.Log(Tracing.Error,
|
|
"InterruptHandle.Wait(id={0:x8}) on bad handle",
|
|
handle.id);
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Convert the handle to a IoIrq and wait on it.
|
|
//
|
|
IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq;
|
|
bool ret = irq.WaitForInterrupt();
|
|
|
|
Tracing.Log(Tracing.Debug, "InterruptHandle.Wait(id={0:x8})", handle.id);
|
|
|
|
return ret;
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static void Pulse(InterruptHandle handle)
|
|
{
|
|
if (handle.id == UIntPtr.Zero) {
|
|
Tracing.Log(Tracing.Error,
|
|
"InterruptHandle.Wait(id={0:x8}) on bad handle",
|
|
handle.id);
|
|
return;
|
|
}
|
|
IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq;
|
|
irq.Pulse();
|
|
Tracing.Log(Tracing.Debug, "InterruptHandle.Pulse(id={0:x8})",
|
|
handle.id);
|
|
}
|
|
|
|
[ExternalEntryPoint]
|
|
public static bool Ack(InterruptHandle handle)
|
|
{
|
|
if (handle.id == UIntPtr.Zero) {
|
|
Tracing.Log(Tracing.Error,
|
|
"InterruptHandle.Ack(id={0:x8}) on bad handle",
|
|
handle.id);
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Convert the handle to an auto-reset event; set the event.
|
|
//
|
|
IoIrq irq = HandleTable.GetHandle(handle.id) as IoIrq;
|
|
bool ret = irq.AckInterrupt();
|
|
|
|
Tracing.Log(Tracing.Debug, "InterruptHandle.Ack(id={0:x8})", handle.id);
|
|
return ret;
|
|
}
|
|
|
|
}
|
|
}
|