diff --git a/defs.h b/defs.h index 64ee013..f271b59 100644 --- a/defs.h +++ b/defs.h @@ -70,8 +70,7 @@ int fd_read(struct fd *fd, char *addr, int n); int fd_write(struct fd *fd, char *addr, int n); // ide.c -extern int disk_channel; void ide_init(void); void ide_intr(void); -int ide_start_read(uint32_t secno, void *dst, unsigned nsecs); -int ide_read(uint32_t secno, void *dst, unsigned nsecs); +void* ide_start_read(uint32_t secno, void *dst, unsigned nsecs); +int ide_finish_read(void *); diff --git a/ide.c b/ide.c index 12e8af4..95df053 100644 --- a/ide.c +++ b/ide.c @@ -16,6 +16,14 @@ #define IDE_DF 0x20 #define IDE_ERR 0x01 +struct ide_request { + uint32_t secno; + void *dst; + unsigned nsecs; +}; +struct ide_request request[NREQUEST]; +int head, tail; + static int diskno = 0; int disk_channel; @@ -44,11 +52,9 @@ void ide_intr(void) { cprintf("ide_intr\n"); - wakeup(&disk_channel); + wakeup(&request[tail]); } - - int ide_probe_disk1(void) { @@ -79,35 +85,66 @@ ide_set_disk(int d) diskno = d; } -int +void +ide_start_request (void) +{ + struct ide_request *r; + + if (head == tail) { + r = &request[tail]; + ide_wait_ready(0); + outb(0x3f6, 0); + outb(0x1F2, r->nsecs); + outb(0x1F3, r->secno & 0xFF); + outb(0x1F4, (r->secno >> 8) & 0xFF); + outb(0x1F5, (r->secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((r->secno>>24)&0x0F)); + outb(0x1F7, 0x20); // CMD 0x20 means read sector + } +} + +void * ide_start_read(uint32_t secno, void *dst, unsigned nsecs) { + struct ide_request *r; + if(nsecs > 256) panic("ide_start_read: nsecs too large"); - ide_wait_ready(0); + while ((head + 1) % NREQUEST == tail) + sleep (&disk_channel); - outb(0x3f6, 0); - outb(0x1F2, nsecs); - outb(0x1F3, secno & 0xFF); - outb(0x1F4, (secno >> 8) & 0xFF); - outb(0x1F5, (secno >> 16) & 0xFF); - outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); - outb(0x1F7, 0x20); // CMD 0x20 means read sector + r = &request[head]; + r->secno = secno; + r->dst = dst; + r->nsecs = nsecs; - return 0; + ide_start_request(); + + head = (head + 1) % NREQUEST; + + return r; } int -ide_read(uint32_t secno, void *dst, unsigned nsecs) +ide_finish_read(void *c) { - int r; + int r = 0; + struct ide_request *req = (struct ide_request *) c; - for (; nsecs > 0; nsecs--, dst += 512) { + for (; req->nsecs > 0; req->nsecs--, req->dst += 512) { if ((r = ide_wait_ready(1)) < 0) - return r; - insl(0x1F0, dst, 512/4); + break; + insl(0x1F0, req->dst, 512/4); } + + if ((head + 1) % NREQUEST == tail) { + wakeup(&disk_channel); + } + + tail = (tail + 1) % NREQUEST; + ide_start_request(); + return 0; } diff --git a/param.h b/param.h index dac7e10..bdd8b70 100644 --- a/param.h +++ b/param.h @@ -4,3 +4,4 @@ #define NCPU 8 #define NOFILE 16 // file descriptors per process #define NFD 100 // file descriptors per system +#define NREQUEST 100 // outstanding disk requests diff --git a/syscall.c b/syscall.c index c7627ea..787eb64 100644 --- a/syscall.c +++ b/syscall.c @@ -229,15 +229,16 @@ sys_block(void) { char buf[512]; int i, j; + void *c; cprintf("%d: call sys_block\n", cpu()); for (i = 0; i < 100; i++) { - if (ide_start_read(i, buf, 1)) { + if ((c = ide_start_read(i, buf, 1)) == 0) { panic("couldn't start read\n"); } cprintf("call sleep\n"); - sleep (&disk_channel); - if (ide_read(i, buf, 1)) { + sleep (c); + if (ide_finish_read(c)) { panic("couldn't do read\n"); } cprintf("sector %d: ", i);