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

📄 fdc.c

📁 用于motorala 68K系列处理器的小实时多任务操作系统 The OMU Kernel was written to provide a cut-down Unix-like O/S for a
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************* *	Fdc.c	High level floppy disk driver ******************************************************************************* * * Handler for Codata Format 5.25in Floppy Disks * as well as rpa type 5.25in disks (ie 10 sect * per surface vs 9 *	the codata type floppy will be read from minor device *	numbers 0,1,2,3 and the ibm double sided 40 track will be assumed *	for minor device nos 4,5,6,7 *	the minor device values of 4,5,6,7 are only used in this  *	file, values of 0 1 2 3 will be passed on to the select *	routine. * Robin Alston 5.85 */#include	"buffer.h"#include	"flformat.h"#include 	"numbers.h"#include	<errno.h>#include	"../../include/buf.h"#include	<sys/ioctl.h>#define		LAST_TRACK	(79)int	nofdopen;		/* Total Number of devices open */struct drive_info fdstatus[4];struct fd_buffer fdb[NO_BUFS];	/* the track buffer */short P_TRK, fdcerror;struct buf tmpb;		/* used in the ioctl and full track buffering */int	dtype;/* *	this implements at the moment a simple track buffering scheme *	of NO_BUFS buffers. Buffers are write thru ie a write of one *	block will update the relevant buffer (if one exists) and *	will allways write to the disk as well */fdopen(drive){	/* If first open initialise bits */	if(!nofdopen++){		/* Init the buffering and device handler */		ibuffers();		fdcinit();	}	if(!fdstatus[drive & 0x3].d_nopen++){		/* Sets drive type */		if(drive & 0x04){			fdstatus[drive & 0x3].d_type = DTYPE40 | DTYPEINTEL;		}		else fdstatus[drive & 0x3].d_type = DTYPE80;		if(select(drive & 0x3) == ERROR){			printf("Deverr: drive %d unavailiable\n", drive);			return ERROR;		}		restor(0);		fdstatus[drive & 0x3].d_curtrk = 0;	}	return NOERROR;}fdclose(drive){	register short p = 0;	nofdopen--;	fdstatus[drive & 0x3].d_nopen--;	if(fdstatus[drive & 0x3].d_nopen <= 0){		fdstatus[drive & 0x3].d_nopen = 0;		/* Release all system buffers */		sync();		while(p < NO_BUFS){			/* release all the allocated buffers */			if(fdb[p].d_minor == drive){				/* When a real buffering scheme is worked				 * out a buffer flush will go in here				 */#ifdef FULLBUFFERING 				if(fdb[p].type & WRITTEN)					/* Attempt to flush a dirty buffer					 */					if(flush1(p) == ERROR)						/* Oh well it was a good try						 * for the mo leave its state						 * alone						 */						return ERROR;#endif FULLBUFFERING 				fdb[p].type = AVAILABLE;				/* make it the oldest buffer */				oldest(fdb[p].age);			}			p++;		}	}	return NOERROR;}ibuffers(){	/*		init the buffering scheme	 */	register short p = 0;	while(p < NO_BUFS){		fdb[p].age = p;		fdb[p++].type = AVAILABLE;	}}fdstrat(buf)struct buf *buf;{	register short blk, dev, p;	int	err;	blk = buf->b_bno;	dev = buf->b_dev;	/* verify track number and minor device no */	if(blk > CD_B_MAX){		deverr("block no. too large", 1, buf);		buf->b_flags |= ABORT;		return error(ENXIO);	}	if((dev < 0) || (dev > 7)){		deverr("minor dev out of range", 1, buf);		buf->b_flags |= ABORT;		return error(ENXIO);	}	dtype = fdstatus[buf->b_dev & 0x3].d_type;	/* Check if write if so put straight to disk */	if(buf->b_flags & WRITE)		err = write_1(buf);	/* copy to disk */	else		err = read_1(buf);	/* go get a buffer */	/* Test if error occured if so report it and return -1 */	if(err == ERROR){		buf->b_flags |= ABORT;		return error(EIO);	}	else return err;}write_1(b)struct buf *b;{	/*		If no full buffering then		write a buffer to the disk AND write thru the		disk buffer if it has one for the relevant track		If full buffering write into already existing buffer		or first get one from a disk	 */	register short p;#ifdef TFLOPPYprintf("write_1: ");printf("block: %d\n\r",b->b_bno);#endif TFLOPPY#ifdef FULLBUFFERING 	/*		may have to read the track then do a thru_write	 */	if(((p = inbuffers(b)) == NOTFOUND) && ((getfdisk(b,"pre-read") == ERROR) || ((p = inbuffers(b)) == NOTFOUND)))		/*			problems		 */		return ERROR;	thru_write(b,p);	return NOERROR;#else	if((p = inbuffers(b)) != NOTFOUND)		thru_write(b,p);	return puttdisk(b);#endif FULLBUFFERING }read_1(b)struct buf *b;{	/*		attempt to obtain a buffer from track buffering,		if failed then try and get a track from a disk itself	 */	register short p, offset;	if(((p = inbuffers(b)) == NOTFOUND) && ((getfdisk(b,"read") == ERROR) || ((p = inbuffers(b)) == NOTFOUND))){		b->b_flags |= ABORT;		return ERROR;	}	offset = (b->b_bno - fdb[p].bstart) * SIZE;#ifdef TFLOPPYprintf("read_1: block %d buffer %d offset %x\n\r",b->b_bno,p,offset);#endif TFLOPPY	bytecp((fdb[p].fdata + offset),b->b_buf,SIZE);	return NOERROR;}inbuffers(b)struct buf *b;{	/*	 * tells whether the buffer b is in the disk buffering (fdb)	 * if so returns in which one eles returns NOTFOUND	 */	register short p = 0;	while(p < NO_BUFS){		/* wander thru the whole set of buffers */		if((fdb[p].type != AVAILABLE) && INBUF(fdb[p],b)){			/* found it, make it youngest too */#ifdef TFLOPPYprintf("Found %d in buffer %d\n\r",b->b_bno,p);#endif TFLOPPY			youngest(fdb[p].age);			return p;		}		else			p++;	}#ifdef TFLOPPYprintf("%d not found in buffers\n\r",b->b_bno);#endif TFLOPPY	return NOTFOUND;}thru_write(b,p)struct buf *b;short p;{	/*	 *	writes the buffer b into the buffer fdb[p]	 */	register short offset;	offset = (b->b_bno - fdb[p].bstart) * SIZE;#ifdef TFLOPPYprintf("Write thru: block %d buffer %d offset %x\n\r",b->b_bno,p,offset);#endif TFLOPPY	bytecp(b->b_buf,fdb[p].fdata + offset,SIZE);	/* copy the buf */	fdb[p].type |= WRITTEN;	youngest(fdb[p].age);	/* make this buffer the youngest */}diskset(b,trackn)struct buf *b;short trackn;{	/*		select disk side etc using info in b		returns which sector this buffer should		be on this disk track and also sets the		global P_TRK to how many sectors per		track surface there are on this device		if trackn <> NOTATRACK then the seek will 		be to that track else will seek to where		the block should be	 */	register short p_trk, trk, blk;	short sideno, drive, reps;	struct drive_info *fds;	int	rtrack;	char	twostep;	drive = b->b_dev;	blk = b->b_bno;	switch(drive){	case 0: case 1: case 2: case 3:		/* codata type */		p_trk = CD_PERTRK;		break;	case 4: case 5: case 6: case 7:		/* codata type */		p_trk = CD_PERTRK;		break;	}	trk = rtrack = (trackn == NOTATRACK)? (blk / p_trk) : trackn;	/* Checks if single sided */	if(!(fdstatus[drive & 0x3].d_type & DTYPESS)){		sideno = (trk & 1)? ONE : ZERO;		trk /= 2;		rtrack /= 2;	}	else{		sideno = ZERO;	}	/* Checks if 40 track */	if(fdstatus[drive & 0x3].d_type & DTYPE40){		trk *= 2;		twostep = 1;	}	else twostep = 0;#ifdef TFLOPPYprintf("diskset: blk %d, trk %d, rtrk %d, side %d, twostep %d\n",blk,trk,rtrack,sideno,twostep);#endif TFLOPPY	if(trk > LAST_TRACK){		deverr("track number too big",1,b);		b->b_flags |= ABORT;		return ERROR;	}	/* select drive */	if (select(drive & 0x3) == ERROR){		deverr("drive not ready", 1, b);		b->b_flags |= ABORT;		return ERROR;	}	/* find current position */	fds = &fdstatus[drive & 0x3];	if ((set_track(fds->d_curtrk)) != trk){		if(reps = doseek(trk, twostep)) {			if (reps >= 10)				b->b_flags |= ABORT;			deverr("seek", reps, b);			if (reps >= 10)				return ERROR;		}		fds->d_curtrk = trk;	}	side(sideno);	/* get correct side */	P_TRK = p_trk;	set_track(rtrack);		/* Sets real track required 40/80 */	return ((blk % p_trk) + 1);	/* return the sector number */}getfdisk(b,errmsg)struct buf *b;char *errmsg;{	short p, reps;	p = oldest(NO_BUFS - 1);	/* get LRU buffer */#ifdef FULLBUFFERING 	if(fdb[p].type & WRITTEN)		/*			attempt to write out a dirty buffer		 */		if(flush1(p) == ERROR)			/*				Oh heck, what do we do now, anything				we do might f..k up the buffering scheme				so for the mo do nowt.			 */			return ERROR;		else			/*				mark this buffer as available, so no				matter what happens it will be available				in the worst case			 */			fdb[p].type = AVAILABLE;#endif FULLBUFFERING 	if(diskset(b,NOTATRACK) == ERROR)	/* sets the side. track and drive */		return ERROR;	reps = tr_read(fdb[p].fdata, P_TRK);	/* read the whole track */	/* errors? */	if (reps) {		deverr(errmsg, reps, b);		if (reps >= 10){			b->b_flags |= ABORT;			fdb[p].type = AVAILABLE;			return ERROR;		}	}	/* no fatal errors */	youngest(fdb[p].age);	/* make this one the youngest */	fdb[p].bstart = (b->b_bno / P_TRK) * P_TRK;	fdb[p].bend = fdb[p].bstart + P_TRK - 1;	fdb[p].type = READABLE;	fdb[p].d_minor = b->b_dev;	b->b_flags &= ~WRITE;#ifdef TFLOPPYprintf("Read: block %d, buffer %d, start %d end %d\n\r",b->b_bno,p,fdb[p].bstart,fdb[p].bend);#endif TFLOPPY	return NOERROR;}puttdisk(b)struct buf *b;{	/*		write the buffer to the disk	 */	register short p, reps, sect;	if((sect = diskset(b,NOTATRACK)) == ERROR)		return ERROR;	reps = se_write(b->b_buf,sect);	/*  write the sector out */	/* errors? */	if (reps) {		deverr("write", reps, b);		if (reps >= 10){			b->b_flags |= ABORT;			return ERROR;		}	}	/* no fatal errors */	b->b_flags &= ~WRITE;	return NOERROR;}se_write(b,s)char *b;short s;{	/*		writes one sector from b to sect s		assumes that the disk side, track		already correct	 */	register short count = 0,err;	while(count < 10){		if(err = write_sect(b,s,1,0)){			fdcerror = err;			count++;		}		else			break;	}	return count;}tr_read(buffer,nsects)char	*buffer;short	nsects;{	/*

⌨️ 快捷键说明

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