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

1992/0129/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" 
1992/0111    
#include	"../port/error.h" 
1991/0110    
#include	"devtab.h" 
#include	"io.h" 
 
1991/0927    
#define DATASIZE	(8*1024) 
 
1991/0823    
typedef struct Partition	Partition; 
typedef struct Drive		Drive; 
1991/0112    
 
1991/0110    
enum { 
1991/0823    
	Npart=		8+2,	/* 8 sub partitions, disk, and partition */ 
1991/1019    
	Ndisk=		64,	/* maximum disks; if you change it, you must 
				   map from dev to disk */ 
1991/0110    
 
1991/0823    
	/* file types */ 
1991/0112    
	Qdir=		0, 
1991/0110    
}; 
1991/0823    
#define PART(x)		((x)&0xF) 
1991/0927    
#define DRIVE(x)	(((x)>>4)&(Ndisk-1)) 
1991/0823    
#define MKQID(d,p)	(((d)<<4) | (p)) 
1991/0110    
 
1991/0823    
struct Partition 
1991/0112    
{ 
1991/0823    
	ulong	start; 
	ulong	end; 
	char	name[NAMELEN+1]; 
1991/0112    
}; 
1991/0823    
 
struct Drive 
1991/0112    
{ 
1991/0823    
	ulong		bytes;			/* bytes per block */ 
	int		npart;			/* actual number of partitions */ 
	int		drive; 
	Partition	p[Npart]; 
1991/0112    
}; 
1991/0110    
 
1991/0823    
static Drive	wren[Ndisk]; 
1991/0110    
 
1991/0823    
static void	wrenpart(int); 
1991/1203    
static long	wrenio(Chan*, int, char*, ulong, ulong); 
1991/0115    
 
1991/0110    
/* 
 *  accepts [0-7].[0-7], or abbreviation 
 */ 
static int 
wrendev(char *p) 
{ 
1991/1019    
	int drive, unit; 
1991/0823    
 
1991/1019    
	if(p == 0 || p[0] == '\0') 
		return 0; 
1991/0823    
	if(p[0] < '0' || p[0] > '7') 
1992/0114    
		error(Ebadarg); 
1991/1019    
	drive = p[0] - '0'; 
	unit = 0; 
	if(p[1]){ 
		if(p[1] != '.' || p[2] < '0' || p[2] > '7' || p[3] != '\0') 
1992/0114    
			error(Ebadarg); 
1991/1019    
		unit = p[2] - '0'; 
	} 
	return (drive << 3) | unit; 
1991/0110    
} 
 
static int 
1991/0823    
wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp) 
1991/0110    
{ 
1991/0823    
	Qid qid; 
	int drive; 
	char name[NAMELEN+4]; 
	Drive *dp; 
	Partition *pp; 
	ulong l; 
1991/0112    
 
1991/0823    
	qid.vers = 0; 
1991/0927    
	drive = c->dev; 
1991/0823    
	if(drive >= Ndisk) 
1991/0110    
		return -1; 
1991/0823    
	dp = &wren[drive]; 
1991/0112    
 
1991/0823    
	if(s >= dp->npart) 
1991/0927    
		return -1; 
1991/0823    
 
	pp = &dp->p[s]; 
1991/0927    
	if(drive & 7) 
		sprint(name, "hd%d.%d%s", drive>>3, drive&7, pp->name); 
	else 
		sprint(name, "hd%d%s", drive>>3, pp->name); 
1991/0823    
	name[NAMELEN] = 0; 
	qid.path = MKQID(drive, s); 
	l = (pp->end - pp->start) * dp->bytes; 
1991/1112    
	devdir(c, qid, name, l, eve, 0666, dirp); 
1991/0110    
	return 1; 
} 
 
void 
wrenreset(void) 
1991/0112    
{ 
} 
 
1991/0110    
void 
wreninit(void) 
1991/0823    
{ 
} 
1991/0110    
 
/* 
 *  param is #r<target>.<lun> 
 */ 
Chan * 
wrenattach(char *param) 
{ 
	Chan *c; 
1991/0823    
	int drive; 
1991/0112    
 
1991/0823    
	drive = wrendev(param); 
	wrenpart(drive); 
1991/0921    
	c = devattach('w', param); 
1991/0823    
	c->dev = drive; 
1991/0110    
	return c; 
} 
 
1991/0823    
Chan* 
1991/0110    
wrenclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int 
wrenwalk(Chan *c, char *name) 
{ 
1991/0823    
	return devwalk(c, name, 0, 0, wrengen); 
1991/0110    
} 
 
void 
1991/0823    
wrenstat(Chan *c, char *dp) 
1991/0110    
{ 
1991/0823    
	devstat(c, dp, 0, 0, wrengen); 
1991/0110    
} 
 
1991/0823    
Chan* 
1991/0110    
wrenopen(Chan *c, int omode) 
{ 
1991/0823    
	return devopen(c, omode, 0, 0, wrengen); 
1991/0110    
} 
 
void 
wrencreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1210    
	USED(c, name, omode, perm); 
1991/0110    
	error(Eperm); 
} 
 
void 
wrenclose(Chan *c) 
1991/0823    
{ 
1991/1210    
	USED(c); 
1991/0823    
} 
1991/0110    
 
1991/0823    
void 
wrenremove(Chan *c) 
{ 
1991/1210    
	USED(c); 
1991/0823    
	error(Eperm); 
} 
 
void 
wrenwstat(Chan *c, char *dp) 
{ 
1991/1210    
	USED(c, dp); 
1991/0823    
	error(Eperm); 
} 
 
1991/0110    
long 
1991/0411    
wrenread(Chan *c, char *a, long n, ulong offset) 
1991/0110    
{ 
1991/0112    
	if(c->qid.path == CHDIR) 
1991/0823    
		return devdirread(c, a, n, 0, 0, wrengen); 
1991/1203    
	return wrenio(c, 0, a, n, offset); 
1991/0110    
} 
 
long 
1991/0411    
wrenwrite(Chan *c, char *a, long n, ulong offset) 
1991/0110    
{ 
1992/0129    
	n = wrenio(c, 1, a, n, offset); 
	if(n) 
		return n; 
	error("end of device"); 
1991/1203    
} 
 
static long 
wrenio(Chan *c, int write, char *a, ulong len, ulong offset) 
{ 
1991/0823    
	Drive *d; 
	Partition *p; 
1991/1203    
	Scsibuf *b; 
	ulong block, n, max, x; 
1991/0823    
 
	d = &wren[DRIVE(c->qid.path)]; 
1992/0114    
	if(d->npart == 0)			/* drive repartitioned */ 
		error(Eio); 
1991/0823    
	p = &d->p[PART(c->qid.path)]; 
 
	block = offset / d->bytes + p->start; 
1991/1203    
	n = (offset + len + d->bytes - 1) / d->bytes + p->start - block; 
	max = DATASIZE / d->bytes; 
	if(n > max) 
		n = max; 
1991/0823    
	if(block + n > p->end) 
		n = p->end - block; 
1991/1203    
	if(block >= p->end || n == 0) 
1991/0823    
		return 0; 
1991/0927    
	b = scsibuf(); 
1991/0823    
	if(waserror()){ 
1991/0927    
		scsifree(b); 
1991/0823    
		nexterror(); 
1991/0110    
	} 
1991/1203    
	offset %= d->bytes; 
1991/0927    
	if(write){ 
1991/1203    
		if(offset || len % d->bytes){ 
			x = scsibread(d->drive, b, n, d->bytes, block); 
			if(x < n * d->bytes){ 
				n = x / d->bytes; 
				x = n * d->bytes - offset; 
				if(len > x) 
					len = x; 
			} 
		} 
		memmove((char*)b->virt + offset, a, len); 
		x = scsibwrite(d->drive, b, n, d->bytes, block); 
		if(x < offset) 
			len = 0; 
		else if(len > x - offset) 
			len = x - offset; 
1991/0927    
	}else{ 
1991/1203    
		x = scsibread(d->drive, b, n, d->bytes, block); 
		if(x < offset) 
			len = 0; 
		else if(len > x - offset) 
			len = x - offset; 
		memmove(a, (char*)b->virt + offset, len); 
1991/0927    
	} 
1991/0823    
	poperror(); 
1991/0927    
	scsifree(b); 
1991/1203    
	return len; 
1991/0110    
} 
 
1991/0823    
/* 
 *  read partition table.  The partition table is just ascii strings. 
 */ 
#define MAGIC "plan9 partitions" 
static void 
wrenpart(int dev) 
1991/0110    
{ 
1991/0823    
	Drive *dp; 
	Partition *pp; 
	uchar buf[32]; 
1991/0927    
	Scsibuf *b; 
	char *rawpart, *line[Npart+1], *field[3]; 
1991/0823    
	ulong n; 
	int i; 
1991/0110    
 
1991/0823    
	scsiready(dev); 
	scsisense(dev, buf); 
1991/1220    
	if (scsicap(dev, buf)) 
		error(Eio); 
1991/0823    
	dp = &wren[dev]; 
	dp->drive = dev; 
1991/0927    
 
1991/0823    
	/* 
	 *  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    
 
1991/0823    
	/* 
	 *  read partition table from disk, null terminate 
	 */ 
1991/0927    
	b = scsibuf(); 
1991/0823    
	if(waserror()){ 
1991/0927    
		scsifree(b); 
1991/0823    
		nexterror(); 
	} 
1991/0927    
	scsibread(dev, b, 1, dp->bytes, dp->p[0].end-1); 
	rawpart = b->virt; 
	rawpart[dp->bytes-1] = 0; 
1991/0823    
 
	/* 
	 *  parse partition table. 
	 */ 
1991/0927    
	n = getfields(rawpart, line, Npart+1, '\n'); 
1992/0109    
	if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){ 
1991/0927    
		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++; 
1991/0823    
		} 
	} 
	poperror(); 
1991/0927    
	scsifree(b); 
1991/0110    
} 


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