com32/src/ata-pio.c

52 lines
2.0 KiB
C

#include <ata-pio.h>
#include <video.h>
uint16_t ata_identify[256];
// 0: disk is initialized
// 1: no disks
// 2: no disk on requested interface
// 3: ATAPI
int ata_init(uint8_t bus, uint8_t drive) {
uint16_t io_base = ATA_IO_BASE - (bus ? ATA_SECONDARY_OFFSET : 0);
if(inb(io_base + ATA_STATUS_REGISTER) == 0xFF) return 1;
outb(io_base + ATA_DRIVE_REGISTER, drive ? 0xB0 : 0xA0);
for(int i = 2; i < 6; i++) outb(io_base + i, 0);
outb(io_base + ATA_STATUS_REGISTER, 0xEC);
uint8_t status;
do {
status = inb(io_base + ATA_STATUS_REGISTER);
if(!status) return 2;
} while((status & 0x80));
if(inb(io_base + 4) || inb(io_base + 5)) return 3;
do {
status = inb(io_base + ATA_STATUS_REGISTER);
if(status & 1) return inb(io_base + ATA_ERROR_REGISTER);
} while(!(status & 8));
uint16_t err = inb(io_base + ATA_ERROR_REGISTER);
if(err) return err;
for(int i = 0; i < 256; i++) ata_identify[i] = inw(io_base);
return 0;
}
uint16_t ata_setuprw(uint8_t bus, uint8_t drive, uint16_t sectors, uint16_t lba_high, uint32_t lba_low) {
uint16_t io_base = ATA_IO_BASE - (bus ? ATA_SECONDARY_OFFSET : 0);
outb(io_base + ATA_DRIVE_REGISTER, 0x40 | ((!!drive) << 4));
uint8_t mports[4] = {2, 3, 4, 5};
uint8_t dat[8] = {sectors >> 8, lba_low >> 24, lba_high >> 8, lba_high, sectors, lba_low, lba_low >> 8, lba_low >> 16};
for(int i = 0; i < 8; i++) outb(io_base + mports[i % 4], dat[i]);
return io_base;
}
int ata_read(uint8_t bus, uint8_t drive, uint16_t* buf, uint16_t sectors, uint16_t lba_high, uint32_t lba_low) {
uint16_t io_base = ata_setuprw(bus, drive, sectors, lba_high, lba_low);
outb(io_base + ATA_COMMAND_REGISTER, 0x24);
for(int i = 0; i < sectors * 256; i++) buf[i] = inw(io_base);
}
int ata_write(uint8_t bus, uint8_t drive, uint16_t* buf, uint16_t sectors, uint16_t lba_high, uint32_t lba_low) {
uint16_t io_base = ata_setuprw(bus, drive, sectors, lba_high, lba_low);
outb(io_base + ATA_COMMAND_REGISTER, 0x34);
for(int i = 0; i < sectors * 256; i++) outw(io_base, buf[i]);
outb(io_base + ATA_COMMAND_REGISTER, 0xE7);
}