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

1991/0110/port/devwren.c (diff list | history)

1991/0110/sys/src/9/port/devwren.c:1,2541991/0112/sys/src/9/port/devwren.c:1,328 (short | long | prev | next)
1991/0110    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
#include	"devtab.h" 
#include	"io.h" 
 
#include	"scsi.h" 
 
1991/0112    
typedef struct Part	Part; 
typedef struct Disk	Disk; 
 
1991/0110    
enum { 
	Qdir, Qdata, Qstruct, 
}; 
1991/0112    
	Npart=		2,	/* maximum partitions per disk */ 
	Ndisk=		64,	/* maximum disks */ 
1991/0110    
 
static Dirtab wrendir[]={ 
	"data",		{Qdata},	0,	0600, 
	"struct",	{Qstruct},	8,	0400, 
1991/0112    
	Qdir=		0, 
	Qdata=		16, 
	Qstruct=	32, 
 
	Mask=		0x7, 
1991/0110    
}; 
 
#define	NWREN	(sizeof wrendir/sizeof(Dirtab)) 
1991/0112    
static Dirtab *wrendir; 
#define	NWREN	(2*(Npart+1)) 
1991/0110    
 
static long	maxblock[64]; 
static long	blocksize[64]; 
1991/0112    
struct Part 
{ 
	ulong 	firstblock; 
	ulong 	maxblock; 
}; 
struct Disk 
{ 
	ulong	blocksize; 
	Part	p[Npart]; 
}; 
1991/0110    
 
static Scsi	staticcmd;		/* BUG */ 
static uchar	datablk[4*512];		/* BUG */ 
1991/0112    
static Disk	wren[Ndisk]; 
1991/0110    
 
1991/0112    
static Scsi	staticcmd;			/* BUG */ 
static uchar	datablk[2*4*512];		/* BUG */ 
 
1991/0110    
/* 
 *  accepts [0-7].[0-7], or abbreviation 
 */ 
static int 
wrendev(char *p) 
{ 
	int dev = 0; 
	if (p==0 || p[0]==0) 
		goto out; 
	if (p[0]<'0' || p[0]>'7') 
		goto cant; 
	dev = (p[0]-'0')<<3; 
	if (p[1]==0) 
		goto out; 
	if (p[1]!='.') 
		goto cant; 
	if (p[2]==0) 
		goto out; 
	if (p[2]<'0' || p[2]>'7') 
		goto cant; 
	dev |= p[2]-'0'; 
	if (p[3]!=0) 
		goto cant; 
out: 
1991/0112    
	if(dev >= Ndisk) 
		error(Ebadarg); 
1991/0110    
	return dev; 
cant: 
	error(Ebadarg); 
} 
 
static int 
wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp) 
{ 
	long l; 
	if(tab==0 || s>=ntab) 
1991/0112    
	Part *p; 
	Disk *d; 
 
	if(s >= ntab) 
1991/0110    
		return -1; 
	tab+=s; 
	if (tab->qid.path==Qdata && 0<=c->dev && c->dev<64) 
		l = maxblock[c->dev]*blocksize[c->dev]; 
1991/0112    
	if(c->dev >= Ndisk) 
		return -1; 
 
	tab += s; 
	d = &wren[c->dev]; 
	p = &d->p[tab->qid.path&Mask]; 
	if((tab->qid.path&~Mask) == Qdata) 
		l = d->blocksize * (p->maxblock - p->firstblock); 
1991/0110    
	else 
		l = tab->length; 
1991/0112    
		l = 8; 
1991/0110    
	devdir(c, tab->qid, tab->name, l, tab->perm, dp); 
	return 1; 
} 
 
void 
wrenreset(void) 
{} 
1991/0112    
{ 
	Dirtab *p; 
	int i; 
1991/0110    
 
1991/0112    
	p = wrendir = ialloc((Npart+1) * 2 * sizeof(Dirtab), 0); 
	for(i = 0; i < Npart; i++){ 
		sprint(p->name, "data%d", i); 
		p->qid.path = Qdata + i; 
		p->perm = 0600; 
		p++->length = 0; 
		strcpy(p->name, "struct%d"); 
		p->qid.path = Qstruct + i; 
		p->perm = 0600; 
		p++->length = 0; 
	} 
	strcpy(p->name, "data"); 
	p->qid.path = Qdata + Npart; 
	p->perm = 0600; 
	p++->length = 0; 
	strcpy(p->name, "struct"); 
	p->qid.path = Qstruct + Npart; 
	p->perm = 0600; 
	p->length = 0; 
} 
 
1991/0110    
void 
wreninit(void) 
{ 
	Scsi *cmd = &staticcmd; 
	cmd->cmd.base = cmd->cmdblk; 
	cmd->data.base = datablk; 
} 
 
/* 
 *  param is #r<target>.<lun> 
 */ 
Chan * 
wrenattach(char *param) 
{ 
	uchar buf[32]; 
	int dev; 
	Chan *c; 
1991/0112    
	Disk *d; 
	ulong plen; 
	int i; 
 
1991/0110    
	dev = wrendev(param); 
	scsiready(dev); 
	scsisense(dev, buf); 
	scsicap(dev, buf); 
	c = devattach('r', param); 
	c->dev = dev; 
	maxblock[dev] = BGLONG(&buf[0]); 
	blocksize[dev] = BGLONG(&buf[4]); 
1991/0112    
	d = &wren[dev]; 
	d->blocksize = BGLONG(&buf[4]); 
	plen = BGLONG(&buf[0]); 
	d->p[Npart].firstblock = 0; 
	d->p[Npart].maxblock = plen; 
	plen = plen/Npart; 
	for(i = 0; i < Npart; i++){ 
		d->p[i].firstblock = i*plen; 
		d->p[i].maxblock = (i+1)*plen; 
	} 
1991/0110    
	return c; 
} 
 
Chan * 
wrenclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int 
wrenwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, wrendir, NWREN, wrengen); 
} 
 
void 
wrenstat(Chan *c, char *db) 
{ 
	devstat(c, db, wrendir, NWREN, wrengen); 
} 
 
Chan * 
wrenopen(Chan *c, int omode) 
{ 
	if (c->qid.path == Qdata && scsiready(c->dev) != 0) 
		error(Eio); 
	return devopen(c, omode, wrendir, NWREN, wrengen); 
} 
 
void 
wrencreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	error(Eperm); 
} 
 
void 
wrenclose(Chan *c) 
{} 
 
#define	PSHORT(p, v)		((p)[0]=(v), (p)[1]=((v)>>8)) 
#define	PLONG(p, v)		(PSHORT(p, (v)), PSHORT(p+2, (v)>>16)) 
long 
wrenread(Chan *c, char *a, long n) 
{ 
	Scsi *cmd = &staticcmd; 
	unsigned long lbn; 
1991/0112    
	Part *p; 
	Disk *d; 
 
1991/0110    
	if (n == 0) 
		return 0; 
	switch ((int)(c->qid.path & ~CHDIR)) { 
	case Qdir: 
1991/0112    
 
	if(c->qid.path == CHDIR) 
1991/0110    
		return devdirread(c, a, n, wrendir, NWREN, wrengen); 
1991/0112    
 
	d = &wren[c->dev]; 
	p = &(d->p[Mask&c->qid.path]); 
	switch ((int)(c->qid.path & ~Mask)) { 
1991/0110    
	case Qdata: 
		if (n % blocksize[c->dev] || c->offset % blocksize[c->dev]) 
1991/0112    
		if (n % d->blocksize || c->offset % d->blocksize) 
1991/0110    
			error(Ebadarg); 
		lbn = c->offset/blocksize[c->dev]; 
		if (lbn >= maxblock[c->dev]) 
1991/0112    
		lbn = (c->offset/d->blocksize) + p->firstblock; 
		if (lbn >= p->maxblock) 
1991/0110    
			error(Ebadarg); 
		if (n > sizeof datablk) 
			n = sizeof datablk; 
		qlock(cmd); 
		if (waserror()) { 
			qunlock(cmd); 
			nexterror(); 
		} 
		cmd->target = c->dev>>3; 
		cmd->lun = c->dev&7; 
		cmd->cmd.ptr = cmd->cmd.base; 
		cmd->cmdblk[0] = 0x08; 
		cmd->cmdblk[1] = lbn>>16; 
		cmd->cmdblk[2] = lbn>>8; 
		cmd->cmdblk[3] = lbn; 
		cmd->cmdblk[4] = n/blocksize[c->dev]; 
1991/0112    
		cmd->cmdblk[4] = n/d->blocksize; 
1991/0110    
		cmd->cmdblk[5] = 0x00; 
		cmd->cmd.lim = &cmd->cmdblk[6]; 
		cmd->data.lim = cmd->data.base + n; 
		cmd->data.ptr = cmd->data.base; 
		cmd->save = cmd->data.base; 
		scsiexec(cmd, 1); 
		n = cmd->data.ptr - cmd->data.base; 
		memcpy(a, cmd->data.base, n); 
		qunlock(cmd); 
		break; 
	case Qstruct: 
		if (n < 8) 
			error(Ebadarg); 
		if (c->offset >= 8) 
			return 0; 
		n = 8; 
		PLONG((uchar *)&a[0], maxblock[c->dev]); 
		PLONG((uchar *)&a[4], blocksize[c->dev]); 
1991/0112    
		PLONG((uchar *)&a[0], p->maxblock - p->firstblock); 
		PLONG((uchar *)&a[4], d->blocksize); 
1991/0110    
		break; 
	default: 
		panic("wrenread"); 
	} 
	return n; 
} 
 
long 
wrenwrite(Chan *c, char *a, long n) 
{ 
	Scsi *cmd = &staticcmd; 
	unsigned long lbn; 
1991/0112    
	Part *p; 
	Disk *d; 
 
1991/0110    
	if (n == 0) 
		return 0; 
	switch ((int)(c->qid.path & ~CHDIR)) { 
1991/0112    
 
	d = &wren[c->dev]; 
	p = &(d->p[Mask&c->qid.path]); 
	switch ((int)(c->qid.path & ~Mask)) { 
1991/0110    
	case Qdata: 
		if (n % blocksize[c->dev] || c->offset % blocksize[c->dev]) 
1991/0112    
		if (n % d->blocksize || c->offset % d->blocksize) 
1991/0110    
			error(Ebadarg); 
		lbn = c->offset/blocksize[c->dev]; 
		if (lbn >= maxblock[c->dev]) 
1991/0112    
		lbn = c->offset/d->blocksize + p->firstblock; 
		if (lbn >= p->maxblock) 
1991/0110    
			error(Ebadarg); 
		if (n > sizeof datablk) 
			n = sizeof datablk; 
		qlock(cmd); 
		if (waserror()) { 
			qunlock(cmd); 
			nexterror(); 
		} 
		cmd->target = c->dev>>3; 
		cmd->lun = c->dev&7; 
		cmd->cmd.ptr = cmd->cmd.base; 
		cmd->cmdblk[0] = 0x0a; 
		cmd->cmdblk[1] = lbn>>16; 
		cmd->cmdblk[2] = lbn>>8; 
		cmd->cmdblk[3] = lbn; 
		cmd->cmdblk[4] = n/blocksize[c->dev]; 
1991/0112    
		cmd->cmdblk[4] = n/d->blocksize; 
1991/0110    
		cmd->cmdblk[5] = 0x00; 
		cmd->cmd.lim = &cmd->cmdblk[6]; 
		cmd->data.lim = cmd->data.base + n; 
		cmd->data.ptr = cmd->data.base; 
		cmd->save = cmd->data.base; 
		memcpy(cmd->data.base, a, n); 
		scsiexec(cmd, 0); 
		n = cmd->data.ptr - cmd->data.base; 
		qunlock(cmd); 
		break; 
	default: 
		panic("wrenwrite"); 
	} 
	return n; 
} 
 
void 
wrenremove(Chan *c) 
{ 
	error(Eperm); 
} 
 
void 
wrenwstat(Chan *c, char *dp) 
{ 
	error(Eperm); 
} 


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