shithub: riscv

Download patch

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);