Skip to content
Snippets Groups Projects
Commit d7b44dbc authored by rsc's avatar rsc
Browse files

minor cleanups

parent cb30c818
No related branches found
No related tags found
No related merge requests found
......@@ -26,20 +26,16 @@ static struct spinlock ide_lock;
static struct buf *ide_queue;
static int disk_1_present;
static int ide_probe_disk1(void);
static void ide_start_request();
//PAGEBREAK: 10
// Wait for IDE disk to become ready.
static int
ide_wait_ready(int check_error)
{
int r;
while(((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
while(((r = inb(0x1f7)) & IDE_BSY) || !(r & IDE_DRDY))
;
if(check_error && (r & (IDE_DF|IDE_ERR)) != 0)
return -1;
return 0;
......@@ -48,105 +44,103 @@ ide_wait_ready(int check_error)
void
ide_init(void)
{
int i;
initlock(&ide_lock, "ide");
irq_enable(IRQ_IDE);
ioapic_enable(IRQ_IDE, ncpu - 1);
ide_wait_ready(0);
disk_1_present = ide_probe_disk1();
// Check if disk 1 is present
outb(0x1f6, 0xE0 | (1<<4));
for(i=0; i<1000; i++){
if(inb(0x1f7) != 0){
disk_1_present = 1;
break;
}
}
// Switch back to disk 0.
outb(0x1f6, 0xE0 | (0<<4));
}
// Probe to see if disk 1 exists (we assume disk 0 exists).
static int
ide_probe_disk1(void)
// Start the request for b. Caller must hold ide_lock.
static void
ide_start_request(struct buf *b)
{
int r, x;
if(b == 0)
panic("ide_start_request");
// 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++)
;
// switch back to Device 0
outb(0x1F6, 0xE0 | (0<<4));
return x < 1000;
outb(0x3f6, 0); // generate interrupt
outb(0x1f2, 1); // number of sectors
outb(0x1f3, b->sector & 0xff);
outb(0x1f4, (b->sector >> 8) & 0xff);
outb(0x1f5, (b->sector >> 16) & 0xff);
outb(0x1f6, 0xE0 | ((b->dev&1)<<4) | ((b->sector>>24)&0x0f));
if(b->flags & B_WRITE){
outb(0x1f7, IDE_CMD_WRITE);
outsl(0x1f0, b->data, 512/4);
}else{
outb(0x1f7, IDE_CMD_READ);
}
}
// Interrupt handler - wake up the request that just finished.
// Interrupt handler.
void
ide_intr(void)
{
struct buf *b;
acquire(&ide_lock);
if(ide_queue){
if((ide_queue->flags & B_WRITE) == 0)
if(ide_wait_ready(1) >= 0)
insl(0x1F0, ide_queue->data, 512/4);
ide_queue->done = 1;
wakeup(ide_queue);
ide_queue = ide_queue->qnext;
ide_start_request();
} else {
if((b = ide_queue) == 0){
cprintf("stray ide interrupt\n");
release(&ide_lock);
return;
}
release(&ide_lock);
}
// Start the next request in the queue.
// Caller must hold ide_lock.
static void
ide_start_request (void)
{
if(ide_queue){
ide_wait_ready(0);
outb(0x3f6, 0); // generate interrupt
outb(0x1F2, 1); // number of sectors
outb(0x1F3, ide_queue->sector & 0xFF);
outb(0x1F4, (ide_queue->sector >> 8) & 0xFF);
outb(0x1F5, (ide_queue->sector >> 16) & 0xFF);
outb(0x1F6, 0xE0 |
((ide_queue->dev & 1)<<4) |
((ide_queue->sector>>24)&0x0F));
if(ide_queue->flags & B_WRITE){
outb(0x1F7, IDE_CMD_WRITE);
outsl(0x1F0, ide_queue->data, 512/4);
} else {
outb(0x1F7, IDE_CMD_READ);
}
}
// Read data if needed.
if((b->flags & B_WRITE) == 0 && ide_wait_ready(1) >= 0)
insl(0x1f0, b->data, 512/4);
// Wake process waiting for this buf.
b->done = 1;
wakeup(b);
// Start disk on next buf in queue.
if((ide_queue = b->qnext) != 0)
ide_start_request(ide_queue);
release(&ide_lock);
}
//PAGEBREAK: 30
// Queue up a disk operation and wait for it to finish.
// b must have B_BUSY set.
//PAGEBREAK!
// Queue a disk operation and wait for it to finish.
void
ide_rw(struct buf *b)
{
struct buf **pp;
if((b->dev & 0xff) && !disk_1_present)
if(!(b->flags & B_BUSY))
panic("ide_rw: buf not busy");
if(b->dev != 0 && !disk_1_present)
panic("ide disk 1 not present");
acquire(&ide_lock);
// Append b to ide_queue.
b->done = 0;
b->qnext = 0;
// append b to ide_queue
pp = &ide_queue;
while(*pp)
pp = &(*pp)->qnext;
for(pp=&ide_queue; *pp; pp=&(*pp)->qnext)
;
*pp = b;
// Start disk if necessary.
if(ide_queue == b)
ide_start_request();
ide_start_request(b);
// Wait for request to finish.
while(!b->done)
sleep(b, &ide_lock);
release(&ide_lock);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment