-
Notifications
You must be signed in to change notification settings - Fork 0
Storage Drivers
NtinosTheGamer2324 edited this page Dec 11, 2025
·
1 revision
ModuOS supports multiple storage interfaces through a layered driver architecture.
┌─────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────┘
File: src/drivers/Drive/vDrive.c
Provides a unified interface for all storage devices regardless of underlying controller type.
#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;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);File: src/drivers/Drive/ATA/ata.c
ATA (AT Attachment) is the legacy IDE interface for hard drives. ATAPI (ATA Packet Interface) extends ATA for CD/DVD drives.
Primary Channel (0x1F0):
- Master (drive 0)
- Slave (drive 1)
Secondary Channel (0x170):
- Master (drive 2)
- Slave (drive 3)
#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#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 commandint 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;
}File: src/drivers/Drive/SATA/AHCI.c
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 HBA (Host Adapter) │
│ ┌──────┬──────┬──────┬──────┐ │
│ │Port 0│Port 1│Port 2│Port 3│ │
│ └──┬───┴──┬───┴──┬───┴──┬───┘ │
└─────┼──────┼──────┼──────┼─────────┘
│ │ │ │
[SATA] [SATA] [SATA] [SATA]
Drive Drive Drive Drive
HBA Memory Registers:
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:
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;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);
}
}
}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
}File: src/drivers/Drive/vDrive.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
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;
}
}
}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
| 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 |
- File Systems - Using storage
- PCI Subsystem - Finding controllers
- Device Drivers - Driver overview