Code: Select all
s32int ata_read(struct ata_drive *d, u32int segment, u8int segnum, void *buf) {
u8int stat;
segment &= 0x0fffffff; // 28-bit LBA
outportb(d->io_base + ATA_PORT_SECTORS, segnum);
outportb(d->io_base + ATA_PORT_ADDR1, (u8int) segment);
outportb(d->io_base + ATA_PORT_ADDR2, (u8int) (segment >> 8));
outportb(d->io_base + ATA_PORT_ADDR3, (u8int) (segment >> 16));
outportb(d->io_base + ATA_PORT_DSELECT, 0xe0 | segment >> 24);
outportb(d->io_base + ATA_PORT_CMD, 0x20);
inportb(d->io_base + ATA_PORT_CMD); // 400 ns delay
inportb(d->io_ctrl + ATA_PORT_CMD);
inportb(d->io_ctrl + ATA_PORT_CMD);
inportb(d->io_ctrl + ATA_PORT_CMD);
u16int i = 0;
u8int j = 0;
u16int k = 0;
u16int *b = (u16int *) buf;
while (j < segnum) {
/* wait = 0; */
/* while (!wait); // spin on the wait lock */
while ((stat = inportb(d->io_ctrl))) {
if (stat & 0x80) {
continue;
}
if (stat & 0x21) {
printf("error: %x", stat);
return 1;
}
if (stat & 0x08) {
break;
}
}
for (i = 0; i < 256; i++,k++) {
b[k] = inportw(d->io_base + ATA_PORT_DATA);
}
}
return 0;
}
Code: Select all
#define ATA_PORT_DATA 0x0
#define ATA_PORT_ERRINF 0x1
#define ATA_PORT_SECTORS 0x2
#define ATA_PORT_ADDR1 0x3
#define ATA_PORT_ADDR2 0x4
#define ATA_PORT_ADDR3 0x5
#define ATA_PORT_DSELECT 0x6
#define ATA_PORT_CMD 0x7
Code: Select all
void ata_init(struct ata_drive **d) {
/* if (inportb(0x1f7) == 0xff) { // floating bus; no drives */
/* *d = 0; */
/* return; */
/* } */
*d = kmalloc(sizeof(struct ata_drive));
struct ata_drive *da = *d;
da[0].bus = 0;
da[0].port = 1;
da[0].func = 1;
da[0].io_base = 0x1f0;
da[0].io_ctrl = 0x3f6;
da[0].irq = IRQ14;
register_interrupt_handler(IRQ14, ata_interrupt_handler);
return;
}