163 lines
4.9 KiB
C#
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
|
|
}
|