mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 21:08:51 +00:00
[AHCI] Read sector, Stop & Start Command, Port Rebase
This commit is contained in:
parent
538f3e3c77
commit
ee2ddf33ce
1 changed files with 453 additions and 119 deletions
|
|
@ -47,14 +47,61 @@ namespace Cosmos.HAL.Drivers.PCI.SATA
|
|||
|
||||
public enum FISType
|
||||
{
|
||||
FIS_Type_RegisterH2D = 0x27, // Register FIS: Host to Device
|
||||
FIS_Type_RegisterD2H = 0x34, // Register FIS: Device to Host
|
||||
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
|
||||
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 struct HBACommandHeader
|
||||
{
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
public uint[] Reserved1; // [4]
|
||||
}
|
||||
|
||||
public struct 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] // = 24 + 128 = 152
|
||||
}
|
||||
public struct 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 uint InterruptOnCompletion; // Interrupt on completion // 1 bit
|
||||
}
|
||||
|
||||
public enum PortType
|
||||
|
|
@ -66,72 +113,72 @@ namespace Cosmos.HAL.Drivers.PCI.SATA
|
|||
PM = 0x04
|
||||
}
|
||||
|
||||
//public struct FIS_REG_H2D
|
||||
//{
|
||||
// public byte FISType;
|
||||
//
|
||||
// public byte Options;
|
||||
// // Reserved
|
||||
// //public byte CMDCTRL;
|
||||
// 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 struct 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 struct FIS_REG_D2H {
|
||||
// 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 struct 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 struct FIS_DATA {
|
||||
// public byte FISType;
|
||||
//
|
||||
// public byte Options;
|
||||
// // Reserved
|
||||
//
|
||||
// // Reserved
|
||||
// public byte Payload;
|
||||
//}
|
||||
public struct FISData {
|
||||
public byte FISType;
|
||||
|
||||
//public byte Options;
|
||||
// Reserved
|
||||
|
||||
// Reserved
|
||||
public byte Payload;
|
||||
}
|
||||
|
||||
// Unused
|
||||
//public struct PIO_SETUP {
|
||||
|
|
@ -189,58 +236,82 @@ namespace Cosmos.HAL.Drivers.PCI.SATA
|
|||
|
||||
public class AHCI
|
||||
{
|
||||
public const uint SSTS_ADDRESS = 0x00000133;
|
||||
public const uint SATA_SIG_ATA = 0x00000101; // SATA drive
|
||||
public const uint SATA_SIG_ATAPI = 0xEB140101; // SATAPI drive
|
||||
public const uint SATA_SIG_SEMB = 0xC33C0101; // Enclosure management bridge
|
||||
public const uint SATA_SIG_PM = 0x96690101; // Port multiplier
|
||||
public const uint PORT_DET_PRESENT = 0x00000003;
|
||||
public const uint PORT_IPM_ACTIVE = 0x00000001;
|
||||
public static uint PortLocation;
|
||||
//___________________________________________________//
|
||||
// SATA Signatures Constants //
|
||||
public const uint SATA_SIG_ATA = 0x00000101; // SATA drive
|
||||
public const uint SATA_SIG_ATAPI = 0xEB140101; // SATAPI drive
|
||||
public const uint SATA_SIG_SEMB = 0xC33C0101; // Enclosure management bridge
|
||||
public const uint SATA_SIG_PM = 0x96690101; // Port multiplier
|
||||
//
|
||||
// SATA Status Bits Constants //
|
||||
public const uint PORT_DET_PRESENT = 0x00000003; // DET Present Value
|
||||
public const uint PORT_IPM_ACTIVE = 0x00000001; // IPM Active Value
|
||||
//
|
||||
public const uint AHCI_BASE = 0x00400000; // AHCI Base
|
||||
//
|
||||
// ATA Device Status //
|
||||
public const uint ATA_DEV_BUSY = 0x00000080; // ATA Device Busy
|
||||
public const uint ATA_DEV_DRQ = 0x00000008; // ATA Device DRQ?
|
||||
//
|
||||
// HBA PortX Command Constants //
|
||||
public const uint HBA_PxCMD_CR = (01 << 15); //
|
||||
public const uint HBA_PxCMD_FR = (01 << 14); //
|
||||
public const uint HBA_PxCMD_FRE = (01 << 04); //
|
||||
public const uint HBA_PxCMD_SUD = (01 << 01); //
|
||||
public const uint HBA_PxCMD_ST = (01 << 00); //
|
||||
public const uint HBA_PxIS_TFES = (01 << 30); //
|
||||
//
|
||||
// ATA Command Constants //
|
||||
public const uint ATA_CMD_READ_DMA_EX = 0x00000025; //
|
||||
public const uint ATA_CMD_WRITE_DMA_EX = 0x00000025; //
|
||||
//
|
||||
//___________________________________________________//
|
||||
private static uint mPortLocation;
|
||||
private static uint[] mPorts = new uint[32];
|
||||
|
||||
public static PCIDevice mAHCIDevice = HAL.PCI.GetDeviceClass(0x01, 0x06);
|
||||
public static uint BAR5 = mAHCIDevice.BaseAddressBar[5].BaseAddress;
|
||||
public static MemoryBlock mAHCIMemory = new MemoryBlock(BAR5, 0x10FF);
|
||||
public static MemoryBlock mAHCIPortMemory = new MemoryBlock(BAR5 + PortLocation, 0x10FF);
|
||||
public static MemoryBlock mAHCIPortMemory = new MemoryBlock(BAR5 + mPortLocation, 0x10FF);
|
||||
internal static Debugger mAHCIDebugger = new Debugger("HAL", "AHCI");
|
||||
|
||||
internal class PortHelper
|
||||
{
|
||||
public static PortRegisters GetPort(int aPortNumber)
|
||||
{
|
||||
PortLocation = (uint)(aPortNumber);
|
||||
if (aPortNumber == 00) PortLocation = 0x0100;
|
||||
else if (aPortNumber == 01) PortLocation = 0x0180;
|
||||
else if (aPortNumber == 02) PortLocation = 0x0200;
|
||||
else if (aPortNumber == 03) PortLocation = 0x0280;
|
||||
else if (aPortNumber == 04) PortLocation = 0x0300;
|
||||
else if (aPortNumber == 05) PortLocation = 0x0380;
|
||||
else if (aPortNumber == 06) PortLocation = 0x0400;
|
||||
else if (aPortNumber == 07) PortLocation = 0x0480;
|
||||
else if (aPortNumber == 08) PortLocation = 0x0500;
|
||||
else if (aPortNumber == 09) PortLocation = 0x0580;
|
||||
else if (aPortNumber == 10) PortLocation = 0x0600;
|
||||
else if (aPortNumber == 11) PortLocation = 0x0680;
|
||||
else if (aPortNumber == 12) PortLocation = 0x0700;
|
||||
else if (aPortNumber == 13) PortLocation = 0x0780;
|
||||
else if (aPortNumber == 14) PortLocation = 0x0800;
|
||||
else if (aPortNumber == 15) PortLocation = 0x0880;
|
||||
else if (aPortNumber == 16) PortLocation = 0x0900;
|
||||
else if (aPortNumber == 17) PortLocation = 0x0980;
|
||||
else if (aPortNumber == 18) PortLocation = 0x0A00;
|
||||
else if (aPortNumber == 19) PortLocation = 0x0A80;
|
||||
else if (aPortNumber == 20) PortLocation = 0x0B00;
|
||||
else if (aPortNumber == 21) PortLocation = 0x0B80;
|
||||
else if (aPortNumber == 22) PortLocation = 0x0C00;
|
||||
else if (aPortNumber == 23) PortLocation = 0x0C80;
|
||||
else if (aPortNumber == 24) PortLocation = 0x0D00;
|
||||
else if (aPortNumber == 25) PortLocation = 0x0D80;
|
||||
else if (aPortNumber == 26) PortLocation = 0x0E00;
|
||||
else if (aPortNumber == 27) PortLocation = 0x0E80;
|
||||
else if (aPortNumber == 28) PortLocation = 0x0F00;
|
||||
else if (aPortNumber == 29) PortLocation = 0x0F80;
|
||||
else if (aPortNumber == 30) PortLocation = 0x1000;
|
||||
else if (aPortNumber == 31) PortLocation = 0x1080;
|
||||
mPortLocation = (uint)(aPortNumber);
|
||||
if (aPortNumber == 00) mPortLocation = 0x0100;
|
||||
else if (aPortNumber == 01) mPortLocation = 0x0180;
|
||||
else if (aPortNumber == 02) mPortLocation = 0x0200;
|
||||
else if (aPortNumber == 03) mPortLocation = 0x0280;
|
||||
else if (aPortNumber == 04) mPortLocation = 0x0300;
|
||||
else if (aPortNumber == 05) mPortLocation = 0x0380;
|
||||
else if (aPortNumber == 06) mPortLocation = 0x0400;
|
||||
else if (aPortNumber == 07) mPortLocation = 0x0480;
|
||||
else if (aPortNumber == 08) mPortLocation = 0x0500;
|
||||
else if (aPortNumber == 09) mPortLocation = 0x0580;
|
||||
else if (aPortNumber == 10) mPortLocation = 0x0600;
|
||||
else if (aPortNumber == 11) mPortLocation = 0x0680;
|
||||
else if (aPortNumber == 12) mPortLocation = 0x0700;
|
||||
else if (aPortNumber == 13) mPortLocation = 0x0780;
|
||||
else if (aPortNumber == 14) mPortLocation = 0x0800;
|
||||
else if (aPortNumber == 15) mPortLocation = 0x0880;
|
||||
else if (aPortNumber == 16) mPortLocation = 0x0900;
|
||||
else if (aPortNumber == 17) mPortLocation = 0x0980;
|
||||
else if (aPortNumber == 18) mPortLocation = 0x0A00;
|
||||
else if (aPortNumber == 19) mPortLocation = 0x0A80;
|
||||
else if (aPortNumber == 20) mPortLocation = 0x0B00;
|
||||
else if (aPortNumber == 21) mPortLocation = 0x0B80;
|
||||
else if (aPortNumber == 22) mPortLocation = 0x0C00;
|
||||
else if (aPortNumber == 23) mPortLocation = 0x0C80;
|
||||
else if (aPortNumber == 24) mPortLocation = 0x0D00;
|
||||
else if (aPortNumber == 25) mPortLocation = 0x0D80;
|
||||
else if (aPortNumber == 26) mPortLocation = 0x0E00;
|
||||
else if (aPortNumber == 27) mPortLocation = 0x0E80;
|
||||
else if (aPortNumber == 28) mPortLocation = 0x0F00;
|
||||
else if (aPortNumber == 29) mPortLocation = 0x0F80;
|
||||
else if (aPortNumber == 30) mPortLocation = 0x1000;
|
||||
else if (aPortNumber == 31) mPortLocation = 0x1080;
|
||||
PortRegisters Port = new PortRegisters()
|
||||
{
|
||||
CLB = mAHCIPortMemory[0x00],
|
||||
|
|
@ -298,38 +369,46 @@ namespace Cosmos.HAL.Drivers.PCI.SATA
|
|||
// Search for disks
|
||||
var xImplementedPort = aGeneric.PI;
|
||||
var xPort = 0;
|
||||
var xPortType = 0U;
|
||||
var xSupportedPorts = 0x1F;
|
||||
while (xPort <= xSupportedPorts)
|
||||
{
|
||||
if (xImplementedPort != 0)
|
||||
{
|
||||
PortType dt = CheckPortType(PortHelper.GetPort(xPort));
|
||||
PortType PortType = CheckPortType(PortHelper.GetPort(xPort));
|
||||
var xPortString = "0:" + xPort;
|
||||
if (dt == PortType.SATA) // If Port Type was SATA.
|
||||
if (PortType == PortType.SATA) // If Port Type was SATA.
|
||||
{
|
||||
mAHCIDebugger.Send("SATA drive found at port " + xPortString);
|
||||
Console.WriteLine("SATA Drive found at port " + xPortString);
|
||||
xPortType = 0x01;
|
||||
PortRebase(PortHelper.GetPort(xPort), xPort);
|
||||
Read(PortHelper.GetPort(xPort), 0, 0, 2, (ushort)BAR5);
|
||||
}
|
||||
else if (dt == PortType.SATAPI) // If Port Type was SATAPI.
|
||||
else if (PortType == PortType.SATAPI) // If Port Type was SATAPI.
|
||||
{
|
||||
mAHCIDebugger.Send("SATAPI drive found at port " + xPortString);
|
||||
Console.WriteLine("CD/DVD Drive found at port " + xPortString);
|
||||
xPortType = 0x02;
|
||||
}
|
||||
else if (dt == PortType.SEMB) // If Port Type was SEMB.
|
||||
else if (PortType == PortType.SEMB) // If Port Type was SEMB.
|
||||
{
|
||||
mAHCIDebugger.Send("SEMB drive found at port " + xPortString);
|
||||
Console.WriteLine("SEMB Drive found at port " + xPortString);
|
||||
xPortType = 0x03;
|
||||
}
|
||||
else if (dt == PortType.PM) // If Port Type was Port Mulitplier.
|
||||
else if (PortType == PortType.PM) // If Port Type was Port Mulitplier.
|
||||
{
|
||||
mAHCIDebugger.Send("Port Multiplier drive found at port " + xPortString);
|
||||
Console.WriteLine("Port Multiplier Drive found at port " + xPortString);
|
||||
xPortType = 0x04;
|
||||
}
|
||||
else if (dt == PortType.Nothing) // If Nothing in this Port.
|
||||
else if (PortType == PortType.Nothing) // If Nothing in this Port.
|
||||
mAHCIDebugger.Send("No drive found at port " + xPortString);
|
||||
else // If Implemented Port value was not zero and not one of the above.
|
||||
mAHCIDebugger.Send("Unknown drive found at port " + xPortString);
|
||||
}
|
||||
mPorts[xPort] = xPortType;
|
||||
xPort++;
|
||||
xImplementedPort >>= 1;
|
||||
}
|
||||
|
|
@ -363,6 +442,260 @@ namespace Cosmos.HAL.Drivers.PCI.SATA
|
|||
}
|
||||
}
|
||||
|
||||
public void PortRebase(PortRegisters aPort, int aPortNumber)
|
||||
{
|
||||
StopCMD(aPort);
|
||||
|
||||
aPort.CLB = (uint)(AHCI_BASE + (aPortNumber << 10));
|
||||
aPort.CLBU = 0;
|
||||
mAHCIPortMemory.Fill(aPort.CLB, 0, 1024);
|
||||
|
||||
// FIS offset: 32K+256*portno
|
||||
// FIS entry size = 256 bytes per port
|
||||
aPort.FB = (uint)(AHCI_BASE + (32 << 10) + (aPortNumber << 8));
|
||||
aPort.FBU = 0;
|
||||
mAHCIPortMemory.Fill(aPort.FB, 0, 256);
|
||||
|
||||
HBACommandHeader[] xCMDHeader = new HBACommandHeader[32];
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
xCMDHeader[i].PRDTL = 8; // 8 prdt entries per command table
|
||||
// 256 bytes per command table, 64+16+48+16*8
|
||||
// Command table offset: 40K + 8K*portno + cmdheader_index*256
|
||||
xCMDHeader[i].CTBA = (uint)(AHCI_BASE + (40 << 10) + (aPortNumber << 13) + (i << 8));
|
||||
xCMDHeader[i].CTBAU = 0;
|
||||
mAHCIPortMemory.Fill(xCMDHeader[i].CTBA, 0, 256);
|
||||
}
|
||||
|
||||
StartCMD(aPort);
|
||||
}
|
||||
public void StartCMD(PortRegisters aPort)
|
||||
{
|
||||
while ((aPort.CMD & HBA_PxCMD_CR) != 0) ;
|
||||
|
||||
aPort.CMD |= HBA_PxCMD_FRE;
|
||||
aPort.CMD |= HBA_PxCMD_ST;
|
||||
}
|
||||
|
||||
public void StopCMD(PortRegisters aPort)
|
||||
{
|
||||
aPort.CMD &= ~HBA_PxCMD_ST;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if ((aPort.CMD & HBA_PxCMD_FR) != 0)
|
||||
continue;
|
||||
if ((aPort.CMD & HBA_PxCMD_CR) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
aPort.CMD &= ~HBA_PxCMD_FRE;
|
||||
}
|
||||
|
||||
public bool Read(PortRegisters aPort, uint aStartLow, uint aStartHigh, uint aCount, ushort aBuffer)
|
||||
{
|
||||
aPort.IS -= 1;
|
||||
int xSpin = 0; // Spin lock Timeout Counter
|
||||
int xSlot = FindCMDSlot(aPort);
|
||||
if (xSlot == -1)
|
||||
return false;
|
||||
|
||||
HBACommandHeader xCMDHeader = new HBACommandHeader();
|
||||
aPort.CLB += (uint)xSlot;
|
||||
xCMDHeader.CFL = (byte)(17 / sizeof(uint));
|
||||
xCMDHeader.Write = 0;
|
||||
xCMDHeader.PRDTL = (ushort)(((aCount - 1) >> 4) + 1);
|
||||
|
||||
HBACommandTable xCMDTable = new HBACommandTable(); // xCMDHeader.CTBA
|
||||
mAHCIPortMemory.Fill(xCMDHeader.CTBA, 0, (158 + (xCMDHeader.PRDTL - 1U)) * 24);
|
||||
xCMDTable.PRDTEntry = new HBAPRDTEntry[1];
|
||||
|
||||
int i = 0; // i for PRDTEntry outside the loop?
|
||||
|
||||
for (i = 0; i < xCMDHeader.PRDTL - 1; i++)
|
||||
{
|
||||
|
||||
xCMDTable.PRDTEntry[i].DBA = (uint)(aBuffer);
|
||||
xCMDTable.PRDTEntry[i].DBC = 8 * 1024;
|
||||
xCMDTable.PRDTEntry[i].InterruptOnCompletion = 1;
|
||||
aBuffer += 4 * 1024;
|
||||
aCount -= 16;
|
||||
}
|
||||
// Last entry
|
||||
|
||||
xCMDTable.PRDTEntry[i].DBA = (uint)aBuffer;
|
||||
xCMDTable.PRDTEntry[i].DBC = aCount << 9;
|
||||
xCMDTable.PRDTEntry[i].InterruptOnCompletion = 1;
|
||||
|
||||
// Setup the command
|
||||
FISRegisterH2D CommandFIS = new FISRegisterH2D() // Address CMDTBL.CFIS;
|
||||
{
|
||||
FISType = (byte)FISType.FIS_Type_RegisterH2D,
|
||||
IsCommand = 1,
|
||||
Command = (byte)ATA_CMD_READ_DMA_EX,
|
||||
|
||||
LBA0 = (byte)aStartLow,
|
||||
LBA1 = (byte)(aStartLow >> 8),
|
||||
LBA2 = (byte)(aStartLow >> 16),
|
||||
Device = 1 << 6, // LBA Mode
|
||||
|
||||
LBA3 = (byte)(aStartLow >> 24),
|
||||
LBA4 = (byte)aStartHigh,
|
||||
LBA5 = (byte)(aStartHigh >> 8),
|
||||
|
||||
CountL = (byte)(aCount & 0xFF),
|
||||
CountH = (byte)(aCount >> 8),
|
||||
};
|
||||
while ((aPort.TFD & (ATA_DEV_BUSY | ATA_DEV_DRQ)) != 0 && xSpin < 1000000)
|
||||
{
|
||||
xSpin++;
|
||||
}
|
||||
if (xSpin == 1000000)
|
||||
{
|
||||
mAHCIDebugger.Send("Port timed out");
|
||||
return false;
|
||||
}
|
||||
|
||||
aPort.CI = 1U << xSlot; // Issue with Command
|
||||
|
||||
// Wait for Completion
|
||||
while (true)
|
||||
{
|
||||
// In some longer duration reads, It may be Helpful to Spin on the DPS bit
|
||||
// in the aPort.IS port field as well (1 << 5)
|
||||
if ((aPort.CI & (1 << xSlot)) == 0)
|
||||
break;
|
||||
if ((aPort.IS == HBA_PxIS_TFES))
|
||||
{
|
||||
Console.WriteLine("Error occured while Reading the Disk");
|
||||
mAHCIDebugger.Send("Read disk error!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check Again
|
||||
if (aPort.IS == HBA_PxIS_TFES)
|
||||
{
|
||||
Console.WriteLine("Error occured while Reading the Disk");
|
||||
mAHCIDebugger.Send("Read disk error!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inverting Some codes (Read -> Write)
|
||||
public bool Write(PortRegisters aPort, uint aStartLow, uint aStartHigh, uint aCount, ushort aBuffer)
|
||||
{
|
||||
aPort.IS -= 1;
|
||||
int xSpin = 0; // Spin lock Timeout Counter
|
||||
int xSlot = FindCMDSlot(aPort);
|
||||
if (xSlot == -1)
|
||||
return false;
|
||||
|
||||
HBACommandHeader xCMDHeader = new HBACommandHeader();
|
||||
aPort.CLB += (uint)xSlot;
|
||||
xCMDHeader.CFL = 15 / sizeof(uint);
|
||||
xCMDHeader.Write = 1;
|
||||
xCMDHeader.PRDTL = (ushort)(((aCount - 1) >> 4) + 1);
|
||||
|
||||
HBACommandTable xCMDTable = new HBACommandTable(); // xCMDHeader.CTBA
|
||||
mAHCIPortMemory.Fill(xCMDHeader.CTBA, 0, (158 + (xCMDHeader.PRDTL - 1U)) * 24);
|
||||
xCMDTable.PRDTEntry = new HBAPRDTEntry[1];
|
||||
|
||||
int i = 0; // i for PRDTEntry outside the loop?
|
||||
|
||||
for (i = 0; i < xCMDHeader.PRDTL - 1; i++)
|
||||
{
|
||||
|
||||
xCMDTable.PRDTEntry[i].DBA = (uint)(aBuffer);
|
||||
xCMDTable.PRDTEntry[i].DBC = 8 * 1024;
|
||||
xCMDTable.PRDTEntry[i].InterruptOnCompletion = 1;
|
||||
aBuffer += 4 * 1024;
|
||||
aCount -= 16;
|
||||
}
|
||||
// Last entry
|
||||
|
||||
xCMDTable.PRDTEntry[i].DBA = (uint)aBuffer;
|
||||
xCMDTable.PRDTEntry[i].DBC = aCount << 9;
|
||||
xCMDTable.PRDTEntry[i].InterruptOnCompletion = 1;
|
||||
|
||||
// Setup the command
|
||||
FISRegisterH2D CommandFIS = new FISRegisterH2D // Address CMDTBL.CFIS;
|
||||
{
|
||||
FISType = (byte)FISType.FIS_Type_RegisterH2D,
|
||||
IsCommand = 1,
|
||||
Command = (byte)ATA_CMD_WRITE_DMA_EX,
|
||||
|
||||
LBA0 = (byte)aStartLow,
|
||||
LBA1 = (byte)(aStartLow >> 8),
|
||||
LBA2 = (byte)(aStartLow >> 16),
|
||||
Device = 1 << 6, // LBA Mode
|
||||
|
||||
LBA3 = (byte)(aStartLow >> 24),
|
||||
LBA4 = (byte)aStartHigh,
|
||||
LBA5 = (byte)(aStartHigh >> 8),
|
||||
|
||||
CountL = (byte)(aCount & 0xFF),
|
||||
CountH = (byte)(aCount >> 8)
|
||||
};
|
||||
|
||||
while ((aPort.TFD & (ATA_DEV_BUSY | ATA_DEV_DRQ)) != 0 && xSpin < 1000000)
|
||||
{
|
||||
xSpin++;
|
||||
}
|
||||
|
||||
if (xSpin == 1000000)
|
||||
{
|
||||
mAHCIDebugger.Send("Port timed out");
|
||||
return false;
|
||||
}
|
||||
|
||||
aPort.CI = 1U << xSlot; // Issue with Command
|
||||
|
||||
// Wait for Completion
|
||||
while (true)
|
||||
{
|
||||
// In some longer duration writes, It may be Helpful to Spin on the DPS bit
|
||||
// in the aPort.IS port field as well (1 << 5)
|
||||
if ((aPort.CI & (1 << xSlot)) == 0)
|
||||
break;
|
||||
if ((aPort.IS == HBA_PxIS_TFES))
|
||||
{
|
||||
Console.WriteLine("Error occured while Writing to the Disk");
|
||||
mAHCIDebugger.Send("Write disk error!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check Again
|
||||
if (aPort.IS == HBA_PxIS_TFES)
|
||||
{
|
||||
Console.WriteLine("Error occured while Writing to the Disk");
|
||||
mAHCIDebugger.Send("Write disk error!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int FindCMDSlot(PortRegisters aPort)
|
||||
{
|
||||
// If not set in SACT and CI, the slot is free
|
||||
var xSlots = (aPort.SACT | aPort.CI);
|
||||
for (int i = 0; i < xSlots; i++)
|
||||
{
|
||||
if ((xSlots & 1) == 0)
|
||||
mAHCIDebugger.Send("Found a command slot: ");
|
||||
mAHCIDebugger.SendNumber(i);
|
||||
return i;
|
||||
xSlots >>= 1;
|
||||
}
|
||||
mAHCIDebugger.Send("Cannot find free command list entry");
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void InitSATA()
|
||||
{
|
||||
GenericRegisters mGeneric = new GenericRegisters()
|
||||
|
|
@ -384,6 +717,7 @@ namespace Cosmos.HAL.Drivers.PCI.SATA
|
|||
};
|
||||
var xSelf = new AHCI();
|
||||
xSelf.SearchForDisks(mGeneric);
|
||||
//xSelf.GetPartitions(xPorts, );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue