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

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

1991/0706/sys/src/9/port/devwren.c:7,471991/0823/sys/src/9/port/devwren.c:7,47 (short | long | prev | next)
1991/0110    
#include	"devtab.h" 
#include	"io.h" 
 
1991/0112    
typedef struct Part	Part; 
typedef struct Disk	Disk; 
1991/0823    
typedef struct Partition	Partition; 
typedef struct Drive		Drive; 
1991/0112    
 
1991/0110    
enum { 
1991/0112    
	Npart=		2,	/* maximum partitions per disk */ 
1991/0823    
	Npart=		8+2,	/* 8 sub partitions, disk, and partition */ 
1991/0112    
	Ndisk=		64,	/* maximum disks */ 
1991/0110    
 
1991/0823    
	/* file types */ 
1991/0112    
	Qdir=		0, 
	Qdata=		16, 
	Qstruct=	32, 
                 
	Mask=		0x7, 
1991/0110    
}; 
1991/0823    
#define PART(x)		((x)&0xF) 
#define DRIVE(x)	(((x)>>4)&0x7) 
#define MKQID(d,p)	(((d)<<4) | (p)) 
1991/0110    
 
1991/0112    
static Dirtab *wrendir; 
#define	NWREN	(2*(Npart+1)) 
1991/0110    
                 
1991/0112    
struct Part 
1991/0823    
struct Partition 
1991/0112    
{ 
	ulong 	firstblock; 
	ulong 	maxblock; 
1991/0823    
	ulong	start; 
	ulong	end; 
	char	name[NAMELEN+1]; 
1991/0112    
}; 
struct Disk 
1991/0823    
 
struct Drive 
1991/0112    
{ 
	ulong	blocksize; 
	Part	p[Npart]; 
1991/0823    
	ulong		bytes;			/* bytes per block */ 
	int		npart;			/* actual number of partitions */ 
	int		drive; 
	Partition	p[Npart]; 
1991/0112    
}; 
1991/0110    
 
1991/0112    
static Disk	wren[Ndisk]; 
1991/0823    
static Drive	wren[Ndisk]; 
1991/0110    
 
1991/0603    
void	wrenint(uchar*, ulong); 
                 
1991/0423    
#define	DATASIZE	(8*1024)	/* BUG */ 
1991/0112    
 
1991/0115    
#define	BGLONG(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3]) 
1991/0823    
static void	wrenpart(int); 
static long	wrenio(Drive *, Partition *, int, char *, ulong, ulong); 
1991/0115    
 
1991/0110    
/* 
 *  accepts [0-7].[0-7], or abbreviation 
1991/0706/sys/src/9/port/devwren.c:50,701991/0823/sys/src/9/port/devwren.c:50,71
1991/0110    
wrendev(char *p) 
{ 
	int dev = 0; 
	if (p==0 || p[0]==0) 
1991/0823    
 
	if(p == 0 || p[0] == 0) 
1991/0110    
		goto out; 
	if (p[0]<'0' || p[0]>'7') 
1991/0823    
	if(p[0] < '0' || p[0] > '7') 
1991/0110    
		goto cant; 
	dev = (p[0]-'0')<<3; 
	if (p[1]==0) 
1991/0823    
	dev = (p[0] - '0') << 3; 
	if(p[1] == 0) 
1991/0110    
		goto out; 
	if (p[1]!='.') 
1991/0823    
	if(p[1] != '.') 
1991/0110    
		goto cant; 
	if (p[2]==0) 
1991/0823    
	if(p[2] == 0) 
1991/0110    
		goto out; 
	if (p[2]<'0' || p[2]>'7') 
1991/0823    
	if(p[2] < '0' || p[2] > '7') 
1991/0110    
		goto cant; 
	dev |= p[2]-'0'; 
	if (p[3]!=0) 
1991/0823    
	dev |= p[2] - '0'; 
	if(p[3] != 0) 
1991/0110    
		goto cant; 
out: 
1991/0112    
	if(dev >= Ndisk) 
1991/0706/sys/src/9/port/devwren.c:75,991991/0823/sys/src/9/port/devwren.c:76,106
1991/0110    
} 
 
static int 
wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp) 
1991/0823    
wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp) 
1991/0110    
{ 
	long l; 
1991/0112    
	Part *p; 
	Disk *d; 
1991/0823    
	Qid qid; 
	int drive; 
	char name[NAMELEN+4]; 
	Drive *dp; 
	Partition *pp; 
	ulong l; 
1991/0112    
 
	if(s >= ntab) 
1991/0823    
	qid.vers = 0; 
	drive = s/Npart; 
	s = s % Npart; 
	if(drive >= Ndisk) 
1991/0110    
		return -1; 
1991/0112    
	if(c->dev >= Ndisk) 
		return -1; 
1991/0823    
	dp = &wren[drive]; 
1991/0112    
 
	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 
1991/0112    
		l = 8; 
1991/0110    
	devdir(c, tab->qid, tab->name, l, tab->perm, dp); 
1991/0823    
	if(s >= dp->npart) 
		return 0; 
 
	pp = &dp->p[s]; 
	sprint(name, "hd%d%s", drive, pp->name); 
	name[NAMELEN] = 0; 
	qid.path = MKQID(drive, s); 
	l = (pp->end - pp->start) * dp->bytes; 
	devdir(c, qid, name, l, 0600, dirp); 
1991/0110    
	return 1; 
} 
 
1991/0706/sys/src/9/port/devwren.c:100,1321991/0823/sys/src/9/port/devwren.c:107,118
1991/0110    
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; 
1991/0115    
		sprint(p->name, "struct%d", i); 
1991/0112    
		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) 
1991/0423    
{} 
1991/0823    
{ 
} 
1991/0110    
 
/* 
 *  param is #r<target>.<lun> 
1991/0706/sys/src/9/port/devwren.c:134,1671991/0823/sys/src/9/port/devwren.c:120,136
1991/0110    
Chan * 
wrenattach(char *param) 
{ 
	uchar buf[32]; 
	int dev; 
	Chan *c; 
1991/0112    
	Disk *d; 
	ulong plen; 
	int i; 
1991/0823    
	int drive; 
1991/0112    
 
1991/0110    
	dev = wrendev(param); 
	scsiready(dev); 
	scsisense(dev, buf); 
	scsicap(dev, buf); 
1991/0823    
	drive = wrendev(param); 
	wrenpart(drive); 
1991/0110    
	c = devattach('r', param); 
	c->dev = dev; 
1991/0112    
	d = &wren[dev]; 
	d->blocksize = BGLONG(&buf[4]); 
1991/0429    
                 
1991/0706    
	plen = BGLONG(&buf[0])+1; 
1991/0112    
	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/0823    
	c->dev = drive; 
1991/0110    
	return c; 
} 
 
Chan * 
1991/0823    
Chan* 
1991/0110    
wrenclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
1991/0706/sys/src/9/port/devwren.c:170,1901991/0823/sys/src/9/port/devwren.c:139,157
1991/0110    
int 
wrenwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, wrendir, NWREN, wrengen); 
1991/0823    
	return devwalk(c, name, 0, 0, wrengen); 
1991/0110    
} 
 
void 
wrenstat(Chan *c, char *db) 
1991/0823    
wrenstat(Chan *c, char *dp) 
1991/0110    
{ 
	devstat(c, db, wrendir, NWREN, wrengen); 
1991/0823    
	devstat(c, dp, 0, 0, wrengen); 
1991/0110    
} 
 
Chan * 
1991/0823    
Chan* 
1991/0110    
wrenopen(Chan *c, int omode) 
{ 
	if (c->qid.path == Qdata && scsiready(c->dev) != 0) 
		error(Eio); 
	return devopen(c, omode, wrendir, NWREN, wrengen); 
1991/0823    
	return devopen(c, omode, 0, 0, wrengen); 
1991/0110    
} 
 
void 
1991/0706/sys/src/9/port/devwren.c:195,3171991/0823/sys/src/9/port/devwren.c:162,325
1991/0110    
 
void 
wrenclose(Chan *c) 
{} 
1991/0823    
{ 
} 
1991/0110    
 
1991/0823    
void 
wrenremove(Chan *c) 
{ 
	error(Eperm); 
} 
 
void 
wrenwstat(Chan *c, char *dp) 
{ 
	error(Eperm); 
} 
 
1991/0110    
long 
1991/0411    
wrenread(Chan *c, char *a, long n, ulong offset) 
1991/0110    
{ 
1991/0423    
	Scsi *cmd; 
	ulong lbn; 
1991/0112    
	Part *p; 
	Disk *d; 
1991/0823    
	Drive *d; 
	Partition *p; 
1991/0112    
 
1991/0110    
	if (n == 0) 
		return 0; 
1991/0112    
 
	if(c->qid.path == CHDIR) 
1991/0110    
		return devdirread(c, a, n, wrendir, NWREN, wrengen); 
1991/0823    
		return devdirread(c, a, n, 0, 0, wrengen); 
1991/0112    
 
	d = &wren[c->dev]; 
	p = &(d->p[Mask&c->qid.path]); 
	switch ((int)(c->qid.path & ~Mask)) { 
1991/0110    
	case Qdata: 
1991/0411    
		if (n % d->blocksize || offset % d->blocksize) 
1991/0110    
			error(Ebadarg); 
1991/0411    
		lbn = (offset/d->blocksize) + p->firstblock; 
1991/0112    
		if (lbn >= p->maxblock) 
1991/0110    
			error(Ebadarg); 
1991/0423    
		if (n > DATASIZE) 
			n = DATASIZE; 
		cmd = scsicmd(c->dev, 0x08, n); 
1991/0110    
		if (waserror()) { 
			qunlock(cmd); 
			nexterror(); 
		} 
		cmd->cmdblk[1] = lbn>>16; 
		cmd->cmdblk[2] = lbn>>8; 
		cmd->cmdblk[3] = lbn; 
1991/0112    
		cmd->cmdblk[4] = n/d->blocksize; 
1991/0110    
		scsiexec(cmd, 1); 
		n = cmd->data.ptr - cmd->data.base; 
1991/0318    
		memmove(a, cmd->data.base, n); 
1991/0110    
		qunlock(cmd); 
1991/0604    
		poperror(); 
1991/0110    
		break; 
	case Qstruct: 
1991/0603    
		if (n < 2*sizeof(ulong)) 
1991/0110    
			error(Ebadarg); 
1991/0603    
		if (offset >= 2*sizeof(ulong)) 
1991/0110    
			return 0; 
1991/0603    
		n = 2*sizeof(ulong); 
		wrenint((uchar*)a, p->maxblock - p->firstblock); 
		wrenint((uchar*)a+sizeof(ulong), d->blocksize); 
1991/0110    
		break; 
	default: 
		panic("wrenread"); 
	} 
	return n; 
1991/0823    
	d = &wren[DRIVE(c->qid.path)]; 
	p = &d->p[PART(c->qid.path)]; 
	return wrenio(d, p, 0, a, n, offset); 
1991/0110    
} 
 
long 
1991/0411    
wrenwrite(Chan *c, char *a, long n, ulong offset) 
1991/0110    
{ 
1991/0823    
	Drive *d; 
	Partition *p; 
 
	d = &wren[DRIVE(c->qid.path)]; 
	p = &d->p[PART(c->qid.path)]; 
	return wrenio(d, p, 1, a, n, offset); 
} 
 
static long 
wrenio(Drive *d, Partition *p, int write, char *a, ulong n, ulong offset) 
{ 
1991/0423    
	Scsi *cmd; 
	ulong lbn; 
1991/0112    
	Part *p; 
	Disk *d; 
1991/0823    
	void *b; 
	ulong block; 
1991/0112    
 
1991/0110    
	if (n == 0) 
1991/0823    
	if(n % d->bytes || offset % d->bytes) 
		error(Ebadarg); 
	block = offset / d->bytes + p->start; 
	if(block >= p->end) 
1991/0110    
		return 0; 
1991/0112    
                 
	d = &wren[c->dev]; 
	p = &(d->p[Mask&c->qid.path]); 
	switch ((int)(c->qid.path & ~Mask)) { 
1991/0110    
	case Qdata: 
1991/0411    
		if (n % d->blocksize || offset % d->blocksize) 
1991/0110    
			error(Ebadarg); 
1991/0411    
		lbn = offset/d->blocksize + p->firstblock; 
1991/0112    
		if (lbn >= p->maxblock) 
1991/0110    
			error(Ebadarg); 
1991/0423    
		if (n > DATASIZE) 
			n = DATASIZE; 
		cmd = scsicmd(c->dev, 0x0a, n); 
1991/0110    
		if (waserror()) { 
			qunlock(cmd); 
			nexterror(); 
		} 
		cmd->cmdblk[1] = lbn>>16; 
		cmd->cmdblk[2] = lbn>>8; 
		cmd->cmdblk[3] = lbn; 
1991/0112    
		cmd->cmdblk[4] = n/d->blocksize; 
1991/0318    
		memmove(cmd->data.base, a, n); 
1991/0110    
		scsiexec(cmd, 0); 
		n = cmd->data.ptr - cmd->data.base; 
1991/0823    
	if(n > DATASIZE) 
		n = DATASIZE; 
	n /= d->bytes; 
	if(block + n > p->end) 
		n = p->end - block; 
	if(n == 0) 
		return 0; 
	if(write) 
		cmd = scsicmd(d->drive, 0x0a, n*d->bytes); 
	else 
		cmd = scsicmd(d->drive, 0x08, n*d->bytes); 
	if(waserror()){ 
1991/0110    
		qunlock(cmd); 
1991/0604    
		poperror(); 
1991/0110    
		break; 
	default: 
		panic("wrenwrite"); 
1991/0823    
		nexterror(); 
1991/0110    
	} 
1991/0823    
	cmd->cmdblk[1] = block>>16; 
	cmd->cmdblk[2] = block>>8; 
	cmd->cmdblk[3] = block; 
	cmd->cmdblk[4] = n; 
	if(write) 
		memmove(cmd->data.base, a, n*d->bytes); 
	scsiexec(cmd, !write); 
	n = cmd->data.ptr - cmd->data.base; 
	if(!write) 
		memmove(a, cmd->data.base, n); 
	qunlock(cmd); 
	poperror(); 
1991/0110    
	return n; 
} 
 
void 
wrenremove(Chan *c) 
1991/0823    
/* 
 *  read partition table.  The partition table is just ascii strings. 
 */ 
#define MAGIC "plan9 partitions" 
static void 
wrenpart(int dev) 
1991/0110    
{ 
	error(Eperm); 
} 
1991/0823    
	Scsi *cmd; 
	Drive *dp; 
	Partition *pp; 
	uchar buf[32]; 
	char *b; 
	char *line[Npart+1]; 
	char *field[3]; 
	ulong n; 
	int i; 
1991/0110    
 
void 
wrenwstat(Chan *c, char *dp) 
{ 
	error(Eperm); 
1991/0603    
} 
1991/0823    
	scsiready(dev); 
	scsisense(dev, buf); 
	scsicap(dev, buf); 
	dp = &wren[dev]; 
	dp->drive = dev; 
	if(dp->npart) 
		return; 
	/* 
	 *  we always have a partition for the whole disk 
	 *  and one for the partition table 
	 */ 
	dp->bytes = (buf[4]<<24)+(buf[5]<<16)+(buf[6]<<8)+(buf[7]); 
	pp = &dp->p[0]; 
	strcpy(pp->name, "disk"); 
	pp->start = 0; 
	pp->end = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]) + 1; 
	pp++; 
	strcpy(pp->name, "partition"); 
	pp->start = dp->p[0].end - 1; 
	pp->end = dp->p[0].end; 
	dp->npart = 2; 
1991/0603    
 
void 
wrenint(uchar *a, ulong x) 
{ 
	a[0] = x >> 24; 
	a[1] = x >> 16; 
	a[2] = x >> 8; 
	a[3] = x; 
1991/0823    
	/* 
	 *  read partition table from disk, null terminate 
	 */ 
	cmd = scsicmd(dev, 0x08, dp->bytes); 
	if(waserror()){ 
		qunlock(cmd); 
		nexterror(); 
	} 
	n = dp->p[0].end-1; 
	cmd->cmdblk[1] = n>>16; 
	cmd->cmdblk[2] = n>>8; 
	cmd->cmdblk[3] = n; 
	cmd->cmdblk[4] = 1; 
	scsiexec(cmd, 1); 
	cmd->data.base[dp->bytes-1] = 0; 
 
	/* 
	 *  parse partition table. 
	 */ 
	n = getfields((char *)cmd->data.base, line, Npart+1, '\n'); 
	if(strncmp(line[0], MAGIC, sizeof(MAGIC)-1) != 0) 
		goto out; 
	for(i = 1; i < n; i++){ 
		pp++; 
		if(getfields(line[i], field, 3, ' ') != 3){ 
			break; 
		} 
		strncpy(pp->name, field[0], NAMELEN); 
		pp->start = strtoul(field[1], 0, 0); 
		pp->end = strtoul(field[2], 0, 0); 
		if(pp->start > pp->end || pp->start >= dp->p[0].end){ 
			break; 
		} 
		dp->npart++; 
	} 
out: 
	qunlock(cmd); 
	poperror(); 
1991/0110    
} 


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