⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 juke.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
{	uchar cmd[12], buf[4];	int s;	static recur = 0;	memset(cmd, 0, sizeof(cmd));	cmd[0] = 0xa5;	/* move medium */	cmd[2] = trans>>8;	cmd[3] = trans;	cmd[4] = from>>8;	cmd[5] = from;	cmd[6] = to>>8;	cmd[7] = to;	if(rot)		cmd[10] = 1;	s = scsiio(w->juke, SCSInone, cmd, sizeof(cmd), buf, 0);	if(s) {		print("scsio status #%x\n", s);		print("move medium t=%d fr=%d to=%d rot=%d\n",			trans, from, to, rot);//		panic("mmove");		if(recur == 0) {			recur = 1;			print("element from=%d\n", from);			element(w, from);			print("element to=%d\n", to);			element(w, to);			print("element trans=%d\n", trans);			element(w, trans);			recur = 0;		}		return 1;	}	return 0;}staticvoidgeometry(Juke *w){	int s;	uchar cmd[6], buf[4+20];	memset(cmd, 0, sizeof(cmd));	memset(buf, 0, sizeof(buf));	cmd[0] = 0x1a;		/* mode sense */	cmd[2] = 0x1d;		/* element address assignment */	cmd[4] = sizeof(buf);	/* allocation length */	s = scsiio(w->juke, SCSIread, cmd, sizeof(cmd), buf, sizeof(buf));	if(s)		panic("geometry #%x\n", s);	w->mt0 = (buf[4+2]<<8) | buf[4+3];	w->nmt = (buf[4+4]<<8) | buf[4+5];	w->se0 = (buf[4+6]<<8) | buf[4+7];	w->nse = (buf[4+8]<<8) | buf[4+9];	w->ie0 = (buf[4+10]<<8) | buf[4+11];	w->nie = (buf[4+12]<<8) | buf[4+13];	w->dt0 = (buf[4+14]<<8) | buf[4+15];	w->ndt = (buf[4+16]<<8) | buf[4+17];	memset(cmd, 0, 6);	memset(buf, 0, sizeof(buf));	cmd[0] = 0x1a;		/* mode sense */	cmd[2] = 0x1e;		/* transport geometry */	cmd[4] = sizeof(buf);	/* allocation length */	s = scsiio(w->juke, SCSIread, cmd, sizeof(cmd), buf, sizeof(buf));	if(s)		panic("geometry #%x\n", s);	w->rot = buf[4+2] & 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();}staticvoidelement(Juke *w, int e){	uchar cmd[12], buf[8+8+88];	int s, t;	memset(cmd, 0, sizeof(cmd));	memset(buf, 0, sizeof(buf));	cmd[0] = 0xb8;		/* read element status */	cmd[2] = e>>8;		/* starting element */	cmd[3] = e;	cmd[5] = 1;		/* number of elements */	cmd[9] = sizeof(buf);	/* allocation length */	s = scsiio(w->juke, SCSIread, cmd, sizeof(cmd), buf, sizeof(buf));	if(s) {		print("scsiio #%x\n", s);		goto bad;	}	s = (buf[0]<<8) | buf[1];	if(s != e) {		print("element = %d\n", s);		goto bad;	}	if(buf[3] != 1) {		print("number reported = %d\n", buf[3]);		goto bad;	}	s = (buf[8+8+0]<<8) | buf[8+8+1];	if(s != e) {		print("element1 = %d\n", s);		goto bad;	}	switch(buf[8+0]) {	/* element type */	default:		print("unknown element %d: %d\n", e, buf[8+0]);		goto bad;	case 1:			/* transport */		s = e - w->mt0;		if(s < 0 || s >= w->nmt)			goto bad;		if(buf[8+8+2] & 1)			print("transport %d full %d.%d\n", s,				(buf[8+8+10]<<8) | buf[8+8+11],				(buf[8+8+9]>>6) & 1);		break;	case 2:			/* storage */		s = e - w->se0;		if(s < 0 || s >= w->nse)			goto bad;		w->side[s].status = Sempty;		if(buf[8+8+2] & 1)			w->side[s].status = Sunload;		if(w->rot)			w->side[w->nse+s].status = w->side[s].status;		break;	case 3:			/* import/export */		s = e - w->ie0;		if(s < 0 || s >= w->nie)			goto bad;		print("import/export %d #%.2x %d.%d\n", s,			buf[8+8+2],			(buf[8+8+10]<<8) | buf[8+8+11],			(buf[8+8+9]>>6) & 1);		break;	case 4:			/* data transfer */		s = e - w->dt0;		if(s < 0 || s >= w->ndt)			goto bad;		print("data transfer %d #%.2x %d.%d\n", s,			buf[8+8+2],			(buf[8+8+10]<<8) | buf[8+8+11],			(buf[8+8+9]>>6) & 1);		if(buf[8+8+2] & 1) {			t = ((buf[8+8+10]<<8) | buf[8+8+11]) - w->se0;			if (t < 0 || t >= w->nse || t >= MAXSIDE ||			    s >= MAXDRIVE) {				print(		"element: juke %Z lies; claims side %d is in drive %d\n",					w->juke, t, s);	/* lying sack of ... */				/*				 * at minimum, we've avoided corrupting our				 * data structures.  if we know that numbers				 * like w->nside are valid here, we could use				 * them in more stringent tests.				 * perhaps should whack the jukebox upside the				 * head here to knock some sense into it.				 */				goto bad;			}			print("r%d in drive %d\n", t, s);			if(mmove(w, w->mt0, w->dt0+s, w->se0+t, (buf[8+8+9]>>6) & 1)) {				print("mmove initial unload\n");				goto bad;			}			w->side[t].status = Sunload;			if(w->rot)				w->side[w->nse+t].status = Sunload;		}		if(buf[8+8+2] & 4) {			print("drive w%d has exception #%.2x #%.2x\n", s,				buf[8+8+4], buf[8+8+5]);			goto bad;		}		break;	}	return;bad:	/* panic("element") */ ;}staticvoidpositions(Juke *w){	int i, f;	/* mark empty shelves */	for(i=0; i<w->nse; i++)		element(w, w->se0+i);	for(i=0; i<w->nmt; i++)		element(w, w->mt0+i);	for(i=0; i<w->nie; i++)		element(w, w->ie0+i);	for(i=0; i<w->ndt; i++)		element(w, w->dt0+i);	f = 0;	for(i=0; i<w->nse; i++) {		if(w->side[i].status == Sempty) {			if(f) {				print("r%d\n", i-1);				f = 0;			}		} else {			if(!f) {				print("	shelves r%d-", i);				f = 1;			}		}	}	if(f)		print("r%d\n", i-1);}staticvoidjinit(Juke *w, Device *d, int o){	int p;	Device *dev = d;	switch(d->type) {	default:		print("juke platter not (devmcat of) dev(l)worm: %Z\n", d);		panic("jinit: type");	case Devmcat:		/*		 * we don't call mcatinit(d) here, so we have to set d->cat.ndev		 * ourselves.		 */		for(d=d->cat.first; d; d=d->link)			jinit(w, d, o++);		dev->cat.ndev = o;		break;	case Devlworm:		p = d->wren.targ;		if(p < 0 || p >= w->nside)			panic("jinit partition %Z\n", d);		w->side[p].ord = o;	case Devworm:		if(d->private) {			print("juke platter private pointer set %p\n",				d->private);			panic("jinit: private");		}		d->private = w;		break;	}}Side*wormi(char *arg){	int i, j;	Juke *w;	Side *v;	i = number(arg, -1, 10) - 1;	w = jukelist;	if(i < 0 || i >= w->nside) {		print("bad unit number %s (%d)\n", arg, i+1);		return 0;	}	j = i;	if(j >= w->nse)		j -= w->nse;	if(j < w->nside) {		v = &w->side[j];		qlock(v);		if(v->status == Sstart) {			if(mmove(w, w->mt0, w->dt0+v->drive, v->elem, v->rot)) {				qunlock(v);				return 0;			}			v->status = Sunload;		}		qunlock(v);	}	j += w->nse;	if(j < w->nside) {		v = &w->side[j];		qlock(v);		if(v->status == Sstart) {			if(mmove(w, w->mt0, w->dt0+v->drive, v->elem, v->rot)) {				qunlock(v);				return 0;			}			v->status = Sunload;		}		qunlock(v);	}	v = &w->side[i];	qlock(v);	return v;}staticvoidcmd_wormoffline(int argc, char *argv[]){	int u, i;	Juke *w;	if(argc <= 1) {		print("usage: wormoffline drive\n");		return;	}	u = number(argv[1], -1, 10);	w = jukelist;	if(u < 0 || u >= w->ndrive) {		print("bad drive %s (0<=%d<%d)\n", argv[1], u, w->ndrive);		return;	}	if(w->offline[u])		print("drive %d already offline\n", u);	w->offline[u] = 1;	for(i=0; i<w->ndrive; i++)		if(w->offline[i] == 0)			return;	print("that would take all drives offline\n");	w->offline[u] = 0;}staticvoidcmd_wormonline(int argc, char *argv[]){	int u;	Juke *w;	if(argc <= 1) {		print("usage: wormonline drive\n");		return;	}	u = number(argv[1], -1, 10);	w = jukelist;	if(u < 0 || u >= w->ndrive) {		print("bad drive %s (0<=%d<%d)\n", argv[1], u, w->ndrive);		return;	}	if(w->offline[u] == 0)		print("drive %d already online\n", u);	w->offline[u] = 0;}staticvoidcmd_wormreset(int, char *[]){	Juke *w;	for(w=jukelist; w; w=w->link) {		qlock(w);		positions(w);		qunlock(w);	}}staticvoidcmd_wormeject(int argc, char *argv[]){	Juke *w;	Side *v;	if(argc <= 1) {		print("usage: wormeject unit\n");		return;	}	v = wormi(argv[1]);	if(v == 0)		return;	w = jukelist;	mmove(w, w->mt0, v->elem, w->ie0, 0);	qunlock(v);}staticvoidcmd_wormingest(int argc, char *argv[]){	Juke *w;	Side *v;	if(argc <= 1) {		print("usage: wormingest unit\n");		return;	}	v = wormi(argv[1]);	if(v == 0)		return;	w = jukelist;	mmove(w, w->mt0, w->ie0, v->elem, 0);	qunlock(v);}voidjukeinit(Device *d){	Juke *w;	Device *xdev;	Side *v;	int i;	/* j(w<changer>w<station0>...)(r<platters>) */	xdev = d->j.j;	if(xdev->type != Devmcat) {		print("juke union not mcat\n");		goto bad;	}	/*	 * pick up the changer device	 */	xdev = xdev->cat.first;	if(xdev->type != Devwren) {		print("juke changer not wren %Z\n", xdev);		goto bad;	}	for(w=jukelist; w; w=w->link)		if(xdev == w->juke)			goto found;	/*	 * allocate a juke structure	 * no locking problems.	 */	w = ialloc(sizeof(Juke), 0);	w->link = jukelist;	jukelist = w;	print("alloc juke %Z\n", xdev);	qlock(w);	qunlock(w);	w->name = "juke";	w->juke = xdev;	geometry(w);	/*	 * pick up each side	 */	w->nside = w->nse;	if(w->rot)		w->nside += w->nside;	if(w->nside > MAXSIDE) {		print("too many sides: %d max %d\n", w->nside, MAXSIDE);		goto bad;	}	for(i=0; i<w->nse; i++) {		v = &w->side[i];		qlock(v);		qunlock(v);		v->name = "shelf";		v->elem = w->se0 + i;		v->rot = 0;		v->status = Sempty;		v->time = toytime();		if(w->rot) {			v += w->nse;			qlock(v);			qunlock(v);			v->name = "shelf";			v->elem = w->se0 + i;			v->rot = 1;			v->status = Sempty;			v->time = toytime();		}	}	positions(w);	w->ndrive = w->ndt;	if(w->ndrive > MAXDRIVE) {		print("ndrives truncated to %d\n", MAXDRIVE);		w->ndrive = MAXDRIVE;	}	/*	 * pick up each drive	 */	for(i=0; i<w->ndrive; i++)		w->drive[i] = devnone;	cmd_install("wormreset", "-- put drives back where jukebox thinks they belong", cmd_wormreset);	cmd_install("wormeject", "unit -- shelf to outside", cmd_wormeject);	cmd_install("wormingest", "unit -- outside to shelf", cmd_wormingest);	cmd_install("wormoffline", "unit -- disable drive", cmd_wormoffline);	cmd_install("wormonline", "unit -- enable drive", cmd_wormonline);found:	i = 0;	while(xdev = xdev->link) {		if(xdev->type != Devwren) {			print("drive not devwren: %Z\n", xdev);			goto bad;		}		if(w->drive[i]->type != Devnone &&		   xdev != w->drive[i]) {			print("double init drive %d %Z %Z\n", i, w->drive[i], xdev);			goto bad;		}		if(i >= w->ndrive) {			print("too many drives %Z\n", xdev);			goto bad;		}		w->drive[i++] = xdev;	}	if(i <= 0) {		print("no drives\n");		goto bad;	}	/*	 * put w pointer in each platter	 */	d->private = w;	jinit(w, d->j.m, 0);	w->probeok = 1;	return;bad:	panic("juke init");}/* * called periodically */voidwormprobe(void){	int i, drive;	Timet t;	Side *v;	Juke *w;	t = toytime() - TWORM;	for(w=jukelist; w; w=w->link) {		if(w->probeok == 0 || !canqlock(w))			continue;		for(i=0; i<w->nside; i++) {			v = &w->side[i];			if(!canqlock(v))				continue;			if(v->status == Sstart && t > v->time) {				drive = v->drive;				print("	time   r%ld drive %Z\n",					v-w->side, w->drive[drive]);				mmove(w, w->mt0, w->dt0+drive, v->elem, v->rot);				v->status = Sunload;			}			qunlock(v);		}		qunlock(w);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -