From 96a35b2b6aa9efdc1f286c83bc8be7334f932aff Mon Sep 17 00:00:00 2001 From: KingLuigi4932 Date: Mon, 25 Dec 2017 08:40:29 +0300 Subject: [PATCH] [AHCI] First working AHCI Controller --- source/Cosmos.HAL2/BlockDevice/AHCI.cs | 169 +++++++++++++++---------- 1 file changed, 99 insertions(+), 70 deletions(-) diff --git a/source/Cosmos.HAL2/BlockDevice/AHCI.cs b/source/Cosmos.HAL2/BlockDevice/AHCI.cs index 1cd5b45aa..cd260aa7f 100644 --- a/source/Cosmos.HAL2/BlockDevice/AHCI.cs +++ b/source/Cosmos.HAL2/BlockDevice/AHCI.cs @@ -10,10 +10,10 @@ using Cosmos.Core.Memory.Old; namespace Cosmos.HAL.BlockDevice { - public class AHCI + public class AHCI : Drivers.PCIDriver { internal static Debugger mAHCIDebugger = new Debugger("HAL", "AHCI"); - internal static PCIDevice xDevice = HAL.PCI.GetDevice(0x01, 0x06); + internal static PCIDevice xDevice = HAL.PCI.GetDevice(0x001, 0x0006); private static List mPorts = new List(); private static GenericRegisters mGeneric; @@ -55,16 +55,16 @@ namespace Cosmos.HAL.BlockDevice internal static void InitDriver() { - if (xDevice != null) - { - AHCI Driver = new AHCI(xDevice); - } + + if (xDevice == null) return; + AHCI Driver = new AHCI(xDevice); } - internal PCIDevice GetDevice() => xDevice; + internal override PCIDevice GetDevice() => xDevice; public AHCI(PCIDevice aAHCIDevice) { + mAHCIDebugger.Send("Something wrong!"); aAHCIDevice.EnableBusMaster(true); aAHCIDevice.EnableMemory(true); @@ -80,7 +80,7 @@ namespace Cosmos.HAL.BlockDevice { if(xPort.mPortType == PortType.SATA) { - mAHCIDebugger.Send($"{xPort.mPortName} Port [0:{xPort.mPortNumber}]"); + mAHCIDebugger.Send($"{xPort.mPortName} Port 0:{xPort.mPortNumber}"); var xMBRData = new byte[512]; xPort.ReadBlock(0UL, 1U, xMBRData); var xMBR = new MBR(xMBRData); @@ -88,6 +88,7 @@ namespace Cosmos.HAL.BlockDevice if (xMBR.EBRLocation != 0) { // EBR Detected! + mAHCIDebugger.Send("EBR Detected within MBR code"); var xEBRData = new byte[512]; xPort.ReadBlock(xMBR.EBRLocation, 1U, xEBRData); var xEBR = new EBR(xEBRData); @@ -99,7 +100,7 @@ namespace Cosmos.HAL.BlockDevice } } - mAHCIDebugger.Send($"Number of MBR partitions in port [0:{xPort.mPortNumber}]: "); + mAHCIDebugger.Send($"Number of MBR partitions found on port 0:{xPort.mPortNumber} "); mAHCIDebugger.SendNumber(xMBR.Partitions.Count); for (int i = 0; i < xMBR.Partitions.Count; i++) { @@ -119,16 +120,50 @@ namespace Cosmos.HAL.BlockDevice else if (xPort.mPortType == PortType.SATAPI) { mAHCIDebugger.Send($"{xPort.mPortName} Port 0:{xPort.mPortNumber}"); - // TODO: Implement ISO-9660 or UDF and Fix SATAPI + + // Just to test Read Sector! + + //byte[] xMBRData = new byte[512]; + //xPort.ReadBlock(0UL, 1U, xMBRData); + //MBR xMBR = new MBR(xMBRData); + + //mAHCIDebugger.Send($"Number of corrupted MBR partitions found on port 0:{xPort.mPortNumber} "); + //mAHCIDebugger.SendNumber(xMBR.Partitions.Count); + //for (int i = 0; i < xMBR.Partitions.Count; i++) + //{ + // var xPart = xMBR.Partitions[i]; + // if (xPart == null) + // { + // Console.WriteLine("Null partition found at idx: " + i); + // } + // else + // { + // var xPartDevice = new Partition(xPort, xPart.StartSector, xPart.SectorCount); + // BlockDevice.Devices.Add(xPartDevice); + // Console.WriteLine("Found corrupted partition at idx: " + i); + // } + //} } } } - private void Wait(int microsecondsTimeout) + public static void HBAReset() + { + mGeneric.GlobalHostControl = 1; + uint HR = 0; + do + { + Wait(1); + HR = mGeneric.GlobalHostControl & 1; + } while (HR != 0); + } + + public static void Wait(int microsecondsTimeout) { byte xVoid; for (int i = 0; i < microsecondsTimeout; i++) { + // Random IOPort xVoid = Core.Global.BaseIOGroups.TextScreen.Data1.Byte; xVoid = Core.Global.BaseIOGroups.TextScreen.Data1.Byte; xVoid = Core.Global.BaseIOGroups.TextScreen.Data1.Byte; @@ -144,26 +179,26 @@ namespace Cosmos.HAL.BlockDevice private void GetCapabilities() { - NumOfPorts = mGeneric.Capabilities & 0x1F; - SupportsExternalSATA = (mGeneric.Capabilities >> 5 & 1) == 1; - EnclosureManagementSupported = (mGeneric.Capabilities >> 6 & 1) == 1; - CommandCompletionCoalsecingSupported = (mGeneric.Capabilities >> 7 & 1) == 1; - NumOfCommandSlots = mGeneric.Capabilities >> 8 & 0x1F; - PartialStateCapable = (mGeneric.Capabilities >> 13 & 1) == 1; - SlumberStateCapable = (mGeneric.Capabilities >> 14 & 1) == 1; - PIOMultipleDRQBlock = (mGeneric.Capabilities >> 15 & 1) == 1; - FISBasedSwitchingSupported = (mGeneric.Capabilities >> 16 & 1) == 1; - SupportsPortMutliplier = (mGeneric.Capabilities >> 17 & 1) == 1; - SupportsAHCIModeOnly = (mGeneric.Capabilities >> 18 & 1) == 1; - InterfaceSpeedSupport = mGeneric.Capabilities >> 20 & 0x0F; - SupportsCommandListOverride = (mGeneric.Capabilities >> 24 & 1) == 1; - SupportsActivityLED = (mGeneric.Capabilities >> 25 & 1) == 1; + NumOfPorts = mGeneric.Capabilities & 0x1F; + SupportsExternalSATA = (mGeneric.Capabilities >> 5 & 1) == 1; + EnclosureManagementSupported = (mGeneric.Capabilities >> 6 & 1) == 1; + CommandCompletionCoalsecingSupported = (mGeneric.Capabilities >> 7 & 1) == 1; + NumOfCommandSlots = mGeneric.Capabilities >> 8 & 0x1F; + PartialStateCapable = (mGeneric.Capabilities >> 13 & 1) == 1; + SlumberStateCapable = (mGeneric.Capabilities >> 14 & 1) == 1; + PIOMultipleDRQBlock = (mGeneric.Capabilities >> 15 & 1) == 1; + FISBasedSwitchingSupported = (mGeneric.Capabilities >> 16 & 1) == 1; + SupportsPortMutliplier = (mGeneric.Capabilities >> 17 & 1) == 1; + SupportsAHCIModeOnly = (mGeneric.Capabilities >> 18 & 1) == 1; + InterfaceSpeedSupport = mGeneric.Capabilities >> 20 & 0x0F; + SupportsCommandListOverride = (mGeneric.Capabilities >> 24 & 1) == 1; + SupportsActivityLED = (mGeneric.Capabilities >> 25 & 1) == 1; SupportsAggressiveLinkPowerManagement = (mGeneric.Capabilities >> 26 & 1) == 1; - SupportsStaggeredSpinup = (mGeneric.Capabilities >> 27 & 1) == 1; - SupportsMechanicalPresenceSwitch = (mGeneric.Capabilities >> 28 & 1) == 1; - SupportsSNotificationRegister = (mGeneric.Capabilities >> 29 & 1) == 1; - SupportsNativeCommandQueuing = (mGeneric.Capabilities >> 30 & 1) == 1; - Supports64bitAddressing = (mGeneric.Capabilities >> 31 & 1) == 1; + SupportsStaggeredSpinup = (mGeneric.Capabilities >> 27 & 1) == 1; + SupportsMechanicalPresenceSwitch = (mGeneric.Capabilities >> 28 & 1) == 1; + SupportsSNotificationRegister = (mGeneric.Capabilities >> 29 & 1) == 1; + SupportsNativeCommandQueuing = (mGeneric.Capabilities >> 30 & 1) == 1; + Supports64bitAddressing = (mGeneric.Capabilities >> 31 & 1) == 1; } private void GetPorts() @@ -171,45 +206,40 @@ namespace Cosmos.HAL.BlockDevice // Search for disks var xImplementedPort = mGeneric.ImplementedPorts; var xPort = 0; - while (xPort < NumOfPorts) + for(; xPort < 32; xPort++) { if ((xImplementedPort & 1) != 0) { - PortRegisters xPortReg = new PortRegisters((uint)mABAR + 0x100 + (uint)(0x80 * xPort), (uint)xPort); + PortRegisters xPortReg = new PortRegisters((uint)mABAR + 0x100, (uint)xPort); PortType PortType = CheckPortType(xPortReg); xPortReg.mPortType = PortType; var xPortString = "0:" + ((xPort.ToString().Length <= 1) ? xPort.ToString().PadLeft(1, '0') : xPort.ToString()); - if (PortType == PortType.SATA) // If Port Type was SATA. + if (PortType == PortType.SATA) // If Port type was SATA. { - Console.WriteLine("Initializing Port " + xPortString + " with type SATA"); - UInt16[] xSectorData = new UInt16[256]; + mAHCIDebugger.Send("Initializing Port " + xPortString + " with type SATA"); PortRebase(xPortReg, (uint)xPort); - SATA xSATAPort = new SATA(xPortReg); + var xSATAPort = new SATA(xPortReg); mPorts.Add(xSATAPort); } - else if (PortType == PortType.SATAPI) // If Port Type was SATAPI. + else if (PortType == PortType.SATAPI) // If Port type was SATAPI. { - mAHCIDebugger.Send("SATAPI"); - Console.WriteLine("Initializing Port " + xPortString + " with type Serial ATAPI"); + mAHCIDebugger.Send("Initializing Port " + xPortString + " with type Serial ATAPI"); //PortRebase(xPortReg, (uint)xPort); - //SATAPI xSATAPIPort = new SATAPI(xPortReg); + //var xSATAPIPort = new SATAPI(xPortReg); //mPorts.Add(xSATAPIPort); } - else if (PortType == PortType.SEMB) // If Port Type was SEMB. + else if (PortType == PortType.SEMB) // If Port type was SEMB. { - Console.WriteLine("SEMB Drive at port " + xPortString + " found, which is not supported yet!"); + mAHCIDebugger.Send("SEMB Drive at port " + xPortString + " found, which is not supported yet!"); } - else if (PortType == PortType.PM) // If Port Type was Port Mulitplier. + 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!"); + mAHCIDebugger.Send("Port Multiplier Drive at port " + xPortString + " found, which is not supported yet!"); } - else if (PortType == PortType.Nothing) - mAHCIDebugger.Send("No drive found at port: " + xPortString); - else + else if (PortType != PortType.Nothing) mAHCIDebugger.Send("Unknown drive found with signature: 0x" + xPortReg.SIG);// If Implemented Port value was not zero and non of the above. } xImplementedPort >>= 1; - xPort++; } } @@ -219,10 +249,8 @@ namespace Cosmos.HAL.BlockDevice var xSPD = (CurrentInterfaceSpeedStatus)((aPort.SSTS >> 4) & 0x0F); var xDET = (DeviceDetectionStatus)(aPort.SSTS & 0x0F); var xSignature = aPort.SIG; - //var LBALow = (byte)(Port.SIG >> 08); - //var LBAMedium = (byte)(Port.SIG >> 16); - //var LBAHigh = (byte)(Port.SIG >> 24); + // Check if not reading wrong data! if (xIPM != InterfacePowerManagementStatus.Active) return PortType.Nothing; if (xDET != DeviceDetectionStatus.DeviceDetectedWithPhy) @@ -241,49 +269,47 @@ namespace Cosmos.HAL.BlockDevice private void PortRebase(PortRegisters aPort, uint aPortNumber) { mAHCIDebugger.Send("Stop"); - if (!StopCMD(aPort)) aPort.SCTL = 1; + if (!StopCMD(aPort)) SATA.PortReset(aPort); - ulong mCLBAddress = Heap.MemAlloc(1024); - aPort.CLB = (uint)mCLBAddress & 0xFFFFFFFF; - - var mFBAddress = Heap.MemAlloc(256); - aPort.FB = (uint)mFBAddress & 0xFFFFFFFF; + aPort.CLB = (uint)Base.AHCI + (0x400 * aPortNumber); + aPort.FB = (uint)Base.AHCI + 0x8000 + (0x100 * aPortNumber); aPort.SERR = 1; aPort.IS = 0; aPort.IE = 0; - + new MemoryBlock(aPort.CLB, 1024).Fill(0); new MemoryBlock(aPort.FB, 256).Fill(0); - - GetCommandHeader(aPort); // Rebasing Command Header - StartCMD(aPort); + GetCommandHeader(aPort); // Rebase Command header + + if (!StartCMD(aPort)) SATA.PortReset(aPort); + aPort.IS = 0; aPort.IE = 0xFFFFFFFF; + + mAHCIDebugger.Send("Finished!"); } private static HBACommandHeader[] GetCommandHeader(PortRegisters aPort) { - var xCTBAAddress = Heap.MemAlloc(256); HBACommandHeader[] xCMDHeader = new HBACommandHeader[32]; for (uint i = 0; i < xCMDHeader.Length; i++) { xCMDHeader[i] = new HBACommandHeader(aPort.CLB, i) { - PRDTL = 8, // 8 prdt entries per command table - // 256 bytes per command table, 64+16+48+16*8 - CTBA = xCTBAAddress + (256 * i), - //TODO: Use the below register as the upper base address if HBA - // supports S64A (64-bit Addressing) + PRDTL = 8, + + CTBA = (uint)(Base.AHCI + 0xA000) + (0x2000 * aPort.mPortNumber) + (0x100 * i), + CTBAU = 0 }; - new MemoryBlock(xCMDHeader[i].CTBA, 256).Fill(0); + new MemoryBlock(xCMDHeader[i].CTBA, 0x100).Fill(0); } return xCMDHeader; } - private void StartCMD(PortRegisters aPort) + private bool StartCMD(PortRegisters aPort) { int xSpin; for (xSpin = 0; xSpin < 101; xSpin++) @@ -291,12 +317,15 @@ namespace Cosmos.HAL.BlockDevice if ((aPort.CMD & (uint)CommandAndStatus.CMDListRunning) == 0) break; Wait(5000); } - if (xSpin == 101) return; + if (xSpin == 101) return false; aPort.CMD |= (1 << 4); aPort.CMD |= (1 << 0); + + return true; } + // Thanks to Microsoft for the detailed info about stopping command process! private bool StopCMD(PortRegisters aPort) { int xSpin;