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

📄 devfloppy.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  send a command to the floppy */static intfloppycmd(void){	int i;	int tries;	fl.nstat = 0;	for(i = 0; i < fl.ncmd; i++){		for(tries = 0; ; tries++){			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)				break;			if(tries > 1000){				DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);				fldump();				/* empty fifo, might have been a bad command */				floppyresult();				return -1;			}			microdelay(8);	/* for machine independence */		}		outb(Pfdata, fl.cmd[i]);	}	return 0;}/* *  get a command result from the floppy * *  when the controller goes ready waiting for a command *  (instead of sending results), we're done *  */static intfloppyresult(void){	int i, s;	int tries;	/* get the result of the operation */	for(i = 0; i < sizeof(fl.stat); i++){		/* wait for status byte */		for(tries = 0; ; tries++){			s = inb(Pmsr)&(Ffrom|Fready);			if(s == Fready){				fl.nstat = i;				return fl.nstat;			}			if(s == (Ffrom|Fready))				break;			if(tries > 1000){				DPRINT("floppyresult: %d stats\n", i);				fldump();				fl.confused = 1;				return -1;			}			microdelay(8);	/* for machine independence */		}		fl.stat[i] = inb(Pfdata);	}	fl.nstat = sizeof(fl.stat);	return fl.nstat;}/* *  calculate physical address of a logical byte offset into the disk * *  truncate dp->length if it crosses a track boundary */static voidfloppypos(FDrive *dp, long off){	int lsec;	int ltrack;	int end;	lsec = off/dp->t->bytes;	ltrack = lsec/dp->t->sectors;	dp->tcyl = ltrack/dp->t->heads;	dp->tsec = (lsec % dp->t->sectors) + 1;	dp->thead = (lsec/dp->t->sectors) % dp->t->heads;	/*	 *  can't read across track boundaries.	 *  if so, decrement the bytes to be read.	 */	end = (ltrack+1)*dp->t->sectors*dp->t->bytes;	if(off+dp->len > end)		dp->len = end - off;}/* *  get the interrupt cause from the floppy. */static intfloppysense(void){	fl.ncmd = 0;	fl.cmd[fl.ncmd++] = Fsense;	if(floppycmd() < 0)		return -1;	if(floppyresult() < 2){		DPRINT("can't read sense response\n");		fldump();		fl.confused = 1;		return -1;	}	return 0;}static intcmddone(void *){	return fl.ncmd == 0;}/* *  Wait for a floppy interrupt.  If none occurs in 5 seconds, we *  may have missed one.  This only happens on some portables which *  do power management behind our backs.  Call the interrupt *  routine to try to clear any conditions. */static voidfloppywait(void){	tsleep(&fl.r, cmddone, 0, 5000);	if(!cmddone(0)){		floppyintr(0);		fl.confused = 1;	}}/* *  we've lost the floppy position, go to cylinder 0. */static intfloppyrecal(FDrive *dp){	dp->ccyl = -1;	dp->cyl = -1;	fl.ncmd = 0;	fl.cmd[fl.ncmd++] = Frecal;	fl.cmd[fl.ncmd++] = dp->dev;	if(floppycmd() < 0)		return -1;	floppywait();	if(fl.nstat < 2){		DPRINT("recalibrate: confused %ux\n", inb(Pmsr));		fl.confused = 1;		return -1;	}	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){		DPRINT("recalibrate: failed\n");		dp->confused = 1;		return -1;	}	dp->cyl = fl.stat[1];	if(dp->cyl != 0){		DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);		dp->cyl = -1;		dp->confused = 1;		return -1;	}	dp->confused = 0;	return 0;}/* *  if the controller or a specific drive is in a confused state, *  reset it and get back to a known state */static voidfloppyrevive(void){	FDrive *dp;	/*	 *  reset the controller if it's confused	 */	if(fl.confused){		DPRINT("floppyrevive in\n");		fldump();		/* reset controller and turn all motors off */		splhi();		fl.ncmd = 1;		fl.cmd[0] = 0;		outb(Pdor, 0);		delay(10);		outb(Pdor, Fintena|Fena);		delay(10);		spllo();		fl.motor = 0;		fl.confused = 0;		floppywait();		/* mark all drives in an unknown state */		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)			dp->confused = 1;		/* set rate to a known value */		outb(Pdsr, 0);		fl.rate = 0;		DPRINT("floppyrevive out\n");		fldump();	}}/* *  seek to the target cylinder * *	interrupt, no results */static longfloppyseek(FDrive *dp, long off){	floppypos(dp, off);	if(dp->cyl == dp->tcyl)		return dp->tcyl;	dp->cyl = -1;	fl.ncmd = 0;	fl.cmd[fl.ncmd++] = Fseek;	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;	if(floppycmd() < 0)		return -1;	floppywait();	if(fl.nstat < 2){		DPRINT("seek: confused\n");		fl.confused = 1;		return -1;	}	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){		DPRINT("seek: failed\n");		dp->confused = 1;		return -1;	}	dp->cyl = dp->tcyl;	return dp->tcyl;}/* *  read or write to floppy.  try up to three times. */static longfloppyxfer(FDrive *dp, int cmd, void *a, long off, long n){	long offset;	int tries;	if(off >= dp->t->cap)		return 0;	if(off + n > dp->t->cap)		n = dp->t->cap - off;	/* retry on error (until it gets ridiculous) */	tries = 0;	while(waserror()){		if(tries++ > 20)			nexterror();		DPRINT("floppyxfer: retrying\n");		/*floppyon(dp);*/	}	dp->len = n;	if(floppyseek(dp, off) < 0){		DPRINT("xfer: seek failed\n");		dp->confused = 1;		error(Eio);	}	/*	 *  set up the dma (dp->len may be trimmed)	 */	if(waserror()){		dmaend(DMAchan);		nexterror();	}	dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);	if(dp->len < 0)		error(Eio);	/*	 *  start operation	 */	fl.ncmd = 0;	fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;	fl.cmd[fl.ncmd++] = dp->tcyl;	fl.cmd[fl.ncmd++] = dp->thead;	fl.cmd[fl.ncmd++] = dp->tsec;	fl.cmd[fl.ncmd++] = dp->t->bcode;	fl.cmd[fl.ncmd++] = dp->t->sectors;	fl.cmd[fl.ncmd++] = dp->t->gpl;	fl.cmd[fl.ncmd++] = 0xFF;	if(floppycmd() < 0)		error(Eio);	/* Poll ready bits and transfer data */	floppyexec((char*)a, dp->len, cmd==Fread);	/*	 *  give bus to DMA, floppyintr() will read result	 */	floppywait();	dmaend(DMAchan);	poperror();	/*	 *  check for errors	 */	if(fl.nstat < 7){		DPRINT("xfer: confused\n");		fl.confused = 1;		error(Eio);	}	if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){		DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],			fl.stat[1], fl.stat[2]);		DPRINT("offset %lud len %ld\n", off, dp->len);		if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){			DPRINT("DMA overrun: retry\n");		} else			dp->confused = 1;		error(Eio);	}	/*	 *  check for correct cylinder	 */	offset = fl.stat[3] * dp->t->heads + fl.stat[4];	offset = offset*dp->t->sectors + fl.stat[5] - 1;	offset = offset * c2b[fl.stat[6]];	if(offset != off+dp->len){		DPRINT("xfer: ends on wrong cyl\n");		dp->confused = 1;		error(Eio);	}	poperror();	dp->lasttouched = m->ticks;	return dp->len;}/* *  format a track */static voidfloppyformat(FDrive *dp, char *params){ 	int cyl, h, sec;	ulong track;	uchar *buf, *bp;	FType *t;	char *f[3];	/*	 *  set the type	 */	if(getfields(params, f, 3, 1, " ") > 1){		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){			if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){				dp->t = t;				floppydir[NFDIR*dp->dev].length = dp->t->cap;				break;			}		}		if(t >= &floppytype[nelem(floppytype)])			error(Ebadarg);	} else {		floppysetdef(dp);		t = dp->t;	}	/*	 *  buffer for per track info	 */	buf = smalloc(t->sectors*4);	if(waserror()){		free(buf);		nexterror();	}	/* force a recalibrate to cylinder 0 */	dp->confused = 1;	if(!waserror()){		floppyon(dp);		poperror();	}	/*	 *  format a track at time	 */	for(track = 0; track < t->tracks*t->heads; track++){		cyl = track/t->heads;		h = track % t->heads;		/*		 *  seek to track, ignore errors		 */		floppyseek(dp, track*t->tsize);		dp->cyl = cyl;		dp->confused = 0;		/*		 *  set up the dma (dp->len may be trimmed)		 */		bp = buf;		for(sec = 1; sec <= t->sectors; sec++){			*bp++ = cyl;			*bp++ = h;			*bp++ = sec;			*bp++ = t->bcode;		}		if(waserror()){			dmaend(DMAchan);			nexterror();		}		if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)			error(Eio);		/*		 *  start operation		 */		fl.ncmd = 0;		fl.cmd[fl.ncmd++] = Fformat;		fl.cmd[fl.ncmd++] = (h<<2) | dp->dev;		fl.cmd[fl.ncmd++] = t->bcode;		fl.cmd[fl.ncmd++] = t->sectors;		fl.cmd[fl.ncmd++] = t->fgpl;		fl.cmd[fl.ncmd++] = 0x5a;		if(floppycmd() < 0)			error(Eio);		/* Poll ready bits and transfer data */		floppyexec((char *)buf, bp-buf, 0);		/*		 *  give bus to DMA, floppyintr() will read result		 */		floppywait();		dmaend(DMAchan);		poperror();		/*		 *  check for errors		 */		if(fl.nstat < 7){			DPRINT("format: confused\n");			fl.confused = 1;			error(Eio);		}		if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){			DPRINT("format: failed %ux %ux %ux\n",				fl.stat[0], fl.stat[1], fl.stat[2]);			dp->confused = 1;			error(Eio);		}	}	free(buf);	dp->confused = 1;	poperror();}static voidfloppyintr(Ureg *){	switch(fl.cmd[0]&~Fmulti){	case Fread:	case Fwrite:	case Fformat:	case Fdumpreg: 		floppyresult();		break;	case Fseek:	case Frecal:	default:		floppysense();	/* to clear interrupt */		break;	}	fl.ncmd = 0;	wakeup(&fl.r);}Dev floppydevtab = {	'f',	"floppy",	floppyreset,	devinit,	floppyattach,	devclone,	floppywalk,	floppystat,	floppyopen,	devcreate,	floppyclose,	floppyread,	devbread,	floppywrite,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

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