* same with xv6
[mascara-docs.git] / i386 / ucla / src / lab5 / fs / ide.c
blobf84791150ef2bd41ea826fe5beed6885a7b65f59
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 <inc/lib.h>
8 #include "ide.h"
9 #include <inc/x86.h>
11 #define IDE_BSY 0x80
12 #define IDE_DRDY 0x40
13 #define IDE_DF 0x20
14 #define IDE_ERR 0x01
16 static int diskno = 1;
18 static int
19 ide_wait_ready(bool check_error)
21 int r;
23 while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
24 /* do nothing */;
26 if (check_error && (r & (IDE_DF|IDE_ERR)) != 0)
27 return -E_IO;
28 return 0;
31 bool
32 ide_probe_disk1(void)
34 int r, x;
36 // wait for Device 0 to be ready
37 ide_wait_ready(0);
39 // switch to Device 1
40 outb(0x1F6, 0xE0 | (1<<4));
42 // check for Device 1 to be ready for a while
43 for (x = 0;
44 x < 1000 && ((r = inb(0x1F7)) & (IDE_BSY|IDE_DF|IDE_ERR)) != 0;
45 x++)
46 /* do nothing */;
48 // switch back to Device 0
49 outb(0x1F6, 0xE0 | (0<<4));
51 cprintf("Device 1 presence: %d\n", (x < 1000));
52 return (x < 1000);
55 void
56 ide_set_disk(int d)
58 if (d != 0 && d != 1)
59 panic("bad disk number");
60 diskno = d;
63 int
64 ide_read(uint32_t secno, void *dst_voidp, size_t nsecs)
66 char *dst = (char *) dst_voidp;
67 int r;
69 assert(nsecs <= 256);
71 ide_wait_ready(0);
73 outb(0x1F2, nsecs);
74 outb(0x1F3, secno & 0xFF);
75 outb(0x1F4, (secno >> 8) & 0xFF);
76 outb(0x1F5, (secno >> 16) & 0xFF);
77 outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
78 outb(0x1F7, 0x20); // CMD 0x20 means read sector
80 for (; nsecs > 0; nsecs--, dst += SECTSIZE) {
81 if ((r = ide_wait_ready(1)) < 0)
82 return r;
83 insl(0x1F0, dst, SECTSIZE/4);
86 return 0;
89 int
90 ide_write(uint32_t secno, const void *src_voidp, size_t nsecs)
92 const char *src = (const char *) src_voidp;
93 int r;
95 assert(nsecs <= 256);
97 ide_wait_ready(0);
99 outb(0x1F2, nsecs);
100 outb(0x1F3, secno & 0xFF);
101 outb(0x1F4, (secno >> 8) & 0xFF);
102 outb(0x1F5, (secno >> 16) & 0xFF);
103 outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
104 outb(0x1F7, 0x30); // CMD 0x30 means write sector
106 for (; nsecs > 0; nsecs--, src += SECTSIZE) {
107 if ((r = ide_wait_ready(1)) < 0)
108 return r;
109 outsl(0x1F0, src, SECTSIZE/4);
112 return 0;