This source file includes following definitions.
- idewait
- ideinit
- idestart
- ideintr
- iderw
1
2
3 #include "types.h"
4 #include "defs.h"
5 #include "param.h"
6 #include "memlayout.h"
7 #include "mmu.h"
8 #include "proc.h"
9 #include "x86.h"
10 #include "traps.h"
11 #include "spinlock.h"
12 #include "sleeplock.h"
13 #include "fs.h"
14 #include "buf.h"
15
16 #define SECTOR_SIZE 512
17 #define IDE_BSY 0x80
18 #define IDE_DRDY 0x40
19 #define IDE_DF 0x20
20 #define IDE_ERR 0x01
21
22 #define IDE_CMD_READ 0x20
23 #define IDE_CMD_WRITE 0x30
24 #define IDE_CMD_RDMUL 0xc4
25 #define IDE_CMD_WRMUL 0xc5
26
27
28
29
30
31 static struct spinlock idelock;
32 static struct buf *idequeue;
33
34 static int havedisk1;
35 static void idestart(struct buf*);
36
37
38 static int
39 idewait(int checkerr)
40 {
41 int r;
42
43 while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
44 ;
45 if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0)
46 return -1;
47 return 0;
48 }
49
50 void
51 ideinit(void)
52 {
53 int i;
54
55 initlock(&idelock, "ide");
56 ioapicenable(IRQ_IDE, ncpu - 1);
57 idewait(0);
58
59
60 outb(0x1f6, 0xe0 | (1<<4));
61 for(i=0; i<1000; i++){
62 if(inb(0x1f7) != 0){
63 havedisk1 = 1;
64 break;
65 }
66 }
67
68
69 outb(0x1f6, 0xe0 | (0<<4));
70 }
71
72
73 static void
74 idestart(struct buf *b)
75 {
76 if(b == 0)
77 panic("idestart");
78 if(b->blockno >= FSSIZE)
79 panic("incorrect blockno");
80 int sector_per_block = BSIZE/SECTOR_SIZE;
81 int sector = b->blockno * sector_per_block;
82 int read_cmd = (sector_per_block == 1) ? IDE_CMD_READ : IDE_CMD_RDMUL;
83 int write_cmd = (sector_per_block == 1) ? IDE_CMD_WRITE : IDE_CMD_WRMUL;
84
85 if (sector_per_block > 7) panic("idestart");
86
87 idewait(0);
88 outb(0x3f6, 0);
89 outb(0x1f2, sector_per_block);
90 outb(0x1f3, sector & 0xff);
91 outb(0x1f4, (sector >> 8) & 0xff);
92 outb(0x1f5, (sector >> 16) & 0xff);
93 outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f));
94 if(b->flags & B_DIRTY){
95 outb(0x1f7, write_cmd);
96 outsl(0x1f0, b->data, BSIZE/4);
97 } else {
98 outb(0x1f7, read_cmd);
99 }
100 }
101
102
103 void
104 ideintr(void)
105 {
106 struct buf *b;
107
108
109 acquire(&idelock);
110
111 if((b = idequeue) == 0){
112 release(&idelock);
113 return;
114 }
115 idequeue = b->qnext;
116
117
118 if(!(b->flags & B_DIRTY) && idewait(1) >= 0)
119 insl(0x1f0, b->data, BSIZE/4);
120
121
122 b->flags |= B_VALID;
123 b->flags &= ~B_DIRTY;
124 wakeup(b);
125
126
127 if(idequeue != 0)
128 idestart(idequeue);
129
130 release(&idelock);
131 }
132
133
134
135
136
137 void
138 iderw(struct buf *b)
139 {
140 struct buf **pp;
141
142 if(!holdingsleep(&b->lock))
143 panic("iderw: buf not locked");
144 if((b->flags & (B_VALID|B_DIRTY)) == B_VALID)
145 panic("iderw: nothing to do");
146 if(b->dev != 0 && !havedisk1)
147 panic("iderw: ide disk 1 not present");
148
149 acquire(&idelock);
150
151
152 b->qnext = 0;
153 for(pp=&idequeue; *pp; pp=&(*pp)->qnext)
154 ;
155 *pp = b;
156
157
158 if(idequeue == b)
159 idestart(b);
160
161
162 while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){
163 sleep(b, &idelock);
164 }
165
166
167 release(&idelock);
168 }