miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
Loading...
Searching...
No Matches
ata.h File Reference
#include <miniOS/types.h>
Include dependency graph for ata.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  __attribute__

Macros

#define ATA_PRIMARY_BASE   0x1F0
#define ATA_PRIMARY_CTRL   0x3F6
#define ATA_SECONDARY_BASE   0x170
#define ATA_SECONDARY_CTRL   0x376
#define ATA_PRIMARY_IRQ   14
#define ATA_SECONDARY_IRQ   15
#define ATA_MASTER   0xA0
#define ATA_SLAVE   0xB0
#define ATA_REG_DATA   0x00
#define ATA_REG_ERROR   0x01 /* read */
#define ATA_REG_FEATURES   0x01 /* write */
#define ATA_REG_SECCOUNT0   0x02
#define ATA_REG_LBA0   0x03
#define ATA_REG_LBA1   0x04
#define ATA_REG_LBA2   0x05
#define ATA_REG_HDDEVSEL   0x06
#define ATA_REG_STATUS   0x07 /* read */
#define ATA_REG_COMMAND   0x07 /* write */
#define ATA_SR_BSY   0x80
#define ATA_SR_DRDY   0x40
#define ATA_SR_DRQ   0x08
#define ATA_SR_ERR   0x01
#define BMR_CMD   0x00 /* bit 0 = start/stop, bit 3 = dir (0=read) */
#define BMR_STATUS   0x02 /* bit 0 = active, bit 1 = error, bit 2 = IRQ */
#define BMR_PRDT   0x04 /* 32-bit physical address of PRD table */
#define SECTOR_SIZE   512 /* bytes per ATA sector */
#define MAX_SECTORS_PER_RW   8 /* 8 x 512 B = 4 KiB bounce buffer */
#define ATA_CMD_READ_DMA_EXT   0x25 /* READ DMA EXT (48-bit LBA) */
#define ATA_CMD_WRITE_DMA_EXT   0x35 /* WRITE DMA EXT (48-bit LBA) */
#define ATA_CMD_CACHE_FLUSH_EXT   0xEA /* CACHE FLUSH EXT — flushes write-back cache */
#define PRD_LAST_ENTRY   0x8000 /* bit 15 = last entry in PRD table */
#define BMR_ACTIVE_BIT   0x01 /* DMA transfer in progress */
#define BMR_ERROR_BIT   0x02 /* DMA error occurred */
#define BMR_IRQ_BIT   0x04 /* IRQ fired (DMA complete) */
#define BMR_START_BIT   0x01 /* BMR_CMD bit 0: start DMA */

Functions

int ata_init (void)
int ata_read_sectors (uint64_t lba, uint16_t count, void *buf)
int ata_write_sectors (uint64_t lba, uint16_t count, const void *buf)
int ata_flush (void)

Macro Definition Documentation

◆ ATA_CMD_CACHE_FLUSH_EXT

#define ATA_CMD_CACHE_FLUSH_EXT   0xEA /* CACHE FLUSH EXT — flushes write-back cache */

◆ ATA_CMD_READ_DMA_EXT

#define ATA_CMD_READ_DMA_EXT   0x25 /* READ DMA EXT (48-bit LBA) */

◆ ATA_CMD_WRITE_DMA_EXT

#define ATA_CMD_WRITE_DMA_EXT   0x35 /* WRITE DMA EXT (48-bit LBA) */

◆ ATA_MASTER

#define ATA_MASTER   0xA0

◆ ATA_PRIMARY_BASE

#define ATA_PRIMARY_BASE   0x1F0

◆ ATA_PRIMARY_CTRL

#define ATA_PRIMARY_CTRL   0x3F6

◆ ATA_PRIMARY_IRQ

#define ATA_PRIMARY_IRQ   14

◆ ATA_REG_COMMAND

#define ATA_REG_COMMAND   0x07 /* write */

◆ ATA_REG_DATA

#define ATA_REG_DATA   0x00

◆ ATA_REG_ERROR

#define ATA_REG_ERROR   0x01 /* read */

◆ ATA_REG_FEATURES

#define ATA_REG_FEATURES   0x01 /* write */

◆ ATA_REG_HDDEVSEL

#define ATA_REG_HDDEVSEL   0x06

◆ ATA_REG_LBA0

#define ATA_REG_LBA0   0x03

◆ ATA_REG_LBA1

#define ATA_REG_LBA1   0x04

◆ ATA_REG_LBA2

#define ATA_REG_LBA2   0x05

◆ ATA_REG_SECCOUNT0

#define ATA_REG_SECCOUNT0   0x02

◆ ATA_REG_STATUS

#define ATA_REG_STATUS   0x07 /* read */

◆ ATA_SECONDARY_BASE

#define ATA_SECONDARY_BASE   0x170

◆ ATA_SECONDARY_CTRL

#define ATA_SECONDARY_CTRL   0x376

◆ ATA_SECONDARY_IRQ

#define ATA_SECONDARY_IRQ   15

◆ ATA_SLAVE

#define ATA_SLAVE   0xB0

◆ ATA_SR_BSY

#define ATA_SR_BSY   0x80

◆ ATA_SR_DRDY

#define ATA_SR_DRDY   0x40

◆ ATA_SR_DRQ

#define ATA_SR_DRQ   0x08

◆ ATA_SR_ERR

#define ATA_SR_ERR   0x01

◆ BMR_ACTIVE_BIT

#define BMR_ACTIVE_BIT   0x01 /* DMA transfer in progress */

◆ BMR_CMD

#define BMR_CMD   0x00 /* bit 0 = start/stop, bit 3 = dir (0=read) */

◆ BMR_ERROR_BIT

#define BMR_ERROR_BIT   0x02 /* DMA error occurred */

◆ BMR_IRQ_BIT

#define BMR_IRQ_BIT   0x04 /* IRQ fired (DMA complete) */

◆ BMR_PRDT

#define BMR_PRDT   0x04 /* 32-bit physical address of PRD table */

◆ BMR_START_BIT

#define BMR_START_BIT   0x01 /* BMR_CMD bit 0: start DMA */

◆ BMR_STATUS

#define BMR_STATUS   0x02 /* bit 0 = active, bit 1 = error, bit 2 = IRQ */

◆ MAX_SECTORS_PER_RW

#define MAX_SECTORS_PER_RW   8 /* 8 x 512 B = 4 KiB bounce buffer */

◆ PRD_LAST_ENTRY

#define PRD_LAST_ENTRY   0x8000 /* bit 15 = last entry in PRD table */

◆ SECTOR_SIZE

#define SECTOR_SIZE   512 /* bytes per ATA sector */

Function Documentation

◆ ata_flush()

int ata_flush ( void )

ata_flush() - Flush the ATA drive's write-back cache to stable storage.

Issues CACHE FLUSH EXT command (0xEA) to the primary master ATA drive. Waits for BSY=0 after issuing the command. Required after write sequences to guarantee persistence across power-off.

Returns
: 0 on success, -1 on timeout or drive error.

ata_flush() - Issue CACHE FLUSH EXT to force write-back cache to disk.

Waits for drive ready, issues CACHE FLUSH EXT (0xEA), then waits for BSY=0. Must be called after all ext2 write operations to guarantee EXT2W-07 (data survives power-off / QEMU restart).

Returns
: 0 on success, -1 on timeout.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ata_init()

int ata_init ( void )

ata_init() - Initialise the ATA driver via PCI Bus Mastering DMA.

Scans PCI configuration space (bus 0, devices 0-31, function 0) for a PCI IDE controller (class 0x01, subclass 0x01). Reads the Bus Master Register (BMR) base from BAR4. Allocates a 4 KiB DMA bounce buffer at the fixed virtual address 0xFFFF830000000000 (PML4 slot 262). Sets up a single Physical Region Descriptor (PRD) entry pointing to the bounce buffer's physical address.

Returns
: 0 on success, -1 if no PCI IDE controller was found.

ata_init() - Locate IDE controller in pci_devices[] and set up DMA infrastructure.

Searches pci_devices[] (populated by pci_init()) for class=0x01 subclass=0x01 (IDE controller). Reads BAR4 for Bus Master Register base port (g_bmr_base). Enables PCI bus mastering via command register bit 2. Maps the DMA bounce buffer: vmm_map_page(0xFFFF830000000000, pmm_alloc_frame(), PAGE_PRESENT|PAGE_WRITE). Stores bounce buffer kernel VA in g_dma_buf and physical address in g_dma_phys. Sets up g_prd[0] with phys_addr=g_dma_phys, byte_count=4096, flags=0x8000 (last entry).

Must be called after pci_init().

Returns
: 0 on success, -1 if no PCI IDE controller found in pci_devices[].
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ata_read_sectors()

int ata_read_sectors ( uint64_t lba,
uint16_t count,
void * buf )

ata_read_sectors() - Read sectors from the primary master ATA drive via DMA. @lba: 48-bit Logical Block Address of the first sector to read. @count: Number of 512-byte sectors to read. Maximum 8 (4 KiB bounce buffer limit). @buf: Destination buffer. Must be at least @count * 512 bytes.

Programs the ATA controller with 48-bit LBA addressing, starts a Bus Mastering DMA read into the bounce buffer at 0xFFFF830000000000, waits for the DMA IRQ (polling BMR_STATUS bit 2), then copies from bounce buffer to @buf.

Context: Polling-based (no interrupts used for synchronisation in this implementation). Not ISR-safe.

Returns
: 0 on success, -1 on DMA error (BMR status error bit set) or ATA drive error (status register ERR bit set).

ata_read_sectors() - Read sectors from primary master ATA drive via Bus Mastering DMA. @lba: 48-bit LBA of the first sector. @count: Number of 512-byte sectors (1-8; 4 KiB bounce buffer limits to 8 max). @buf: Destination buffer (at least @count * 512 bytes).

Programs the primary ATA controller (base port 0x1F0): selects master drive (0xA0), writes high and low bytes of sector count and 48-bit LBA to LBA registers, issues READ DMA EXT command (0x25). Writes g_prd physical address to BMR_PRDT, clears BMR_STATUS interrupt/error bits, and sets BMR_CMD bit 0 to start DMA. Polls BMR_STATUS until bit 2 (IRQ) is set or bit 1 (error) is set. Stops DMA via BMR_CMD. Copies from g_dma_buf to @buf.

Context: Polling-based; not ISR-safe.

Returns
: 0 on success, -1 on DMA or ATA drive error.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ata_write_sectors()

int ata_write_sectors ( uint64_t lba,
uint16_t count,
const void * buf )

ata_write_sectors() - Write sectors to the primary master ATA drive via DMA. @lba: 48-bit Logical Block Address of the first sector to write. @count: Number of 512-byte sectors to write. Maximum 8 (4 KiB bounce buffer limit). @buf: Source buffer. Must be at least @count * 512 bytes.

Copies @buf into the DMA bounce buffer, programs the ATA controller with 48-bit LBA, starts a Bus Mastering DMA write (BMR_CMD direction bit 3 = 1), issues WRITE DMA EXT (0x35), waits for DMA completion, then stops DMA.

Context: Polling-based. Not ISR-safe.

Returns
: 0 on success, -1 on DMA or ATA error.

ata_write_sectors() - Write sectors to the primary master ATA drive via DMA. @lba: 48-bit LBA of the first sector. @count: Number of 512-byte sectors (1-8; 4 KiB bounce buffer limits to 8 max). @buf: Source buffer (at least @count * 512 bytes).

Copies @buf into the DMA bounce buffer (write direction: caller → g_dma_buf). Programs the ATA controller with 48-bit LBA, sets BMR direction bit 3=1 (write), issues WRITE DMA EXT (0x35). Polls BMR_STATUS until completion.

Context: Polling-based; not ISR-safe.

Returns
: 0 on success, -1 on DMA or ATA drive error.
Here is the call graph for this function:
Here is the caller graph for this function: