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

2001/0905/port/devsd.c (diff list | history)

2001/0613/sys/src/9/port/devsd.c:15,262001/0905/sys/src/9/port/devsd.c:15,29 (short | long | prev | next)
2000/0506    
extern Dev sddevtab; 
extern SDifc* sdifc[]; 
 
static QLock sdqlock; 
static SDev* sdlist; 
static SDunit** sdunit; 
static int* sdunitflg; 
static int sdnunit; 
2001/0905    
typedef struct { 
	SDev 	*dt_dev; 
	int		dt_nunits;		/* num units in dev */ 
} dev_t; 
2000/0506    
 
2001/0905    
static dev_t 	*devs;		/* all devices */ 
static QLock	devslock;		/* insertion and removal of devices */ 
static int		ndevs;		/* total number of devices in the system */ 
 
2000/0506    
enum { 
	Rawcmd, 
	Rawdata, 
2001/0613/sys/src/9/port/devsd.c:30,352001/0905/sys/src/9/port/devsd.c:33,40
2000/0506    
enum { 
	Qtopdir		= 1,		/* top level directory */ 
	Qtopbase, 
2001/0905    
	Qtopctl = Qtopbase, 
	Qtopstat, 
1994/0913    
 
2000/0506    
	Qunitdir,			/* directory per unit */ 
	Qunitbase, 
2001/0613/sys/src/9/port/devsd.c:51,632001/0905/sys/src/9/port/devsd.c:56,78
2001/0613    
	NUnit		= (1<<UnitLOG), 
	UnitMASK	= (NUnit-1), 
	UnitSHIFT	= (PartLOG+TypeLOG), 
2001/0905    
 
	DevLOG		= 8, 
	NDev		= (1 << DevLOG), 
	DevMASK	= (NDev-1), 
	DevSHIFT = (UnitLOG+PartLOG+TypeLOG), 
 
	Ncmd = 20, 
1994/0913    
}; 
 
2001/0613    
#define TYPE(q)		((((ulong)(q).path)>>TypeSHIFT) & TypeMASK) 
#define PART(q)		((((ulong)(q).path)>>PartSHIFT) & PartMASK) 
#define UNIT(q)		((((ulong)(q).path)>>UnitSHIFT) & UnitMASK) 
#define QID(u, p, t)	(((u)<<UnitSHIFT)|((p)<<PartSHIFT)|((t)<<TypeSHIFT)) 
2001/0905    
#define DEV(q)			((((ulong)(q).path)>>DevSHIFT) & DevMASK) 
#define QID(d,u, p, t)	(((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\ 
					 ((p)<<PartSHIFT)|((t)<<TypeSHIFT)) 
2000/0506    
 
2001/0905    
 
2000/0506    
static void 
sdaddpart(SDunit* unit, char* name, ulong start, ulong end) 
1994/0913    
{ 
2001/0613/sys/src/9/port/devsd.c:206,2152001/0905/sys/src/9/port/devsd.c:221,250
1994/0913    
	return 1; 
} 
 
2001/0905    
static SDev * 
sdgetdev(int idno) 
{ 
	SDev *sdev; 
	int i; 
 
	qlock(&devslock); 
	for (i = 0; i != ndevs; i++) 
		if (devs[i].dt_dev->idno == idno) 
			break; 
	 
	if (i == ndevs) 
		sdev = nil; 
	else { 
		sdev = devs[i].dt_dev; 
		incref(&sdev->r); 
	} 
	qunlock(&devslock); 
	return sdev; 
} 
 
2000/0506    
static SDunit* 
sdgetunit(SDev* sdev, int subno) 
1994/0913    
{ 
2000/0506    
	int index; 
	SDunit *unit; 
2001/0527    
	char buf[32]; 
1994/0913    
 
2001/0613/sys/src/9/port/devsd.c:219,2412001/0905/sys/src/9/port/devsd.c:254,280
2000/0506    
	 * The device will be probed if it has not already been 
	 * successfully accessed. 
	 */ 
	qlock(&sdqlock); 
	index = sdev->index+subno; 
	unit = sdunit[index]; 
2001/0905    
	qlock(&sdev->unitlock); 
	if (subno > sdev->nunit) { 
		qunlock(&sdev->unitlock); 
		return nil; 
	} 
 
	unit = sdev->unit[subno]; 
2000/0506    
	if(unit == nil){ 
1995/0405    
		/* 
2000/0506    
		 * Probe the unit only once. This decision 
		 * may be a little severe and reviewed later. 
1995/0405    
		 */ 
2000/0506    
		if(sdunitflg[index]){ 
			qunlock(&sdqlock); 
2001/0905    
		if(sdev->unitflg[subno]){ 
			qunlock(&sdev->unitlock); 
2000/0506    
			return nil; 
		} 
		if((unit = malloc(sizeof(SDunit))) == nil){ 
			qunlock(&sdqlock); 
2001/0905    
			qunlock(&sdev->unitlock); 
2000/0506    
			return nil; 
		} 
		sdunitflg[index] = 1; 
2001/0905    
		sdev->unitflg[subno] = 1; 
1995/0329    
 
2000/0506    
		if(sdev->enabled == 0 && sdev->ifc->enable) 
			sdev->ifc->enable(sdev); 
2001/0613/sys/src/9/port/devsd.c:254,2952001/0905/sys/src/9/port/devsd.c:293,313
2000/0506    
		 * sdunit[] array. 
		 */ 
		if(unit->dev->ifc->verify(unit) == 0){ 
			qunlock(&sdqlock); 
2001/0905    
			qunlock(&sdev->unitlock); 
2000/0506    
			free(unit); 
			return nil; 
		} 
		sdunit[index] = unit; 
2001/0905    
		sdev->unit[subno] = unit; 
2000/0506    
	} 
	qunlock(&sdqlock); 
1998/0930    
                 
2001/0905    
	qunlock(&sdev->unitlock); 
2000/0506    
	return unit; 
} 
1994/0913    
 
2000/0506    
static SDunit* 
sdindex2unit(int index) 
{ 
	SDev *sdev; 
1994/0913    
                 
2000/0506    
	/* 
	 * Associate a unit with a given index into the top-level 
	 * device directory. 
	 * The device will be probed if it has not already been 
	 * successfully accessed. 
	 */ 
	for(sdev = sdlist; sdev != nil; sdev = sdev->next){ 
		if(index >= sdev->index && index < sdev->index+sdev->nunit) 
			return sdgetunit(sdev, index-sdev->index); 
	} 
1995/0403    
                 
2000/0506    
	return nil; 
1995/0403    
                 
2000/0506    
} 
1995/0403    
                 
2000/0506    
static void 
sdreset(void) 
{ 
	int i; 
	SDev *sdev, *tail; 
2001/0905    
	SDev *sdev, *tail, *sdlist; 
2000/0506    
 
	/* 
	 * Probe all configured controllers and make a list 
2001/0613/sys/src/9/port/devsd.c:297,3032001/0905/sys/src/9/port/devsd.c:315,321
2000/0506    
	 * of units attached and marking each device with an index 
	 * into the linear top-level directory array of units. 
	 */ 
	tail = nil; 
2001/0905    
	tail = sdlist = nil; 
2000/0506    
	for(i = 0; sdifc[i] != nil; i++){ 
		if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil) 
			continue; 
2001/0613/sys/src/9/port/devsd.c:305,3182001/0905/sys/src/9/port/devsd.c:323,333
2000/0506    
			tail->next = sdev; 
		else 
			sdlist = sdev; 
		for(tail = sdev; tail->next != nil; tail = tail->next){ 
			sdev->index = sdnunit; 
			sdnunit += tail->nunit; 
1994/0913    
		} 
2000/0506    
		tail->index = sdnunit; 
		sdnunit += tail->nunit; 
2001/0905    
		for(tail = sdev; tail->next != nil; tail = tail->next) 
			ndevs++; 
		ndevs++; 
2000/0506    
	} 
1994/0913    
                 
2001/0905    
	 
2000/0506    
	/* 
	 * Legacy and option code goes here. This will be hard... 
	 */ 
2001/0613/sys/src/9/port/devsd.c:323,3392001/0905/sys/src/9/port/devsd.c:338,345
2000/0506    
	 * probed and structures allocated when attached. 
	 * Allocate controller names for the different types. 
	 */ 
	if(sdnunit == 0) 
2001/0905    
	if(ndevs == 0) 
2000/0506    
		return; 
2001/0613    
	if(sdnunit > NUnit) 
		sdnunit = NUnit; 
2000/0506    
	if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil) 
		return; 
	if((sdunitflg = malloc(sdnunit*sizeof(int))) == nil){ 
		free(sdunit); 
		sdunit = nil; 
		return; 
	} 
	for(i = 0; sdifc[i] != nil; i++){ 
2000/0515    
		/* 
		 * BUG: no check is made here or later when a 
2001/0613/sys/src/9/port/devsd.c:342,3472001/0905/sys/src/9/port/devsd.c:348,368
2000/0506    
		if(sdifc[i]->id) 
			sdifc[i]->id(sdlist); 
	} 
2001/0905    
 
	/*  
	  * The IDs have been set, unlink the sdlist and copy the spec to 
	  * the devtab. 
	  */ 
	devs = (dev_t *)malloc(ndevs * sizeof(dev_t)); 
	memset(devs, 0, ndevs * sizeof(dev_t)); 
	i = 0; 
	while (sdlist != nil) { 
		devs[i].dt_dev = sdlist; 
		devs[i].dt_nunits = sdlist->nunit; 
		sdlist = sdlist->next; 
		devs[i].dt_dev->next = nil; 
		i++; 
	} 
2000/0506    
} 
 
static int 
2001/0613/sys/src/9/port/devsd.c:352,3622001/0905/sys/src/9/port/devsd.c:373,390
2000/0506    
	SDpart *pp; 
2000/0706    
	SDperm *perm; 
2000/0506    
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
	int rv; 
2000/0506    
 
2000/0617    
	unit = sdunit[UNIT(c->qid)]; 
2001/0905    
	sdev = sdgetdev(DEV(c->qid)); 
	assert(sdev); 
	unit = sdev->unit[UNIT(c->qid)]; 
 
	rv = -1; 
2000/0506    
	switch(i){ 
	case Qctl: 
2001/0527    
		mkqid(&q, QID(UNIT(c->qid), PART(c->qid), Qctl), unit->vers, QTFILE); 
2001/0905    
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),  
			   unit->vers, QTFILE); 
2000/0706    
		perm = &unit->ctlperm; 
2001/0527    
		if(emptystr(perm->user)){ 
			kstrdup(&perm->user, eve); 
2001/0613/sys/src/9/port/devsd.c:363,3712001/0905/sys/src/9/port/devsd.c:391,402
2000/0706    
			perm->perm = 0640; 
		} 
		devdir(c, q, "ctl", 0, perm->user, perm->perm, dp); 
2000/0506    
		return 1; 
2001/0905    
		rv = 1; 
		break; 
 
2000/0506    
	case Qraw: 
2001/0527    
		mkqid(&q, QID(UNIT(c->qid), PART(c->qid), Qraw), unit->vers, QTFILE); 
2001/0905    
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),  
			   unit->vers, QTFILE); 
2000/0706    
		perm = &unit->rawperm; 
2001/0527    
		if(emptystr(perm->user)){ 
			kstrdup(&perm->user, eve); 
2001/0613/sys/src/9/port/devsd.c:372,3962001/0905/sys/src/9/port/devsd.c:403,441
2001/0527    
			perm->perm = DMEXCL|0600; 
2000/0706    
		} 
		devdir(c, q, "raw", 0, perm->user, perm->perm, dp); 
2000/0506    
		return 1; 
2001/0905    
		rv = 1; 
		break; 
 
2000/0506    
	case Qpart: 
		pp = &unit->part[PART(c->qid)]; 
		l = (pp->end - pp->start) * (vlong)unit->secsize; 
2001/0527    
		mkqid(&q, QID(UNIT(c->qid), PART(c->qid), Qpart), unit->vers+pp->vers, QTFILE); 
2001/0905    
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),  
			   unit->vers+pp->vers, QTFILE); 
2001/0527    
		if(emptystr(pp->user)) 
			kstrdup(&pp->user, eve); 
2000/0506    
		devdir(c, q, pp->name, l, pp->user, pp->perm, dp); 
		return 1; 
	}	 
	return -1; 
2001/0905    
		rv = 1; 
		break; 
	} 
	 
	decref(&sdev->r); 
	return rv; 
2000/0506    
} 
 
static int 
sd1gen(Chan*, int i, Dir*) 
2001/0905    
sd1gen(Chan* c, int i, Dir* dp) 
2000/0506    
{ 
2001/0905    
	Qid q; 
 
2000/0506    
	switch(i){ 
	default: 
		return -1; 
2001/0905    
	case Qtopctl: 
		mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE); 
		devdir(c, q, "sdctl", 0, eve, 0640, dp); 
		return 1; 
	case Qtopstat: 
		mkqid(&q, QID(0, 0, 0, Qtopstat), 0, QTFILE); 
		devdir(c, q, "sdstat", 0, eve, 0640, dp); 
		return 1; 
2000/0506    
	} 
	return -1; 
} 
2001/0613/sys/src/9/port/devsd.c:403,4382001/0905/sys/src/9/port/devsd.c:448,517
2000/0506    
	int i, r; 
	SDpart *pp; 
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
2000/0506    
 
	switch(TYPE(c->qid)){ 
	case Qtopdir: 
2001/0905    
	case Qtopdir: { 
2000/0506    
		if(s == DEVDOTDOT){ 
2001/0527    
			mkqid(&q, QID(s, 0, Qtopdir), 0, QTDIR); 
2001/0905    
			mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); 
2001/0527    
			sprint(up->genbuf, "#%C", sddevtab.dc); 
			devdir(c, q, up->genbuf, 0, eve, 0555, dp); 
2000/0506    
			return 1; 
1994/0913    
		} 
2000/0506    
		if(s < sdnunit){ 
2000/0706    
			if((unit = sdunit[s]) == nil){ 
				if((unit = sdindex2unit(s)) == nil) 
					return 0; 
			} 
2001/0527    
			mkqid(&q, QID(s, 0, Qunitdir), 0, QTDIR); 
			if(emptystr(unit->user)) 
				kstrdup(&unit->user, eve); 
2000/0706    
			devdir(c, q, unit->name, 0, unit->user, unit->perm, dp); 
2000/0506    
			return 1; 
2001/0905    
 
		if (s == 0 || s == 1) 
			return sd1gen(c, s + Qtopbase, dp); 
		s -= 2; 
 
		qlock(&devslock); 
		for (i = 0; i != ndevs; i++) { 
			if (s < devs[i].dt_nunits) 
				break; 
			s -= devs[i].dt_nunits; 
2000/0506    
		} 
		s -= sdnunit; 
		return sd1gen(c, s+Qtopbase, dp); 
2001/0905    
		 
		if (i == ndevs) { 
			/* Run of the end of the list */ 
			qunlock(&devslock); 
			return -1; 
		} 
 
		if ((sdev = devs[i].dt_dev) == nil) { 
			qunlock(&devslock); 
			return 0; 
		} 
 
		incref(&sdev->r); 
		qunlock(&devslock); 
 
		if((unit = sdev->unit[s]) == nil) 
			if((unit = sdgetunit(sdev, s)) == nil) { 
				decref(&sdev->r); 
				return 0; 
			} 
 
		mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR); 
		if(emptystr(unit->user)) 
			kstrdup(&unit->user, eve); 
		devdir(c, q, unit->name, 0, unit->user, unit->perm, dp); 
		decref(&sdev->r); 
		return 1; 
	} 
 
2000/0506    
	case Qunitdir: 
		if(s == DEVDOTDOT){ 
2001/0527    
			mkqid(&q, QID(s, 0, Qtopdir), 0, QTDIR); 
2001/0905    
			mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR); 
2001/0527    
			sprint(up->genbuf, "#%C", sddevtab.dc); 
			devdir(c, q, up->genbuf, 0, eve, 0555, dp); 
2000/0506    
			return 1; 
		} 
		unit = sdunit[UNIT(c->qid)]; 
2001/0905    
		 
		if ((sdev = sdgetdev(DEV(c->qid))) == nil) { 
			devdir(c, q, "unavailable", 0, eve, 0, dp); 
			return 1; 
		} 
 
		unit = sdev->unit[UNIT(c->qid)]; 
2000/0506    
		qlock(&unit->ctl); 
2000/0617    
 
		/* 
2001/0613/sys/src/9/port/devsd.c:450,4812001/0905/sys/src/9/port/devsd.c:529,570
2000/0506    
		if(i < Qpart){ 
			r = sd2gen(c, i, dp); 
			qunlock(&unit->ctl); 
2001/0905    
			decref(&sdev->r); 
2000/0506    
			return r; 
		} 
		i -= Qpart; 
2000/0809    
		if(unit->part == nil || i >= unit->npart){ 
2000/0506    
			qunlock(&unit->ctl); 
2001/0905    
			decref(&sdev->r); 
2000/0506    
			break; 
		} 
		pp = &unit->part[i]; 
2000/0617    
		if(!pp->valid){ 
2000/0506    
			qunlock(&unit->ctl); 
2001/0905    
			decref(&sdev->r); 
2000/0506    
			return 0; 
		} 
		l = (pp->end - pp->start) * (vlong)unit->secsize; 
2001/0527    
		mkqid(&q, QID(UNIT(c->qid), i, Qpart), unit->vers+pp->vers, QTFILE); 
2001/0905    
		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),  
			    unit->vers+pp->vers, QTFILE); 
2001/0527    
		if(emptystr(pp->user)) 
			kstrdup(&pp->user, eve); 
2000/0506    
		devdir(c, q, pp->name, l, pp->user, pp->perm, dp); 
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		return 1; 
	case Qraw: 
	case Qctl: 
	case Qpart: 
		unit = sdunit[UNIT(c->qid)]; 
2001/0905    
		if ((sdev = sdgetdev(DEV(c->qid))) == nil) { 
			devdir(c, q, "unavailable", 0, eve, 0, dp); 
			return 1; 
		} 
		unit = sdev->unit[UNIT(c->qid)]; 
2000/0506    
		qlock(&unit->ctl); 
		r = sd2gen(c, TYPE(c->qid), dp); 
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		return r; 
	default: 
		break; 
2001/0613/sys/src/9/port/devsd.c:490,5002001/0905/sys/src/9/port/devsd.c:579,589
2000/0506    
	Chan *c; 
	char *p; 
	SDev *sdev; 
	int idno, subno; 
2001/0905    
	int idno, subno, i; 
1994/0913    
 
2000/0506    
	if(sdnunit == 0 || *spec == '\0'){ 
2001/0905    
	if(ndevs == 0 || *spec == '\0'){ 
2000/0506    
		c = devattach(sddevtab.dc, spec); 
2001/0527    
		mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR); 
2001/0905    
		mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR); 
2000/0506    
		return c; 
1996/0607    
	} 
1998/0512    
 
2001/0613/sys/src/9/port/devsd.c:504,5192001/0905/sys/src/9/port/devsd.c:593,615
2000/0506    
	subno = strtol(&spec[3], &p, 0); 
	if(p == &spec[3]) 
		error(Ebadspec); 
	for(sdev = sdlist; sdev != nil; sdev = sdev->next){ 
		if(sdev->idno == idno && subno < sdev->nunit) 
2001/0905    
 
	qlock(&devslock); 
	for (sdev = nil, i = 0; i != ndevs; i++) 
		if ((sdev = devs[i].dt_dev) != nil && sdev->idno == idno) 
2000/0506    
			break; 
	} 
	if(sdev == nil || sdgetunit(sdev, subno) == nil) 
2001/0905    
 
	if (i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil) { 
		qunlock(&devslock); 
2000/0506    
		error(Enonexist); 
2001/0905    
	} 
	incref(&sdev->r); 
	qunlock(&devslock); 
2000/0506    
 
	c = devattach(sddevtab.dc, spec); 
2001/0527    
	mkqid(&c->qid, QID(sdev->index+subno, 0, Qunitdir), 0, QTDIR); 
2000/0506    
	c->dev = sdev->index+subno; 
2001/0905    
	mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR); 
	c->dev = (sdev->idno << UnitLOG) + subno; 
	decref(&sdev->r); 
2000/0506    
	return c; 
1994/0913    
} 
 
2001/0613/sys/src/9/port/devsd.c:534,5502001/0905/sys/src/9/port/devsd.c:630,652
1994/0913    
{ 
2000/0506    
	SDpart *pp; 
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
	uchar tp; 
2000/0506    
 
	c = devopen(c, omode, 0, 0, sdgen); 
2001/0905    
	if ((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart) 
		return c; 
 
	sdev = sdgetdev(DEV(c->qid)); 
	if (sdev == nil) 
		error(Enonexist); 
	unit = sdev->unit[UNIT(c->qid)]; 
 
2000/0506    
	switch(TYPE(c->qid)){ 
	default: 
		break; 
2000/0617    
	case Qctl: 
		unit = sdunit[UNIT(c->qid)]; 
		c->qid.vers = unit->vers; 
		break; 
2000/0526    
	case Qraw: 
		unit = sdunit[UNIT(c->qid)]; 
2000/0617    
		c->qid.vers = unit->vers; 
2000/0531    
		if(!canlock(&unit->rawinuse)){ 
			c->flag &= ~COPEN; 
2001/0613/sys/src/9/port/devsd.c:553,5592001/0905/sys/src/9/port/devsd.c:655,660
2000/0526    
		unit->state = Rawcmd; 
		break; 
2000/0506    
	case Qpart: 
		unit = sdunit[UNIT(c->qid)]; 
		qlock(&unit->ctl); 
		if(waserror()){ 
			qunlock(&unit->ctl); 
2001/0613/sys/src/9/port/devsd.c:566,5712001/0905/sys/src/9/port/devsd.c:667,673
2000/0506    
		poperror(); 
		break; 
	} 
2001/0905    
	decref(&sdev->r); 
2000/0506    
	return c; 
1994/0913    
} 
 
2001/0613/sys/src/9/port/devsd.c:573,5782001/0905/sys/src/9/port/devsd.c:675,681
2000/0506    
sdclose(Chan* c) 
1994/0913    
{ 
2000/0506    
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
1994/0913    
 
2001/0527    
	if(c->qid.type & QTDIR) 
1994/0913    
		return; 
2001/0613/sys/src/9/port/devsd.c:583,5902001/0905/sys/src/9/port/devsd.c:686,697
2000/0506    
	default: 
		break; 
	case Qraw: 
		unit = sdunit[UNIT(c->qid)]; 
2000/0526    
		unlock(&unit->rawinuse); 
2001/0905    
		sdev = sdgetdev(DEV(c->qid)); 
		if (sdev) { 
			unit = sdev->unit[UNIT(c->qid)]; 
			unlock(&unit->rawinuse); 
			decref(&sdev->r); 
		} 
2000/0506    
		break; 
1996/0607    
	} 
1994/0913    
} 
2001/0613/sys/src/9/port/devsd.c:597,6052001/0905/sys/src/9/port/devsd.c:704,718
2000/0506    
	uchar *b; 
	SDpart *pp; 
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
2000/0506    
	ulong bno, max, nb, offset; 
1998/0319    
 
2000/0506    
	unit = sdunit[UNIT(c->qid)]; 
2001/0905    
	sdev = sdgetdev(DEV(c->qid)); 
	if (sdev == nil) 
		error(Enonexist); 
	unit = sdev->unit[UNIT(c->qid)]; 
	if (unit == nil) 
		error(Enonexist); 
1994/0913    
 
2000/0617    
	nchange = 0; 
2000/0506    
	qlock(&unit->ctl); 
2001/0613/sys/src/9/port/devsd.c:612,6172001/0905/sys/src/9/port/devsd.c:725,731
2000/0617    
 
		/* other errors; give up */ 
2000/0506    
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		nexterror(); 
	} 
2000/0617    
	pp = &unit->part[PART(c->qid)]; 
2001/0613/sys/src/9/port/devsd.c:640,6452001/0905/sys/src/9/port/devsd.c:754,760
2000/0506    
		if(write) 
			error(Eio); 
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		poperror(); 
		return 0; 
	} 
2001/0613/sys/src/9/port/devsd.c:653,6582001/0905/sys/src/9/port/devsd.c:768,775
2000/0506    
		error(Enomem); 
	if(waserror()){ 
		sdfree(b); 
2001/0905    
		if(!(unit->inquiry[1] & 0x80)) 
			decref(&sdev->r);		/* gadverdamme! */ 
2000/0506    
		nexterror(); 
	} 
1996/0607    
 
2001/0613/sys/src/9/port/devsd.c:696,7012001/0905/sys/src/9/port/devsd.c:813,819
2000/0506    
		poperror(); 
	} 
1997/0408    
 
2001/0905    
	decref(&sdev->r); 
2000/0506    
	return len; 
} 
1994/0913    
 
2001/0613/sys/src/9/port/devsd.c:742,7502001/0905/sys/src/9/port/devsd.c:860,869
2000/0506    
static long 
sdread(Chan *c, void *a, long n, vlong off) 
{ 
	char *p; 
2001/0905    
	char *p, *e, *buf; 
2000/0506    
	SDpart *pp; 
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
2000/0506    
	ulong offset; 
	int i, l, status; 
1994/0913    
 
2001/0613/sys/src/9/port/devsd.c:752,7622001/0905/sys/src/9/port/devsd.c:871,904
2000/0506    
	switch(TYPE(c->qid)){ 
	default: 
		error(Eperm); 
2001/0905    
	case Qtopstat: 
		p = buf = malloc(READSTR); 
		assert(p); 
		e = p + READSTR; 
		qlock(&devslock); 
		for (i = 0; i != ndevs; i++) { 
			SDev *sdev = devs[i].dt_dev; 
 
			if (sdev->ifc->stat) 
				p = sdev->ifc->stat(sdev, p, e); 
			else 
				p = seprint(e, "%s; no statistics available\n", sdev->name); 
		} 
		qunlock(&devslock); 
		n = readstr(off, a, n, buf); 
		free(buf); 
		return n; 
 
2000/0506    
	case Qtopdir: 
	case Qunitdir: 
		return devdirread(c, a, n, 0, 0, sdgen); 
2001/0905    
 
2000/0506    
	case Qctl: 
		unit = sdunit[UNIT(c->qid)]; 
2001/0905    
		sdev = sdgetdev(DEV(c->qid)); 
		if (sdev == nil) 
			error(Enonexist); 
 
		unit = sdev->unit[UNIT(c->qid)]; 
2000/0506    
		p = malloc(READSTR); 
		l = snprint(p, READSTR, "inquiry %.48s\n", 
			(char*)unit->inquiry+8); 
2001/0613/sys/src/9/port/devsd.c:785,7982001/0905/sys/src/9/port/devsd.c:927,947
2000/0506    
			} 
2000/0104    
		} 
2000/0506    
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		l = readstr(offset, a, n, p); 
		free(p); 
		return l; 
2001/0905    
 
2000/0506    
	case Qraw: 
		unit = sdunit[UNIT(c->qid)]; 
2001/0905    
		sdev = sdgetdev(DEV(c->qid)); 
		if (sdev == nil) 
			error(Enonexist); 
 
		unit = sdev->unit[UNIT(c->qid)]; 
2000/1129    
		qlock(&unit->raw); 
		if(waserror()){ 
			qunlock(&unit->raw); 
2001/0905    
			decref(&sdev->r); 
2000/1129    
			nexterror(); 
		} 
2000/0506    
		if(unit->state == Rawdata){ 
2001/0613/sys/src/9/port/devsd.c:808,8152001/0905/sys/src/9/port/devsd.c:957,966
2000/1129    
		} else 
			i = 0; 
		qunlock(&unit->raw); 
2001/0905    
		decref(&sdev->r); 
2000/1129    
		poperror(); 
		return i; 
2001/0905    
 
2000/0506    
	case Qpart: 
		return sdbio(c, 0, a, n, off); 
1994/0913    
	} 
2001/0613/sys/src/9/port/devsd.c:817,8222001/0905/sys/src/9/port/devsd.c:968,1070
2000/0506    
	return 0; 
1994/0913    
} 
 
2001/0905    
typedef struct { 
	int		o_on; 
	char		*o_spec; 
	DevConf	o_cf; 
} confdata_t; 
 
static void 
parse_switch(confdata_t *cd, char *option) 
{ 
	if (!strcmp("on", option)) 
		cd->o_on = 1; 
	else if (!strcmp("off", option)) 
		cd->o_on = 0; 
	else 
		error(Ebadarg); 
} 
 
static void 
parse_spec(confdata_t *cd, char *option) 
{ 
	if (strlen(option) > 1)  
		error(Ebadarg); 
	cd->o_spec = option; 
} 
 
static port_t * 
getnewport(DevConf *dc) 
{ 
	port_t *p; 
 
	p = (port_t *)malloc((dc->nports + 1) * sizeof(port_t)); 
	if (dc->nports > 0) { 
		memmove(p, dc->ports, dc->nports * sizeof(port_t)); 
		free(dc->ports); 
	} 
	dc->ports = p; 
	p = &dc->ports[dc->nports++]; 
	p->size = -1; 
	p->port = (ulong)-1; 
	return p; 
} 
 
static void 
parse_port(confdata_t *cd, char *option) 
{ 
	char *e; 
	port_t *p; 
	 
	p = (cd->o_cf.nports == 0 ||  
	        cd->o_cf.ports[cd->o_cf.nports -1].port != (ulong)-1)? 
			getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1]; 
	p->port = strtol(option, &e, 0); 
	if (e == nil || *e != '\0') 
		error(Ebadarg); 
} 
 
static void 
parse_size(confdata_t *cd, char *option) 
{ 
	char *e; 
	port_t *p; 
 
	p = (cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports -1].size != -1)? 
			getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1]; 
	p->size = 	(int)strtol(option, &e, 0); 
	if (e == nil || *e != '\0') 
		error(Ebadarg); 
} 
 
static void 
parse_irq(confdata_t *cd, char *option) 
{ 
	char *e; 
 
	cd->o_cf.interrupt = strtoul(option, &e, 0); 
	if (e == nil || *e != '\0') 
		error(Ebadarg); 
} 
 
static void 
parse_type(confdata_t *cd, char *option) 
{ 
	cd->o_cf.type = option; 
} 
 
static struct { 
	char *option; 
	void	(*parse)(confdata_t *, char *); 
} options[] = { 
	{ 	"switch",		parse_switch,	}, 
	{	"spec",		parse_spec,	}, 
	{	"port",		parse_port,	}, 
	{	"size",		parse_size,	}, 
	{	"irq",			parse_irq,		}, 
	{	"type",		parse_type,	}, 
}; 
 
1994/0913    
static long 
2000/0506    
sdwrite(Chan *c, void *a, long n, vlong off) 
1994/0913    
{ 
2001/0613/sys/src/9/port/devsd.c:823,8402001/0905/sys/src/9/port/devsd.c:1071,1139
2000/0506    
	Cmdbuf *cb; 
	SDreq *req; 
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
2000/0506    
	ulong end, start; 
1994/0913    
 
2000/0506    
	switch(TYPE(c->qid)){ 
	default: 
		error(Eperm); 
2001/0905    
	case Qtopctl: { 
		confdata_t cd; 
		char buf[256], *field[Ncmd]; 
		int nf, i, j; 
 
		memset(&cd, 0, sizeof(confdata_t)); 
		if(n > sizeof(buf)-1) n = sizeof(buf)-1; 
		memmove(buf, a, n); 
		buf[n] = '\0'; 
 
		cd.o_on = -1; 
		cd.o_spec = '\0'; 
		memset(&cd.o_cf, 0, sizeof(DevConf)); 
 
		nf = getfields(buf, field, Ncmd, 1, " \t\n"); 
		for (i = 0; i < nf; i++) { 
			char *opt = field[i++]; 
			if (i >= nf) 
				error(Ebadarg); 
			for (j = 0; j != nelem(options); j++) 
				if (!strcmp(opt, options[j].option)) 
					break; 
					 
			if (j == nelem(options)) 
				error(Ebadarg); 
			options[j].parse(&cd, field[i]); 
		} 
 
		if (cd.o_on < 0)  
			error(Ebadarg); 
 
		if (cd.o_on) { 
			if (cd.o_spec == '\0' || cd.o_cf.nports == 0 ||  
			     cd.o_cf.interrupt == 0 || cd.o_cf.type == nil) 
				error(Ebadarg); 
		} 
		else { 
			if (cd.o_spec == '\0') 
				error(Ebadarg); 
		} 
 
		if (sddevtab.config == nil) 
			error("No configuration function"); 
		sddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf); 
		break; 
	} 
2000/0506    
	case Qctl: 
		cb = parsecmd(a, n); 
		unit = sdunit[UNIT(c->qid)]; 
2001/0905    
		sdev = sdgetdev(DEV(c->qid)); 
		if (sdev == nil) 
			error(Enonexist); 
		unit = sdev->unit[UNIT(c->qid)]; 
1995/0403    
 
2000/0506    
		qlock(&unit->ctl); 
		if(waserror()){ 
			qunlock(&unit->ctl); 
2001/0905    
			decref(&sdev->r); 
2000/0506    
			free(cb); 
			nexterror(); 
		} 
2001/0613/sys/src/9/port/devsd.c:862,8762001/0905/sys/src/9/port/devsd.c:1161,1180
2000/0506    
		else 
			error(Ebadctl); 
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		poperror(); 
		free(cb); 
		break; 
2000/0526    
 
2000/0506    
	case Qraw: 
		unit = sdunit[UNIT(c->qid)]; 
2001/0905    
		sdev = sdgetdev(DEV(c->qid)); 
		if (sdev == nil) 
			error(Enonexist); 
		unit = sdev->unit[UNIT(c->qid)]; 
2000/1129    
		qlock(&unit->raw); 
		if(waserror()){ 
			qunlock(&unit->raw); 
2001/0905    
			decref(&sdev->r); 
2000/1129    
			nexterror(); 
		} 
2000/0526    
		switch(unit->state){ 
2001/0613/sys/src/9/port/devsd.c:904,9092001/0905/sys/src/9/port/devsd.c:1208,1214
2000/1129    
			n = sdrio(unit->req, a, n); 
1996/0607    
		} 
2000/1129    
		qunlock(&unit->raw); 
2001/0905    
		decref(&sdev->r); 
2000/1129    
		poperror(); 
2001/0527    
		break; 
2000/0506    
	case Qpart: 
2001/0613/sys/src/9/port/devsd.c:920,9332001/0905/sys/src/9/port/devsd.c:1225,1243
2000/0506    
	SDpart *pp; 
2000/0706    
	SDperm *perm; 
2000/0506    
	SDunit *unit; 
2001/0905    
	SDev *sdev; 
2000/0506    
 
2001/0527    
	if(c->qid.type & QTDIR) 
2000/0506    
		error(Eperm); 
2001/0905    
		error(Eperm);  
2000/0506    
 
	unit = sdunit[UNIT(c->qid)]; 
2001/0905    
	sdev = sdgetdev(DEV(c->qid)); 
	if (sdev == nil) 
		error(Enonexist); 
	unit = sdev->unit[UNIT(c->qid)]; 
2000/0506    
	qlock(&unit->ctl); 
	if(waserror()){ 
		qunlock(&unit->ctl); 
2001/0905    
		decref(&sdev->r); 
2000/0506    
		nexterror(); 
1994/0913    
	} 
1996/0607    
 
2001/0613/sys/src/9/port/devsd.c:957,9662001/0905/sys/src/9/port/devsd.c:1267,1428
2001/0527    
	perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777); 
2000/0506    
 
	qunlock(&unit->ctl); 
2001/0905    
	decref(&sdev->r); 
2000/0506    
	poperror(); 
2001/0527    
	return n; 
1994/0913    
} 
2000/0506    
 
2001/0905    
static char 
getspec(char base) 
{ 
	while (1) { 
		int i; 
		SDev *sdev; 
 
		for (i = 0; i != ndevs; i++) 
			if ((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base) 
				break; 
 
		if (i == ndevs) 
			return base; 
		base++; 
	} 
	return '\0'; 
} 
 
static int 
configure(char *spec, DevConf *cf) 
{ 
	ISAConf isa; 
	dev_t *_devs; 
	SDev *tail, *sdev, *(*probe)(DevConf *); 
	char *p, name[32]; 
	int i, added_devs; 
 
	if ((p = strchr(cf->type, '/')) != nil) 
		*p++ = '\0'; 
 
	for(i = 0; sdifc[i] != nil; i++) 
		if(!strcmp(sdifc[i]->name, cf->type)) 
			break; 
 
	if (sdifc[i] == nil) 
		error("type not found"); 
	 
	if ((probe = sdifc[i]->probe) == nil) 
		error("No probe function"); 
 
	if (p) { 
		/* Try to find the card on the ISA bus.  This code really belongs 
		     in sdata and I'll move it later.  Really! */ 
		memset(&isa, 0, sizeof(isa)); 
		isa.port = cf->ports[0].port; 
		isa.irq = cf->interrupt; 
 
		if (pcmspecial(p, &isa) < 0) 
			error("Cannot find controller"); 
	} 
 
	qlock(&devslock); 
	if (waserror()) { 
		qunlock(&devslock); 
		nexterror(); 
	} 
	 
	for (i = 0; i != ndevs; i++) 
		if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) 
			break; 
	if (i != ndevs) 
		error(Eexist); 
 
	if ((sdev = (*probe)(cf)) == nil) 
		error("Cannot probe controller"); 
	poperror(); 
 
	added_devs = 0; 
	tail = sdev; 
	while (tail) { 
		added_devs++; 
		tail = tail->next; 
	} 
	 
	_devs = (dev_t *)malloc((ndevs + added_devs) * sizeof(dev_t)); 
	memmove(_devs, devs, ndevs * sizeof(dev_t)); 
	free(devs); 
	devs = _devs; 
 
	while (sdev) { 
		/* Assign `spec' to the device */ 
		*spec = getspec(*spec); 
		snprint(name, sizeof(name), "sd%c", *spec); 
		kstrdup(&sdev->name, name); 
		sdev->idno = *spec; 
 
		devs[ndevs].dt_dev = sdev; 
		devs[ndevs].dt_nunits = sdev->nunit; 
		sdev = sdev->next; 
		devs[ndevs].dt_dev->next = nil; 
		ndevs++; 
	} 
 
	qunlock(&devslock); 
	return 0; 
} 
 
static int 
unconfigure(char *spec) 
{ 
	int i;	 
	SDev *sdev; 
 
	qlock(&devslock); 
	if (waserror()) { 
		qunlock(&devslock); 
		nexterror(); 
	} 
 
	for (sdev = nil, i = 0; i != ndevs; i++) 
		if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec) 
			break; 
 
	if (i == ndevs) 
		error(Enonexist); 
 
	if (sdev->r.ref) 
		error(Einuse); 
 
	/* make sure no interrupts arrive anymore before removing resources */ 
	if (sdev->enabled && sdev->ifc->disable) 
		sdev->ifc->disable(sdev); 
 
	/* we're alone and the device tab is locked; make the device unavailable */ 
	memmove(&devs[i], &devs[ndevs - 1], sizeof(dev_t)); 
	memset(&devs[ndevs - 1], 0, sizeof(dev_t)); 
	ndevs--; 
 
	qunlock(&devslock); 
	poperror(); 
 
	for (i = 0; i != sdev->nunit; i++) 
		if (sdev->unit[i]) { 
			SDunit *unit = sdev->unit[i]; 
 
			free(unit->name); 
			free(unit->user); 
			free(unit); 
		} 
 
	if (sdev->ifc->clear) 
		sdev->ifc->clear(sdev); 
	return 0; 
} 
 
static int 
sdconfig(int on, char *spec, DevConf *cf) 
{ 
	return on? configure(spec, cf): unconfigure(spec); 
} 
 
2000/0506    
Dev sddevtab = { 
	'S', 
	"sd", 
2001/0613/sys/src/9/port/devsd.c:979,9822001/0905/sys/src/9/port/devsd.c:1441,1446
2000/0506    
	devbwrite, 
	devremove, 
	sdwstat, 
2001/0905    
	devpower, 
	sdconfig, 
2000/0506    
}; 


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