1 // Simple PIO-based (non-DMA) IDE driver code.
19 #define IDE_CMD_READ 0x20
20 #define IDE_CMD_WRITE 0x30
22 // idequeue points to the buf now being read/written to the disk.
23 // idequeue->qnext points to the next buf to be processed.
24 // You must hold idelock while manipulating queue.
26 static struct spinlock idelock
;
27 static struct buf
*idequeue
;
30 static void idestart(struct buf
*);
32 // Wait for IDE disk to become ready.
38 while(((r
= inb(0x1f7)) & (IDE_BSY
|IDE_DRDY
)) != IDE_DRDY
)
40 if(checkerr
&& (r
& (IDE_DF
|IDE_ERR
)) != 0)
50 initlock(&idelock
, "ide");
52 ioapicenable(IRQ_IDE
, ncpu
- 1);
55 // Check if disk 1 is present
56 outb(0x1f6, 0xe0 | (1<<4));
57 for(i
=0; i
<1000; i
++){
64 // Switch back to disk 0.
65 outb(0x1f6, 0xe0 | (0<<4));
68 // Start the request for b. Caller must hold idelock.
70 idestart(struct buf
*b
)
76 outb(0x3f6, 0); // generate interrupt
77 outb(0x1f2, 1); // number of sectors
78 outb(0x1f3, b
->sector
& 0xff);
79 outb(0x1f4, (b
->sector
>> 8) & 0xff);
80 outb(0x1f5, (b
->sector
>> 16) & 0xff);
81 outb(0x1f6, 0xe0 | ((b
->dev
&1)<<4) | ((b
->sector
>>24)&0x0f));
82 if(b
->flags
& B_DIRTY
){
83 outb(0x1f7, IDE_CMD_WRITE
);
84 outsl(0x1f0, b
->data
, 512/4);
86 outb(0x1f7, IDE_CMD_READ
);
96 // First queued buffer is the active request.
98 if((b
= idequeue
) == 0){
100 // cprintf("spurious IDE interrupt\n");
105 // Read data if needed.
106 if(!(b
->flags
& B_DIRTY
) && idewait(1) >= 0)
107 insl(0x1f0, b
->data
, 512/4);
109 // Wake process waiting for this buf.
111 b
->flags
&= ~B_DIRTY
;
114 // Start disk on next buf in queue.
122 // Sync buf with disk.
123 // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.
124 // Else if B_VALID is not set, read buf from disk, set B_VALID.
130 if(!(b
->flags
& B_BUSY
))
131 panic("iderw: buf not busy");
132 if((b
->flags
& (B_VALID
|B_DIRTY
)) == B_VALID
)
133 panic("iderw: nothing to do");
134 if(b
->dev
!= 0 && !havedisk1
)
135 panic("iderw: ide disk 1 not present");
137 acquire(&idelock
); //DOC: acquire-lock
139 // Append b to idequeue.
141 for(pp
=&idequeue
; *pp
; pp
=&(*pp
)->qnext
) //DOC: insert-queue
145 // Start disk if necessary.
149 // Wait for request to finish.
150 while((b
->flags
& (B_VALID
|B_DIRTY
)) != B_VALID
){