mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
41 lines
3.0 KiB
Markdown
41 lines
3.0 KiB
Markdown
# AHCI Storage Driver
|
|
|
|
BoredOS implements an Advanced Host Controller Interface (AHCI) driver to interface with Serial ATA (SATA) mass storage devices. The driver is located in `src/dev/ahci.c` and allows the OS to read and write sectors directly to physical hard drives or solid-state drives using DMA (Direct Memory Access).
|
|
|
|
## 1. Discovery and Initialization
|
|
|
|
The AHCI initialization process (`ahci_init`) starts by querying the PCI subsystem:
|
|
1. It searches for a PCI device with Class `0x01` (Mass Storage) and Subclass `0x06` (SATA).
|
|
2. It calls `pci_enable_bus_mastering` and `pci_enable_mmio` to ensure the controller can perform DMA and its registers are accessible.
|
|
3. It retrieves the **ABAR** (AHCI Base Address Register) from PCI BAR5.
|
|
4. The ABAR points to the `HBA_MEM` structure (Host Bus Adapter Memory Registers). The kernel iterates through the `pi` (Ports Implemented) bitmask to find active SATA ports.
|
|
|
|
## 2. Port Configuration
|
|
|
|
For every active SATA port found, the driver must allocate memory structures that the hardware will use to process commands:
|
|
1. **Command List Base (`clb`)**: A 1KB memory region holding 32 Command Headers.
|
|
2. **FIS Base (`fb`)**: A 256-byte memory region where the HBA writes incoming Frame Information Structures (FIS) from the drive.
|
|
3. **Command Tables (`ctba`)**: A larger memory region allocated for each Command Header, containing the actual SATA command bytes and the scatter/gather lists (PRDT).
|
|
|
|
*Note:* All AHCI data structures must be allocated in physically contiguous memory and properly aligned (e.g., 1KB or 256-byte boundaries) because the HBA reads them directly from physical RAM via DMA.
|
|
|
|
## 3. Physical Region Descriptor Tables (PRDT)
|
|
|
|
When reading or writing data, BoredOS must tell the AHCI controller where in RAM the data should be stored or fetched. This is done using PRDT entries.
|
|
|
|
Each `HBA_PRDT_ENTRY` specifies:
|
|
- A physical Data Base Address (`dba`).
|
|
- A Byte Count (`dbc`), limited to a maximum of 4MB per entry.
|
|
|
|
If a read/write request spans multiple fragmented pages or exceeds 4MB, the driver constructs multiple PRDT entries within the Command Table to form a scatter/gather list. The AHCI hardware seamlessly processes these entries as a single contiguous disk operation.
|
|
|
|
## 4. Reading and Writing Sectors
|
|
|
|
To execute a command (e.g., `ahci_read_sectors` or `ahci_write_sectors`):
|
|
1. The driver finds a free slot in the Command List.
|
|
2. It populates the Command Header, setting the `cfl` (Command FIS Length) and `w` (Write) bit.
|
|
3. It builds a Host-to-Device Register FIS (`FIS_REG_H2D`) in the Command Table, issuing the `ATA_CMD_READ_DMA_EX` or `ATA_CMD_WRITE_DMA_EX` command and specifying the starting LBA (Logical Block Address) and sector count.
|
|
4. It sets up the PRDT entries pointing to the physical memory of the provided buffer.
|
|
5. It sets the corresponding bit in the Port's Command Issue register (`ci`).
|
|
6. The driver then polls the `ci` register (or waits for an interrupt) until the bit clears, indicating the hardware has completed the DMA transfer.
|