summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--kernel/virtio.h10
-rw-r--r--kernel/virtio_disk.c61
3 files changed, 40 insertions, 33 deletions
diff --git a/.gitignore b/.gitignore
index fe754f0..07216f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,6 @@ initcode
initcode.out
kernelmemfs
mkfs
+kernel/kernel
+user/usys.S
.gdbinit
diff --git a/kernel/virtio.h b/kernel/virtio.h
index c142af9..03b53a9 100644
--- a/kernel/virtio.h
+++ b/kernel/virtio.h
@@ -43,6 +43,10 @@
#define VIRTIO_RING_F_INDIRECT_DESC 28
#define VIRTIO_RING_F_EVENT_IDX 29
+// this many virtio descriptors.
+// must be a power of two.
+#define NUM 8
+
struct VRingDesc {
uint64 addr;
uint32 len;
@@ -60,3 +64,9 @@ struct VRingUsedElem {
// for disk ops
#define VIRTIO_BLK_T_IN 0 // read the disk
#define VIRTIO_BLK_T_OUT 1 // write the disk
+
+struct UsedArea {
+ uint16 flags;
+ uint16 id;
+ struct VRingUsedElem elems[NUM];
+};
diff --git a/kernel/virtio_disk.c b/kernel/virtio_disk.c
index 6bcad9c..855c902 100644
--- a/kernel/virtio_disk.c
+++ b/kernel/virtio_disk.c
@@ -22,10 +22,6 @@
struct spinlock virtio_disk_lock;
-// this many virtio descriptors.
-// must be a power of two.
-#define NUM 8
-
// memory for virtio descriptors &c for queue 0.
// this is a global instead of allocated because it has
// to be multiple contiguous pages, which kalloc()
@@ -34,7 +30,7 @@ __attribute__ ((aligned (PGSIZE)))
static char pages[2*PGSIZE];
static struct VRingDesc *desc;
static uint16 *avail;
-static char *used;
+static struct UsedArea *used;
// our own book-keeping.
static char free[NUM]; // is a descriptor free?
@@ -106,7 +102,7 @@ virtio_disk_init(void)
desc = (struct VRingDesc *) pages;
avail = (uint16*)(((char*)desc) + NUM*sizeof(struct VRingDesc));
- used = pages + PGSIZE;
+ used = (struct UsedArea *) (pages + PGSIZE);
for(int i = 0; i < NUM; i++)
free[i] = 1;
@@ -153,6 +149,21 @@ free_chain(int i)
}
}
+static int
+alloc3_desc(int *idx)
+{
+ for(int i = 0; i < 3; i++){
+ idx[i] = alloc_desc();
+ if(idx[i] < 0){
+ for(int j = 0; j < i; j++)
+ free_desc(idx[j]);
+ return -1;
+ break;
+ }
+ }
+ return 0;
+}
+
void
virtio_disk_rw(struct buf *b)
{
@@ -167,21 +178,12 @@ virtio_disk_rw(struct buf *b)
// allocate the three descriptors.
int idx[3];
while(1){
- int done = 1;
- for(int i = 0; i < 3; i++){
- idx[i] = alloc_desc();
- if(idx[i] < 0){
- for(int j = 0; j < i; j++)
- free_desc(idx[j]);
- done = 0;
- break;
- }
- }
- if(done)
+ if(alloc3_desc(idx) == 0) {
break;
+ }
sleep(&free[0], &virtio_disk_lock);
}
-
+
// format the three descriptors.
// qemu's virtio-blk.c reads them.
@@ -242,28 +244,21 @@ virtio_disk_rw(struct buf *b)
void
virtio_disk_intr()
{
- // the used area is:
- // uint16 flags
- // uint16 idx
- // array of VRingUsedElem
- volatile uint16 *idxp = (uint16 *)(used + 2);
- volatile struct VRingUsedElem *e0 = (struct VRingUsedElem *)(used + 4);
-
acquire(&virtio_disk_lock);
- while((used_idx % NUM) != (*idxp % NUM)){
- volatile struct VRingUsedElem *ue = &e0[used_idx];
+ while((used_idx % NUM) != (used->id % NUM)){
+ int id = used->elems[used_idx].id;
- if(info[ue->id].status != 0)
+ if(info[id].status != 0)
panic("virtio_disk_intr status");
- info[ue->id].b->flags |= B_VALID;
- info[ue->id].b->flags &= ~B_DIRTY;
+ info[id].b->flags |= B_VALID;
+ info[id].b->flags &= ~B_DIRTY;
- wakeup(info[ue->id].b);
+ wakeup(info[id].b);
- info[ue->id].b = 0;
- free_chain(ue->id);
+ info[id].b = 0;
+ free_chain(id);
used_idx = (used_idx + 1) % NUM;
}