ata.c (1909B)
1 #include "oxytoxin.h" 2 3 extern void ata_entry(void); 4 5 static void ata_io_wait(void) { 6 inb(0x1F7); 7 inb(0x1F7); 8 inb(0x1F7); 9 inb(0x1F7); 10 } 11 12 static int ata_wait_drq(void) { 13 uint8_t status; 14 15 while (1) { 16 status = inb(0x1F7); 17 if (status & ATA_DRIVE_ERR) return -1; 18 if (!(status & ATA_DRIVE_BUSY) && (status & ATA_DRIVE_REQ_READY)) return 0; 19 } 20 } 21 22 void ata_read_sectors(void *trg, unsigned int lba, unsigned char size) { 23 uint16_t *target; 24 int count; 25 int i; 26 int j; 27 28 outb(0x1F6, 0xE0 | ((lba >> 24) & 0x0F)); 29 outb(0x1F2, size); 30 outb(0x1F3, (unsigned char) lba); 31 outb(0x1F4, (unsigned char) (lba >> 8)); 32 outb(0x1F5, (unsigned char) (lba >> 16)); 33 outb(0x3F6, 0x02); 34 outb(0x1F7, ATA_CMD_READ); 35 36 ata_io_wait(); 37 38 target = (uint16_t *) trg; 39 count = (size == 0) ? 256 : size; 40 41 for (i = 0; i < count; i++) { 42 if (ata_wait_drq() != 0) return; /* read error */ 43 44 for (j = 0; j < 256; j++) { 45 target[j] = inw(0x1F0); 46 } 47 target += 256; 48 } 49 } 50 51 void ata_write_sectors(const void *src, unsigned int lba, unsigned char size) { 52 const uint16_t *source; 53 int count; 54 int i; 55 int j; 56 57 outb(0x1F6, 0xE0 | ((lba >> 24) & 0x0F)); 58 outb(0x1F2, size); 59 outb(0x1F3, (unsigned char) lba); 60 outb(0x1F4, (unsigned char) (lba >> 8)); 61 outb(0x1F5, (unsigned char) (lba >> 16)); 62 outb(0x3F6, 0x02); 63 outb(0x1F7, ATA_CMD_WRITE); 64 65 ata_io_wait(); 66 67 source = (const uint16_t *) src; 68 count = (size == 0) ? 256 : size; 69 70 for (i = 0; i < count; i++) { 71 if (ata_wait_drq() != 0) return; /* write error */ 72 73 for (j = 0; j < 256; j++) { 74 outw(0x1F0, source[j]); 75 } 76 source += 256; 77 } 78 79 outb(0x1F7, ATA_CMD_CACHE_FLUSH); 80 ata_io_wait(); 81 } 82 83 void ata_handler(void) { 84 inb(0x1F7); /* reset IRQ */ 85 outb(0x20, 0x20); /* eoi for master pic1 */ 86 outb(0xA0, 0x20); /* eoi for slave pic2 */ 87 } 88 89 void ata_init(void) { 90 idt_register(0x2E, ata_entry); 91 }