henesyinit from p9fd787fda5 years agoHistory
943 lines · 16.4 KB · C
RawDownload
#include	"all.h" #define	SCSInone	SCSIread#define	MAXDRIVE	10#define	MAXSIDE		300#define	FIXEDSIZE	1#define	TWORM		MINUTE(10)#define	THYSTER		SECOND(10) #define	EXIT	0 typedef	struct	Side	Side;struct	Side{	QLock;			/* protects loading/unloading */	int	elem;		/* element number */	int	drive;		/* if loaded, where */	uchar	status;		/* Sunload, etc */	uchar	rot;		/* if backside */	int	ord;		/* ordinal number for labeling */ 	long	time;		/* time since last access, to unspin */	long	stime;		/* time since last spinup, for hysteresis */	long	nblock;		/* number of native blocks */	long	block;		/* bytes per native block */	long	mult;		/* multiplier to get plan9 blocks */	long	max;		/* max size in plan9 blocks */}; typedef	struct	Juke	Juke;struct	Juke{	QLock;			/* protects drive mechanism */	Side	side[MAXSIDE];	int	nside;		/* how many storage elements (*2 if rev) */	int	ndrive;		/* number of transfer elements */	int	swab;		/* data is swabbed */	Device*	juke;		/* devworm of changer */	Device*	drive[MAXDRIVE];/* devworm for i/o */	long	fixedsize;	/* one size fits all */	int	probeok;	/* wait for init to probe */ 	/* geometry returned by mode sense */	int	mt0,	nmt;	int	se0,	nse;	int	ie0,	nie;	int	dt0,	ndt;	int	rot; 	Juke*	link;};static	Juke*	jukelist; enum{	Sempty = 0,	/* does not exist */	Sunload,	/* on the shelf */	Sstart,		/* loaded and spinning */}; static	Side*	wormunit(Device*);static	void	shelves(void);static	void	mmove(Juke*, int, int, int, int);static	int	bestdrive(Juke*, int);static	void	waitready(Device*);static	int	wormsense(Juke*, int); /* * mounts and spins up the device *	locks the structure */staticSide*wormunit(Device *d){	int p, s, drive;	Side *v;	Juke *w;	Device *dev;	uchar cmd[10], buf[8]; 	w = d->private;	p = d->wren.targ;	if(p < 0 || p >= w->nside)		panic("wormunit partition %Z\n", d); 	/*	 * if disk is unloaded, must load it	 * into next (circular) logical unit	 */	v = &w->side[p];	qlock(v);	if(v->status == Sunload) {		for(;;) {			qlock(w);			drive = bestdrive(w, p);			if(drive >= 0)				break;			qunlock(w);			waitsec(100);		}		print("	load  r%ld drive %Z\n", v-w->side, w->drive[drive]);		mmove(w, w->mt0, v->elem, w->dt0+w->drive[drive]->wren.lun, v->rot);		v->drive = drive;		v->status = Sstart;		v->stime = toytime();		qunlock(w);		waitready(w->drive[drive]);		v->stime = toytime();	}	if(v->status != Sstart) {		if(v->status == Sempty)			print("worm: unit empty %Z\n", d);		else			print("worm: not started %Z\n", d);		goto sbad;	} 	v->time = toytime();	if(v->block)		return v; 	/*	 * capacity command	 */	dev = w->drive[v->drive];	memset(cmd, 0, sizeof(cmd));	memset(buf, 0, sizeof(buf));	cmd[0] = 0x25;	/* read capacity */	cmd[1] = (dev->wren.lun&0x7) << 5;	s = scsiio(w->drive[v->drive], SCSIread,		cmd, sizeof(cmd), buf, sizeof(buf));	if(s)		goto sbad; 	v->nblock =		(buf[0]<<24) |		(buf[1]<<16) |		(buf[2]<<8) |		(buf[3]<<0);	v->block =		(buf[4]<<24) |		(buf[5]<<16) |		(buf[6]<<8) |		(buf[7]<<0);	v->mult =		(RBUFSIZE + v->block - 1) /		v->block;	v->max =		(v->nblock + 1) / v->mult; 	print("	worm %Z: drive %Z\n", d, w->drive[v->drive]);	print("		%ld blocks at %ld bytes each\n",		v->nblock, v->block);	print("		%ld logical blocks at %d bytes each\n",		v->max, RBUFSIZE);	print("		%ld multiplier\n",		v->mult);	if(d->type != Devlworm)		return v;	/* check for label */	print("label %Z ordinal %d\n", d, v->ord);	qunlock(v);	return wormunit(d); sbad:	qunlock(v);	panic("wormunit sbad");	return 0;} staticvoidwaitready(Device *d){	uchar cmd[6];	int s, e; 	for(e=0;e<100;e++) {		memset(cmd, 0, sizeof(cmd));		cmd[1] = (d->wren.lun&0x7) << 5;		s = scsiio(d, SCSInone, cmd, sizeof(cmd), cmd, 0);		if(s == 0)			break;		waitsec(100);	}} staticintbestdrive(Juke *w, int side){	Side *v, *bv[MAXDRIVE];	int i, s, e, drive;	long t, t0; loop:	/* build table of what platters on what drives */	for(i=0; i<w->ndt; i++)		bv[i] = 0; 	v = &w->side[0];	for(i=0; i<w->nside; i++, v++) {		s = v->status;		if(s == Sstart) {			drive = v->drive;			if(drive >= 0 && drive < w->ndt)				bv[drive] = v;		}	} 	/*	 * find oldest drive, but must be	 * at least THYSTER old.	 */	e = w->side[side].elem;	t0 = toytime() - THYSTER;	t = t0;	drive = -1;	for(i=0; i<w->ndt; i++) {		v = bv[i];		if(v == 0) {		/* 2nd priority: empty drive */			if(w->drive[i] != devnone) {				drive = i;				t = 0;			}			continue;		}		if(v->elem == e) {	/* 1st priority: other side */			drive = -1;			if(v->stime < t0)				drive = i;			break;		}		if(v->stime < t) {	/* 3rd priority: by time */			drive = i;			t = v->stime;		}	} 	if(drive >= 0) {		v = bv[drive];		if(v) {			qlock(v);			if(v->status != Sstart) {				qunlock(v);				goto loop;			}			print("	unload r%ld drive %Z\n",				v-w->side, w->drive[drive]);			mmove(w, w->mt0, w->dt0+w->drive[drive]->wren.lun,				v->elem, v->rot);			v->status = Sunload;			qunlock(v);		}	}	return drive;} longwormsize(Device *d){	Side *v;	Juke *w;	long size; 	w = d->private;	if(w->fixedsize) {		size = w->fixedsize;		goto out;	} 	v = wormunit(d);	if(v == 0)		return 0;	size = v->max;	qunlock(v);	if(FIXEDSIZE)		w->fixedsize = size;out:	if(d->type == Devlworm)		return size-1;	return size;} staticintwormiocmd(Device *d, int io, long b, void *c){	Side *v;	Juke *w;	long l, m;	int s;	Device *dev;	uchar cmd[10]; 	w = d->private;	v = wormunit(d);	if(v == 0) {		qunlock(v);		return 0x71;	}	if(b >= v->max) {		qunlock(v);		print("worm: wormiocmd out of range %Z(%ld)\n", d, b);		return 0x071;	} 	dev = w->drive[v->drive];	memset(cmd, 0, sizeof(cmd));	cmd[0] = 0x28;		/* extended read */	if(io != SCSIread) {		cmd[0] = 0x2a;	/* extended write */		if(w->swab)			swab(c, 1);	}	cmd[1] = (dev->wren.lun&0x7) << 5; 	m = v->mult;	l = b * m;	cmd[2] = l>>24;	cmd[3] = l>>16;	cmd[4] = l>>8;	cmd[5] = l; 	cmd[7] = m>>8;	cmd[8] = m; 	s = scsiio(dev, io, cmd, sizeof(cmd), c, RBUFSIZE);	if(w->swab)		swab(c, 0);	qunlock(v);	return s;} intwormread(Device *d, long b, void *c){	int s; 	s = wormiocmd(d, SCSIread, b, c);	if(s) {		print("wormread: %Z(%ld) bad status #%x\n", d, b, s);		cons.nwormre++;		return s;	}	return 0;} intwormwrite(Device *d, long b, void *c){	int s; 	s = wormiocmd(d, SCSIwrite, b, c);	if(s) {		print("wormwrite: %Z(%ld) bad status #%x\n", d, b, s);		cons.nwormwe++;		return s;	}	return 0;} staticvoidmmove(Juke *w, int trans, int from, int to, int rot){	uchar cmd[10], buf[8];	int s, u, p; 	s = 0;	if(trans != w->mt0)		goto bad; 	if(from >= w->se0 && from <= w->se0+w->nse && 	   to >= w->dt0 && to < w->dt0+w->ndt) {		p = from - w->se0;		u = to - w->dt0; 		print("worm: set %d; lun %d\n", p, u);		memset(cmd, 0, 6);		cmd[0] = 0xd6;	/* disk set */		cmd[1] = u << 5;		cmd[3] = (p << 1) | rot;		s = scsiio(w->juke, SCSInone, cmd, 6, buf, 0);		if(s)			goto bad; 		memset(cmd, 0, 6);		cmd[0] = 0x15;	/* mode select */		cmd[1] = u << 5;		cmd[4] = 6;		memset(buf, 0, 6);		buf[2] = 1;	/* ebc */		buf[4] = 7;	/* ealt,evrf,edtre */		s = scsiio(w->juke, SCSIwrite, cmd, 6, buf, 6);		if(s)			goto bad; 		print("worm: start %d; lun %d\n", p, u);		memset(cmd, 0, 6);		cmd[0] = 0x1b;	/* disk start */		cmd[1] = u << 5;		cmd[4] = 1;		s = scsiio(w->juke, SCSInone, cmd, 6, buf, 0);		if(s)			goto bad;		return;	}	if(from >= w->dt0 && from <= w->dt0+w->ndt && 	   to >= w->se0 && to < w->se0+w->nse) {		p = to - w->se0;		u = from - w->dt0; 		print("worm: stop %d; lun %d\n", p, u);		memset(cmd, 0, 6);		cmd[0] = 0x1b;	/* disk stop */		cmd[1] = u << 5;		s = scsiio(w->juke, SCSInone, cmd, 6, buf, 0);		if(s)			goto bad; 		print("worm: release %d; lun %d\n", p, u);		memset(cmd, 0, 6);		cmd[0] = 0xd7;	/* disk release */		cmd[1] = u << 5;		s = scsiio(w->juke, SCSInone, cmd, 6, buf, 0);		if(s)			goto bad;		return;	}	print("not load or unload\n"); bad:	print("scsio status #%x\n", s);	print("move meduim t=%d fr=%d to=%d rot=%d", trans, from, to, rot);	panic("mmove"); } staticvoidgeometry(Juke *w){	int s; 	s = wormsense(w, 0);	while(s == 0x70) {		delay(3000);		s = wormsense(w, 0);	} 	w->se0 = 0;	w->nse = 50;	w->dt0 = 110;	w->ndt = 2;		/* 1-8 */	w->mt0 = 110;	w->nmt = 1;	w->ie0 = 111;	w->nie = 1;  	w->rot = 1; 	print("	mt %d %d\n", w->mt0, w->nmt);	print("	se %d %d\n", w->se0, w->nse);	print("	ie %d %d\n", w->ie0, w->nie);	print("	dt %d %d\n", w->dt0, w->ndt);	print("	rot %d\n", w->rot);	prflush();	/**/ } staticintwormsense(Juke *w, int lun){	uchar cmd[6], buf[4];	int s;	char *sc; 	memset(cmd, 0, 6);	cmd[0] = 0x03;	/* request sense */	cmd[1] = lun<<5;	memset(buf, 0, 4);	s = 0x70;	/* robs fault */	if(!scsiio(w->juke, SCSIread, cmd, 6, buf, 4))		s = buf[0] & 0x7f;	sc = wormscode[s];	if(!sc)		sc = "unknown";	print("	sense code %.2x %s\n", s, sc);	return s;} staticvoidelement(Juke *w, int e){	uchar cmd[6], buf[128], *p, *q;

Lines 1–500 of 943.