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

📄 devfloppy.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h"#include	"floppy.h"/* Intel 82077A (8272A compatible) floppy controller *//* This module expects the following functions to be defined * elsewhere:  *  * inb() * outb() * floppyexec() * floppyeject()  * floppysetup0() * floppysetup1() * dmainit() * dmasetup() * dmaend() *  * On DMA systems, floppyexec() should be an empty function;  * on non-DMA systems, dmaend() should be an empty function;  * dmasetup() may enforce maximum transfer sizes.  */enum {	/* file types */	Qdir=		0, 	Qdata=		(1<<2),	Qctl=		(2<<2),	Qmask=		(3<<2),	DMAchan=	2,	/* floppy dma channel */};#define DPRINT if(floppydebug)printint floppydebug = 0;/* *  types of drive (from PC equipment byte) */enum{	Tnone=		0,	T360kb=		1,	T1200kb=	2,	T720kb=		3,	T1440kb=	4,};FType floppytype[] ={ { "3½HD",	T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54,	0, }, { "3½DD",	T1440kb, 512,  9, 2, 1, 80, 0x1B, 0x54, 2, }, { "3½DD",	T720kb,  512,  9, 2, 1, 80, 0x1B, 0x54, 2, }, { "5¼HD",	T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, }, { "5¼DD",	T1200kb, 512,  9, 2, 2, 40, 0x2A, 0x50, 1, }, { "ATT3B1",	T1200kb, 512,  8, 2, 2, 48, 0x2A, 0x50, 1, }, { "5¼DD",	T360kb,  512,  9, 2, 1, 40, 0x2A, 0x50, 2, },};/* *  bytes per sector encoding for the controller. *  - index for b2c is is (bytes per sector/128). *  - index for c2b is code from b2c */static int b2c[] ={[1]	0,[2]	1,[4]	2,[8]	3,};static int c2b[] ={	128,	256,	512,	1024,};FController	fl;#define MOTORBIT(i)	(1<<((i)+4))/* *  predeclared */static int	cmddone(void*);static void	floppyformat(FDrive*, char*);static void	floppykproc(void*);static void	floppypos(FDrive*,long);static int	floppyrecal(FDrive*);static int	floppyresult(void);static void	floppyrevive(void);static long	floppyseek(FDrive*, long);static int	floppysense(void);static void	floppywait(void);static long	floppyxfer(FDrive*, int, void*, long, long);Dirtab floppydir[]={	"fd0disk",		{Qdata + 0},	0,	0660,	"fd0ctl",		{Qctl + 0},	0,	0660,	"fd1disk",		{Qdata + 1},	0,	0660,	"fd1ctl",		{Qctl + 1},	0,	0660,	"fd2disk",		{Qdata + 2},	0,	0660,	"fd2ctl",		{Qctl + 2},	0,	0660,	"fd3disk",		{Qdata + 3},	0,	0660,	"fd3ctl",		{Qctl + 3},	0,	0660,};#define NFDIR	2	/* directory entries/drive */static voidfldump(void){	DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),		inb(Pdor), inb(Pmsr), inb(Pdir));}/* *  set floppy drive to its default type */static voidfloppysetdef(FDrive *dp){	FType *t;	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)		if(dp->dt == t->dt){			dp->t = t;			floppydir[NFDIR*dp->dev].length = dp->t->cap;			break;		}}static voidfloppyreset(void){	FDrive *dp;	FType *t;	ulong maxtsize;		floppysetup0(&fl);	if(fl.ndrive == 0)		return;	/*	 *  init dependent parameters	 */	maxtsize = 0;	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){		t->cap = t->bytes * t->heads * t->sectors * t->tracks;		t->bcode = b2c[t->bytes/128];		t->tsize = t->bytes * t->sectors;		if(maxtsize < t->tsize)			maxtsize = t->tsize;	}	dmainit(DMAchan, maxtsize);	/*	 *  allocate the drive storage	 */	fl.d = xalloc(fl.ndrive*sizeof(FDrive));	fl.selected = fl.d;	/*	 *  stop the motors	 */	fl.motor = 0;	delay(10);	outb(Pdor, fl.motor | Fintena | Fena);	delay(10);	/*	 *  init drives	 */	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){		dp->dev = dp - fl.d;		dp->dt = T1440kb;		floppysetdef(dp);		dp->cyl = -1;			/* because we don't know */		dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);		dp->ccyl = -1;		dp->vers = 0;	}	/*	 *  first operation will recalibrate	 */	fl.confused = 1;	floppysetup1(&fl);}static Chan*floppyattach(char *spec){	static int kstarted;	if(fl.ndrive == 0)		error(Enodev);	if(kstarted == 0){		/*		 *  watchdog to turn off the motors		 */		kstarted = 1;		kproc("floppy", floppykproc, 0);	}	return devattach('f', spec);}static intfloppywalk(Chan *c, char *name){	return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen);}static voidfloppystat(Chan *c, char *dp){	devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen);}static Chan*floppyopen(Chan *c, int omode){	return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen);}static voidfloppyclose(Chan *){}static voidislegal(ulong offset, long n, FDrive *dp){	if(offset % dp->t->bytes)		error(Ebadarg);	if(n % dp->t->bytes)		error(Ebadarg);}/* *  check if the floppy has been replaced under foot.  cause *  an error if it has. * *  a seek and a read clears the condition.  this was determined *  experimentally, there has to be a better way. * *  if the read fails, cycle through the possible floppy *  density till one works or we've cycled through all *  possibilities for this drive. */static voidchanged(Chan *c, FDrive *dp){	ulong old;	FType *start;	/*	 *  if floppy has changed or first time through	 */	if((inb(Pdir)&Fchange) || dp->vers == 0){		DPRINT("changed\n");		fldump();		dp->vers++;		floppysetdef(dp);		start = dp->t;		dp->confused = 1;	/* make floppyon recal */		floppyon(dp);		floppyseek(dp, dp->t->heads*dp->t->tsize);		while(waserror()){			while(++dp->t){				if(dp->t == &floppytype[nelem(floppytype)])					dp->t = floppytype;				if(dp->dt == dp->t->dt)					break;			}			floppydir[NFDIR*dp->dev].length = dp->t->cap;			floppyon(dp);			DPRINT("changed: trying %s\n", dp->t->name);			fldump();			if(dp->t == start)				nexterror();		}		floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);		poperror();	}	old = c->qid.vers;	c->qid.vers = dp->vers;	if(old && old != dp->vers)		error(Eio);}static intreadtrack(FDrive *dp, int cyl, int head){	int i, nn, sofar;	ulong pos;	nn = dp->t->tsize;	if(dp->ccyl==cyl && dp->chead==head)		return nn;	pos = (cyl*dp->t->heads+head) * nn;	for(sofar = 0; sofar < nn; sofar += i){		dp->ccyl = -1;		i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);		if(i <= 0)			return -1;	}	dp->ccyl = cyl;	dp->chead = head;	return nn;}static longfloppyread(Chan *c, void *a, long n, vlong off){	FDrive *dp;	long rv;	int sec, head, cyl;	long len;	uchar *aa;	ulong offset = off;	if(c->qid.path == CHDIR)		return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen);	rv = 0;	dp = &fl.d[c->qid.path & ~Qmask];	switch ((int)(c->qid.path & Qmask)) {	case Qdata:		islegal(offset, n, dp);		aa = a;		qlock(&fl);		if(waserror()){			qunlock(&fl);			nexterror();		}		floppyon(dp);		changed(c, dp);		for(rv = 0; rv < n; rv += len){			/*			 *  all xfers come out of the track cache			 */			dp->len = n - rv;			floppypos(dp, offset+rv);			cyl = dp->tcyl;			head = dp->thead;			len = dp->len;			sec = dp->tsec;			if(readtrack(dp, cyl, head) < 0)				break;			memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);		}		qunlock(&fl);		poperror();		break;	case Qctl:		return readstr(offset, a, n, dp->t->name);	default:		panic("floppyread: bad qid");	}	return rv;}#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)static longfloppywrite(Chan *c, void *a, long n, vlong off){	FDrive *dp;	long rv, i;	char *aa = a;	char ctlmsg[64];	ulong offset = off;	rv = 0;	dp = &fl.d[c->qid.path & ~Qmask];	switch ((int)(c->qid.path & Qmask)) {	case Qdata:		islegal(offset, n, dp);		qlock(&fl);		if(waserror()){			qunlock(&fl);			nexterror();		}		floppyon(dp);		changed(c, dp);		for(rv = 0; rv < n; rv += i){			floppypos(dp, offset+rv);			if(dp->tcyl == dp->ccyl)				dp->ccyl = -1;			i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv);			if(i < 0)				break;			if(i == 0)				error(Eio);		}		qunlock(&fl);		poperror();		break;	case Qctl:		rv = n;		qlock(&fl);		if(waserror()){			qunlock(&fl);			nexterror();		}		if(n >= sizeof(ctlmsg))			n = sizeof(ctlmsg) - 1;		memmove(ctlmsg, aa, n);		ctlmsg[n] = 0;		if(SNCMP(ctlmsg, "eject") == 0){			floppyeject(dp);		} else if(SNCMP(ctlmsg, "reset") == 0){			fl.confused = 1;			floppyon(dp);		} else if(SNCMP(ctlmsg, "format") == 0){			floppyformat(dp, ctlmsg);		} else if(SNCMP(ctlmsg, "debug") == 0){			floppydebug = 1;		} else			error(Ebadctl);		poperror();		qunlock(&fl);		break;	default:		panic("floppywrite: bad qid");	}	return rv;}static voidfloppykproc(void *){	FDrive *dp;	while(waserror())		;	for(;;){		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){			if((fl.motor&MOTORBIT(dp->dev))			&& TK2SEC(m->ticks - dp->lasttouched) > 5			&& canqlock(&fl)){				if(TK2SEC(m->ticks - dp->lasttouched) > 5)					floppyoff(dp);				qunlock(&fl);			}		}		tsleep(&fl.kr, return0, 0, 1000);	}}/* *  start a floppy drive's motor. */static voidfloppyon(FDrive *dp){	int alreadyon;	int tries;	if(fl.confused)		floppyrevive();	/* start motor and select drive */	alreadyon = fl.motor & MOTORBIT(dp->dev);	fl.motor |= MOTORBIT(dp->dev);	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);	if(!alreadyon){		/* wait for drive to spin up */		tsleep(&dp->r, return0, 0, 750);		/* clear any pending interrupts */		floppysense();	}	/* set transfer rate */	if(fl.rate != dp->t->rate){		fl.rate = dp->t->rate;		outb(Pdsr, fl.rate);	}	/* get drive to a known cylinder */	if(dp->confused)		for(tries = 0; tries < 4; tries++)			if(floppyrecal(dp) >= 0)				break;	dp->lasttouched = m->ticks;	fl.selected = dp;}/* *  stop the floppy if it hasn't been used in 5 seconds */static voidfloppyoff(FDrive *dp){	fl.motor &= ~MOTORBIT(dp->dev);	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);}

⌨️ 快捷键说明

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