shithub: riscv

Download patch

ref: 215b67ff3d630c56418026dda7ae68f23111c4a5
parent: d46099e3afa9681a4f98e0d2574c2ad65820ed7e
author: cinap_lenrek <[email protected]>
date: Sun Jul 30 23:19:24 EDT 2017

nusb/usbd: create endpoint files for conf #1, usb3 preparation

--- a/sys/src/cmd/nusb/lib/parse.c
+++ b/sys/src/cmd/nusb/lib/parse.c
@@ -27,7 +27,12 @@
 		return -1;
 	}
 	d->csp = CSP(dd->bDevClass, dd->bDevSubClass, dd->bDevProtocol);
-	d->ep[0]->maxpkt = xd->maxpkt = dd->bMaxPacketSize0;
+	d->ver = GET2(dd->bcdUSB);
+	xd->isusb3 = (d->ver >= 0x0300);
+	if(xd->isusb3)
+		d->ep[0]->maxpkt = xd->maxpkt = 1<<dd->bMaxPacketSize0;
+	else
+		d->ep[0]->maxpkt = xd->maxpkt = dd->bMaxPacketSize0;
 	d->class = dd->bDevClass;
 	d->nconf = dd->bNumConfigurations;
 	if(d->nconf == 0)
--- a/sys/src/cmd/nusb/lib/usb.h
+++ b/sys/src/cmd/nusb/lib/usb.h
@@ -36,7 +36,7 @@
 	Rep	= 2,		/* endpoint */
 	Rother	= 3,
 
-	/* standard requests */
+	/* standard requests (USB2.0) */
 	Rgetstatus	= 0,
 	Rclearfeature	= 1,
 	Rsetfeature	= 3,
@@ -49,6 +49,10 @@
 	Rsetiface	= 11,
 	Rsynchframe	= 12,
 
+	/* standard requests (USB3.0) */
+	Rsethubdepth	= 12,
+	Rgetporterrcnt	= 13,
+
 	Rgetcur	= 0x81,
 	Rgetmin	= 0x82,
 	Rgetmax	= 0x83,
@@ -169,6 +173,7 @@
 	int	id;		/* usb id for device or ep. number */
 	int	dfd;		/* descriptor for the data file */
 	int	cfd;		/* descriptor for the control file */
+	int	isusb3;		/* this is a usb3 device */
 	int	maxpkt;		/* cached from usb description */
 	Ref	nerrs;		/* number of errors in requests */
 	Usbdev*	usb;		/* USB description */
@@ -182,6 +187,7 @@
  */
 struct Usbdev
 {
+	int	ver;		/* usb version */
 	ulong	csp;		/* USB class/subclass/proto */
 	int	vid;		/* vendor id */
 	int	did;		/* product (device) id */
--- a/sys/src/cmd/nusb/usbd/dat.h
+++ b/sys/src/cmd/nusb/usbd/dat.h
@@ -50,9 +50,7 @@
 	Pconfiged,
 
 	/* Delays, timeouts (ms) */
-//	Spawndelay	= 1000,		/* how often may we re-spawn a driver */
 	Spawndelay	= 250,		/* how often may we re-spawn a driver */
-//	Connectdelay	= 1000,		/* how much to wait after a connect */
 	Connectdelay	= 500,		/* how much to wait after a connect */
 	Resetdelay	= 20,		/* how much to wait after a reset */
 	Enabledelay	= 20,		/* how much to wait after an enable */
@@ -82,6 +80,7 @@
 	Port	*port;
 	int	failed;		/* I/O error while enumerating */
 	int	isroot;		/* set if root hub */
+	int	depth;		/* hub depth */
 	Dev	*dev;		/* for this hub */
 	Hub	*next;		/* in list of hubs */
 };
@@ -89,13 +88,11 @@
 struct Port
 {
 	int	state;		/* state of the device */
-	int	sts;		/* old port status */
+	u32int	sts;		/* old port status */
 	uchar	removable;
 	uchar	pwrctl;
 	Dev	*dev;		/* attached device (if non-nil) */
 	Hub	*hub;		/* non-nil if hub attached */
-	int	devnb;		/* device number */
-	uvlong	*devmaskp;	/* ptr to dev mask */
 };
 
 /* USB HUB descriptor */
--- a/sys/src/cmd/nusb/usbd/fns.h
+++ b/sys/src/cmd/nusb/usbd/fns.h
@@ -1,6 +1,6 @@
-int	attachdev(Port*);
-void	detachdev(Port*);
+int	attachdev(Hub*, Port*);
+void	detachdev(Hub*, Port*);
 void	work(void);
-Hub*	newhub(char *, Dev *);
+Hub*	newhub(char *, Dev*, Hub*);
 void	hname(char *);
 void	checkidle(void);
--- a/sys/src/cmd/nusb/usbd/hub.c
+++ b/sys/src/cmd/nusb/usbd/hub.c
@@ -10,35 +10,9 @@
 static int nhubs;
 static int mustdump;
 static int pollms = Pollms;
-static Lock masklck;
 
 static char *dsname[] = { "disabled", "attached", "configed" };
 
-int
-getdevnb(uvlong *maskp)
-{
-	int i;
-
-	lock(&masklck);
-	for(i = 0; i < 8 * sizeof *maskp; i++)
-		if((*maskp & (1ULL<<i)) == 0){
-			*maskp |= 1ULL<<i;
-			unlock(&masklck);
-			return i;
-		}
-	unlock(&masklck);
-	return -1;
-}
-
-void
-putdevnb(uvlong *maskp, int id)
-{
-	lock(&masklck);
-	if(id >= 0)
-		*maskp &= ~(1ULL<<id);
-	unlock(&masklck);
-}
-
 static int
 hubfeature(Hub *h, int port, int f, int on)
 {
@@ -51,25 +25,6 @@
 	return usbcmd(h->dev, Rh2d|Rclass|Rother, cmd, f, port, nil, 0);
 }
 
-/*
- * This may be used to detect overcurrent on the hub
- */
-static void
-checkhubstatus(Hub *h)
-{
-	uchar buf[4];
-	int sts;
-
-	if(h->isroot)	/* not for root hubs */
-		return;
-	if(usbcmd(h->dev, Rd2h|Rclass|Rdev, Rgetstatus, 0, 0, buf, 4) < 0){
-		dprint(2, "%s: get hub status: %r\n", h->dev->dir);
-		return;
-	}
-	sts = GET2(buf);
-	dprint(2, "hub %s: status %#ux\n", h->dev->dir, sts);
-}
-
 static int
 confighub(Hub *h)
 {
@@ -124,6 +79,10 @@
 		pp->removable = (dd->DeviceRemovable[offset] & mask) != 0;
 		pp->pwrctl = (PortPwrCtrlMask[offset] & mask) != 0;
 	}
+	if(h->dev->isusb3){
+		type = Rh2d|Rclass|Rdev;
+		usbcmd(h->dev, type, Rsethubdepth, h->depth, 0, nil, 0);
+	}
 	return 0;
 }
 
@@ -143,7 +102,7 @@
 	if(nr < 0)
 		goto Done;
 	buf[nr] = 0;
-
+	d->isusb3 = strstr(buf, "speed super") != nil;
 	p = strstr(buf, "ports ");
 	if(p == nil)
 		fprint(2, "%s: %s: no port information\n", argv0, d->dir);
@@ -160,7 +119,7 @@
 }
 
 Hub*
-newhub(char *fn, Dev *d)
+newhub(char *fn, Dev *d, Hub *ph)
 {
 	Hub *h;
 	int i;
@@ -169,17 +128,20 @@
 	h = emallocz(sizeof(Hub), 1);
 	h->isroot = (d == nil);
 	if(h->isroot){
+		h->depth = -1;
 		h->dev = opendev(fn);
 		if(h->dev == nil){
 			fprint(2, "%s: opendev: %s: %r", argv0, fn);
 			goto Fail;
 		}
+		configroothub(h);	/* never fails */
 		if(opendevdata(h->dev, ORDWR) < 0){
 			fprint(2, "%s: opendevdata: %s: %r\n", argv0, fn);
+			closedev(h->dev);
 			goto Fail;
 		}
-		configroothub(h);	/* never fails */
 	}else{
+		h->depth = ph->depth+1;
 		h->dev = d;
 		if(confighub(h) < 0){
 			fprint(2, "%s: %s: config: %r\n", argv0, fn);
@@ -186,10 +148,6 @@
 			goto Fail;
 		}
 	}
-	if(h->dev == nil){
-		fprint(2, "%s: opendev: %s: %r\n", argv0, fn);
-		goto Fail;
-	}
 	devctl(h->dev, "hub");
 	ud = h->dev->usb;
 	if(h->isroot)
@@ -265,13 +223,13 @@
 	free(h);
 }
 
-static int
+static u32int
 portstatus(Hub *h, int p)
 {
 	Dev *d;
 	uchar buf[4];
+	u32int sts;
 	int t;
-	int sts;
 	int dbg;
 
 	dbg = usbdebug;
@@ -282,34 +240,38 @@
 	if(usbcmd(d, t, Rgetstatus, 0, p, buf, sizeof(buf)) < 0)
 		sts = -1;
 	else
-		sts = GET2(buf);
+		sts = GET4(buf);
 	usbdebug = dbg;
 	return sts;
 }
 
 static char*
-stsstr(int sts)
+stsstr(int sts, int isusb3)
 {
 	static char s[80];
 	char *e;
 
 	e = s;
-	if(sts&PSsuspend)
-		*e++ = 'z';
-	if(sts&PSreset)
-		*e++ = 'r';
-	if(sts&PSslow)
-		*e++ = 'l';
-	if(sts&PShigh)
-		*e++ = 'h';
-	if(sts&PSchange)
-		*e++ = 'c';
-	if(sts&PSenable)
-		*e++ = 'e';
-	if(sts&PSstatuschg)
-		*e++ = 's';
 	if(sts&PSpresent)
 		*e++ = 'p';
+	if(sts&PSenable)
+		*e++ = 'e';
+	if(sts&PSovercurrent)
+		*e++ = 'o';
+	if(sts&PSreset)
+		*e++ = 'r';
+	if(!isusb3){
+		if(sts&PSslow)
+			*e++ = 'l';
+		if(sts&PShigh)
+			*e++ = 'h';
+		if(sts&PSchange)
+			*e++ = 'c';
+		if(sts&PSstatuschg)
+			*e++ = 's';
+		if(sts&PSsuspend)
+			*e++ = 'z';
+	}
 	if(e == s)
 		*e++ = '-';
 	*e = 0;
@@ -322,6 +284,8 @@
 	uchar buf[64];	/* More room to try to get device-specific descriptors */
 	DDev *dd;
 
+	if(d->isusb3)
+		return 512;
 	dd = (DDev*)buf;
 	if(islow)
 		dd->bMaxPacketSize0 = 8;
@@ -336,7 +300,7 @@
  * BUG: does not consider max. power avail.
  */
 static Dev*
-portattach(Hub *h, int p, int sts)
+portattach(Hub *h, int p, u32int sts)
 {
 	Dev *d;
 	Port *pp;
@@ -352,31 +316,43 @@
 	nd = nil;
 	pp->state = Pattached;
 	dprint(2, "%s: %s: port %d attach sts %#ux\n", argv0, d->dir, p, sts);
-	sleep(Connectdelay);
-	if(hubfeature(h, p, Fportenable, 1) < 0)
-		dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
-	sleep(Enabledelay);
-	if(hubfeature(h, p, Fportreset, 1) < 0){
-		dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	sleep(Resetdelay);
-	sts = portstatus(h, p);
-	if(sts < 0)
-		goto Fail;
-	if((sts & PSenable) == 0){
-		dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
-		hubfeature(h, p, Fportenable, 1);
+	if(h->dev->isusb3){
+		sleep(Connectdelay);
 		sts = portstatus(h, p);
-		if((sts & PSenable) == 0)
+		if(sts == -1)
 			goto Fail;
+		if((sts & PSenable) == 0){
+			dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
+			goto Fail;
+		}
+		sp = "super";
+	} else {
+		sleep(Connectdelay);
+		if(hubfeature(h, p, Fportenable, 1) < 0)
+			dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
+		sleep(Enabledelay);
+		if(hubfeature(h, p, Fportreset, 1) < 0){
+			dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p);
+			goto Fail;
+		}
+		sleep(Resetdelay);
+		sts = portstatus(h, p);
+		if(sts == -1)
+			goto Fail;
+		if((sts & PSenable) == 0){
+			dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
+			hubfeature(h, p, Fportenable, 1);
+			sts = portstatus(h, p);
+			if((sts & PSenable) == 0)
+				goto Fail;
+		}
+		sp = "full";
+		if(sts & PSslow)
+			sp = "low";
+		if(sts & PShigh)
+			sp = "high";
 	}
-	sp = "full";
-	if(sts & PSslow)
-		sp = "low";
-	if(sts & PShigh)
-		sp = "high";
-	dprint(2, "%s: %s: port %d: attached status %#ux\n", argv0, d->dir, p, sts);
+	dprint(2, "%s: %s: port %d: attached status %#ux, speed %s\n", argv0, d->dir, p, sts, sp);
 
 	if(devctl(d, "newdev %s %d", sp, p) < 0){
 		fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p);
@@ -413,7 +389,7 @@
 		dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p);
 		goto Fail;
 	}
-
+	nd->isusb3 = h->dev->isusb3;
 	mp=getmaxpkt(nd, strcmp(sp, "low") == 0);
 	if(mp < 0){
 		dprint(2, "%s: %s: port %d: getmaxpkt: %r\n", argv0, d->dir, p);
@@ -422,9 +398,6 @@
 		dprint(2, "%s; %s: port %d: maxpkt %d\n", argv0, d->dir, p, mp);
 		devctl(nd, "maxpkt %d", mp);
 	}
-	if((sts & PSslow) != 0 && strcmp(sp, "full") == 0)
-		dprint(2, "%s: %s: port %d: %s is full speed when port is low\n",
-			argv0, d->dir, p, nd->dir);
 	if(configdev(nd) < 0){
 		dprint(2, "%s: %s: port %d: configdev: %r\n", argv0, d->dir, p);
 		goto Fail;
@@ -446,7 +419,8 @@
 	pp->sts = 0;
 	if(pp->hub != nil)
 		pp->hub = nil;	/* hub closed by enumhub */
-	hubfeature(h, p, Fportenable, 0);
+	if(!h->dev->isusb3)
+		hubfeature(h, p, Fportenable, 0);
 	if(nd != nil)
 		devctl(nd, "detach");
 	closedev(nd);
@@ -475,11 +449,8 @@
 		closehub(pp->hub);
 		pp->hub = nil;
 	}
-	if(pp->devmaskp != nil)
-		putdevnb(pp->devmaskp, pp->devnb);
-	pp->devmaskp = nil;
 	if(pp->dev != nil){
-		detachdev(pp);
+		detachdev(h, pp);
 
 		devctl(pp->dev, "detach");
 		closedev(pp->dev);
@@ -523,7 +494,7 @@
 static void
 portreset(Hub *h, int p)
 {
-	int sts;
+	u32int sts;
 	Dev *d, *nd;
 	Port *pp;
 
@@ -537,10 +508,12 @@
 	}
 	sleep(Resetdelay);
 	sts = portstatus(h, p);
-	if(sts < 0)
+	if(sts == -1)
 		goto Fail;
 	if((sts & PSenable) == 0){
 		dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
+		if(h->dev->isusb3)
+			goto Fail;
 		hubfeature(h, p, Fportenable, 1);
 		sts = portstatus(h, p);
 		if((sts & PSenable) == 0)
@@ -572,7 +545,8 @@
 	pp->sts = 0;
 	if(pp->hub != nil)
 		pp->hub = nil;	/* hub closed by enumhub */
-	hubfeature(h, p, Fportenable, 0);
+	if(!h->dev->isusb3)
+		hubfeature(h, p, Fportenable, 0);
 	if(nd != nil)
 		devctl(nd, "detach");
 	closedev(nd);
@@ -579,9 +553,9 @@
 }
 
 static int
-portgone(Port *pp, int sts)
+portgone(Port *pp, u32int sts)
 {
-	if(sts < 0)
+	if(sts == -1)
 		return 1;
 	/*
 	 * If it was enabled and it's not now then it may be reconnect.
@@ -595,7 +569,7 @@
 static int
 enumhub(Hub *h, int p)
 {
-	int sts;
+	u32int sts;
 	Dev *d;
 	Port *pp;
 	int onhubs;
@@ -607,22 +581,24 @@
 		fprint(2, "%s: %s: port %d enumhub\n", argv0, d->dir, p);
 
 	sts = portstatus(h, p);
-	if(sts < 0){
+	if(sts == -1){
 		hubfail(h);		/* avoid delays on detachment */
 		return -1;
 	}
 	pp = &h->port[p];
 	onhubs = nhubs;
-	if((sts & PSsuspend) != 0){
-		if(hubfeature(h, p, Fportenable, 1) < 0)
-			dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
-		sleep(Enabledelay);
-		sts = portstatus(h, p);
-		fprint(2, "%s: %s: port %d: resumed (sts %#ux)\n", argv0, d->dir, p, sts);
+	if(!h->dev->isusb3){
+		if((sts & PSsuspend) != 0){
+			if(hubfeature(h, p, Fportenable, 1) < 0)
+				dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
+			sleep(Enabledelay);
+			sts = portstatus(h, p);
+			fprint(2, "%s: %s: port %d: resumed (sts %#ux)\n", argv0, d->dir, p, sts);
+		}
 	}
 	if((pp->sts & PSpresent) == 0 && (sts & PSpresent) != 0){
 		if(portattach(h, p, sts) != nil)
-			if(attachdev(pp) < 0)
+			if(attachdev(h, pp) < 0)
 				portdetach(h, p);
 	}else if(portgone(pp, sts)){
 		portdetach(h, p);
@@ -629,9 +605,9 @@
 	}else if(portresetwanted(h, p))
 		portreset(h, p);
 	else if(pp->sts != sts){
-		dprint(2, "%s: %s port %d: sts %s %#x ->",
-			argv0, d->dir, p, stsstr(pp->sts), pp->sts);
-		dprint(2, " %s %#x\n",stsstr(sts), sts);
+		dprint(2, "%s: %s port %d: sts %s %#ux ->",
+			argv0, d->dir, p, stsstr(pp->sts, h->dev->isusb3), pp->sts);
+		dprint(2, " %s %#ux\n",stsstr(sts, h->dev->isusb3), sts);
 	}
 	pp->sts = sts;
 	if(onhubs != nhubs)
@@ -663,7 +639,7 @@
 	hubs = nil;
 	while((fn = rendezvous(work, nil)) != nil){
 		dprint(2, "%s: %s starting\n", argv0, fn);
-		h = newhub(fn, nil);
+		h = newhub(fn, nil, nil);
 		if(h == nil)
 			fprint(2, "%s: %s: newhub failed: %r\n", argv0, fn);
 		free(fn);
--- a/sys/src/cmd/nusb/usbd/usbd.c
+++ b/sys/src/cmd/nusb/usbd/usbd.c
@@ -373,9 +373,10 @@
 }
 
 int
-attachdev(Port *p)
+attachdev(Hub *h, Port *p)
 {
 	Dev *d = p->dev;
+	int id;
 
 	if(d->usb->class == Clhub){
 		/*
@@ -384,11 +385,21 @@
 		 * has the config address in use.
 		 * We cancel kernel debug for these eps. too chatty.
 		 */
-		if((p->hub = newhub(d->dir, d)) == nil)
+		if((p->hub = newhub(d->dir, d, h)) == nil)
 			return -1;
 		return 0;
 	}
 
+	/* create all endpoint files for default conf #1 */
+	for(id=1; id<nelem(d->usb->ep); id++){
+		Ep *ep = d->usb->ep[id];
+		if(ep != nil && ep->conf != nil && ep->conf->cval == 1){
+			Dev *epd = openep(d, id);
+			if(epd != nil)
+				closedev(epd);
+		}
+	}
+
 	/* close control endpoint so driver can open it */
 	close(d->dfd);
 	d->dfd = -1;
@@ -406,7 +417,7 @@
 }
 
 void
-detachdev(Port *p)
+detachdev(Hub *, Port *p)
 {
 	Dev *d = p->dev;