diff options
author | rtm <rtm> | 2006-06-16 20:29:25 +0000 |
---|---|---|
committer | rtm <rtm> | 2006-06-16 20:29:25 +0000 |
commit | ae6e8aa730fa410118c0532938d4a9e62b08bbe8 (patch) | |
tree | 8341e238d7b725a2aeec1476bc0f46c46b5c90e8 /ide.c | |
parent | be0a7eacdab4443199ed0ed4379a84edc7c98fd6 (diff) | |
download | xv6-labs-ae6e8aa730fa410118c0532938d4a9e62b08bbe8.tar.gz xv6-labs-ae6e8aa730fa410118c0532938d4a9e62b08bbe8.tar.bz2 xv6-labs-ae6e8aa730fa410118c0532938d4a9e62b08bbe8.zip |
checkpoint
Diffstat (limited to 'ide.c')
-rw-r--r-- | ide.c | 117 |
1 files changed, 117 insertions, 0 deletions
@@ -0,0 +1,117 @@ +/* + * Minimal PIO-based (non-interrupt-driven) IDE driver code. + * For information about what all this IDE/ATA magic means, + * see the materials available on the class references page. + */ + +#include "types.h" +#include "param.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "x86.h" + +#define IDE_BSY 0x80 +#define IDE_DRDY 0x40 +#define IDE_DF 0x20 +#define IDE_ERR 0x01 + +static int diskno = 0; + +static int +ide_wait_ready(int check_error) +{ + int r; + + while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) + /* do nothing */; + + if (check_error && (r & (IDE_DF|IDE_ERR)) != 0) + return -1; + return 0; +} + +int +ide_probe_disk1(void) +{ + int r, x; + + // wait for Device 0 to be ready + ide_wait_ready(0); + + // switch to Device 1 + outb(0x1F6, 0xE0 | (1<<4)); + + // check for Device 1 to be ready for a while + for (x = 0; x < 1000 && (r = inb(0x1F7)) == 0; x++) + /* do nothing */; + + // switch back to Device 0 + outb(0x1F6, 0xE0 | (0<<4)); + + cprintf("Device 1 presence: %d\n", (x < 1000)); + return (x < 1000); +} + +void +ide_set_disk(int d) +{ + if (d != 0 && d != 1) + panic("bad disk number"); + diskno = d; +} + +int +ide_read(uint32_t secno, void *dst, unsigned nsecs) +{ + int r; + + if(nsecs > 256) + panic("ide_read"); + + ide_wait_ready(0); + + outb(0x3f6, 0); + outb(0x1F2, nsecs); + outb(0x1F3, secno & 0xFF); + outb(0x1F4, (secno >> 8) & 0xFF); + outb(0x1F5, (secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); + outb(0x1F7, 0x20); // CMD 0x20 means read sector + + sleep(0); + + for (; nsecs > 0; nsecs--, dst += 512) { + if ((r = ide_wait_ready(1)) < 0) + return r; + insl(0x1F0, dst, 512/4); + } + + return 0; +} + +int +ide_write(uint32_t secno, const void *src, unsigned nsecs) +{ + int r; + + if(nsecs > 256) + panic("ide_write"); + + ide_wait_ready(0); + + outb(0x1F2, nsecs); + outb(0x1F3, secno & 0xFF); + outb(0x1F4, (secno >> 8) & 0xFF); + outb(0x1F5, (secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); + outb(0x1F7, 0x30); // CMD 0x30 means write sector + + for (; nsecs > 0; nsecs--, src += 512) { + if ((r = ide_wait_ready(1)) < 0) + return r; + outsl(0x1F0, src, 512/4); + } + + return 0; +} |