oxytoxin

unix-like kernel
git clone git://git.evenfri.pw/oxytoxin.git
Log | Files | Refs | README | LICENSE

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 }