mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-01-07 21:26:30 +00:00
93 lines
No EOL
2.6 KiB
HolyC
Executable file
93 lines
No EOL
2.6 KiB
HolyC
Executable file
//TODO: Test
|
|
I64 AHCILBA48CapacityGet(U16 *id_record)
|
|
{//Get capacity of drive.
|
|
return *&id_record[ATA_IDENT_LBA48_CAPACITY](U64 *) - 1;
|
|
//return (id_record)(U64 *)[ATA_IDENT_LBA48_CAPACITY / 4] - 1;
|
|
}
|
|
|
|
I64 AHCIPortCmdSlotGet(CAHCIPort *port)
|
|
{//Get next free command slot in port; if none, return -1.
|
|
I64 i;
|
|
U32 slots = port->sata_active | port->cmd_issue;
|
|
|
|
for (i = 0; i < blkdev.cmd_slot_count; i++)
|
|
{
|
|
if (!(slots & 1))
|
|
return i;
|
|
slots >>= 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
Bool AHCIPortIsIdle(CAHCIPort *port)
|
|
{//Check if command engine is running on port.
|
|
return !(port->cmd & (AHCI_PxCMDF_ST | AHCI_PxCMDF_CR | AHCI_PxCMDF_FR | AHCI_PxCMDF_FRE));
|
|
}
|
|
|
|
U0 AHCIPortCmdStop(CAHCIPort *port)
|
|
{//Stop command engine on port.
|
|
//Btr(&port->cmd, AHCI_PxCMDf_ST);
|
|
//Btr(&port->cmd, AHCI_PxCMDf_FRE);
|
|
port->cmd &= ~(AHCI_PxCMDF_ST | AHCI_PxCMDF_FRE);
|
|
//while (port->cmd & (AHCI_PxCMDF_CR | AHCI_PxCMDF_FR));
|
|
while (Bt(&port->cmd, AHCI_PxCMDf_CR) || Bt(&port->cmd, AHCI_PxCMDf_FR));
|
|
}
|
|
|
|
U0 AHCIPortCmdStart(CAHCIPort *port)
|
|
{//Start command engine on port.
|
|
while (Bt(&port->cmd, AHCI_PxCMDf_CR))
|
|
Bts(&port->cmd, AHCI_PxCMDf_FRE);
|
|
Bts(&port->cmd, AHCI_PxCMDf_ST);
|
|
//port->command |= AHCI_PxCMDF_FRE | AHCI_PxCMDF_ST;
|
|
}
|
|
|
|
Bool AHCIPortWait(CAHCIPort *port, F64 timeout)
|
|
{//Wait until DRQ and BSY are clear in the port task file.
|
|
do
|
|
if (!(port->task_file_data & (ATAS_DRQ | ATAS_BSY)))
|
|
return TRUE;
|
|
while (timeout > tS);
|
|
return FALSE;
|
|
}
|
|
|
|
//TODO: explain&comment statements in this function
|
|
U0 AHCIPortReset(CAHCIPort *port)
|
|
{//Software reset of port. Port cmd engine must be started after this.
|
|
//If port is not responsive, then perform a full port reset.
|
|
AHCIPortCmdStop(port);
|
|
port->interrupt_status = port->interrupt_status; //Acknowledge all interrupt statuses.
|
|
|
|
if (!AHCIPortWait(port, tS + 1))
|
|
{//Perform a 'more intrusive' HBA<->Port comm reset (sec. 10.4.2 of spec).
|
|
port->sata_ctrl = AHCI_PxSCTLF_DET_INIT;
|
|
Sleep(1);
|
|
port->sata_ctrl = 0;
|
|
}
|
|
while (port->sata_status & 0xF != AHCI_PxSSTSF_DET_PRESENT);
|
|
port->sata_error = 0;
|
|
}
|
|
|
|
U0 AHCIPortIdentify(CBlkDev *bd)
|
|
{//Perform the ATA_IDENTIFY command and set bd.dev_id_record to result.
|
|
|
|
}
|
|
|
|
U0 AHCIInit()
|
|
{
|
|
CAHCIHba *hba;
|
|
CAHCIPort *port;
|
|
I64 i, bdf = PCIClassFind(PCIC_STORAGE << 16 | PCISC_AHCI << 8 + 1, 0); //0x010601, last byte = prog_if, AHCI 1.0 support.
|
|
|
|
if (bdf == -1)
|
|
{
|
|
"No AHCI controller found.\n";
|
|
return;
|
|
}
|
|
hba = dev.uncached_alias + PCIReadU32(bdf.u8[2], bdf.u8[1], bdf.u8[0], PCIR_BASE5) & ~0x1F; //Last 5 bits not part of addr.
|
|
|
|
|
|
Bts(&hba->ghc, AHCI_GHCf_HBA_RESET);
|
|
while (Bt(&hba->ghc, AHCI_GHCf_HBA_RESET));
|
|
|
|
Bts(&hba->ghc, AHCI_GHCf_AHCI_ENABLE);
|
|
} |