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

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

port/devwren.c on 1991/0110
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" 
 
enum { 
	Qdir, Qdata, Qstruct, 
}; 
 
static Dirtab wrendir[]={ 
	"data",		{Qdata},	0,	0600, 
	"struct",	{Qstruct},	8,	0400, 
}; 
 
#define	NWREN	(sizeof wrendir/sizeof(Dirtab)) 
 
static long	maxblock[64]; 
static long	blocksize[64]; 
 
static Scsi	staticcmd;		/* BUG */ 
static uchar	datablk[4*512];		/* BUG */ 
 
/* 
 *  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: 
	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) 
		return -1; 
	tab+=s; 
	if (tab->qid.path==Qdata && 0<=c->dev && c->dev<64) 
		l = maxblock[c->dev]*blocksize[c->dev]; 
	else 
		l = tab->length; 
	devdir(c, tab->qid, tab->name, l, tab->perm, dp); 
	return 1; 
} 
 
void 
wrenreset(void) 
{} 
 
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; 
	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]); 
	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; 
	if (n == 0) 
		return 0; 
	switch ((int)(c->qid.path & ~CHDIR)) { 
	case Qdir: 
		return devdirread(c, a, n, wrendir, NWREN, wrengen); 
	case Qdata: 
		if (n % blocksize[c->dev] || c->offset % blocksize[c->dev]) 
			error(Ebadarg); 
		lbn = c->offset/blocksize[c->dev]; 
		if (lbn >= maxblock[c->dev]) 
			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]; 
		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]); 
		break; 
	default: 
		panic("wrenread"); 
	} 
	return n; 
} 
 
long 
wrenwrite(Chan *c, char *a, long n) 
{ 
	Scsi *cmd = &staticcmd; 
	unsigned long lbn; 
	if (n == 0) 
		return 0; 
	switch ((int)(c->qid.path & ~CHDIR)) { 
	case Qdata: 
		if (n % blocksize[c->dev] || c->offset % blocksize[c->dev]) 
			error(Ebadarg); 
		lbn = c->offset/blocksize[c->dev]; 
		if (lbn >= maxblock[c->dev]) 
			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]; 
		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)