/////////////////////////////////////////////////////////////////////////////// // // 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 }