plan 9 kernel history: overview | file list | diff list

2002/0416/port/devpnp.c (diff list | history)

2001/0728/sys/src/9/port/devpnp.c:21,262001/0731/sys/src/9/port/devpnp.c:21,27 (short | long)
2001/0728    
	int		csn; 
	ulong	id1; 
	ulong	id2; 
2001/0731    
	char		*cfgstr; 
2001/0728    
	int		ncfg; 
	Card*	next; 
}; 
2001/0728/sys/src/9/port/devpnp.c:62,672001/0731/sys/src/9/port/devpnp.c:63,69
2001/0728    
}; 
 
extern Dev pnpdevtab; 
2001/0731    
static int wrconfig(Card*, char*); 
2001/0728    
 
static char key[32] = 
{ 
2001/0728/sys/src/9/port/devpnp.c:230,2362001/0731/sys/src/9/port/devpnp.c:232,238
2001/0728    
 
/* look for cards, and assign them CSNs */ 
static int 
pnpscan(int rddata) 
2001/0731    
pnpscan(int rddata, int dawn) 
2001/0728    
{ 
	Card *c; 
	int csn, ok; 
2001/0728/sys/src/9/port/devpnp.c:238,2442001/0731/sys/src/9/port/devpnp.c:240,246
2001/0728    
 
	ilock(&pnp); 
	pnp.rddata = rddata; 
	initiation(); 
2001/0731    
	initiation();				/* upsilon sigma */ 
2001/0728    
	cmd(0x02, 0x04+0x01);		/* reset CSN on all cards and reset logical devices */ 
	delay(1);					/* delay after resetting cards */ 
 
2001/0728/sys/src/9/port/devpnp.c:254,2612001/0731/sys/src/9/port/devpnp.c:256,269
2001/0728    
			c->id1 = id1; 
			c->id2 = id2; 
		} 
2001/0731    
		else if(c->cfgstr != nil) { 
			if(!wrconfig(c, c->cfgstr)) 
				print("pnp%d: bad cfg: %s\n", c->csn, c->cfgstr); 
			c->cfgstr = nil; 
		} 
2001/0728    
		cmd(0x06, c->csn);		/* set the card's csn */ 
		print("pnp%d: %s\n", c->csn, serial(id1, id2)); 
2001/0731    
		if(dawn) 
			print("pnp%d: %s\n", c->csn, serial(id1, id2)); 
2001/0728    
		c->ncfg = pnpncfg(rddata); 
		cmd(0x03, 0);		/* Wake all cards with a CSN of 0, putting this card to sleep */ 
	} 
2001/0728/sys/src/9/port/devpnp.c:296,3082001/0731/sys/src/9/port/devpnp.c:304,321
2001/0728    
		x = strtoul(&s[3], 0, 16); 
		id1 = (i1<<2)|((i2>>3)&3)|((i2&7)<<13)|(i3<<8)|((x&0xff)<<24)|((x&0xff00)<<8); 
		id2 = strtoul(&s[8], &p, 16); 
		if(*p != ' ' && *p != '\0') 
2001/0731    
		if(*p == ' ') 
			p++; 
		else if(*p == '\0') 
			p = nil; 
		else 
2001/0728    
			goto bad; 
		c = findcsn(csn, 1); 
		c->id1 = id1; 
		c->id2 = id2; 
2001/0731    
		c->cfgstr = p; 
2001/0728    
	} 
	pnpscan(isa.port); 
2001/0731    
	pnpscan(isa.port, 1); 
2001/0728    
} 
 
static int 
2001/0728/sys/src/9/port/devpnp.c:334,3402001/0731/sys/src/9/port/devpnp.c:347,352
2001/0728    
	Card *cp; 
	char name[KNAMELEN]; 
 
DPRINT("pnpgen s %d offset %uld qid %lux\n", s, (ulong)c->offset, (ulong)c->qid.path); 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
		if(s == DEVDOTDOT){ 
2001/0728/sys/src/9/port/devpnp.c:351,3612001/0731/sys/src/9/port/devpnp.c:363,371
2001/0728    
			devdir(c, q, name, 0, eve, 0555, dp); 
			return 1; 
		} 
DPRINT("Qpnpdir s %d\n", s); 
		if(s < nelem(pnpdir)) 
2001/0731    
		if(s < nelem(pnpdir)-1) 
2001/0728    
			return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp); 
		s -= nelem(pnpdir); 
DPRINT("Qpnpdir s now %d\n", s); 
2001/0731    
		s -= nelem(pnpdir)-1; 
2001/0728    
		ilock(&pnp); 
		cp = pnp.cards; 
		while(s >= 2 && cp != nil) { 
2001/0728/sys/src/9/port/devpnp.c:363,3692001/0731/sys/src/9/port/devpnp.c:373,378
2001/0728    
			cp = cp->next; 
		} 
		iunlock(&pnp); 
DPRINT("Qpnpdir s now %d, cp %p\n", s, cp); 
		if(cp == nil) 
			return -1; 
		return pnpgen1(c, s+Qcsnctl, cp->csn, cp, dp); 
2001/0728/sys/src/9/port/devpnp.c:472,4932001/0731/sys/src/9/port/devpnp.c:481,505
2001/0728    
} 
 
static long 
pnpwrite(Chan *c, void *a, long n, vlong offset) 
2001/0731    
pnpwrite(Chan *c, void *a, long n, vlong) 
2001/0728    
{ 
2001/0731    
	int csn; 
	Card *cp; 
2001/0728    
	ulong port; 
	char buf[256]; 
 
2001/0731    
	if(n >= sizeof(buf)) 
		n = sizeof(buf)-1; 
	strncpy(buf, a, n); 
	buf[n] = 0; 
 
2001/0728    
	switch(TYPE(c->qid)){ 
	case Qpnpctl: 
		if(n >= sizeof(buf)) 
			n = sizeof(buf)-1; 
		strncpy(buf, a, n); 
		buf[n] = 0; 
		if(strncmp(buf, "rddata ", 7) == 0) { 
			port = strtoul(buf+7, 0, 0); 
2001/0731    
		if(strncmp(buf, "port ", 5) == 0) { 
			port = strtoul(buf+5, 0, 0); 
2001/0728    
			if(port < 0x203 || port > 0x3ff) 
				error("bad value for rddata port"); 
			if(!pnpscan(port)) 
2001/0731    
			if(!pnpscan(port, 0)) 
2001/0728    
				error("no cards found"); 
		} 
		else if(strncmp(buf, "debug ", 6) == 0) 
2001/0728/sys/src/9/port/devpnp.c:495,5062001/0731/sys/src/9/port/devpnp.c:507,550
2001/0728    
		else 
			error(Ebadctl); 
		break; 
2001/0731    
	case Qcsnctl: 
		csn = CSN(c->qid); 
		ilock(&pnp); 
		cp = findcsn(csn, 0); 
		iunlock(&pnp); 
		if(cp == nil) 
			error(Egreg); 
		if(!wrconfig(cp, buf)) 
			error(Ebadctl); 
		break; 
2001/0728    
	default: 
USED(offset); 
		error(Egreg); 
	} 
	return n; 
} 
2001/0731    
 
static int 
wrconfig(Card *c, char *cmd) 
{ 
	for(;;) { 
		while(*cmd == ' ' || *cmd == '\t' || *cmd == '\n') 
			cmd++; 
		if(*cmd == '\0') 
			break; 
		if(strncmp(cmd, "foo ", 4) == 0) { 
			print("pnp%d: got foo\n", c->csn); 
			cmd += 4; 
		} 
		else if(strncmp(cmd, "bar ", 4) == 0) { 
			print("pnp%d: got bar\n", c->csn); 
			cmd += 4; 
		} 
		else 
			return 0; 
	} 
	return 1; 
} 
 
2001/0728    
 
Dev pnpdevtab = { 
	'$', 
2001/0731/sys/src/9/port/devpnp.c:3,82001/0801/sys/src/9/port/devpnp.c:3,9 (short | long)
2001/0728    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
2001/0801    
#include	"io.h" 
2001/0728    
#include	"../port/error.h" 
 
typedef struct Pnp Pnp; 
2001/0731/sys/src/9/port/devpnp.c:319,3282001/0801/sys/src/9/port/devpnp.c:320,329
2001/0728    
} 
 
static int 
pnpgen1(Chan *c, int t, int csn, Card *cp, Dir *dp) 
2001/0801    
csngen(Chan *c, int t, int csn, Card *cp, Dir *dp) 
2001/0728    
{ 
	Qid q; 
	char buf[20]; 
2001/0801    
	static char buf[20]; 
2001/0728    
 
	switch(t) { 
	case Qcsnctl: 
2001/0731/sys/src/9/port/devpnp.c:340,3512001/0801/sys/src/9/port/devpnp.c:341,373
2001/0728    
} 
 
static int 
2001/0801    
pcigen(Chan *c, int t, int tbdf, Dir *dp) 
{ 
	Qid q; 
	static char name[KNAMELEN]; 
 
	q = (Qid){BUSBDF(tbdf)|t, 0, 0}; 
	switch(t) { 
	case Qpcictl: 
		snprint(name, KNAMELEN, "%d.%d.%dctl", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); 
		devdir(c, q, name, 0, eve, 0444, dp); 
		return 1; 
	case Qpciraw: 
		snprint(name, KNAMELEN, "%d.%d.%draw", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); 
		devdir(c, q, name, 128, eve, 0444, dp); 
		return 1; 
	} 
	return -1; 
} 
 
static int 
2001/0728    
pnpgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) 
{ 
	Qid q; 
	int csn; 
	Card *cp; 
	char name[KNAMELEN]; 
2001/0801    
	Pcidev *p; 
	int csn, tbdf; 
	static char name[KNAMELEN]; 
2001/0728    
 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
2001/0731/sys/src/9/port/devpnp.c:375,3812001/0801/sys/src/9/port/devpnp.c:397,403
2001/0728    
		iunlock(&pnp); 
		if(cp == nil) 
			return -1; 
		return pnpgen1(c, s+Qcsnctl, cp->csn, cp, dp); 
2001/0801    
		return csngen(c, s+Qcsnctl, cp->csn, cp, dp); 
2001/0728    
	case Qpnpctl: 
		return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp); 
	case Qcsnctl: 
2001/0731/sys/src/9/port/devpnp.c:386,3922001/0801/sys/src/9/port/devpnp.c:408,436
2001/0728    
		iunlock(&pnp); 
		if(cp == nil) 
			return -1; 
		return pnpgen1(c, TYPE(c->qid), csn, cp, dp); 
2001/0801    
		return csngen(c, TYPE(c->qid), csn, cp, dp); 
	case Qpcidir: 
		if(s == DEVDOTDOT){ 
			q = (Qid){QID(0, Qtopdir), 0, QTDIR}; 
			snprint(name, KNAMELEN, "#%C", pnpdevtab.dc); 
			devdir(c, q, name, 0, eve, 0555, dp); 
			return 1; 
		} 
		p = pcimatch(nil, 0, 0); 
		while(s >= 2 && p != nil) { 
			p = pcimatch(p, 0, 0); 
			s -= 2; 
		} 
		if(p == nil) 
			return -1; 
		return pcigen(c, s+Qpcictl, p->tbdf, dp); 
	case Qpcictl: 
	case Qpciraw: 
		tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); 
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			return -1; 
		return pcigen(c, TYPE(c->qid), tbdf, dp); 
2001/0728    
	default: 
		break; 
	} 
2001/0731/sys/src/9/port/devpnp.c:430,4382001/0801/sys/src/9/port/devpnp.c:474,483
2001/0728    
static long 
pnpread(Chan *c, void *va, long n, vlong offset) 
{ 
	int csn, i; 
	Card *cp; 
	char *a = va, buf[20]; 
2001/0801    
	Pcidev *p; 
	int csn, i, tbdf; 
	char *a = va, buf[256]; 
2001/0728    
 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
2001/0731/sys/src/9/port/devpnp.c:474,4792001/0801/sys/src/9/port/devpnp.c:519,538
2001/0728    
			error(Egreg); 
		sprint(buf, "%s\n", serial(cp->id1, cp->id2)); 
		return readstr(offset, a, n, buf); 
2001/0801    
	case Qpcictl: 
		tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); 
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			error(Egreg); 
		snprint(buf, sizeof(buf), "class %.2x subclass %.2x piclass %.2x vid %.4x did %.4x intl %d\n", 
			p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl); 
		return readstr(offset, a, n, buf); 
	case Qpciraw: 
		tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); 
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			error(Egreg); 
		break; 
2001/0728    
	default: 
		error(Egreg); 
	} 
2001/0801/sys/src/9/port/devpnp.c:1,32001/0809/sys/src/9/port/devpnp.c:1,14 (short | long)
2001/0809    
/* 
 *	ISA PNP 1.0 support + access to PCI configuration space 
 * 
 *	TODO 
 *		- implement PNP card configuration (setting io bases etc) 
 *		- implement PCI raw access to configuration space 
 *		- implement PCI access to memory/io space/BIOS ROM 
 *		- use c->aux instead of performing lookup on each read/write 
 * 
 *	I also need to write the user program that'll drive the PNP configuration... 
 */ 
2001/0728    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
2001/0801/sys/src/9/port/devpnp.c:11,172001/0809/sys/src/9/port/devpnp.c:22,28
2001/0728    
 
struct Pnp 
{ 
	Lock; 
2001/0809    
	QLock; 
2001/0728    
	int		rddata; 
	int		debug; 
	Card		*cards; 
2001/0801/sys/src/9/port/devpnp.c:167,1922001/0809/sys/src/9/port/devpnp.c:178,208
2001/0728    
	return buf; 
} 
 
/* called with pnp locked */ 
static Card * 
findcsn(int csn, int create) 
2001/0809    
findcsn(int csn, int create, int dolock) 
2001/0728    
{ 
	Card *c, *nc, **l; 
 
2001/0809    
	if(dolock) 
		qlock(&pnp); 
2001/0728    
	l = &pnp.cards; 
	for(c = *l; c != nil; c = *l) { 
		if(c->csn == csn) 
			return c; 
2001/0809    
			goto done; 
2001/0728    
		if(c->csn > csn) 
			break; 
		l = &c->next; 
	} 
	if(!create) 
		return nil; 
	*l = nc = malloc(sizeof(Card)); 
	nc->next = c; 
	nc->csn = csn; 
	return nc; 
2001/0809    
	if(create) { 
		*l = nc = malloc(sizeof(Card)); 
		nc->next = c; 
		nc->csn = csn; 
		c = nc; 
	} 
done: 
	if(dolock) 
		qunlock(&pnp); 
	return c; 
2001/0728    
} 
 
static int 
2001/0801/sys/src/9/port/devpnp.c:236,2462001/0809/sys/src/9/port/devpnp.c:252,260
2001/0731    
pnpscan(int rddata, int dawn) 
2001/0728    
{ 
	Card *c; 
	int csn, ok; 
2001/0809    
	int csn; 
2001/0728    
	ulong id1, id2; 
 
	ilock(&pnp); 
	pnp.rddata = rddata; 
2001/0731    
	initiation();				/* upsilon sigma */ 
2001/0728    
	cmd(0x02, 0x04+0x01);		/* reset CSN on all cards and reset logical devices */ 
	delay(1);					/* delay after resetting cards */ 
2001/0801/sys/src/9/port/devpnp.c:253,2592001/0809/sys/src/9/port/devpnp.c:267,273
2001/0728    
				break; 
		if(c == nil) { 
			csn = newcsn(); 
			c = findcsn(csn, 1); 
2001/0809    
			c = findcsn(csn, 1, 0); 
2001/0728    
			c->id1 = id1; 
			c->id2 = id2; 
		} 
2001/0801/sys/src/9/port/devpnp.c:269,2772001/0809/sys/src/9/port/devpnp.c:283,293
2001/0728    
		cmd(0x03, 0);		/* Wake all cards with a CSN of 0, putting this card to sleep */ 
	} 
	cmd(0x02, 0x02);			/* return cards to Wait for Key state */ 
	ok = (pnp.cards != 0); 
	iunlock(&pnp); 
	return ok; 
2001/0809    
	if(pnp.cards != 0) { 
		pnp.rddata = rddata; 
		return 1; 
	} 
	return 0; 
2001/0728    
} 
 
static void 
2001/0801/sys/src/9/port/devpnp.c:311,3172001/0809/sys/src/9/port/devpnp.c:327,333
2001/0731    
			p = nil; 
		else 
2001/0728    
			goto bad; 
		c = findcsn(csn, 1); 
2001/0809    
		c = findcsn(csn, 1, 0); 
2001/0728    
		c->id1 = id1; 
		c->id2 = id2; 
2001/0731    
		c->cfgstr = p; 
2001/0801/sys/src/9/port/devpnp.c:323,3402001/0809/sys/src/9/port/devpnp.c:339,355
2001/0801    
csngen(Chan *c, int t, int csn, Card *cp, Dir *dp) 
2001/0728    
{ 
	Qid q; 
2001/0801    
	static char buf[20]; 
2001/0728    
 
	switch(t) { 
	case Qcsnctl: 
		q = (Qid){QID(csn, Qcsnctl), 0, 0}; 
		sprint(buf, "csn%dctl", csn); 
		devdir(c, q, buf, 0, eve, 0664, dp); 
2001/0809    
		sprint(up->genbuf, "csn%dctl", csn); 
		devdir(c, q, up->genbuf, 0, eve, 0664, dp); 
2001/0728    
		return 1; 
	case Qcsnraw: 
		q = (Qid){QID(csn, Qcsnraw), 0, 0}; 
		sprint(buf, "csn%draw", csn); 
		devdir(c, q, buf, cp->ncfg, eve, 0444, dp); 
2001/0809    
		sprint(up->genbuf, "csn%draw", csn); 
		devdir(c, q, up->genbuf, cp->ncfg, eve, 0444, dp); 
2001/0728    
		return 1; 
	} 
	return -1; 
2001/0801/sys/src/9/port/devpnp.c:344,3602001/0809/sys/src/9/port/devpnp.c:359,374
2001/0801    
pcigen(Chan *c, int t, int tbdf, Dir *dp) 
{ 
	Qid q; 
	static char name[KNAMELEN]; 
 
	q = (Qid){BUSBDF(tbdf)|t, 0, 0}; 
	switch(t) { 
	case Qpcictl: 
		snprint(name, KNAMELEN, "%d.%d.%dctl", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); 
		devdir(c, q, name, 0, eve, 0444, dp); 
2001/0809    
		sprint(up->genbuf, "%d.%d.%dctl", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); 
		devdir(c, q, up->genbuf, 0, eve, 0444, dp); 
2001/0801    
		return 1; 
	case Qpciraw: 
		snprint(name, KNAMELEN, "%d.%d.%draw", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); 
		devdir(c, q, name, 128, eve, 0444, dp); 
2001/0809    
		sprint(up->genbuf, "%d.%d.%draw", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); 
		devdir(c, q, up->genbuf, 128, eve, 0444, dp); 
2001/0801    
		return 1; 
	} 
	return -1; 
2001/0801/sys/src/9/port/devpnp.c:367,3802001/0809/sys/src/9/port/devpnp.c:381,393
2001/0728    
	Card *cp; 
2001/0801    
	Pcidev *p; 
	int csn, tbdf; 
	static char name[KNAMELEN]; 
2001/0728    
 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
		if(s == DEVDOTDOT){ 
			q = (Qid){QID(0, Qtopdir), 0, QTDIR}; 
			snprint(name, KNAMELEN, "#%C", pnpdevtab.dc); 
			devdir(c, q, name, 0, eve, 0555, dp); 
2001/0809    
			sprint(up->genbuf, "#%C", pnpdevtab.dc); 
			devdir(c, q, up->genbuf, 0, eve, 0555, dp); 
2001/0728    
			return 1; 
		} 
		return devgen(c, nil, topdir, nelem(topdir), s, dp); 
2001/0801/sys/src/9/port/devpnp.c:381,4002001/0809/sys/src/9/port/devpnp.c:394,413
2001/0728    
	case Qpnpdir: 
		if(s == DEVDOTDOT){ 
			q = (Qid){QID(0, Qtopdir), 0, QTDIR}; 
			snprint(name, KNAMELEN, "#%C", pnpdevtab.dc); 
			devdir(c, q, name, 0, eve, 0555, dp); 
2001/0809    
			sprint(up->genbuf, "#%C", pnpdevtab.dc); 
			devdir(c, q, up->genbuf, 0, eve, 0555, dp); 
2001/0728    
			return 1; 
		} 
2001/0731    
		if(s < nelem(pnpdir)-1) 
2001/0728    
			return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp); 
2001/0731    
		s -= nelem(pnpdir)-1; 
2001/0728    
		ilock(&pnp); 
2001/0809    
		qlock(&pnp); 
2001/0728    
		cp = pnp.cards; 
		while(s >= 2 && cp != nil) { 
			s -= 2; 
			cp = cp->next; 
		} 
		iunlock(&pnp); 
2001/0809    
		qunlock(&pnp); 
2001/0728    
		if(cp == nil) 
			return -1; 
2001/0801    
		return csngen(c, s+Qcsnctl, cp->csn, cp, dp); 
2001/0801/sys/src/9/port/devpnp.c:403,4112001/0809/sys/src/9/port/devpnp.c:416,422
2001/0728    
	case Qcsnctl: 
	case Qcsnraw: 
		csn = CSN(c->qid); 
		ilock(&pnp); 
		cp = findcsn(csn, 0); 
		iunlock(&pnp); 
2001/0809    
		cp = findcsn(csn, 0, 1); 
2001/0728    
		if(cp == nil) 
			return -1; 
2001/0801    
		return csngen(c, TYPE(c->qid), csn, cp, dp); 
2001/0801/sys/src/9/port/devpnp.c:412,4192001/0809/sys/src/9/port/devpnp.c:423,430
2001/0801    
	case Qpcidir: 
		if(s == DEVDOTDOT){ 
			q = (Qid){QID(0, Qtopdir), 0, QTDIR}; 
			snprint(name, KNAMELEN, "#%C", pnpdevtab.dc); 
			devdir(c, q, name, 0, eve, 0555, dp); 
2001/0809    
			sprint(up->genbuf, "#%C", pnpdevtab.dc); 
			devdir(c, q, up->genbuf, 0, eve, 0555, dp); 
2001/0801    
			return 1; 
		} 
		p = pcimatch(nil, 0, 0); 
2001/0801/sys/src/9/port/devpnp.c:477,4832001/0809/sys/src/9/port/devpnp.c:488,494
2001/0728    
	Card *cp; 
2001/0801    
	Pcidev *p; 
	int csn, i, tbdf; 
	char *a = va, buf[256]; 
2001/0809    
	char *a = va; 
2001/0728    
 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
2001/0801/sys/src/9/port/devpnp.c:486,5052001/0809/sys/src/9/port/devpnp.c:497,514
2001/0728    
		return devdirread(c, a, n, (Dirtab *)0, 0L, pnpgen); 
	case Qpnpctl: 
		if(pnp.rddata > 0) 
			sprint(buf, "enabled 0x%x\n", pnp.rddata); 
2001/0809    
			sprint(up->genbuf, "enabled 0x%x\n", pnp.rddata); 
2001/0728    
		else 
			sprint(buf, "disabled\n"); 
		return readstr(offset, a, n, buf); 
2001/0809    
			sprint(up->genbuf, "disabled\n"); 
		return readstr(offset, a, n, up->genbuf); 
2001/0728    
	case Qcsnraw: 
		csn = CSN(c->qid); 
		ilock(&pnp); 
		cp = findcsn(csn, 0); 
		iunlock(&pnp); 
2001/0809    
		cp = findcsn(csn, 0, 1); 
2001/0728    
		if(cp == nil) 
			error(Egreg); 
		if(offset+n > cp->ncfg) 
			n = cp->ncfg - offset; 
		ilock(&pnp); 
2001/0809    
		qlock(&pnp); 
2001/0728    
		initiation(); 
		cmd(0x03, csn);				/* Wake up the card */ 
		for (i = 0; i < offset+9; i++)		/* 9 == skip serial + csum */ 
2001/0801/sys/src/9/port/devpnp.c:508,5322001/0809/sys/src/9/port/devpnp.c:517,539
2001/0728    
			a[i] = getresbyte(pnp.rddata); 
		cmd(0x03, 0);					/* Wake all cards with a CSN of 0, putting this card to sleep */ 
		cmd(0x02, 0x02);				/* return cards to Wait for Key state */ 
		iunlock(&pnp); 
2001/0809    
		qunlock(&pnp); 
2001/0728    
		break; 
	case Qcsnctl: 
		csn = CSN(c->qid); 
		ilock(&pnp); 
		cp = findcsn(csn, 0); 
		iunlock(&pnp); 
2001/0809    
		cp = findcsn(csn, 0, 1); 
2001/0728    
		if(cp == nil) 
			error(Egreg); 
		sprint(buf, "%s\n", serial(cp->id1, cp->id2)); 
		return readstr(offset, a, n, buf); 
2001/0809    
		sprint(up->genbuf, "%s\n", serial(cp->id1, cp->id2)); 
		return readstr(offset, a, n, up->genbuf); 
2001/0801    
	case Qpcictl: 
		tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); 
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			error(Egreg); 
		snprint(buf, sizeof(buf), "class %.2x subclass %.2x piclass %.2x vid %.4x did %.4x intl %d\n", 
2001/0809    
		sprint(up->genbuf, "class %.2x subclass %.2x piclass %.2x vid %.4x did %.4x intl %d\n", 
2001/0801    
			p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl); 
		return readstr(offset, a, n, buf); 
2001/0809    
		return readstr(offset, a, n, up->genbuf); 
2001/0801    
	case Qpciraw: 
		tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); 
		p = pcimatchtbdf(tbdf); 
2001/0801/sys/src/9/port/devpnp.c:558,5652001/0809/sys/src/9/port/devpnp.c:565,580
2001/0731    
			port = strtoul(buf+5, 0, 0); 
2001/0728    
			if(port < 0x203 || port > 0x3ff) 
				error("bad value for rddata port"); 
2001/0809    
			qlock(&pnp); 
			if(waserror()) { 
				qunlock(&pnp); 
				nexterror(); 
			} 
			if(pnp.rddata > 0) 
				error("pnp port already set"); 
2001/0731    
			if(!pnpscan(port, 0)) 
2001/0728    
				error("no cards found"); 
2001/0809    
			qunlock(&pnp); 
2001/0728    
		} 
		else if(strncmp(buf, "debug ", 6) == 0) 
			pnp.debug = strtoul(buf+6, 0, 0); 
2001/0801/sys/src/9/port/devpnp.c:568,5762001/0809/sys/src/9/port/devpnp.c:583,589
2001/0728    
		break; 
2001/0731    
	case Qcsnctl: 
		csn = CSN(c->qid); 
		ilock(&pnp); 
		cp = findcsn(csn, 0); 
		iunlock(&pnp); 
2001/0809    
		cp = findcsn(csn, 0, 1); 
2001/0731    
		if(cp == nil) 
			error(Egreg); 
		if(!wrconfig(cp, buf)) 
2001/0809/sys/src/9/port/devpnp.c:624,6292002/0109/sys/src/9/port/devpnp.c:624,630 (short | long)
Add devshutdown.
rsc Fri Mar 4 12:44:25 2005
2001/0728    
 
	pnpreset, 
	devinit, 
2002/0109    
	devshutdown, 
2001/0728    
	pnpattach, 
	pnpwalk, 
	pnpstat, 
2002/0109/sys/src/9/port/devpnp.c:485,4942002/0414/sys/src/9/port/devpnp.c:485,496 (short | long)
2001/0728    
static long 
pnpread(Chan *c, void *va, long n, vlong offset) 
{ 
2002/0414    
	ulong x; 
2001/0728    
	Card *cp; 
2001/0801    
	Pcidev *p; 
	int csn, i, tbdf; 
2002/0414    
	char buf[256], *ebuf, *w; 
2001/0809    
	char *a = va; 
2002/0414    
	int csn, i, tbdf, r; 
2001/0728    
 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
2002/0109/sys/src/9/port/devpnp.c:511,5192002/0414/sys/src/9/port/devpnp.c:513,521
2001/0809    
		qlock(&pnp); 
2001/0728    
		initiation(); 
		cmd(0x03, csn);				/* Wake up the card */ 
		for (i = 0; i < offset+9; i++)		/* 9 == skip serial + csum */ 
2002/0414    
		for(i = 0; i < offset+9; i++)		/* 9 == skip serial + csum */ 
2001/0728    
			getresbyte(pnp.rddata); 
		for (i = 0; i < n; i++) 
2002/0414    
		for(i = 0; i < n; i++) 
2001/0728    
			a[i] = getresbyte(pnp.rddata); 
		cmd(0x03, 0);					/* Wake all cards with a CSN of 0, putting this card to sleep */ 
		cmd(0x02, 0x02);				/* return cards to Wait for Key state */ 
2002/0109/sys/src/9/port/devpnp.c:531,5452002/0414/sys/src/9/port/devpnp.c:533,571
2001/0801    
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			error(Egreg); 
2001/0809    
		sprint(up->genbuf, "class %.2x subclass %.2x piclass %.2x vid %.4x did %.4x intl %d\n", 
2002/0414    
		ebuf = buf+sizeof buf-1;	/* -1 for newline */ 
		w = seprint(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d", 
2001/0801    
			p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl); 
2001/0809    
		return readstr(offset, a, n, up->genbuf); 
2002/0414    
		for(i=0; i<nelem(p->mem); i++){ 
			if(p->mem[i].size == 0) 
				continue; 
			w = seprint(w, ebuf, " %d:%.8lux %d", i, p->mem[i].bar, p->mem[i].size); 
		} 
		*w++ = '\n'; 
		*w = '\0'; 
		return readstr(offset, a, n, buf); 
2001/0801    
	case Qpciraw: 
		tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); 
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			error(Egreg); 
		break; 
2002/0414    
		if(offset > 128) 
			return 0; 
		if(n+offset > 128) 
			n = 128-offset; 
		if(offset%4) 
			error(Ebadarg); 
		r = offset; 
		for(i = 0; i+4 <= n; i+=4) { 
			x = pcicfgr32(p, r); 
			a[0] = x; 
			a[1] = (x>>8); 
			a[2] = (x>>16); 
			a[3] = (x>>24); 
			a += 4; 
			r += 4; 
		} 
		return i; 
2001/0728    
	default: 
		error(Egreg); 
	} 
2002/0414/sys/src/9/port/devpnp.c:549,5582002/0416/sys/src/9/port/devpnp.c:549,558 (short | long)
2001/0801    
		p = pcimatchtbdf(tbdf); 
		if(p == nil) 
			error(Egreg); 
2002/0414    
		if(offset > 128) 
2002/0416    
		if(offset > 256) 
2002/0414    
			return 0; 
		if(n+offset > 128) 
			n = 128-offset; 
2002/0416    
		if(n+offset > 256) 
			n = 256-offset; 
2002/0414    
		if(offset%4) 
			error(Ebadarg); 
		r = offset; 
2002/0416/sys/src/9/port/devpnp.c:3,132002/0427/sys/src/9/port/devpnp.c:3,12 (short | long)
2001/0809    
 * 
 *	TODO 
 *		- implement PNP card configuration (setting io bases etc) 
 *		- implement PCI raw access to configuration space 
2002/0427    
 *		- write user program to drive PNP configuration... 
 *		- extend PCI raw access to configuration space (writes, byte/short access?) 
2001/0809    
 *		- implement PCI access to memory/io space/BIOS ROM 
 *		- use c->aux instead of performing lookup on each read/write 
 * 
 *	I also need to write the user program that'll drive the PNP configuration... 
2002/0427    
 *		- use c->aux instead of performing lookup on each read/write? 
2001/0809    
 */ 
2001/0728    
#include	"u.h" 
#include	"../port/lib.h" 
2002/0416/sys/src/9/port/devpnp.c:601,6062002/0427/sys/src/9/port/devpnp.c:600,606
2001/0731    
			if(!pnpscan(port, 0)) 
2001/0728    
				error("no cards found"); 
2001/0809    
			qunlock(&pnp); 
2002/0427    
			poperror(); 
2001/0728    
		} 
		else if(strncmp(buf, "debug ", 6) == 0) 
			pnp.debug = strtoul(buf+6, 0, 0); 
2002/0416/sys/src/9/port/devpnp.c:624,6452002/0427/sys/src/9/port/devpnp.c:624,631
2001/0731    
static int 
wrconfig(Card *c, char *cmd) 
{ 
	for(;;) { 
		while(*cmd == ' ' || *cmd == '\t' || *cmd == '\n') 
			cmd++; 
		if(*cmd == '\0') 
			break; 
		if(strncmp(cmd, "foo ", 4) == 0) { 
			print("pnp%d: got foo\n", c->csn); 
			cmd += 4; 
		} 
		else if(strncmp(cmd, "bar ", 4) == 0) { 
			print("pnp%d: got bar\n", c->csn); 
			cmd += 4; 
		} 
		else 
			return 0; 
	} 
2002/0427    
	/* This should implement setting of I/O bases, etc */ 
	USED(c, cmd); 
2001/0731    
	return 1; 
} 
 
2002/0427/sys/src/9/port/devpnp.c:127,1472003/0406/sys/src/9/port/devpnp.c:127,147 (short | long)
2001/0728    
	outb(Address, 0x01);	/* point to serial isolation register */ 
	delay(1); 
	csum = 0x6a; 
	for (i = 0; i < 64; i++) { 
2003/0406    
	for(i = 0; i < 64; i++){ 
2001/0728    
		bit = readbit(rddata); 
		csum = (csum>>1) | (((csum&1) ^ ((csum>>1)&1) ^ bit)<<7); 
		p = &id[i>>3]; 
		*p = (*p>>1) | (bit<<7); 
	} 
	for (; i < 72; i++) { 
2003/0406    
	for(; i < 72; i++){ 
2001/0728    
		p = &id[i>>3]; 
		*p = (*p>>1) | (readbit(rddata)<<7); 
	} 
	*id1 = (id[3]<<24)|(id[2]<<16)|(id[1]<<8)|id[0]; 
	*id2 = (id[7]<<24)|(id[6]<<16)|(id[5]<<8)|id[4]; 
	if (*id1 == 0) 
2003/0406    
	if(*id1 == 0) 
2001/0728    
		return 0; 
	if (id[8] != csum) 
2003/0406    
	if(id[8] != csum) 
2001/0728    
		DPRINT("pnp: bad checksum id1 %lux id2 %lux csum %x != %x\n", *id1, *id2, csum, id[8]); /**/ 
	return id[8] == csum; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)