⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devusb.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h"#include	"usb.h"static int debug = 0;#define Chatty	1#define DPRINT if(Chatty)print#define XPRINT if(debug)iprintUsbhost*	usbhost[MaxUsb];static char *devstates[] = {	[Disabled]	"Disabled",	[Attached]	"Attached",	[Enabled]	"Enabled",	[Assigned]	"Assigned",	[Configured]	"Configured",};static	char	Ebadusbmsg[] = "invalid parameters to USB ctl message";enum{	Qtopdir = 0,	Q2nd,	Qnew,	Qport,	Q3rd,	Qctl,	Qstatus,	Qep0,	/* other endpoint files */};/* * Qid path is: *	8 bits of file type (qids above) *	8 bits of slot number; default address 0 used for per-controller files *	4 bits of controller number */enum {	TYPEBITS	= 8,	SLOTBITS	= 8,	CTLRBITS	= 4,	SLOTSHIFT	= TYPEBITS,	CTLRSHIFT	= SLOTSHIFT+SLOTBITS,	TYPEMASK	= (1<<TYPEBITS)-1,	SLOTMASK	= (1<<SLOTBITS)-1,	CTLRMASK	= (1<<CTLRBITS)-1,};#define	TYPE(q)		(((ulong)(q).path)&TYPEMASK)#define	SLOT(q)		((((ulong)(q).path)>>SLOTSHIFT)&SLOTMASK)#define	CTLR(q)		((((ulong)(q).path)>>CTLRSHIFT)&CTLRMASK)#define	PATH(t, s, c)	((t)|((s)<<SLOTSHIFT)|((c)<<CTLRSHIFT))static Dirtab usbdir2[] = {	"new",		{Qnew},			0,	0666,	"port",		{Qport},		0,	0666,};static Dirtab usbdir3[]={	"ctl",		{Qctl},			0,	0666,	"status",	{Qstatus},		0,	0444,	"setup",	{Qep0},			0,	0666,	/* epNdata names are generated on demand */};enum{	PMdisable,	PMenable,	PMreset,};enum{	CMclass,	CMdata,	CMdebug,	CMep,	CMmaxpkt,	CMadjust,	CMspeed,	CMunstall,};static Cmdtab usbportmsg[] ={	PMdisable,	"disable",	2,	PMenable,	"enable",	2,	PMreset,	"reset",	2,};static Cmdtab usbctlmsg[] ={	CMclass,	"class",	0,	CMdata,		"data",		3,	CMdebug,	"debug",	3,	CMep,		"ep",		6,	CMmaxpkt,	"maxpkt",	3,	CMadjust,	"adjust",	3,	CMspeed,	"speed",	2,	CMunstall,	"unstall",	2,};static struct{	char*	type;	int	(*reset)(Usbhost*);} usbtypes[MaxUsb+1];voidaddusbtype(char* t, int (*r)(Usbhost*)){	static int ntype;	if(ntype == MaxUsb)		panic("too many USB host interface types");	usbtypes[ntype].type = t;	usbtypes[ntype].reset = r;	ntype++;}static Udev*usbdeviceofslot(Usbhost *uh, int s){	if(s < 0 || s > nelem(uh->dev))		return nil;	return uh->dev[s];}static Udev*usbdevice(Chan *c){	int bus;	Udev *d;	Usbhost *uh;	bus = CTLR(c->qid);	if(bus > nelem(usbhost) || (uh = usbhost[bus]) == nil) {		error(Egreg);		return nil;		/* for compiler */	}	d = usbdeviceofslot(uh, SLOT(c->qid));	if(d == nil || d->id != c->qid.vers || d->state == Disabled)		error(Ehungup);	return d;}static Endpt *devendpt(Udev *d, int id, int add){	Usbhost *uh;	Endpt *e, **p;	p = &d->ep[id&0xF];	lock(d);	e = *p;	if(e != nil){		incref(e);		XPRINT("incref(0x%p) in devendpt, new value %ld\n", e, e->ref);		unlock(d);		return e;	}	unlock(d);	if(!add)		return nil;	e = mallocz(sizeof(*e), 1);	e->ref = 1;	e->x = id&0xF;	e->id = id;	e->sched = -1;	e->maxpkt = 8;	e->nbuf = 1;	e->dev = d;	e->active = 0;	uh = d->uh;	uh->epalloc(uh, e);	lock(d);	if(*p != nil){		incref(*p);		XPRINT("incref(0x%p) in devendpt, new value %ld\n", *p, (*p)->ref);		unlock(d);		uh->epfree(uh, e);		free(e);		return *p;	}	*p = e;	unlock(d);	e->rq = qopen(8*1024, 0, nil, e);	e->wq = qopen(8*1024, 0, nil, e);	return e;}static voidfreept(Endpt *e){	Usbhost *uh;	if(e != nil && decref(e) == 0){		XPRINT("freept(%d,%d)\n", e->dev->x, e->x);		uh = e->dev->uh;		uh->epclose(uh, e);		e->dev->ep[e->x] = nil;		uh->epfree(uh, e);		free(e);	}}static Udev*usbnewdevice(Usbhost *uh){	int i;	Udev *d;	Endpt *e;	d = nil;	qlock(uh);	if(waserror()){		qunlock(uh);		nexterror();	}	for(i=0; i<nelem(uh->dev); i++)		if(uh->dev[i] == nil){			uh->idgen++;			d = mallocz(sizeof(*d), 1);			d->uh = uh;			d->ref = 1;			d->x = i;			d->id = (uh->idgen << 8) | i;			d->state = Enabled;			XPRINT("calling devendpt in usbnewdevice\n");			e = devendpt(d, 0, 1);	/* always provide control endpoint 0 */			e->mode = ORDWR;			e->iso = 0;			e->sched = -1;			uh->dev[i] = d;			break;		}	poperror();	qunlock(uh);	return d;}static voidfreedev(Udev *d, int ept){	int i;	Endpt *e;	Usbhost *uh;	uh = d->uh;	if(decref(d) == 0){		XPRINT("freedev 0x%p, 0\n", d);		for(i=0; i<nelem(d->ep); i++)			freept(d->ep[i]);		if(d->x >= 0)			uh->dev[d->x] = nil;		free(d);	} else {		if(ept >= 0 && ept < nelem(d->ep)){			e = d->ep[ept];			XPRINT("freedev, freept 0x%p\n", e);			if(e != nil)				uh->epclose(uh, e);		}	}	}static intusbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp){	Qid q;	Udev *d;	Endpt *e;	Dirtab *tab;	Usbhost *uh;	int t, bus, slot, perm;	/*	 * Top level directory contains the controller names.	 */	if(c->qid.path == Qtopdir){		if(s == DEVDOTDOT){			mkqid(&q, Qtopdir, 0, QTDIR);			devdir(c, q, "#U", 0, eve, 0555, dp);			return 1;		}		if(s >= nelem(usbhost) || usbhost[s] == nil)			return -1;		mkqid(&q, PATH(Q2nd, 0, s), 0, QTDIR);		snprint(up->genbuf, sizeof up->genbuf, "usb%d", s);		devdir(c, q, up->genbuf, 0, eve, 0555, dp);		return 1;	}	bus = CTLR(c->qid);	if(bus >= nelem(usbhost) || (uh = usbhost[bus]) == nil)			return -1;	/*	 * Second level contains "new", "port", and a numbered	 * directory for each enumerated device on the bus.	 */	t = TYPE(c->qid);	if(t < Q3rd){		if(s == DEVDOTDOT){			mkqid(&q, Qtopdir, 0, QTDIR);			devdir(c, q, "#U", 0, eve, 0555, dp);			return 1;		}		if(s < nelem(usbdir2)){			d = uh->dev[0];			if(d == nil)				return -1;			tab = &usbdir2[s];			mkqid(&q, PATH(tab->qid.path, 0, bus), d->id, QTFILE);			devdir(c, q, tab->name, tab->length, eve, tab->perm, dp);			return 1;		}		s -= nelem(usbdir2);		if(s >= 0 && s < nelem(uh->dev)) {			d = uh->dev[s];			if(d == nil)				return 0;			sprint(up->genbuf, "%d", s);			mkqid(&q, PATH(Q3rd, s, bus), d->id, QTDIR);			devdir(c, q, up->genbuf, 0, eve, 0555, dp);			return 1;		}		return -1;	}	/*	 * Third level.	 */	slot = SLOT(c->qid);	if(s == DEVDOTDOT) {		mkqid(&q, PATH(Q2nd, 0, bus), c->qid.vers, QTDIR);		snprint(up->genbuf, sizeof up->genbuf, "usb%d", bus);		devdir(c, q, up->genbuf, 0, eve, 0555, dp);		return 1;	}	if(s < nelem(usbdir3)) {		tab = &usbdir3[s];		mkqid(&q, PATH(tab->qid.path, slot, bus), c->qid.vers, QTFILE);		devdir(c, q, tab->name, tab->length, eve, tab->perm, dp);		return 1;	}	s -= nelem(usbdir3);	/* active endpoints */	d = usbdeviceofslot(uh, slot);	if(d == nil || s >= nelem(d->ep))		return -1;	if(s == 0 || (e = d->ep[s]) == nil)	/* ep0data is called "setup" */		return 0;	sprint(up->genbuf, "ep%ddata", s);	mkqid(&q, PATH(Qep0+s, slot, bus), c->qid.vers, QTFILE);	switch(e->mode) {	case OREAD:		perm = 0444;		break;	case OWRITE:		perm = 0222;		break;	default:		perm = 0666;		break;	}	devdir(c, q, up->genbuf, e->buffered, eve, perm, dp);	return 1;}static Usbhost*usbprobe(int cardno, int ctlrno){	Usbhost *uh;	char buf[128], *ebuf, name[64], *p, *type;	uh = malloc(sizeof(Usbhost));	memset(uh, 0, sizeof(Usbhost));	uh->tbdf = BUSUNKNOWN;	if(cardno < 0){		if(isaconfig("usb", ctlrno, uh) == 0){			free(uh);			return nil;		}		for(cardno = 0; usbtypes[cardno].type; cardno++){			type = uh->type;			if(type==nil || *type==0)				type = "uhci";			if(cistrcmp(usbtypes[cardno].type, type))				continue;			break;		}	}	if(cardno >= MaxUsb || usbtypes[cardno].type == nil){		free(uh);		return nil;	}	if(usbtypes[cardno].reset(uh) < 0){		free(uh);		return nil;	}	/*	 * IRQ2 doesn't really exist, it's used to gang the interrupt	 * controllers together. A device set to IRQ2 will appear on	 * the second interrupt controller as IRQ9.	 */	if(uh->irq == 2)		uh->irq = 9;	snprint(name, sizeof(name), "usb%d", ctlrno);	intrenable(uh->irq, uh->interrupt, uh, uh->tbdf, name);	ebuf = buf + sizeof buf;	p = seprint(buf, ebuf, "#U/usb%d: %s: port 0x%luX irq %d", ctlrno, usbtypes[cardno].type, uh->port, uh->irq);	if(uh->mem)		p = seprint(p, ebuf, " addr 0x%luX", PADDR(uh->mem));	if(uh->size)		seprint(p, ebuf, " size 0x%luX", uh->size);	print("%s\n", buf);	return uh;}static voidusbreset(void){	int cardno, ctlrno;	Usbhost *uh;	for(ctlrno = 0; ctlrno < MaxUsb; ctlrno++){		if((uh = usbprobe(-1, ctlrno)) == nil)			continue;		usbhost[ctlrno] = uh;	}	if(getconf("*nousbprobe"))		return;	cardno = ctlrno = 0;	while(usbtypes[cardno].type != nil && ctlrno < MaxUsb){		if(usbhost[ctlrno] != nil){			ctlrno++;			continue;		}		if((uh = usbprobe(cardno, ctlrno)) == nil){			cardno++;			continue;		}		usbhost[ctlrno] = uh;		ctlrno++;	}}voidusbinit(void){	Udev *d;	int ctlrno;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -