~kris/9p

9hist

56f80667320562b36ab312dee8adf2e1aa342064 — David du Colombier 32 years ago 58c5de2
Plan 9 from Bell Labs 1994-09-13
5 files changed, 381 insertions(+), 10 deletions(-)

M pc/devhard.c
M pc/fns.h
M port/devmouse.c
A port/devsd.c
M port/portfns.h
M pc/devhard.c => pc/devhard.c +19 -1
@@ 290,7 290,25 @@ hardcreate(Chan *c, char *name, int omode, ulong perm)
void
hardclose(Chan *c)
{
	USED(c);
	Drive *d;
	Partition *p;

	if(c->mode != OWRITE && c->mode != ORDWR)
		return;

	d = &hard[DRIVE(c->qid.path)];
	p = &d->p[PART(c->qid.path)];
	if(strcmp(p->name, "partition") != 0)
		return;

	if(waserror()){
		qunlock(d);
		nexterror();
	}
	qlock(d);
	hardpart(d);
	qunlock(d);
	poperror();
}

void

M pc/fns.h => pc/fns.h +1 -9
@@ 2,6 2,7 @@

void	aamloop(int);
void	addconf(char*, char*);
void	addscsicard(char*, Scsiio (*)(int, ISAConf*));
void	bbinit(void);
void	bigcursor(void);
void	bootargs(ulong);


@@ 118,12 119,3 @@ Block*	iallocb(int);
void*	ifroute(ulong);
ulong	ifunroute(ulong);
void	parseip(char*, char*);

#define	scsialloc(n)	mallocz((n)+512, 0)
#define scsifree(p)	free(p)

void	addscsicard(char*, Scsiio (*)(int, ISAConf*));
int	scsistart(Target*, char, int);
int	scsireqsense(Target*, char, int);
int	scsicap(Target*, char, ulong*, ulong*);
int	scsibio(Target*, char, int, void*, long, long, long);

M port/devmouse.c => port/devmouse.c +2 -0
@@ 324,6 324,7 @@ mouseclock(void)
		mouse.redraw = cursoron(0);
		unlock(&cursor);
	}
	graphicsactive(0);
}

/*


@@ 350,6 351,7 @@ mousetrack(int b, int dx, int dy)
	mouse.buttons = b;
	mouse.redraw = 1;
	wakeup(&mouse.r);
	graphicsactive(1);
}

/*

A port/devsd.c => port/devsd.c +352 -0
@@ 0,0 1,352 @@
/*
 *  SCSI disc driver
 */
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"devtab.h"

enum
{
	LogNpart	= 3,
	Npart		= 1<<LogNpart,
	Ndisk		= 32,
	Nlun		= 8,
};
#define DRIVE(qid)	((qid).path>>LogNpart)
#define PART(qid)	((qid).path&(Npart-1))

typedef struct Part Part;
typedef struct Disk Disk;

struct Part
{
	ulong	beg;
	ulong	end;
	char	name[NAMELEN];
};

struct Disk
{
	QLock;
	Target*	t;
	uchar	lun;
	char	id[NAMELEN];
	char	vol[NAMELEN];

	uchar*	inquire;
	ulong	size;
	ulong	bsize;

	int	npart;
	Part	table[Npart];
};

int	ndisk;
Disk	disk[Ndisk];

static	void	sdrdpart(Disk*);
static	long	sdio(Chan*, int, char*, ulong, ulong);

static int
sdgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
{
	Qid qid;
	Disk *d;
	Part *p;
	int unit;
	char name[2*NAMELEN];

	USED(tab, ntab);

	d = disk;
	while(s >= d->npart) {
		s -= d->npart;
		d++;
	}
	unit = d - disk;
	if(unit > ndisk)
		return -1;

	p = d->table+s;
	sprint(name, "%s%s", d->vol, p->name);
	name[NAMELEN-1] = '\0';
	qid = (Qid){(unit<<LogNpart)+s, 0};
	devdir(c, qid, name, (p->end - p->beg) * d->bsize, eve, 0666, dirp);
	return 1;
}

void
sdreset(void)
{
}

void
sdinit(void)
{
	Disk *d;
	ulong s, b;
	int dev, i;

	dev = 0;
	for(;;) {
		d = &disk[ndisk];
		dev = scsiinv(dev, 0, &d->t, &d->inquire, d->id);
		if(dev < 0)
			break;

		if(scsistart(d->t, 0, 1) != STok)
			continue;

		/* Search for other lun's */
		for(i = 0; i < Nlun; i++) {
			d->lun = i;
			scsireqsense(d->t, d->lun, 1);

			/* NCR Raid only seems to answer second capacity
			 * command if lun != 0
			 */
			if(scsicap(d->t, d->lun, &s, &b) != STok) {
				scsireqsense(d->t, 0, 1);
				continue;
			}
			scsireqsense(d->t, 0, 1);

			s = 0;
			b = 0;
			if(scsicap(d->t, d->lun, &s, &b) != STok) {
				scsireqsense(d->t, 0, 1);
				continue;
			}

			if(scsireqsense(d->t, d->lun, 1) != STok)
				continue;

			if(s == 0 || b == 0)
				continue;

			d->size = s;
			d->bsize = b;
			sprint(d->vol, "sd%d", ndisk);

			if(++ndisk >= Ndisk)
				break;
			d++;
			d->t = d[-1].t;
			d->inquire = d[-1].inquire;
			strcpy(d->id, d[-1].id);
		}

		if(ndisk >= Ndisk) {
			print("devsd: configure more disks\n");
			break;
		}
	}
}

Chan*
sdattach(char *spec)
{
	int i;

	for(i = 0; i < ndisk; i++)
		sdrdpart(&disk[i]);
	
	return devattach('w', spec);
}

Chan *
sdclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
sdwalk(Chan *c, char *name)
{
	return devwalk(c, name, 0, 0, sdgen);
}

void
sdstat(Chan *c, char *db)
{
	devstat(c, db, 0, 0, sdgen);
}

Chan *
sdopen(Chan *c, int omode)
{
	return devopen(c, omode, 0, 0, sdgen);
}

void
sdcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
sdremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
sdwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

void
sdclose(Chan *c)
{
	Disk *d;
	Part *p;

	if(c->mode != OWRITE && c->mode != ORDWR)
		return;

	d = &disk[DRIVE(c->qid)];
	p = &d->table[PART(c->qid)];
	if(strcmp(p->name, "partition"))
		return;

	sdrdpart(d);
}

long
sdread(Chan *c, void *a, long n, ulong offset)
{
	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, 0, 0, sdgen);

	return sdio(c, 0, a, n, offset);
}

long
sdwrite(Chan *c, char *a, long n, ulong offset)
{
	return sdio(c, 1, a, n, offset);
}

static void
sdrdpart(Disk *d)
{
	Part *p;
	int n, i;
	char *b, *line[Npart+2], *field[3];
	static char MAGIC[] = "plan9 partitions";

	b = scsialloc(d->bsize);
	if(b == 0)
		error(Enomem);

	qlock(d);
	
	p = d->table;

	strcpy(p->name, "disk");
	p->beg = 0;
	p->end = d->size + 1;
	p++;
	strcpy(p->name, "partition");
	p->beg = d->table[0].end - 1;
	p->end = d->table[0].end;
	p++;
	d->npart = 2;

	scsibio(d->t, d->lun, SCSIread, b, 1, d->bsize, d->table[0].end-1);
	b[d->bsize-1] = '\0';

	/*
	 *  parse partition table.
	 */
	n = getfields(b, line, Npart+2, '\n');
	if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0) {
		for(i = 1; i < n; i++) {
			switch(getfields(line[i], field, 3, ' ')) {
			case 2:
				if(strcmp(field[0], "unit") == 0)
					strncpy(d->vol, field[1], NAMELEN);
				break;	
			case 3:
				strncpy(p->name, field[0], NAMELEN);
				p->beg = strtoul(field[1], 0, 0);
				p->end = strtoul(field[2], 0, 0);
				if(p->beg > p->end || p->beg >= d->table[0].end)
					break;
				p++;
			}
		}
	}
	d->npart = p - d->table;
	scsifree(b);
	qunlock(d);
}

static long
sdio(Chan *c, int write, char *a, ulong len, ulong offset)
{
	Disk *d;
	Part *p;
	uchar *b;
	ulong block, n, max, x;

	d = &disk[DRIVE(c->qid)];
	p = &d->table[PART(c->qid)];

	block = (offset / d->bsize) + p->beg;
	n = (offset + len + d->bsize - 1) / d->bsize + p->beg - block;
	max = SCSImaxxfer / d->bsize;
	if(n > max)
		n = max;
	if(block + n > p->end)
		n = p->end - block;
	if(block >= p->end || n == 0)
		return 0;

	b = scsialloc(n*d->bsize);
	if(b == 0)
		error(Enomem);
	if(waserror()) {
		scsifree(b);
		nexterror();
	}
	offset %= d->bsize;
	if(write) {
		if(offset || len % d->bsize) {
			x = scsibio(d->t, d->lun, SCSIread, b, n, d->bsize, block);
			if(x < n * d->bsize) {
				n = x / d->bsize;
				x = n * d->bsize - offset;
				if(len > x)
					len = x;
			}
		}
		memmove(b + offset, a, len);
		x = scsibio(d->t, d->lun, SCSIwrite, b, n, d->bsize, block);
		if(x < offset)
			len = 0;
		else
		if(len > x - offset)
			len = x - offset;
	}
	else {
		x = scsibio(d->t, d->lun, SCSIread, b, n, d->bsize, block);
		if(x < offset)
			len = 0;
		else
		if(len > x - offset)
			len = x - offset;
		memmove(a, b+offset, len);
	}
	poperror();
	scsifree(b);
	return len;
}

M port/portfns.h => port/portfns.h +7 -0
@@ 88,6 88,7 @@ void		freesession(Session*);
void		getcolor(ulong, ulong*, ulong*, ulong*);
int		getfields(char*, char**, int, char);
void		gotolabel(Label*);
void		graphicsactive(int);
int		haswaitq(void*);
long		hostdomainwrite(char*, int);
long		hostownerwrite(char*, int);


@@ 225,8 226,14 @@ void		sccsetup(void*, ulong, int);
void		sched(void);
void		schedinit(void);
int		screenbits(void);
#define		scsialloc(n)	mallocz((n)+512, 0)
int		scsibio(Target*, char, int, void*, long, long, long);
int		scsicap(Target*, char, ulong*, ulong*);
int		scsiexec(Target*, int, uchar*, int, void*, int*);
#define		scsifree(p)	free(p)
int		scsiinv(int, int, Target**, uchar**, char*);
int		scsireqsense(Target*, char, int);
int		scsistart(Target*, char, int);
Target*		scsiunit(int, int);
long		seconds(void);
ulong		segattach(Proc*, ulong, char *, ulong, ulong);