# Storage Drivers ModuOS supports multiple storage interfaces through a layered driver architecture. ## Storage Stack ``` ┌─────────────────────────────────────────┐ │ File Systems (FAT32/ISO9660) │ └────────────────┬────────────────────────┘ │ ┌────────────────▼────────────────────────┐ │ vDrive Layer (Virtual Drives) │ │ Unified interface for all │ └────┬───────────────────────┬────────────┘ │ │ ┌────▼──────────┐ ┌──────▼────────────┐ │ ATA/ATAPI │ │ AHCI/SATA │ │ (IDE/PATA) │ │ (Modern SATA) │ └────┬──────────┘ └──────┬────────────┘ │ │ └──────────┬───────────┘ │ ┌───────────────▼─────────────────────────┐ │ Hardware Controllers │ │ IDE Controller | AHCI Controller │ └─────────────────────────────────────────┘ ``` ## Virtual Drive (vDrive) Layer **File**: `src/drivers/Drive/vDrive.c` ### Purpose Provides a **unified interface** for all storage devices regardless of underlying controller type. ### vDrive Structure ```c #define VDRIVE_MAX_DRIVES 8 #define VDRIVE_MAX_PARTITIONS 4 typedef struct { uint8_t initialized; uint8_t type; // 0=None, 1=ATA, 2=AHCI uint8_t exists; uint8_t controller_index; // Index in ATA/AHCI driver char model[41]; uint64_t size_sectors; // Partition table struct { uint8_t exists; uint8_t type; // Partition type (0x0B=FAT32, etc.) uint32_t start_lba; uint32_t size_sectors; } partitions[VDRIVE_MAX_PARTITIONS]; } vdrive_t; ``` ### API ```c int vdrive_init(void); int vdrive_get_count(void); int vdrive_read_sector(int vdrive_id, uint32_t lba, void* buffer); int vdrive_write_sector(int vdrive_id, uint32_t lba, const void* buffer); ``` ## ATA/ATAPI Driver **File**: `src/drivers/Drive/ATA/ata.c` ### Overview **ATA** (AT Attachment) is the legacy IDE interface for hard drives. **ATAPI** (ATA Packet Interface) extends ATA for CD/DVD drives. ### Hardware Channels ``` Primary Channel (0x1F0): - Master (drive 0) - Slave (drive 1) Secondary Channel (0x170): - Master (drive 2) - Slave (drive 3) ``` ### ATA Registers ```c #define ATA_PRIMARY_BASE 0x1F0 #define ATA_PRIMARY_CTRL 0x3F6 #define ATA_SECONDARY_BASE 0x170 #define ATA_SECONDARY_CTRL 0x376 // Register offsets #define REG_DATA 0 // Data port #define REG_ERROR 1 // Error register #define REG_SECCNT 2 // Sector count #define REG_LBA_LO 3 // LBA low byte #define REG_LBA_MID 4 // LBA mid byte #define REG_LBA_HI 5 // LBA high byte #define REG_DRIVE 6 // Drive select #define REG_STATUS 7 // Status register #define REG_COMMAND 7 // Command register ``` ### ATA Commands ```c #define ATA_CMD_IDENTIFY 0xEC // Identify drive #define ATA_CMD_IDENTIFY_PACKET 0xA1 // Identify ATAPI #define ATA_CMD_READ_PIO 0x20 // Read sectors (PIO) #define ATA_CMD_READ_PIO_EXT 0x24 // Read sectors (LBA48) #define ATA_CMD_WRITE_PIO 0x30 // Write sectors #define ATA_CMD_CACHE_FLUSH 0xE7 // Flush cache #define ATA_CMD_PACKET 0xA0 // ATAPI packet command ``` ### Read Operation ```c int ata_read_sector_lba28(int drive_index, uint32_t lba, void* buffer) { // 1. Select drive and wait // 2. Send LBA and sector count // 3. Send READ command // 4. Wait for DRQ (data request) // 5. Read 256 words (512 bytes) uint16_t base = get_base_port(drive_index); uint8_t drive = get_drive_select(drive_index); // Wait for drive ready ata_wait_not_busy(base); // Select drive with LBA mode outb(base + REG_DRIVE, 0xE0 | (drive << 4) | ((lba >> 24) & 0x0F)); // Send sector count and LBA outb(base + REG_SECCNT, 1); outb(base + REG_LBA_LO, lba & 0xFF); outb(base + REG_LBA_MID, (lba >> 8) & 0xFF); outb(base + REG_LBA_HI, (lba >> 16) & 0xFF); // Send read command outb(base + REG_COMMAND, ATA_CMD_READ_PIO); // Wait for data ata_wait_drq(base); // Read data uint16_t *buf = (uint16_t*)buffer; for (int i = 0; i < 256; i++) { buf[i] = inw(base + REG_DATA); } return 0; } ``` ## AHCI/SATA Driver **File**: `src/drivers/Drive/SATA/AHCI.c` ### Overview **AHCI** (Advanced Host Controller Interface) is the modern standard for SATA controllers. **Features**: - Hot-plug support - Native Command Queuing (NCQ) - Port multiplier support - Higher performance than legacy ATA ### AHCI Architecture ``` ┌────────────────────────────────────┐ │ AHCI HBA (Host Adapter) │ │ ┌──────┬──────┬──────┬──────┐ │ │ │Port 0│Port 1│Port 2│Port 3│ │ │ └──┬───┴──┬───┴──┬───┴──┬───┘ │ └─────┼──────┼──────┼──────┼─────────┘ │ │ │ │ [SATA] [SATA] [SATA] [SATA] Drive Drive Drive Drive ``` ### AHCI Structures **HBA Memory Registers**: ```c typedef struct { uint32_t cap; // Host capabilities uint32_t ghc; // Global host control uint32_t is; // Interrupt status uint32_t pi; // Ports implemented uint32_t vs; // Version // ... more registers uint8_t reserved[0xA0-0x2C]; uint8_t vendor[0x100-0xA0]; ahci_port_t ports[32]; // Port registers } ahci_hba_mem_t; ``` **Port Registers**: ```c typedef struct { uint32_t clb; // Command list base address uint32_t clbu; // Command list base address upper uint32_t fb; // FIS base address uint32_t fbu; // FIS base address upper uint32_t is; // Interrupt status uint32_t ie; // Interrupt enable uint32_t cmd; // Command and status uint32_t reserved0; uint32_t tfd; // Task file data uint32_t sig; // Signature uint32_t ssts; // SATA status uint32_t sctl; // SATA control uint32_t serr; // SATA error uint32_t sact; // SATA active uint32_t ci; // Command issue // ... } ahci_port_t; ``` ### AHCI Initialization ```c int ahci_init(void) { // 1. Find AHCI controller via PCI pci_device_t *ahci_dev = pci_find_class(PCI_CLASS_STORAGE, 0x06); // 2. Enable bus mastering pci_enable_bus_mastering(ahci_dev); // 3. Map ABAR (AHCI Base Address Register) uint32_t abar = pci_read_bar(ahci_dev, 5); ahci_hba_mem_t *hba = (ahci_hba_mem_t*)abar; // 4. Enable AHCI mode hba->ghc |= AHCI_GHC_AHCI_ENABLE; // 5. Detect drives on each port uint32_t pi = hba->pi; for (int i = 0; i < 32; i++) { if (pi & (1 << i)) { ahci_probe_port(hba, i); } } } ``` ### Read Operation ```c int ahci_read_sectors(int port, uint64_t lba, uint32_t count, void* buffer) { // 1. Allocate command slot // 2. Build FIS (Frame Information Structure) // 3. Set up PRDT (Physical Region Descriptor Table) // 4. Issue command // 5. Wait for completion // 6. Copy data from buffer } ``` ## Partition Detection **File**: `src/drivers/Drive/vDrive.c` ### MBR Partition Table ```c typedef struct { uint8_t status; // 0x80=bootable uint8_t first_chs[3]; // CHS address (legacy) uint8_t type; // Partition type uint8_t last_chs[3]; // CHS address uint32_t start_lba; // Starting LBA uint32_t size_sectors; // Size in sectors } __attribute__((packed)) mbr_partition_t; ``` **Partition Types**: - `0x0B`: FAT32 - `0x0C`: FAT32 (LBA) - `0x07`: NTFS - `0x83`: Linux ext2/ext3/ext4 - `0x05`: Extended partition ### Partition Scanning ```c void vdrive_scan_partitions(int vdrive_id) { uint8_t mbr[512]; vdrive_read_sector(vdrive_id, 0, mbr); // Check MBR signature if (mbr[510] != 0x55 || mbr[511] != 0xAA) { return; // Invalid MBR } mbr_partition_t *partitions = (mbr_partition_t*)&mbr[446]; for (int i = 0; i < 4; i++) { if (partitions[i].type != 0) { // Valid partition vdrive[vdrive_id].partitions[i].exists = 1; vdrive[vdrive_id].partitions[i].type = partitions[i].type; vdrive[vdrive_id].partitions[i].start_lba = partitions[i].start_lba; vdrive[vdrive_id].partitions[i].size_sectors = partitions[i].size_sectors; } } } ``` ## Driver Performance ### PIO vs. DMA **PIO (Programmed I/O)**: - CPU reads/writes each word - Simple but slow - Used in ModuOS for ATA **DMA (Direct Memory Access)**: - Controller transfers data directly to RAM - CPU-free, higher performance - Planned for future AHCI implementation ### Typical Performance | Interface | Mode | Speed | |-----------|------|-------| | ATA PIO | PIO Mode 4 | ~16 MB/s | | ATA DMA | UDMA 133 | ~133 MB/s | | SATA I | AHCI | ~150 MB/s | | SATA II | AHCI | ~300 MB/s | | SATA III | AHCI | ~600 MB/s | ## Next Steps - [File Systems](File-Systems.md) - Using storage - [PCI Subsystem](PCI-Subsystem.md) - Finding controllers - [Device Drivers](Device-Drivers.md) - Driver overview