ref: 80381d93d9d162b819055eedfdcc6d249def340b
parent: ee983985d959e4686cffa343bcae007abf70f194
author: cinap_lenrek <[email protected]>
date: Sun Apr 22 03:20:30 EDT 2012
sdvirtio: cleanup, add to pccpuf config
--- a/sys/src/9/pc/pccpuf
+++ b/sys/src/9/pc/pccpuf
@@ -89,6 +89,7 @@
sdmylex pci sdscsi
sdiahci pci sdscsi led
sdodin pci sdscsi led
+ sdvirtio pci sdscsi
sdloop
vga3dfx +cur
--- a/sys/src/9/pc/sdvirtio.c
+++ b/sys/src/9/pc/sdvirtio.c
@@ -9,8 +9,7 @@
#include "../port/sd.h"
-typedef struct Vioreqhdr Vioreqhdr;
-typedef struct Vringhdr Vringhdr;
+typedef struct Vring Vring;
typedef struct Vdesc Vdesc;
typedef struct Vused Vused;
typedef struct Vqueue Vqueue;
@@ -42,15 +41,8 @@
Indirect = 4,
};
-struct Vioreqhdr
+struct Vring
{
- u32int typ;
- u32int prio;
- u64int lba;
-};
-
-struct Vringhdr
-{
u16int flags;
u16int idx;
};
@@ -71,22 +63,22 @@
struct Vqueue
{
- int size;
+ int size;
- int free;
- int nfree;
+ int free;
+ int nfree;
- Vdesc *desc;
+ Vdesc *desc;
- Vringhdr *avail;
- u16int *availent;
- u16int *availevent;
+ Vring *avail;
+ u16int *availent;
+ u16int *availevent;
- Vringhdr *used;
- Vused *usedent;
- u16int *usedevent;
+ Vring *used;
+ Vused *usedent;
+ u16int *usedevent;
- u16int lastused;
+ u16int lastused;
Rendez;
QLock;
@@ -118,10 +110,10 @@
q = malloc(sizeof(*q));
p = mallocalign(
PGROUND(sizeof(Vdesc)*size +
- sizeof(Vringhdr) +
+ sizeof(Vring) +
sizeof(u16int)*size +
sizeof(u16int)) +
- PGROUND(sizeof(Vringhdr) +
+ PGROUND(sizeof(Vring) +
sizeof(Vused)*size +
sizeof(u16int)),
BY2PG, 0, 0);
@@ -135,7 +127,7 @@
q->desc = (void*)p;
p += sizeof(Vdesc)*size;
q->avail = (void*)p;
- p += sizeof(Vringhdr);
+ p += sizeof(Vring);
q->availent = (void*)p;
p += sizeof(u16int)*size;
q->availevent = (void*)p;
@@ -143,7 +135,7 @@
p = (uchar*)PGROUND((ulong)p);
q->used = (void*)p;
- p += sizeof(Vringhdr);
+ p += sizeof(Vring);
q->usedent = (void*)p;
p += sizeof(Vused)*size;
q->usedevent = (void*)p;
@@ -216,12 +208,10 @@
viointerrupt(Ureg *, void *arg)
{
Vdev *vd;
- int i;
vd = arg;
if(inb(vd->port+Isr) & 1)
- for(i=0; i<vd->nqueue; i++)
- wakeup(vd->queue[i]);
+ wakeup(vd->queue[0]);
}
static int
@@ -261,44 +251,49 @@
} while(!r.done);
}
-static long
-viobio(SDunit *u, int, int write, void *a, long count, uvlong lba)
+static int
+vioreq(Vdev *vd, int typ, uchar *a, long count, long secsize, uvlong lba)
{
int i, free, head;
- u8int status;
- Vioreqhdr h;
Vqueue *q;
- Vdev *vd;
Vdesc *d;
- uchar *p;
- vd = u->dev->ctlr;
- q = vd->queue[0];
+ u8int status;
+ struct Vioreqhdr {
+ u32int typ;
+ u32int prio;
+ u64int lba;
+ } req;
- lock(q);
- if(q->nfree < (2+count)){
+ status = 0;
+ req.typ = typ;
+ req.prio = 0;
+ req.lba = lba;
+
+ q = vd->queue[0];
+ for(;;){
+ lock(q);
+ if(q->nfree >= count+2)
+ break;
unlock(q);
- error("out of virtio descriptors");
+ if(!waserror())
+ tsleep(&up->sleep, return0, 0, 500);
+ poperror();
}
+
head = free = q->free;
- status = 0;
- h.typ = write != 0;
- h.lba = lba;
- h.prio = 0;
-
d = &q->desc[free]; free = d->next;
- d->addr = PADDR(&h);
- d->len = sizeof(h);
+ d->addr = PADDR(&req);
+ d->len = sizeof(req);
d->flags = Next;
- p = a;
for(i = 0; i<count; i++){
d = &q->desc[free]; free = d->next;
- d->addr = PADDR(p);
- d->len = u->secsize;
- d->flags = write ? Next : (Write|Next);
- p += d->len;
+ d->addr = PADDR(a);
+ d->len = secsize;
+ d->flags = typ ? Next : (Write|Next);
+ a += secsize;
}
d = &q->desc[free]; free = d->next;
@@ -325,10 +320,33 @@
q->nfree += 2+count;
unlock(q);
- if(status != 0)
- error(Eio);
+ return status;
+}
- return count*u->secsize;
+static long
+viobio(SDunit *u, int, int write, void *a, long count, uvlong lba)
+{
+ long ss, cc, max, ret;
+ Vqueue *q;
+ Vdev *vd;
+
+ ss = u->secsize;
+ vd = u->dev->ctlr;
+ q = vd->queue[0];
+ max = q->size-2;
+
+ ret = 0;
+ while(count > 0){
+ if((cc = count) > max)
+ cc = max;
+ if(vioreq(vd, write != 0, (uchar*)a + ret, cc, ss, lba) != 0)
+ error(Eio);
+ ret += cc*ss;
+ count -= cc;
+ lba += cc;
+ }
+
+ return ret;
}
static int
@@ -340,14 +358,12 @@
u = r->unit;
if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
- /* flush */
- // return sdsetsense(r, SDok, 0, 0, 0);
- return sdsetsense(r, SDcheck, 3, 0xc, 2);
+ if(vioreq(u->dev->ctlr, 4, nil, 0, 0, 0) != 0)
+ return sdsetsense(r, SDcheck, 3, 0xc, 2);
+ return sdsetsense(r, SDok, 0, 0, 0);
}
- if((i = sdfakescsi(r)) != SDnostatus){
- r->status = i;
- return i;
- }
+ if((i = sdfakescsi(r)) != SDnostatus)
+ return r->status = i;
if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
return i;
r->rlen = viobio(u, r->lun, rw == SDwrite, r->data, count, lba);