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

📄 devfloppy.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"fs.h"#include	"devfloppy.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(0)printFType 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 vlong	pcfloppyseek(FDrive*, vlong);static int	floppysense(void);static void	floppywait(int);static long	floppyxfer(FDrive*, int, void*, long, long);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));}static voidfloppyalarm(Alarm* a){	FDrive *dp;	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){		if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5)			floppyoff(dp);	}	alarm(5*1000, floppyalarm, 0);	cancel(a);}/* *  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;			break;		}}static void_floppydetach(void){	/*	 *  stop the motors	 */	fl.motor = 0;	delay(10);	outb(Pdor, fl.motor | Fintena | Fena);	delay(10);}intfloppyinit(void){	FDrive *dp;	FType *t;	ulong maxtsize;	int mask;	dmainit(DMAchan);	floppysetup0(&fl);	/*	 *  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;	}	fl.selected = fl.d;	floppydetach = _floppydetach;	floppydetach();	/*	 *  init drives	 */	mask = 0;	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){		dp->dev = dp - fl.d;		if(dp->dt == Tnone)			continue;		mask |= 1<<dp->dev;		floppysetdef(dp);		dp->cyl = -1;			/* because we don't know */		dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);		dp->ccyl = -1;		dp->vers = 0;		dp->maxtries = 5;	}	/*	 *  first operation will recalibrate	 */	fl.confused = 1;	floppysetup1(&fl);	/* to turn the motor off when inactive */	alarm(5*1000, floppyalarm, 0);	return mask;}voidfloppyinitdev(int i, char *name){	if(i >= fl.ndrive)		panic("floppyinitdev");	sprint(name, "fd%d", i);}voidfloppyprintdevs(int i){	if(i >= fl.ndrive)		panic("floppyprintdevs");	print(" fd%d", i);}intfloppyboot(int dev, char *file, Boot *b){	Fs *fs;	if(strncmp(file, "dos!", 4) == 0)		file += 4;	else if(strchr(file, '!') || strcmp(file, "")==0) {		print("syntax is fd0!file\n");		return -1;	}	fs = floppygetfspart(dev, "dos", 1);	if(fs == nil)		return -1;	return fsboot(fs, file, b);}voidfloppyprintbootdevs(int dev){	print(" fd%d", dev);}/* *  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 intchanged(FDrive *dp){	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);		dp->maxtries = 3;		start = dp->t;		/* flopppyon fails if there's no drive */		dp->confused = 1;	/* make floppyon recal */		if(floppyon(dp) < 0)			return -1;		pcfloppyseek(dp, dp->t->heads*dp->t->tsize);		while(floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize) <= 0){			/*			 *  if the xfer attempt doesn't clear the changed bit,			 *  there's no floppy in the drive			 */			if(inb(Pdir)&Fchange)				return -1;			while(++dp->t){				if(dp->t == &floppytype[nelem(floppytype)])					dp->t = floppytype;				if(dp->dt == dp->t->dt)					break;			}			/* flopppyon fails if there's no drive */			if(floppyon(dp) < 0)				return -1;			DPRINT("changed: trying %s\n", dp->t->name);			fldump();			if(dp->t == start)				return -1;		}	}	return 0;}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;}longfloppyread(Fs *fs, void *a, long n){	FDrive *dp;	long rv, offset;	int sec, head, cyl;	long len;	uchar *aa;	aa = a;	dp = &fl.d[fs->dev];	offset = dp->offset;	floppyon(dp);	if(changed(dp))		return -1;	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);	}	dp->offset = offset+rv;	return rv;}void*floppygetfspart(int i, char *name, int chatty){	static Fs fs;	if(strcmp(name, "dos") != 0){		if(chatty)			print("unknown partition fd%d!%s (use fd%d!dos)\n", i, name, i);		return nil;	}	fs.dev = i;	fs.diskread = floppyread;	fs.diskseek = floppyseek;	/* sometimes we get spurious errors and doing it again works */	if(dosinit(&fs) < 0 && dosinit(&fs) < 0){		if(chatty)			print("fd%d!%s does not contain a FAT file system\n", i, name);		return nil;	}	return &fs;}static intreturn0(void*){	return 0;}static voidtimedsleep(int (*f)(void*), void* arg, int ms){	int s;	ulong end;	end = m->ticks + 1 + MS2TK(ms);	while(m->ticks < end && !(*f)(arg)){		s = spllo();		delay(10);		splx(s);	}}/* *  start a floppy drive's motor. */static intfloppyon(FDrive *dp){	int alreadyon;	int tries;	if(fl.confused)		floppyrevive();	/* start motor and select drive */	dp->lasttouched = m->ticks;	alreadyon = fl.motor & MOTORBIT(dp->dev);	if(!alreadyon){		fl.motor |= MOTORBIT(dp->dev);		outb(Pdor, fl.motor | Fintena | Fena | dp->dev);		/* wait for drive to spin up */

⌨️ 快捷键说明

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