#include #include #include "atapi.h" #include "io.h" static struct atapi_drive drives[4] = { 0 }; static void select_drive(uint16_t bus, uint8_t slave) { outb(ATA_REG_DRIVE(bus), slave); } static void busy_wait(uint16_t drive) { int res = 0; while (res & BSY) res = inb(ATA_REG_STATUS(drive)); } static void wait_device_selection(uint16_t drive) { for (int i = 0; i < 4; ++i) inb(drive); } static uint8_t is_atapi_driver(uint16_t bus, uint8_t slave) { static uint8_t atapi_sig[] = { ATAPI_SIG_SC, ATAPI_SIG_LBA_LO, ATAPI_SIG_LBA_MI, ATAPI_SIG_LBA_HI }; uint8_t sig[4]; sig[0] = inb(ATA_REG_SECTOR_COUNT(bus)); sig[1] = inb(ATA_REG_LBA_LO(bus)); sig[2] = inb(ATA_REG_LBA_MI(bus)); sig[3] = inb(ATA_REG_LBA_HI(bus)); if (!memcmp(sig, atapi_sig, 4)) { struct atapi_drive d = { bus, slave }; if (bus == PRIMARY_REG) { if (slave) drives[1] = d; else drives[0] = d; } else { if (slave) drives[3] = d; else drives[2] = d; } return 1; } return 0; } void discover_atapi_drive(void) { // primary_reg outb(PRIMARY_DCR, SRST); outb(PRIMARY_DCR, INTERRUPT_DISABLE); select_drive(PRIMARY_REG, ATA_PORT_MASTER); wait_device_selection(PRIMARY_REG); is_atapi_driver(PRIMARY_REG, ATA_PORT_MASTER); // secondary_reg outb(SECONDARY_DCR, SRST); outb(SECONDARY_DCR, INTERRUPT_DISABLE); }