~kris/9p

9hist

114881b1db2b7dae09130580780eefc631f2daaa — David du Colombier 24 years ago 88f7010
Plan 9 from Bell Labs 2001-10-10
3 files changed, 203 insertions(+), 144 deletions(-)

M pc/devusb.c
M pc/etherwavelan.c
M pc/uarti8250.c
M pc/devusb.c => pc/devusb.c +180 -140
@@ 46,8 46,6 @@ enum {
	Rother = 3,
};

typedef uchar byte;

typedef struct Ctlr Ctlr;
typedef struct Endpt Endpt;
typedef struct Udev Udev;


@@ 71,7 69,10 @@ struct TD {

	/* software */
	ulong	flags;
	Block*	bp;
	union{
		Block*	bp;		/* non-iso */
		ulong	offset;	/* iso */
	};
	Endpt*	ep;
	TD*	next;
};


@@ 162,7 163,7 @@ struct Udev {
	int		busy;
	int		state;
	int		id;
	byte		port;		/* port number on connecting hub */
	uchar	port;		/* port number on connecting hub */
	ulong	csp;
	int		ls;
	int		npt;


@@ 203,18 204,18 @@ struct Endpt {
	int		id;		/* hardware endpoint address */
	int		maxpkt;	/* maximum packet size (from endpoint descriptor) */
	int		data01;	/* 0=DATA0, 1=DATA1 */
	byte		eof;
	uchar	eof;
	ulong	csp;
	byte		isopen;	/* ep operations forbidden on open endpoints */
	byte		mode;	/* OREAD, OWRITE, ORDWR */
	byte		nbuf;	/* number of buffers allowed */
	volatile byte	iso;
	byte		debug;
	byte		active;	/* listed for examination by interrupts */
	uchar	isopen;	/* ep operations forbidden on open endpoints */
	uchar	mode;	/* OREAD, OWRITE, ORDWR */
	uchar	nbuf;	/* number of buffers allowed */
	uchar	iso;
	uchar	debug;
	uchar	active;	/* listed for examination by interrupts */
	int		setin;
	/* ISO related: */
	byte *	tdalloc;
	byte *	bpalloc;
	uchar*	tdalloc;
	uchar*	bpalloc;
	int		hz;
	int		remain;	/* for packet size calculations */
	int		samplesz;


@@ 223,11 224,12 @@ struct Endpt {
	int		psize;	/* (remaining) size of this packet */
	int		off;		/* offset into packet */
	int		isolock;	/* reader/writer interlock with interrupt */
	TD*		td0;		/* first td in array */
	TD*		etd;		/* pointer into circular list of TDs for isochronous ept */
	TD*		xtd;		/* next td to be cleaned */
	uchar*	bp0;		/* first block in array */
	TD	*	td0;		/* first td in array */
	TD	*	etd;		/* pointer into circular list of TDs for isochronous ept */
	TD	*	xtd;		/* next td to be cleaned */
	/* end ISO stuff */
	QH*		epq;		/* queue of TDs for this endpoint */
	QH	*	epq;		/* queue of TDs for this endpoint */
	QLock	rlock;
	Rendez	rr;
	Queue*	rq;


@@ 244,6 246,7 @@ struct Endpt {

	ulong	nbytes;
	ulong	nblocks;
	vlong	time;
};

struct Ctlr {


@@ 816,16 819,17 @@ schedendpt(Endpt *e)
	e->tdalloc = mallocz(0x10 + NFRAME*sizeof(TD), 1);
	e->bpalloc = mallocz(0x10 + e->maxpkt*NFRAME/e->pollms, 1);
	e->td0 = (TD*)(((ulong)e->tdalloc + 0xf) & ~0xf);
	bp = (byte *)(((ulong)e->bpalloc + 0xf) & ~0xf);
	e->bp0 = (uchar *)(((ulong)e->bpalloc + 0xf) & ~0xf);
	frnum = (IN(Frnum) + 1) & 0x3ff;
	frnum = (frnum & ~(e->pollms - 1)) + e->sched;
	e->xtd = &e->td0[(frnum+8)&0x3ff];	/* Next td to finish */
	e->etd = nil;
	e->remain = 0;
	e->nbytes = 0;
	td = e->td0;
	for(i = e->sched; i < NFRAME; i += e->pollms){
		td->bp = (Block *)(bp + e->maxpkt*i/e->pollms);
		td->buffer = PADDR(td->bp);
		bp = e->bp0 + e->maxpkt*i/e->pollms;
		td->buffer = PADDR(bp);
		td->ep = e;
		td->next = &td[1];
		ub->frameld[i] += e->maxpkt;


@@ 1066,15 1070,19 @@ static void
cleaniso(Endpt *e, int frnum)
{
	TD *td;
	int id, n;
	int id, n, i;
	uchar *bp;

	td = e->xtd;
	if (td->status & Active)
		return;
	id = (e->x<<7)|(e->dev->x&0x7F);
	do{
	do {
		if (td->status & AnyError)
			iprint("usbisoerror 0x%lux\n", td->status);
		e->nbytes += (td->status + 1) & 0x3ff;
		if ((td->flags & IsoClean) == 0)
			e->nblocks++;
		if (e->mode == OREAD){
			td->dev = ((e->maxpkt -1)<<21) | ((id&0x7FF)<<8) | TokIN;
		}else{


@@ 1089,23 1097,26 @@ cleaniso(Endpt *e, int frnum)
			break;
		}
	} while ((td->status & Active) == 0);
	e->time = todget(nil);
	e->xtd = td;
	if (e->isolock)
		return;
	for (n = 2; n < 6; n++){
		td = e->td0 + ((frnum + n)&0x3ff);
		i = ((frnum + n)&0x3ff);
		td = e->td0 + i;
		bp = e->bp0 + e->maxpkt*i/e->pollms;
		if (td->status & Active)
			continue;

		if (td == e->etd) {
			XPRINT("*");
			memset((byte*)td->bp+e->off, 0, e->maxpkt-e->off);
			memset(bp+e->off, 0, e->maxpkt-e->off);
			if (e->off == 0)
				td->flags |= IsoClean;
			e->etd = nil;
		}else if ((td->flags & IsoClean) == 0){
			XPRINT("-");
			memset((byte*)td->bp, 0, e->maxpkt);
			memset(bp, 0, e->maxpkt);
			td->flags |= IsoClean;
		}
		td->status = ErrLimit1 | Active | IsoSelect | IOC;


@@ 1113,6 1124,15 @@ cleaniso(Endpt *e, int frnum)
	wakeup(&e->wr);
}

static int sapecount1;
static int sapecount2;
static int sapecmd;
static int sapestatus;
static int sapeintenb;
static int sapeframe;
static int sapeport1;
static int sapeport2;

static void
interrupt(Ureg*, void *a)
{


@@ 1121,27 1141,27 @@ interrupt(Ureg*, void *a)
	int s, frnum;
	QH *q;

sapecount1++;
	ub = a;
	s = IN(Status);
sapestatus = s;
sapeintenb = IN(Usbintr);
sapeframe = IN(Frnum);
sapeport1 = IN(Portsc0);
sapeport2 = IN(Portsc1);
sapecmd = IN(Cmd);

	OUT(Status, s);
	if ((s & 0x1f) == 0)
		return;
sapecount2++;
	frnum = IN(Frnum) & 0x3ff;
	XPRINT("usbint: #%x f%d\n", s, frnum);
//	iprint("usbint: #%x f%d\n", s, frnum);
	if (s & 0x1a) {
		XPRINT("cmd #%x sofmod #%x\n", IN(Cmd), inb(ub->io+SOFMod));
		XPRINT("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1));
	}

	XPRINT("cleanq(ub->ctlq, 0, 0)\n");
	cleanq(ub->ctlq, 0, 0);
	XPRINT("cleanq(ub->bulkq, 0, Vf)\n");
	cleanq(ub->bulkq, 0, Vf);
	XPRINT("clean recvq\n");
	for (q = ub->recvq->next; q; q = q->hlink) {
		XPRINT("cleanq(q, 0, Vf)\n");
		cleanq(q, 0, Vf);
	}
	ilock(&activends);
	for(e = activends.f; e != nil; e = e->activef){
		if(!e->iso && e->epq != nil) {


@@ 1154,6 1174,15 @@ interrupt(Ureg*, void *a)
		}
	}
	iunlock(&activends);
	XPRINT("cleanq(ub->ctlq, 0, 0)\n");
	cleanq(ub->ctlq, 0, 0);
	XPRINT("cleanq(ub->bulkq, 0, Vf)\n");
	cleanq(ub->bulkq, 0, Vf);
	XPRINT("clean recvq\n");
	for (q = ub->recvq->next; q; q = q->hlink) {
		XPRINT("cleanq(q, 0, Vf)\n");
		cleanq(q, 0, Vf);
	}
}

enum


@@ 1267,26 1296,36 @@ usbreset(void)
		return;
	}
	ub = &ubus;
	memset(&cfg, 0, sizeof(cfg));
	cfg = pcimatch(0, 0x8086, 0x7112);	/* Intel chipset PIIX 4*/
	if(cfg == nil) {
		cfg = pcimatch(0, 0x1106, 0x0586);	/* Via chipset */
		if(cfg == nil) {
			DPRINT("No USB device found\n");
			return;
	cfg = nil;
	while(cfg = pcimatch(cfg, 0, 0)){
		/*
		 * Look for devices with the correct class and
		 * sub-class code and known device and vendor ID.
		 */
		if(cfg->ccrb != 0x0C || cfg->ccru != 0x03)
			continue;
		switch(cfg->vid | cfg->did<<16){
		default:
			continue;
		case 0x8086 | 0x7112<<16:	/* 82371[AE]B (PIIX4[E]) */
		case 0x8086 | 0x719A<<16:	/* 82443MX */
		case 0x0586 | 0x1106<<16:	/* VIA 82C586 */
			break;
		}
		if((cfg->mem[4].bar & ~0x0F) != 0)
			break;
	}
	port = cfg->mem[4].bar & ~0x0F;
	if (port == 0) {
		print("usb: failed to map registers\n");
	if(cfg == nil) {
		DPRINT("No USB device found\n");
		return;
	}
	port = cfg->mem[4].bar & ~0x0F;

	DPRINT("USB: %x/%x port 0x%lux size 0x%x irq %d\n",
		cfg->vid, cfg->did, port, cfg->mem[4].size, cfg->intl);

	i = inb(port+SOFMod);
	if(1){
if(0){
		OUT(Cmd, 4);	/* global reset */
		delay(15);
		OUT(Cmd, 0);	/* end reset */


@@ 1327,11 1366,14 @@ usbreset(void)
	ub->recvq = allocqh(ub);
	t = alloctd(ub);	/* inactive TD, looped */
	t->link = PADDR(t);
	ub->bwsop->entries = PADDR(t);
	ub->ctlq->head = PADDR(ub->bwsop) | IsQH;
	ub->bwsop->head = PADDR(ub->bulkq) | IsQH;

	ub->ctlq->head = PADDR(ub->bulkq) | IsQH;
	ub->bulkq->head = PADDR(ub->recvq) | IsQH;
	ub->recvq->head = PADDR(ub->bwsop) | IsQH;	/* loop back */
	ub->recvq->head = PADDR(ub->bwsop) | IsQH;
	ub->bwsop->head = Terminate;	/* loop back */
//	ub->bwsop->head = PADDR(ub->bwsop) | IsQH;	/* loop back */
	ub->bwsop->entries = PADDR(t);

	XPRINT("usbcmd\t0x%.4x\nusbsts\t0x%.4x\nusbintr\t0x%.4x\nfrnum\t0x%.2x\n",
		IN(Cmd), IN(Status), IN(Usbintr), inb(port+Frnum));
	XPRINT("frbaseadd\t0x%.4x\nsofmod\t0x%x\nportsc1\t0x%.4x\nportsc2\t0x%.4x\n",


@@ 1525,8 1567,12 @@ usbopen(Chan *c, int omode)
				XPRINT("usbopen failed (endpoint)\n");
				error(Enodev);
			}
			if(schedendpt(e) < 0)
				error("can't schedule USB endpoint");
			if(schedendpt(e) < 0){
				if (e->isopen)
					error("can't schedule USB endpoint, isopen");
				else
					error("can't schedule USB endpoint");
			}
			e->isopen++;
			eptactivate(e);
		}


@@ 1615,18 1661,21 @@ isoready(void *arg)
}

static long
isoio(Endpt *e, void *a, long n, int w)
isoio(Endpt *e, void *a, long n, vlong offset, int w)
{
	int i, frnum;
	uchar *p, *q;
	uchar *p, *q, *bp;
	Ctlr *ub;
	TD *td;

	p = a;
	qlock(&e->rlock);
	if(waserror()){
		e->isolock = 0;
		qunlock(&e->rlock);
		eptcancel(e);
		nexterror();
	}
	p = a;
	e->isolock = 1;
	do {
		td = e->etd;


@@ 1657,11 1706,10 @@ isoio(Endpt *e, void *a, long n, int w)
				e->psize = (e->etd->status + 1) & 0x7ff;
			if (e->psize > e->maxpkt)
				panic("packet size > maximum");
			e->nbytes += e->psize;
			e->nblocks++;
		}
		td->flags &= ~IsoClean;
		q = (uchar*)td->bp + e->off;
		bp = e->bp0 + (td - e->td0) * e->maxpkt / e->pollms;
		q = bp + e->off;
		if((i = n) >= e->psize)
			i = e->psize;
		if (w)


@@ 1683,6 1731,7 @@ isoio(Endpt *e, void *a, long n, int w)
	} while(n > 0);
	e->isolock = 0;
	poperror();
	qunlock(&e->rlock);
	return p-(uchar*)a;
}



@@ 1701,49 1750,42 @@ readusb(Endpt *e, void *a, long n)
		eptcancel(e);
		nexterror();
	}
	if (e->iso){
		n = isoio(e, a, n, 0);
		poperror();
		qunlock(&e->rlock);
		return n;
	}else{
		p = a;
		do {
			if(e->eof) {
				XPRINT("e->eof\n");
				break;
			}
			if(e->err)
				error(e->err);
			qrcv(e);
			if(!e->iso)
				e->data01 ^= 1;
			sleep(&e->rr, eptinput, e);
			if(e->err)
				error(e->err);
			b = qget(e->rq);	/* TO DO */
			if(b == nil) {
				XPRINT("b == nil\n");
				break;
			}
			if(waserror()){
				freeb(b);
				nexterror();
			}
			l = BLEN(b);
			if((i = l) > n)
				i = n;
			if(i > 0){
				memmove(p, b->rp, i);
				p += i;
			}
			poperror();
	p = a;
	do {
		if(e->eof) {
			XPRINT("e->eof\n");
			break;
		}
		if(e->err)
			error(e->err);
		qrcv(e);
		if(!e->iso)
			e->data01 ^= 1;
		sleep(&e->rr, eptinput, e);
		if(e->err)
			error(e->err);
		b = qget(e->rq);	/* TO DO */
		if(b == nil) {
			XPRINT("b == nil\n");
			break;
		}
		if(waserror()){
			freeb(b);
			n -= i;
			if (l != e->maxpkt)
				break;
		} while (n > 0);
	}
			nexterror();
		}
		l = BLEN(b);
		if((i = l) > n)
			i = n;
		if(i > 0){
			memmove(p, b->rp, i);
			p += i;
		}
		poperror();
		freeb(b);
		n -= i;
		if (l != e->maxpkt)
			break;
	} while (n > 0);
	poperror();
	qunlock(&e->rlock);
	return p-(uchar*)a;


@@ 1820,7 1862,10 @@ usbread(Chan *c, void *a, long n, vlong offset)
			error(Eio);
		if((e = d->ep[t]) == nil || e->mode == OWRITE)
			error(Eio);	/* can't happen */
		n=readusb(e, a, n);
		if (e->iso)
			n=isoio(e, a, n, offset, 0);
		else
			n=readusb(e, a, n);
		break;
	}
	return n;


@@ 1846,51 1891,43 @@ writeusb(Endpt *e, void *a, long n, int tok)
		eptcancel(e);
		nexterror();
	}
	if (e->iso){
		n = isoio(e, a, n, 1);
	p = a;
	do {
		int j;

		if(e->err)
			error(e->err);
		if((i = n) >= e->maxpkt)
			i = e->maxpkt;
		b = allocb(i);
		if(waserror()){
			freeb(b);
			nexterror();
		}
		XPRINT("out [%d]", i);
		for (j = 0; j < i; j++) XPRINT(" %.2x", p[j]);
		XPRINT("\n");
		memmove(b->wp, p, i);
		b->wp += i;
		p += i;
		n -= i;
		poperror();
		qunlock(&e->wlock);
		return n;
	}else{
		p = a;
		do {
			int j;

			if(e->err)
				error(e->err);
			if((i = n) >= e->maxpkt)
				i = e->maxpkt;
			b = allocb(i);
			if(waserror()){
				freeb(b);
				nexterror();
			}
			XPRINT("out [%d]", i);
			for (j = 0; j < i; j++) XPRINT(" %.2x", p[j]);
			XPRINT("\n");
			memmove(b->wp, p, i);
			b->wp += i;
			p += i;
			n -= i;
			poperror();
			qh = qxmit(e, b, tok);
			tok = TokOUT;
			if(!e->iso)
				e->data01 ^= 1;
			if(e->ntd >= e->nbuf) {
				XPRINT("writeusb: sleep %lux\n", &e->wr);
				sleep(&e->wr, qisempty, qh);
				XPRINT("writeusb: awake\n");
			}
		} while(n > 0);
	}
		qh = qxmit(e, b, tok);
		tok = TokOUT;
		e->data01 ^= 1;
		if(e->ntd >= e->nbuf) {
			XPRINT("writeusb: sleep %lux\n", &e->wr);
			sleep(&e->wr, qisempty, qh);
			XPRINT("writeusb: awake\n");
		}
	} while(n > 0);
	poperror();
	qunlock(&e->wlock);
	return p-(uchar*)a;
}

long
usbwrite(Chan *c, void *a, long n, vlong)
usbwrite(Chan *c, void *a, long n, vlong offset)
{
	Udev *d;
	Endpt *e;


@@ 2084,7 2121,10 @@ usbwrite(Chan *c, void *a, long n, vlong)
		if((e = d->ep[t]) == nil || e->mode == OREAD) {
			error(Eio);	/* can't happen */
		}
		n = writeusb(e, a, n, TokOUT);
		if (e->iso)
			n = isoio(e, a, n, offset, 1);
		else
			n = writeusb(e, a, n, TokOUT);
		break;
	}
	return n;

M pc/etherwavelan.c => pc/etherwavelan.c +22 -3
@@ 1187,13 1187,19 @@ interrupt(Ureg* ,void* arg)
	iunlock(&ctlr->Lock);
}

static char* wavenames[] = {
	"WaveLAN/IEEE",
	"TrueMobile 1150",
	nil,
};

static int
reset(Ether* ether)
{
	int i;
	Wltv ltv;
	Ctlr* ctlr;
	char *p;
	char *name, *p;

	if((ctlr = malloc(sizeof(Ctlr))) == nil)
		return -1;


@@ 1212,12 1218,25 @@ reset(Ether* ether)
		goto abort1;
	}

	if ((ctlr->slot = pcmspecial("WaveLAN/IEEE", ether))<0){
		if ((ctlr->slot = pcmspecial("TrueMobile 1150", ether))<0){
	for (i=0; wavenames[i]; i++)
		if ((ctlr->slot = pcmspecial(wavenames[i], ether))>=0)
			break;
	name = wavenames[i];

	if (name == nil){
		for (i=0; i<ether->nopt; i++){
			if (cistrncmp(ether->opt[i], "id=", 3) == 0){
				name = &ether->opt[i][3];
				if ((ctlr->slot = pcmspecial(name, ether)) < 0)
					name = nil;
			}
		}
		if (name == nil){
			DEBUG("no wavelan found\n");
			goto abort;
		}
	}

	// DEBUG("#l%d: port=0x%lx irq=%ld\n",
	//		ether->ctlrno, ether->port, ether->irq);


M pc/uarti8250.c => pc/uarti8250.c +1 -1
@@ 657,7 657,7 @@ i8250console(void)
	}

	uartctl(uart, "b9600 l8 pn s1");
	if(*cmd != nil)
	if(*cmd != '\0')
		uartctl(uart, cmd);
	(*uart->phys->enable)(uart, 0);