#include "atapio.h" // Disk code // Primary ATA Bus: 0x1f0 to 0x1f7 // Device Control Register: 0x3f6 // Secondary ATA Bus: 0x170 to 0x177 // Device Control Register: 0x376 uint16_t identify_result[256]; uint32_t total_28_lbas = 0; uint8_t* rootDirEntries = 0x1000000; uint16_t* FAT1 = 0x1002000; uint16_t countReserved; uint8_t countFATs; uint16_t countRDEs; uint16_t sectorsPerFAT; void init_atapio() { countReserved = *(uint16_t*)0x7c0e; countFATs = *(uint8_t*)0x7c10; countRDEs = *(uint16_t*)0x7c11; sectorsPerFAT = *(uint16_t*)0x7c16; // Select Drive 0 on the Primary Bus outb(0x1f6, 0xa0); // Set sector count to 0 for IDENTIFY outb(0x1f2, 0); // Set LBAlo to 0 outb(0x1f3, 0); // Set LBAmid to 0 outb(0x1f4, 0); // Set LBAhi to 0 outb(0x1f5, 0); // Send IDENTIFY command outb(0x1f7, 0xec); uint8_t status = inb(0x1f7); if (status) { while ((status = inb(0x1f7)) & 0x80); if ( !(inb(0x1f4) || inb(0x1f5)) ) { while ( !(status & 8 || status & 1) ) status = inb(0x1f7); if (!(status & 1)) { for (int index=0; index<256; index++) identify_result[index] = inw(0x1f0); } } } total_28_lbas = *(uint32_t*)(identify_result+60); // We've initialised now, let's load the FAT and RootDirEntries. read_sectors(sectorsPerFAT * countFATs + 1, countRDEs / 16, rootDirEntries); read_sectors(1, sectorsPerFAT, FAT1); } void read_sector(uint32_t address, uint8_t* buffer) { outb(0x1f6, 0xe0 | ((address>>24)&0x0f)); // Read a single sector outb(0x1f2, 1); // Set LBAlo, LBAmid and LBAhi outb(0x1f3, address); outb(0x1f4, address>>8); outb(0x1f5, address>>16); // Send read command outb(0x1f7, 0x20); // Poll uint8_t status = inb(0x1f7); while ( (status & 0x80) && !(status & 8) ) status = inb(0x1f7); for (int index=0; index<256; index++) ((uint16_t*)buffer)[index] = inw(0x1f0); } void read_sectors(uint32_t address, int count, uint8_t* buffer) { for (int i=0; i