singrdk/base/Kernel/Singularity/Io/IoPort.cs

539 lines
15 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: IoPort.cs
//
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SINGULARITY_PROCESS
using Microsoft.Singularity.V1.Services;
#endif
namespace Microsoft.Singularity.Io
{
[CLSCompliant(false)]
public sealed class IoPort
{
private readonly ushort port;
private readonly ushort size;
private readonly bool readable;
private readonly bool writable;
#if SINGULARITY_KERNEL
public IoPort(ushort port, ushort size, Access access)
#elif SINGULARITY_PROCESS
internal IoPort(ushort port, ushort size, Access access)
#endif // SINGULARITY_PROCESS
{
this.port = port;
this.size = size;
this.readable = (access & Access.Read) != 0;
this.writable = (access & Access.Write) != 0;
}
#if SINGULARITY_KERNEL
public IoPort(ushort port, ushort size, bool readable, bool writable)
#elif SINGULARITY_PROCESS
internal IoPort(ushort port, ushort size, bool readable, bool writable)
#endif // SINGULARITY_PROCESS
{
this.port = port;
this.size = size;
this.readable = readable;
this.writable = writable;
}
public ushort Port {
[NoHeapAllocation]
get { return port; }
}
public ushort Size {
[NoHeapAllocation]
get { return size; }
}
public bool Readable {
[NoHeapAllocation]
get { return readable; }
}
public bool Writable {
[NoHeapAllocation]
get { return writable; }
}
public override string ToString()
{
return String.Format("IO:{0,4:x4}[{1}]",
port,
(readable && writable) ? "R/W" :
(readable) ? "R" : "W");
}
[Inline]
public void Write8(byte value)
{
Write8(0, value);
}
[Inline]
public void Write16(ushort value)
{
Write16(0, value);
}
[Inline]
public void Write16(ushort[] values)
{
Write16(0, values);
}
[Inline]
public void Write32(uint value)
{
Write32(0, value);
}
[Inline]
public byte Read8()
{
return Read8(0);
}
[Inline]
public ushort Read16()
{
return Read16(0);
}
[Inline]
public uint Read32()
{
return Read32(0);
}
///////////////////////////////////////////////////////////////////////
//
[Inline]
private void CheckRead(uint offset, uint bytes)
{
#if !DONT_CHECK_IO_BOUNDS
if (!readable) {
Error.ReadNotSupported();
}
else if (offset + bytes > size) {
Error.AccessOutOfRange();
}
#endif // DONT_CHECK_IO_BOUNDS
}
[Inline]
private void CheckWrite(uint offset, uint bytes)
{
#if !DONT_CHECK_IO_BOUNDS
if (!writable) {
Error.WriteNotSupported();
}
else if (offset + bytes > size) {
Error.AccessOutOfRange();
}
#endif // DONT_CHECK_IO_BOUNDS
}
[Inline]
[NoHeapAllocation]
private void DebugBreak()
{
#if SINGULARITY_KERNEL
DebugStub.Break();
#elif SINGULARITY_PROCESS
DebugService.Break();
#endif // SINGULARITY_PROCESS
}
///////////////////////////////////////////////////////////////////////
//
[Inline]
public void Write8(uint offset, byte value)
{
CheckWrite(offset, 1);
HalWriteInt8(port + offset, value);
}
[Inline]
public void Write16(uint offset, ushort value)
{
CheckWrite(offset, 2);
HalWriteInt16(port + offset, value);
}
[Inline]
public void Write16(uint offset, ushort[] values)
{
CheckWrite(offset, 2);
for (int i = 0; i < values.Length; i++) {
HalWriteInt16(port + offset, values[i]);
}
}
[Inline]
public void Write32(uint offset, uint value)
{
CheckWrite(offset, 4);
HalWriteInt32(port + offset, value);
}
[Inline]
public byte Read8(uint offset)
{
CheckRead(offset, 1);
return HalReadInt8(port + offset);
}
[Inline]
public ushort Read16(uint offset)
{
CheckRead(offset, 2);
return HalReadInt16(port + offset);
}
[Inline]
public uint Read32(uint offset)
{
CheckRead(offset, 4);
return HalReadInt32(port + offset);
}
///////////////////////////////////////////////////////////////////////
// Export non-exception throwing operations
//
// These are intended for use in the kernel on
// NoHeapAllocation paths. The caller is expected to
// check the result and/or know pre-conditions for the
// I/O operation.
#region NoHeapAllocation Read/Write operations
#if SINGULARITY_KERNEL
[Inline]
[NoHeapAllocation]
private unsafe IoResult CheckReadNoThrow(uint offset, int bytes)
{
#if !DONT_CHECK_IO_BOUNDS
if (!this.readable) {
return IoResult.ReadNotSupported;
}
if (offset + bytes > this.size) {
return IoResult.AccessOutOfRange;
}
#endif // DONT_CHECK_IO_BOUNDS
return IoResult.Success;
}
[Inline]
[NoHeapAllocation]
private unsafe IoResult CheckWriteNoThrow(uint offset, int bytes)
{
#if !DONT_CHECK_IO_BOUNDS
if (!this.writable) {
return IoResult.WriteNotSupported;
}
if (offset + bytes > this.size) {
return IoResult.AccessOutOfRange;
}
#endif // DONT_CHECK_IO_BOUNDS
return IoResult.Success;
}
[Inline]
[NoHeapAllocation]
public unsafe IoResult Read8NoThrow(uint offset, out byte value)
{
IoResult check = CheckReadNoThrow(offset, 1);
if (IoResult.Success == check) {
value = HalReadInt8(port + offset);
}
else {
value = 0;
}
return check;
}
[Inline]
[NoHeapAllocation]
public unsafe IoResult Read16NoThrow(uint offset, out ushort value)
{
IoResult check = CheckReadNoThrow(offset, 2);
if (IoResult.Success == check) {
value = HalReadInt16(port + offset);
}
else {
value = 0;
}
return check;
}
[Inline]
[NoHeapAllocation]
public unsafe IoResult Read32NoThrow(uint offset, out uint value)
{
IoResult check = CheckReadNoThrow(offset, 4);
if (IoResult.Success == check) {
value = HalReadInt32(port + offset);
}
else {
value = 0;
}
return check;
}
[Inline]
[NoHeapAllocation]
public IoResult Read8NoThrow(out byte value)
{
return Read8NoThrow(0, out value);
}
[Inline]
[NoHeapAllocation]
public IoResult Read16NoThrow(out ushort value)
{
return Read16NoThrow(0, out value);
}
[Inline]
[NoHeapAllocation]
public IoResult Read32NoThrow(out uint value)
{
return Read32NoThrow(0, out value);
}
[Inline]
[NoHeapAllocation]
public unsafe IoResult Write8NoThrow(uint offset, byte value)
{
IoResult check = CheckWriteNoThrow(offset, 1);
if (IoResult.Success == check) {
HalWriteInt8(port + offset, value);
}
return check;
}
[Inline]
[NoHeapAllocation]
public unsafe IoResult Write16NoThrow(uint offset, ushort value)
{
IoResult check = CheckWriteNoThrow(offset, 2);
if (IoResult.Success == check) {
HalWriteInt16(port + offset, value);
}
return check;
}
[Inline]
[NoHeapAllocation]
public unsafe IoResult Write32NoThrow(uint offset, uint value)
{
IoResult check = CheckWriteNoThrow(offset, 4);
if (IoResult.Success == check) {
HalWriteInt32(port + offset, value);
}
return check;
}
[Inline]
[NoHeapAllocation]
public IoResult Write8NoThrow(byte value)
{
return Write8NoThrow(0, value);
}
[Inline]
[NoHeapAllocation]
public IoResult Write16NoThrow(ushort value)
{
return Write16NoThrow(0, value);
}
[Inline]
[NoHeapAllocation]
public IoResult Write32NoThrow(uint value)
{
return Write32NoThrow(0, value);
}
#endif // SINGULARITY_KERNEL
#endregion // NoHeapAllocation Read/Write operations
//////////////////////////////////////////////////////////////////////
//
public byte WaitClear8(byte mask)
{
CheckRead(0, 1);
for (int i = 0; i < 100000000; i++) {
byte value;
if (((value = HalReadInt8(port)) & mask) == 0) {
return value;
}
}
DebugBreak();
return HalReadInt8(port);
}
public ushort WaitClear16(ushort mask)
{
CheckRead(0, 2);
for (int i = 0; i < 100000000; i++) {
ushort value;
if (((value = HalReadInt16(port)) & mask) == 0) {
return value;
}
}
DebugBreak();
return HalReadInt16(port);
}
public uint WaitClear32(uint mask)
{
CheckRead(0, 4);
for (int i = 0; i < 100000000; i++) {
uint value;
if (((value = HalReadInt32(port)) & mask) == 0) {
return value;
}
}
DebugBreak();
return HalReadInt32(port);
}
//////////////////////////////////////////////////////////////////////
//
public byte WaitSet8(byte mask)
{
CheckRead(0, 1);
for (int i = 0; i < 100000000; i++) {
byte value;
if (((value = HalReadInt8(port)) & mask) != 0) {
return value;
}
}
DebugBreak();
return HalReadInt8(port);
}
public ushort WaitSet16(ushort mask)
{
CheckRead(0, 2);
for (int i = 0; i < 100000000; i++) {
ushort value;
if (((value = HalReadInt16(port)) & mask) != 0) {
return value;
}
}
DebugBreak();
return HalReadInt16(port);
}
public uint WaitSet32(uint mask)
{
CheckRead(0, 4);
for (int i = 0; i < 100000000; i++) {
uint value;
if (((value = HalReadInt32(port)) & mask) != 0) {
return value;
}
}
DebugBreak();
return HalReadInt32(port);
}
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(12)]
[NoHeapAllocation]
private static extern byte HalReadInt8(uint port);
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(12)]
[NoHeapAllocation]
private static extern void HalWriteInt8(uint port, byte value);
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(12)]
[NoHeapAllocation]
private static extern ushort HalReadInt16(uint port);
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(12)]
[NoHeapAllocation]
private static extern void HalWriteInt16(uint port, ushort value);
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(12)]
[NoHeapAllocation]
private static extern uint HalReadInt32(uint port);
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(12)]
[NoHeapAllocation]
private static extern void HalWriteInt32(uint port, uint value);
#if DO_UNSAFE_CODE_IN_IO
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[NoHeapAllocation]
private static extern unsafe void HalReadFifo16(uint port,
[In] ushort *data,
uint count);
[AccessedByRuntime("output to header : defined in IoPort.cpp")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[NoHeapAllocation]
private static extern unsafe void HalWriteFifo16(uint port,
[In,Out] ushort *data,
uint Count);
#endif
}
}