summaryrefslogtreecommitdiff
path: root/ide.c
diff options
context:
space:
mode:
authorkaashoek <kaashoek>2006-07-10 19:06:48 +0000
committerkaashoek <kaashoek>2006-07-10 19:06:48 +0000
commit7ea6c9d19747c84ede9b056475cd9046c89a4d33 (patch)
tree447e7a317e09f79b8ab89663822f37f81afd3052 /ide.c
parent084f21430c152eeaeaf8534fab41eca91a5fe7a9 (diff)
downloadxv6-labs-7ea6c9d19747c84ede9b056475cd9046c89a4d33.tar.gz
xv6-labs-7ea6c9d19747c84ede9b056475cd9046c89a4d33.tar.bz2
xv6-labs-7ea6c9d19747c84ede9b056475cd9046c89a4d33.zip
queue with disk requests
Diffstat (limited to 'ide.c')
-rw-r--r--ide.c73
1 files changed, 55 insertions, 18 deletions
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;
}