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

163 lines
4.9 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: IoDma.cs
//
using System;
namespace Microsoft.Singularity.Io
{
public class IoDma
{
[Flags]
public enum Settings : byte
{
// DMA MODE
DemandMode = 0x00,
SingleMode = 0x40,
BlockMode = 0x80,
CascadeMode = 0xC0,
// ADDRESS INCREMENT DECREMENT
AddressIncrement = 0x00,
AddressDecrement = 0x20,
SingleCycle = 0x00,
AutoInit = 0x10,
// TRANSFER TYPE
VerifyTransfer = 0x00,
WriteTransfer = 0x04,
ReadTransfer = 0x08,
}
private byte channel;
private byte modeByte;
private byte controlByte;
private byte controlByteMask;
private bool eightBit;
private IoPort addrPort;
private IoPort countPort;
private IoPort pagePort;
private IoPort maskPort;
private IoPort modePort;
private IoPort clearPort;
[CLSCompliant(false)]
public IoDma(IoDmaRange dmaRange)
: this((byte)dmaRange.Channel)
{
}
[CLSCompliant(false)]
internal IoDma(byte ugly)
{
channel = (byte)ugly;
byte addrReg;
byte countReg;
byte pageReg;
byte maskReg;
byte clearReg;
byte modeReg;
eightBit = true;
controlByte = 0;
modeByte = 0;
controlByteMask = 0;
if (channel < 4) {
// 8 bit transfer
addrReg = (byte)(0x00 + (channel * 2));
countReg = (byte)(0x01 + (channel * 2));
pageReg = (byte)(0x80 + (new byte[4] { 0x7, 0x3, 0x1, 0x2 })[channel]);
maskReg = 0x0A;
clearReg= 0x0C;
modeReg = 0x0B;
eightBit = true;
}
else if (channel > 4 && channel < 8) {
channel -= 4;
//16 bit channel
addrReg = (byte)(0xC0 + (channel * 4));
countReg = (byte)(0xC2 + (channel * 4));
pageReg = (byte)(0x88 + (new byte[4] { 0x7, 0x3, 0x1, 0x2 })[channel]);
maskReg = 0xD4;
clearReg = 0xD8;
modeReg = 0xD6;
eightBit = false;
}
else {
Tracing.Log(Tracing.Fatal, "Invalid DMA Channel {0}", channel);
throw new Exception("Invalid DMA Channel");
}
// create ports
addrPort = new IoPort(addrReg, 1, Access.ReadWrite);
countPort = new IoPort(countReg, 1, Access.ReadWrite);
pagePort = new IoPort(pageReg, 1, Access.ReadWrite);
maskPort = new IoPort(maskReg, 1, Access.ReadWrite);
clearPort = new IoPort(clearReg, 1, Access.ReadWrite);
modePort = new IoPort(modeReg, 1, Access.ReadWrite);
}
public override string ToString()
{
return String.Format("DMA:{0,2:x2} {1}",
channel,
eightBit ? "8-bit" : "16-bit");
}
public void SetControlByteMask(Settings mask)
{
controlByteMask = (byte)mask;
controlByteMask |= channel;
}
public void SetControlByte()
{
controlByte |= controlByteMask;
modePort.Write8(controlByte);
}
public void EnableChannel()
{
maskPort.Write8(channel);
}
public void DisableChannel()
{
maskPort.Write8((byte)(channel | 0x04));
}
public void ClearFlipFlop()
{
clearPort.Write8(0x00);
}
[CLSCompliant(false)]
public void SetTransferLength(ushort length)
{
countPort.Write8((byte)(length & 0xff));//buffersize
countPort.Write8((byte)(length >> 8));//buffersize
}
[CLSCompliant(false)]
public void SetBuffer(IoMemory buffer)
{
uint address = (uint)buffer.PhysicalAddress.Value;
ushort offs = eightBit
? (ushort)((address) & 0xffff)
: (ushort)((address >> 1) & 0xffff);
pagePort.Write8((byte)((address >> 16) & 0xff));
addrPort.Write8((byte)(offs & 0xff));
addrPort.Write8((byte)(offs >> 8));
}
}// end of IoDma class
}