using System; using System.Collections.Generic; using Cosmos.Core; using Cosmos.Core.Memory.Old; using Cosmos.Debug.Kernel; using Cosmos.HAL.Drivers.PCI.Controllers; namespace Cosmos.HAL.BlockDevice { #region Registers //TODO: Must be struct public class GenericRegisters { public uint CAP; public uint GHC; public uint IS; public uint PI; public uint VS; public uint CCC_CTL; public uint CCC_PORTS; public uint EM_LOC; public uint EM_CTL; public uint CAP2; public uint BOHC; public byte[] Reserved0; public byte[] VendorSpecific; public PortRegisters[] Ports; } public class PortRegisters { public uint CLB; public uint CLBU; public uint FB; public uint FBU; public uint IS; public uint IE; public uint CMD; public uint Reserved0; public uint TFD; public uint SIG; public uint SSTS; public uint SCTL; public uint SERR; public uint SACT; public uint CI; public uint SNTF; public uint FBS; public uint[] Reserved1; public uint[] VendorSpecific; } public enum FISType { FIS_Type_RegisterH2D = 0x27, // Register FIS: Host to Device FIS_Type_RegisterD2H = 0x34, // Register FIS: Device to Host FIS_Type_DMA_Activate = 0x39, // DMA Activate FIS_Type_DMA_Setup = 0x41, // DMA Setup: Device to Host FIS_Type_Data = 0x46, // Data FIS: Bidirectional FIS_Type_BIST = 0x58, // BIST FIS_Type_PIO_Setup = 0x5F, // PIO Setup: Device to Host FIS_Type_DeviceBits = 0xA1 // Device bits } public class HBACommandHeader { // DWord 0 public byte CFL; // 5 bits public byte ATAPI; // 1 bit public byte Write; // 1 = H2D | 0 = D2H // 1bit public byte Prefetchable; // 1 bit public byte Reset; // 1 bit public byte BIST; // 1 bit public byte ClearBusy; // 1 bit public byte Reserved0; // 1 bit public byte PMP; // 4 bits public ushort PRDTL; // Physical region descriptor table length in entries // DWord 1 public uint PRDBC; // Physical region descriptor byte count transferred public uint CTBA; // Command table descriptor base address public uint CTBAU; // Command table descriptor base address upper 32 bits (4 bytes) // Reserved1; // [4] } public class HBACommandTable { // 0x00 public byte CFIS; // [64] // = 64 // 0x40 public byte ACMD; // [16] // = 16 + 64 = 80 // 0x50 public byte Reserved; // [48] // = 48 + 80 = 128 public HBAPRDTEntry[] PRDTEntry; // [1] // = 44 + 128 = 172 } public class HBAPRDTEntry { public uint DBA; // Data base address public uint DBAU; // Data base address upper 32 bits public uint Reserved0; public uint DBC; // Byte count, 4M max // 22 bits (2.75 Bytes) public uint Reserved1; // Reserved // 9 bits public int InterruptOnCompletion; // Interrupt on completion // 1 bit } public enum PortType { Nothing = 0x00, SATA = 0x01, SATAPI = 0x02, SEMB = 0x03, PM = 0x04 } public class FISRegisterH2D { public byte FISType; //public byte Options; // Reserved public byte IsCommand; public byte Command; public byte FeatureL; public byte LBA0; public byte LBA1; public byte LBA2; public byte Device; public byte LBA3; public byte LBA4; public byte LBA5; public byte FeatureH; public byte CountL; public byte CountH; public byte ICC; public byte Control; public byte Res2; public static explicit operator byte(FISRegisterH2D v) { byte xValue = sizeof(byte) * 16; return xValue; } } public class FISRegisterD2H { public byte FISType; //public byte Options; // Reserved //public byte InterruptBit; // Rseerved public byte Status; public byte Error; public byte LBA0; public byte LBA1; public byte LBA2; public byte Device; public byte LBA3; public byte LBA4; public byte LBA5; // Reserved public byte CountL; public byte CountH; public byte ICC; public ushort Res2; // Reserved public uint Res3; // Reserved public static explicit operator byte(FISRegisterD2H v) { byte xValue = sizeof(byte) * 15; return xValue; } } public class FISData { public byte FISType; public byte Payload; } #endregion #region Enums public enum DriveSignature : uint // Drive Signature to identify what drive is plugged to Port X:X { SATADrive = 0x00000101, PMDrive = 0x96690101, SATAPIDrive = 0xEB140101, SEMBDrive = 0xC33C0101, NullDrive = 0xFFFFFFFF } public enum InterfacePowerManagementStatus : uint // SATA Status: Interface Power Management Status { NotPresent = 0x00, Active = 0x01, Partial = 0x02, Slumber = 0x06, DeviceSleep = 0x08 } public enum CurrentInterfaceSpeedStatus : uint // SATA Status: Current Interface Speed { NotPresent = 0x00, Gen1Rate = 0x01, Gen2Rate = 0x02, Gen3Rate = 0x03 } public enum DeviceDetectionStatus : uint // SATA Status: Device Detection Status { NotDetected = 0x00, DeviceDetectedNoPhy = 0x01, DeviceDetectedWithPhy = 0x03, PhyOffline = 0x04 } public enum ATADeviceStatus : uint { Busy = 0x80, DRQ = 0x08 } public enum CommandAndStatus : uint { ICC_Reserved0 = 0x0000000F, ICC_DevSleep = 0x00000008, ICC_Slumber = 0x00000006, ICC_Partial = 0x00000002, ICC_Active = 0x00000001, ICC_Idle = 0x00000000, ASP = (01 << 27), ALPE = (01 << 26), EnableATAPILED = (01 << 25), ATAPIDevice = (01 << 24), APSTE = (01 << 23), FISSwitchPort = (01 << 22), ExternalSATAPort = (01 << 21), ColdPresenceDetect = (01 << 20), MPSP = (01 << 19), HotPlugCapPort = (01 << 18), PortMultAttach = (01 << 17), ColdPresenceState = (01 << 16), CMDListRunning = (01 << 15), FISRecieveRunning = (01 << 14), MPSS = (01 << 13), CurrentCMDSlot = (01 << 12), Reserved0 = (01 << 07), FISRecieveEnable = (01 << 04), CMDListOverride = (01 << 03), PowerOnDevice = (01 << 02), SpinUpDevice = (01 << 01), StartProccess = (01 << 00), Null = 0xFFFF } public enum InterruptStatus : int { ColdPortDetectStatus = (01 << 31), TaskFileErrorStatus = (01 << 30), HostBusFatalErrorStatus = (01 << 29), HostBusDataErrorStatus = (01 << 28), InterfaceFatalErrorStatus = (01 << 27), InterfaceNFatalErrorStatus = (01 << 26), OverflowStatus = (01 << 24), IncorrectPMStatus = (01 << 23), PhyRdyChangeStatus = (01 << 22), DevMechanicalPresenceStatus = (01 << 07), PortConnectChangeStatus = (01 << 06), DescriptorProcessed = (01 << 05), UnknownFISInterrupt = (01 << 04), SetDeviceBitsInterrupt = (01 << 03), DMASetupFISInterrupt = (01 << 02), PIOSetupFISInterrupt = (01 << 01), D2HRegFISInterrupt = (01 << 00), Null = 0xFFFF } public enum InterruptEnable : uint { OverflowEnable = (01 << 24), IncorrectPMEnable = (01 << 23), PhyRdyChangeInterruptEnable = (01 << 22), DevMechanicalPresenceEnable = (01 << 07), PortChangeInterruptEnable = (01 << 06), DescProcessedInterruptEnable = (01 << 05), UnknownFISInterruptEnable = (01 << 04), SetDeviceBitsInterruptEnable = (01 << 03), DMASetupFISInterruptEnable = (01 << 02), PIOSetupFISInterruptEnable = (01 << 01), D2HRegFISInterruptEnable = (01 << 00), Null = 0xFFFF } public enum SATACommands : uint { ReadPio = AtaPio.Cmd.ReadPio, ReadPioExt = AtaPio.Cmd.ReadPioExt, ReadDma = AtaPio.Cmd.ReadDma, ReadDmaExt = AtaPio.Cmd.ReadDmaExt, WritePio = AtaPio.Cmd.WritePio, WritePioExt = AtaPio.Cmd.WritePioExt, WriteDma = AtaPio.Cmd.WriteDma, WriteDmaExt = AtaPio.Cmd.WriteDmaExt, CacheFlush = AtaPio.Cmd.CacheFlush, CacheFlushExt = AtaPio.Cmd.CacheFlushExt, Packet = AtaPio.Cmd.Packet, IdentifyPacket = AtaPio.Cmd.IdentifyPacket, Identify = AtaPio.Cmd.Identify, Read = AtaPio.Cmd.Read, Eject = AtaPio.Cmd.Eject } public enum Bases : uint { SATA = 0x00400000 } #endregion public class SATA : BlockDevice { private static uint mPortLocation; private static uint[] mPorts = new uint[32]; private static uint mABAR; private static MemoryBlock mSATAMemory; internal static Debugger mSATADebugger = new Debugger("HAL", "SATA"); public static GenericRegisters mGeneric; public List SATAPorts = new List(32); public static InterfacePowerManagementStatus mIPM; public static DeviceDetectionStatus mDET; private int xPort; private bool is64DMA; #region Registers internal class Registers { public static PortRegisters PortRegisters(int aPortNumber) { mPortLocation = 0x100 + (0x80 * (uint)aPortNumber); PortRegisters xPortReg = new PortRegisters(); xPortReg.CLB = mSATAMemory[mPortLocation + 0x00]; xPortReg.CLBU = mSATAMemory[mPortLocation + 0x04]; xPortReg.FB = mSATAMemory[mPortLocation + 0x08]; xPortReg.FBU = mSATAMemory[mPortLocation + 0x0C]; xPortReg.IS = mSATAMemory[mPortLocation + 0x10]; xPortReg.IE = mSATAMemory[mPortLocation + 0x14]; xPortReg.CMD = mSATAMemory[mPortLocation + 0x18]; xPortReg.Reserved0 = mSATAMemory[mPortLocation + 0x1C]; xPortReg.TFD = mSATAMemory[mPortLocation + 0x20]; xPortReg.SIG = mSATAMemory[mPortLocation + 0x24]; xPortReg.SSTS = mSATAMemory[mPortLocation + 0x28]; xPortReg.SCTL = mSATAMemory[mPortLocation + 0x2C]; xPortReg.SERR = mSATAMemory[mPortLocation + 0x30]; xPortReg.SACT = mSATAMemory[mPortLocation + 0x34]; xPortReg.CI = mSATAMemory[mPortLocation + 0x38]; xPortReg.SNTF = mSATAMemory[mPortLocation + 0x3C]; xPortReg.FBS = mSATAMemory[mPortLocation + 0x40]; xPortReg.Reserved1 = GetValueArray(0x44, 11); xPortReg.VendorSpecific = GetValueArray(0x70, 4); mIPM = (InterfacePowerManagementStatus)((byte)((xPortReg.SSTS >> 8) & 0x0F)); mDET = (DeviceDetectionStatus)((byte)(xPortReg.SSTS & 0x0F)); return xPortReg; } public static PortRegisters PortRegisters(int[] aPortsArray) { foreach (int xPortNumber in aPortsArray) { mPortLocation = 0x100 + (0x80 * (uint)xPortNumber); PortRegisters xPortReg = new PortRegisters(); xPortReg.CLB = mSATAMemory[mPortLocation + 0x00]; xPortReg.CLBU = mSATAMemory[mPortLocation + 0x04]; xPortReg.FB = mSATAMemory[mPortLocation + 0x08]; xPortReg.FBU = mSATAMemory[mPortLocation + 0x0C]; xPortReg.IS = mSATAMemory[mPortLocation + 0x10]; xPortReg.IE = mSATAMemory[mPortLocation + 0x14]; xPortReg.CMD = mSATAMemory[mPortLocation + 0x18]; xPortReg.Reserved0 = mSATAMemory[mPortLocation + 0x1C]; xPortReg.TFD = mSATAMemory[mPortLocation + 0x20]; xPortReg.SIG = mSATAMemory[mPortLocation + 0x24]; xPortReg.SSTS = mSATAMemory[mPortLocation + 0x28]; xPortReg.SCTL = mSATAMemory[mPortLocation + 0x2C]; xPortReg.SERR = mSATAMemory[mPortLocation + 0x30]; xPortReg.SACT = mSATAMemory[mPortLocation + 0x34]; xPortReg.CI = mSATAMemory[mPortLocation + 0x38]; xPortReg.SNTF = mSATAMemory[mPortLocation + 0x3C]; xPortReg.FBS = mSATAMemory[mPortLocation + 0x40]; xPortReg.Reserved1 = GetValueArray(0x44, 11); xPortReg.VendorSpecific = GetValueArray(0x70, 4); return xPortReg; } PortRegisters mNullPort = new PortRegisters(); return mNullPort; } /// /// Note: This method only work when SATA is initialized! /// public static int GetPortNumber() { foreach (int mPort in mPorts) { if (mPort == 1) { return mPort; // Return mPort SATA Type } else { // If mPort's value is not 1 then it is a CD/DVD Drive Port, Port Multiplier, SEMB Port or Nothing in the Port } } return -1; } public static uint[] GetValueArray(uint aStartAddress, int aAmount) { uint[] FinishedArray = new uint[aAmount]; int i = 0; for (uint ui = aStartAddress; ui < aAmount; ui += 0x04) { while (i < aAmount) { FinishedArray[i] = mSATAMemory[ui]; i++; break; } } return FinishedArray; } public static byte[] GetByteValueArray(uint aStartAddress, int aAmount) { byte[] FinishedArray = new byte[aAmount]; for (uint ui = aStartAddress; ui < aAmount; ui += 0x04) { for (int i = 0; i < aAmount; i++) { FinishedArray[i] = mSATAMemory.Bytes[ui]; } } return FinishedArray; } } #endregion public SATA(uint ABAROffset) { // Setting Offset arg to Global offset mABAR = ABAROffset; mSATAMemory = new MemoryBlock(mABAR, 0x10FF); mGeneric = new GenericRegisters { CAP = mSATAMemory[0x00], GHC = mSATAMemory[0x04], IS = mSATAMemory[0x08], PI = mSATAMemory[0x0C], VS = mSATAMemory[0x10], CCC_CTL = mSATAMemory[0x14], CCC_PORTS = mSATAMemory[0x18], EM_LOC = mSATAMemory[0x1C], EM_CTL = mSATAMemory[0x20], CAP2 = mSATAMemory[0x24], BOHC = mSATAMemory[0x28], //Reserved0 = Registers.GetByteValueArray(0x2C, 29), //VendorSpecific = Registers.GetByteValueArray(0xA0, 20), Ports = new PortRegisters[32] }; while (((mSATAMemory[0x04] >> 31) & 1) == 0) ; mBlockSize = 512; mBlockCount = 256; Console.WriteLine("-- 00 --"); SearchForDisks(mGeneric); } private void SearchForDisks(GenericRegisters aGeneric) { // Search for disks var xImplementedPort = aGeneric.PI; var xPort = 0; var xPortType = 0U; while(xPort < 32) { if ((xImplementedPort & 1) != 0) { PortType PortType = CheckPortType(Registers.PortRegisters(xPort)); var xPortString = "0:" + xPort; if (PortType == PortType.SATA) // If Port Type was SATA. { Console.WriteLine("SATA drive at port " + xPortString + " found"); Console.WriteLine("SATA Drive at port " + xPortString); PortRebase(Registers.PortRegisters(xPort), xPort); ushort ReadedBits = new ushort(); SATAPorts.Add(xPort); mSATADebugger.Send("Readen bits: " + ReadedBits); xPortType = 0x01; } else if (PortType == PortType.SATAPI) // If Port Type was SATAPI. { Console.WriteLine("SATAPI drive at port " + xPortString + " found, which is not supported yet!"); Console.WriteLine("CD/DVD Drive at port " + xPortString + " found, which is not supported yet!"); xPortType = 0x02; } else if (PortType == PortType.SEMB) // If Port Type was SEMB. { //Console.WriteLine("SEMB drive at port " + xPortString + " found, which is not supported yet!"); Console.WriteLine("SEMB Drive at port " + xPortString + " found, which is not supported yet!"); xPortType = 0x03; } else if (PortType == PortType.PM) // If Port Type was Port Mulitplier. { //Console.WriteLine("Port Multiplier drive at port " + xPortString + " found, which is not supported yet!"); Console.WriteLine("Port Multiplier Drive at port " + xPortString + " found, which is not supported yet!"); xPortType = 0x04; } //else if (PortType == PortType.Nothing) // If Nothing in this Port. //else // If Implemented Port value was not zero and non of the above. } mPorts[xPort] = xPortType; xImplementedPort >>= 1; xPort++; } } private PortType CheckPortType(PortRegisters Port) { DriveSignature xSignature = (DriveSignature)Port.SIG; uint xSATAStatus = Port.SSTS; if (mIPM != InterfacePowerManagementStatus.Active) return PortType.Nothing; if (mDET != DeviceDetectionStatus.DeviceDetectedWithPhy) return PortType.Nothing; switch (xSignature) { case DriveSignature.SATAPIDrive: return PortType.SATAPI; case DriveSignature.SEMBDrive: return PortType.SEMB; case DriveSignature.PMDrive: return PortType.PM; case DriveSignature.NullDrive: return PortType.Nothing; default: return PortType.SATA; } } public void PortRebase(PortRegisters aPort, int aPortNumber) { StopCMD(aPort); var CLBAddress = Heap.MemAlloc(1024); var FBAddress = Heap.MemAlloc(256); Console.WriteLine(CLBAddress.ToString()); mSATAMemory[mPortLocation] = CLBAddress; new MemoryBlock(mSATAMemory[mPortLocation], 1024).Fill(0); //if(is64DMA) //{ // mSATAMemory[mPortLocation + 0x04] |= CLBUAddress; // new MemoryBlock(mSATAMemory[mPortLocation + 0x04], 1024).Fill(0); //} mSATAMemory[mPortLocation + 0x08] = FBAddress; new MemoryBlock(mSATAMemory[mPortLocation + 0x08], 256).Fill(0); //if (is64DMA) //{ // mSATAMemory[mPortLocation + 0x0C] |= FBUAddress; // new MemoryBlock(mSATAMemory[mPortLocation + 0x0C], 256).Fill(0); //} GetCommandHeader(aPort, aPortNumber); // Rebasing Command Header StartCMD(aPort); } public static HBACommandHeader[] GetCommandHeader(PortRegisters aPort, int aPortNumber) { HBACommandHeader[] xCMDHeader = new HBACommandHeader[32]; for (int i = 0; i < xCMDHeader.Length; i++) { xCMDHeader[i] = new HBACommandHeader(); xCMDHeader[i].PRDTL = 8; // 8 prdt entries per command table // 256 bytes per command table, 64+16+48+16*8 xCMDHeader[i].CTBA = Heap.MemAlloc(256); xCMDHeader[i].CTBAU = 0; new MemoryBlock(xCMDHeader[i].CTBA, 256).Fill(0); var xCMDHeaderMem = new MemoryBlock(mSATAMemory[mPortLocation + 0x00], 1024); xCMDHeaderMem[0x02] = xCMDHeader[i].PRDTL; xCMDHeaderMem[0x08] = xCMDHeader[i].CTBA << 7; xCMDHeaderMem[0x0C] = xCMDHeader[i].CTBAU; } return xCMDHeader; } public void StartCMD(PortRegisters aPort) { while ((mSATAMemory[mPortLocation + 0x18] & (uint)CommandAndStatus.CMDListRunning) != 0) { //Console.WriteLine("Command list is already running"); continue; } Console.WriteLine("Starting Process"); mSATAMemory[mPortLocation + 0x18] |= (uint)CommandAndStatus.FISRecieveEnable; mSATAMemory[mPortLocation + 0x18] |= (uint)CommandAndStatus.StartProccess; } public void StopCMD(PortRegisters aPort) { Console.WriteLine("Stopping Process"); mSATAMemory[mPortLocation + 0x18] &= ~(uint)CommandAndStatus.FISRecieveEnable; mSATAMemory[mPortLocation + 0x18] &= ~(uint)CommandAndStatus.StartProccess; while ((mSATAMemory[mPortLocation + 0x18] & (uint)(CommandAndStatus.FISRecieveRunning | CommandAndStatus.CMDListRunning)) != 0) ; } private bool InternalTransfer(PortRegisters aPort, uint aStartLow, uint aStartHigh, uint aCount, ushort aBuffer, bool aWrite = false) { //mSATAMemory[mPortLocation + 0x10] = unchecked((uint)-1); new MemoryBlock(mSATAMemory.Base + mPortLocation + 0x10, sizeof(uint)).Fill(0); int xSpin = 0; // Spin lock Timeout Counter int xSlot = FindCMDSlot(aPort); Console.WriteLine("My Slot: " + xSlot); if (xSlot == -1) return false; HBACommandHeader xCMDHeader = GetCommandHeader(aPort, Registers.GetPortNumber())[xSlot]; //mSATAMemory[mPortLocation + 0x00] += (uint)xSlot; xCMDHeader.CFL = (byte)(17 / sizeof(uint)); xCMDHeader.Write = (aWrite ? (byte)1 : (byte)0); xCMDHeader.PRDTL = (ushort)(((aCount - 1) >> 4) + 1); var xCMDHeaderMem = new MemoryBlock(mSATAMemory[mPortLocation + 0x00], 1024); xCMDHeaderMem[0x00] = (uint)xCMDHeader.PRDTL << 16; xCMDHeaderMem[0x00] = (uint)xCMDHeader.Write << 6; xCMDHeaderMem[0x00] = (uint)xCMDHeader.CFL << 0; Console.WriteLine(xCMDHeaderMem[0x00].ToString()); Console.WriteLine(xCMDHeaderMem.Base.ToString()); Console.WriteLine(xCMDHeader.CTBA.ToString()); Console.WriteLine("Before Command Table Initialization"); HBACommandTable xCMDTable = new HBACommandTable(); // xCMDHeader.CTBA var xCMDTableMem = new MemoryBlock(xCMDHeader.CTBA, 256); xCMDTableMem.Fill(0, (((158 / 8) + (xCMDHeader.PRDTL - 1U)) * 24), 0); xCMDTable.PRDTEntry = new HBAPRDTEntry[1]; xCMDTable.PRDTEntry[0] = new HBAPRDTEntry(); Console.WriteLine("After Command Table Initialization"); Console.WriteLine("Before MemAlloc"); var xDataBA = Heap.MemAlloc(sizeof(ushort)); Console.WriteLine(xDataBA); var xDataMem = new MemoryBlock(xDataBA, sizeof(ushort)); xDataMem[0x00] = aBuffer; Console.WriteLine(xDataMem[0x00]); Console.WriteLine("After MemAlloc"); uint i = 1; while (i - 1 < xCMDHeader.PRDTL - 1) { Console.WriteLine("On Loop Command Table Initialization"); xCMDTable.PRDTEntry[i - 1].DBA = (uint)(xDataBA); xCMDTable.PRDTEntry[i - 1].DBC = 8 * 1024 - 1; xCMDTable.PRDTEntry[i - 1].InterruptOnCompletion = 1; xCMDTableMem[(0x80 * i) + 0x00] = xCMDTable.PRDTEntry[i - 1].DBA << 1; xCMDTableMem[(0x80 * i) + 0x0C] = xCMDTable.PRDTEntry[i - 1].DBC; xCMDTableMem[(0x80 * i) + 0x0C] = (uint)xCMDTable.PRDTEntry[i - 1].InterruptOnCompletion << 31; aBuffer += 4 * 1024; aCount -= 16; i++; } Console.WriteLine("Last Command Table Initialization"); // Last entry xCMDTable.PRDTEntry[i - 1].DBA = xDataBA; xCMDTable.PRDTEntry[i - 1].DBC = (aCount << 9) - 1; xCMDTable.PRDTEntry[i - 1].InterruptOnCompletion = 1; xCMDTableMem[(0x80 * i) + 0x00] = xCMDTable.PRDTEntry[i - 1].DBA << 1; xCMDTableMem[(0x80 * i) + 0x0C] = xCMDTable.PRDTEntry[i - 1].DBC; xCMDTableMem[(0x80 * i) + 0x0C] = (uint)xCMDTable.PRDTEntry[i - 1].InterruptOnCompletion << 31; Console.WriteLine("Setup Command FIS"); // Setup the command uint xCMDFISAddress = Heap.MemAlloc(0x10); xCMDTableMem[0x00] = (uint)xCMDFISAddress; FISRegisterH2D xCMDFIS = new FISRegisterH2D(); xCMDFIS.FISType = (byte)FISType.FIS_Type_RegisterH2D; xCMDFIS.IsCommand = 1; xCMDFIS.Command = (aWrite ? (byte)SATACommands.WriteDmaExt : (byte)SATACommands.ReadDmaExt); xCMDFIS.LBA0 = (byte)aStartLow; xCMDFIS.LBA1 = (byte)(aStartLow >> 8); xCMDFIS.LBA2 = (byte)(aStartLow >> 16); xCMDFIS.Device = 1 << 6; // LBA Mode xCMDFIS.LBA3 = 0x00; xCMDFIS.LBA4 = 0x00; xCMDFIS.LBA5 = 0x00; xCMDFIS.CountL = (byte)(aCount & 0xFF); xCMDFIS.CountH = (byte)((aCount >> 8) & 0xFF); var xCMDFISMem = new MemoryBlock((uint)xCMDTableMem[0x00], 0x10); Console.WriteLine("Setting values to memory offset: " + xCMDTableMem[0x00]); // DWord 0 xCMDFISMem[0x00] = (byte)(xCMDFIS.FISType); // FIS Type xCMDFISMem[0x00] = (byte)(xCMDFIS.IsCommand >> 15); // IsCommand(or)Control xCMDFISMem[0x00] = (byte)(xCMDFIS.Command >> 16); // Command register // DWord 1 xCMDFISMem[0x04] = (byte)(xCMDFIS.LBA0); // LBA Low register xCMDFISMem[0x04] = (byte)(xCMDFIS.LBA1 >> 8); // LBA Mid register xCMDFISMem[0x04] = (byte)(xCMDFIS.LBA2 >> 16); // LBA Hgh register xCMDFISMem[0x04] = (byte)(xCMDFIS.Device >> 24); // Device register // DWord 2 xCMDFISMem[0x08] = (byte)(xCMDFIS.LBA3); // LBA register xCMDFISMem[0x08] = (byte)(xCMDFIS.LBA4 >> 8); // LBA register xCMDFISMem[0x08] = (byte)(xCMDFIS.LBA5 >> 16); // LBA register // DWord 3 xCMDFISMem[0x0C] = (byte)(xCMDFIS.CountL); // Count Low register xCMDFISMem[0x0C] = (byte)(xCMDFIS.CountH); // Count Hgh register Console.WriteLine(Cosmos.Common.Extensions.ToHexString.ToHex(new MemoryBlock(xCMDFISAddress, 0x10)[0x00])); Console.WriteLine("Spinning on xSpin"); do { xSpin++; Console.WriteLine(xSpin); } while (((mSATAMemory[mPortLocation + 0x20] & (uint)(ATADeviceStatus.Busy | ATADeviceStatus.DRQ)) > 0 && xSpin < 1000000)); if (xSpin == 1000000) { Console.WriteLine("Port timed out"); return false; } mSATAMemory[mPortLocation + 0x38] = (uint)(1 << xSlot); // Issue with Command // Wait for Completion do { // If error occured if (((mSATAMemory[mPortLocation + 0x10] >> 30) & 1) != 0) { Console.WriteLine("Write or Read Disk Error!"); return false; } } while (((mSATAMemory[mPortLocation + 0x38] >> xSlot) & 1) != 0); // Fill in the data if (!aWrite) { aBuffer = xDataMem.Words[0x00]; } return true; } public bool Read(PortRegisters aPort, uint aStartLow, uint aStartHigh, uint aCount, ushort aBuffer) => InternalTransfer(aPort, aStartLow, aStartHigh, aCount, aBuffer, false); public bool Write(PortRegisters aPort, uint aStartLow, uint aStartHigh, uint aCount, ushort aBuffer) => InternalTransfer(aPort, aStartLow, aStartHigh, aCount, aBuffer, true); public int FindCMDSlot(PortRegisters aPort) { // If not set in SACT and CI, the slot is free var xSlots = (mSATAMemory[mPortLocation + 0x34] | mSATAMemory[mPortLocation + 0x38]); //for(int i = 0; i < aPort.VendorSpecific.Length; i++) ////mSATADebugger.SendInternalNumber(aPort.VendorSpecific[i]); for (int i = 0; i < 32; i++) { if ((xSlots & 1) == 0) { return i; } xSlots >>= 1; } //Console.WriteLine("Cannot find free Command list Entry"); return -1; } public SATA(int xPort) { } public override void ReadBlock(ulong aBlockNo, ulong aBlockCount, byte[] aData) { CheckDataSize(aData, aBlockCount); if(SATAPorts.Count > 0) { var xPort = Registers.PortRegisters(SATAPorts[0]); for(int i = 0; i < aData.Length; i += 2) { ushort xData = (ushort)((aData[i + 1] << 8) | aData[i]); Read(xPort, (uint)aBlockNo, 0, (uint)aBlockCount, xData); for (int ui = 0; ui < 200; ui++) ; aData[i+0] = (byte)(xData); aData[i+1] = (byte)(xData >> 8); } } } public override void WriteBlock(ulong aBlockNo, ulong aBlockCount, byte[] aData) { CheckDataSize(aData, aBlockCount); var xPort = Registers.PortRegisters(SATAPorts[0]); for (int i = 0; i < aData.Length; i += 2) { ushort xData = (ushort)((aData[i + 1] << 8) | aData[i]); Write(xPort, (uint)aBlockNo, 0, (uint)aBlockCount, xData); for (int ui = 0; ui < 200; ui++) ; } // Might not work for some reasons :| } } }