* more re-work
[mascara-docs.git] / i386 / junos / MIT / course / src / src.lab / fs / ide.c
blob945cfb031dfb819d0f9e901684aa738e9d50529c
1 /*
2 * Minimal PIO-based (non-interrupt-driven) IDE driver code.
3 * For information about what all this IDE/ATA magic means,
4 * see the materials available on the class references page.
5 */
7 #include "fs.h"
8 #include <inc/x86.h>
10 #define IDE_BSY 0x80
11 #define IDE_DRDY 0x40
12 #define IDE_DF 0x20
13 #define IDE_ERR 0x01
15 static int diskno = 1;
17 static int
18 ide_wait_ready(bool check_error)
20 int r;
22 while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
23 /* do nothing */;
25 if (check_error && (r & (IDE_DF|IDE_ERR)) != 0)
26 return -1;
27 return 0;
30 bool
31 ide_probe_disk1(void)
33 int r, x;
35 // wait for Device 0 to be ready
36 ide_wait_ready(0);
38 // switch to Device 1
39 outb(0x1F6, 0xE0 | (1<<4));
41 // check for Device 1 to be ready for a while
42 for (x = 0;
43 x < 1000 && ((r = inb(0x1F7)) & (IDE_BSY|IDE_DF|IDE_ERR)) != 0;
44 x++)
45 /* do nothing */;
47 // switch back to Device 0
48 outb(0x1F6, 0xE0 | (0<<4));
50 cprintf("Device 1 presence: %d\n", (x < 1000));
51 return (x < 1000);
54 void
55 ide_set_disk(int d)
57 if (d != 0 && d != 1)
58 panic("bad disk number");
59 diskno = d;
62 int
63 ide_read(uint32_t secno, void *dst, size_t nsecs)
65 int r;
67 assert(nsecs <= 256);
69 ide_wait_ready(0);
71 outb(0x1F2, nsecs);
72 outb(0x1F3, secno & 0xFF);
73 outb(0x1F4, (secno >> 8) & 0xFF);
74 outb(0x1F5, (secno >> 16) & 0xFF);
75 outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
76 outb(0x1F7, 0x20); // CMD 0x20 means read sector
78 for (; nsecs > 0; nsecs--, dst += SECTSIZE) {
79 if ((r = ide_wait_ready(1)) < 0)
80 return r;
81 insl(0x1F0, dst, SECTSIZE/4);
84 return 0;
87 int
88 ide_write(uint32_t secno, const void *src, size_t nsecs)
90 int r;
92 assert(nsecs <= 256);
94 ide_wait_ready(0);
96 outb(0x1F2, nsecs);
97 outb(0x1F3, secno & 0xFF);
98 outb(0x1F4, (secno >> 8) & 0xFF);
99 outb(0x1F5, (secno >> 16) & 0xFF);
100 outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
101 outb(0x1F7, 0x30); // CMD 0x30 means write sector
103 for (; nsecs > 0; nsecs--, src += SECTSIZE) {
104 if ((r = ide_wait_ready(1)) < 0)
105 return r;
106 outsl(0x1F0, src, SECTSIZE/4);
109 return 0;