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

📄 fd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Don Ahn. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)fd.c	8.1 (Berkeley) 6/11/93 */#include "fd.h"#if NFD > 0/* * This driver assumed that NFD == 2. Now it works for NFD == 1 or NFD == 2 * It will probably not work for NFD > 2. */#include <sys/param.h>#include <sys/dkbad.h>#include <sys/systm.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/buf.h>#include <sys/uio.h>#include <i386/isa/isa_device.h>#include <i386/isa/fdreg.h>#include <i386/isa/icu.h>#define	FDUNIT(s)	((s)&1)#define	FDTYPE(s)	(((s)>>1)&7)#define FDMOTOR(u) 	(fd_unit[(u)].motor ? (1 << (4 + (u))) : 0)#define b_cylin b_resid#define b_step b_resid#define FDBLK 512#define NUMTYPES 4struct fd_type {	int	sectrac;		/* sectors per track         */	int	secsize;		/* size code for sectors     */	int	datalen;		/* data len when secsize = 0 */	int	gap;			/* gap len between sectors   */	int	tracks;			/* total num of tracks       */	int	size;			/* size of disk in sectors   */	int	steptrac;		/* steps per cylinder        */	int	trans;			/* transfer speed code       */};struct fd_type fd_types[NUMTYPES] = { 	{ 18,2,0xFF,0x1B,80,2880,1,0 },	/* 1.44 meg HD 3.5in floppy    */	{ 15,2,0xFF,0x1B,80,2400,1,0 },	/* 1.2 meg HD floppy           */	{ 9,2,0xFF,0x23,40,720,2,1 },	/* 360k floppy in 1.2meg drive */	{ 9,2,0xFF,0x2A,40,720,1,1 },	/* 360k floppy in DD drive     */};struct fd_u {	int type;		/* Drive type (HD, DD     */	int active;		/* Drive activity boolean */	int motor;		/* Motor on flag          */	struct buf head;	/* Head of buf chain      */	struct buf rhead;	/* Raw head of buf chain  */	int reset;} fd_unit[NFD];extern int hz;/* state needed for current transfer */static fdc;	/* floppy disk controller io base register */int	fd_dmachan = 2;static int fd_skip;static int fd_state;static int fd_retry;static int fd_drive;static int fd_track = -1;static int fd_status[7];/*	make sure bounce buffer for DMA is aligned since the DMA chip	doesn't roll over properly over a 64k boundary*/extern struct buf *dma_bounce[];/****************************************************************************//*                      autoconfiguration stuff                             *//****************************************************************************/int fdprobe(), fdattach(), fd_turnoff();struct	isa_driver fddriver = {	fdprobe, fdattach, "fd",};fdprobe(dev)struct isa_device *dev;{	return 1;}fdattach(dev)struct isa_device *dev;{	int	s;	fdc = dev->id_iobase;	/* Set transfer to 500kbps */	outb(fdc+fdctl,0);	fd_turnoff(0);}intFdsize(dev)dev_t	dev;{	return(2400);}/****************************************************************************//*                               fdstrategy                                 *//****************************************************************************/Fdstrategy(bp)	register struct buf *bp;	/* IO operation to perform */{	register struct buf *dp;	long nblocks,blknum; 	int	unit, type, s; 	unit = FDUNIT(minor(bp->b_dev)); 	type = FDTYPE(minor(bp->b_dev));#ifdef FDTESTprintf("fdstrat%d, blk = %d, bcount = %d, addr = %x|",	unit, bp->b_blkno, bp->b_bcount,bp->b_un.b_addr);#endif	if ((unit >= NFD) || (bp->b_blkno < 0)) {		printf("fdstrat: unit = %d, blkno = %d, bcount = %d\n",			unit, bp->b_blkno, bp->b_bcount);		pg("fd:error in fdstrategy");		bp->b_error = EINVAL;		bp->b_flags |= B_ERROR;		goto bad;	}	/*	 * Set up block calculations.	 */	blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK; 	nblocks = fd_types[type].size;	if (blknum + (bp->b_bcount / FDBLK) > nblocks) {		if (blknum == nblocks) {			bp->b_resid = bp->b_bcount;		} else {			bp->b_error = ENOSPC;			bp->b_flags |= B_ERROR;		}#ifdef FDTESTprintf("fdstrat%d, too big\n");#endif 		goto bad;	} 	bp->b_cylin = blknum / (fd_types[type].sectrac * 2);	dp = &fd_unit[unit].head;	dp->b_step = (fd_types[fd_unit[unit].type].steptrac);	s = splbio();	disksort(dp, bp);	if ((fd_unit[0].head.b_active == 0)#if NFD > 1	    && (fd_unit[1].head.b_active == 0)#endif	    ) {#ifdef FDDEBUGprintf("T|");#endif		dp->b_active = 1;		fd_drive = unit;		fd_track = -1;  /* force seek on first xfer */		untimeout(fd_turnoff,unit);		fdstart(unit);		/* start drive if idle */	}	splx(s);	return;bad:	biodone(bp);}/****************************************************************************//*                            motor control stuff                           *//****************************************************************************/set_motor(unit,reset)int unit,reset;{	outb(fdc+fdout,unit | (reset ? 0 : 0xC)  | FDMOTOR(0) #if NFD > 1	     | FDMOTOR(1)#endif	     );}fd_turnoff(unit)int unit;{	fd_unit[unit].motor = 0;	if (unit) set_motor(0,0);	else set_motor(1,0);}fd_turnon(unit)int unit;{	fd_unit[unit].motor = 1;	set_motor(unit,0);}/****************************************************************************//*                             fdc in/out                                   *//****************************************************************************/intin_fdc(){	int i;	while ((i = inb(fdc+fdsts) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM))		if (i == NE7_RQM) return -1;	return inb(fdc+fddata);}dump_stat(){	int i;	for(i=0;i<7;i++) {		fd_status[i] = in_fdc();		if (fd_status[i] < 0) break;	}printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",	fd_status[0], fd_status[1], fd_status[2], fd_status[3],	fd_status[4], fd_status[5], fd_status[6] );}out_fdc(x)int x;{	int r,errcnt;	static int maxcnt = 0;	errcnt = 0;	do {		r = (inb(fdc+fdsts) & (NE7_DIO|NE7_RQM));		if (r== NE7_RQM) break;		if (r==(NE7_DIO|NE7_RQM)) {			dump_stat(); /* error: direction. eat up output */#ifdef FDOTHERprintf("%lx\n",x);#endif		}		/* printf("Error r = %d:",r); */		errcnt++;	} while (1);	if (errcnt > maxcnt) {		maxcnt = errcnt;#ifdef FDOTHERprintf("New MAX = %d\n",maxcnt);#endif	}	outb(fdc+fddata,x);}/* see if fdc responding */intcheck_fdc(){	int i;	for(i=0;i<100;i++) {		if (inb(fdc+fdsts)& NE7_RQM) return 0;	}	return 1;}/****************************************************************************//*                           fdopen/fdclose                                 *//****************************************************************************/Fdopen(dev, flags)	dev_t	dev;	int	flags;{ 	int unit = FDUNIT(minor(dev)); 	int type = FDTYPE(minor(dev));	int s;	printf("fdopen %x %d %d\n", minor(dev), unit, type);	/* check bounds */	if (unit >= NFD) return(ENXIO);	if (type >= NUMTYPES) return(ENXIO);/*	if (check_fdc()) return(EBUSY);*/	/* Set proper disk type, only allow one type */	return 0;}Fdclose(dev, flags)	dev_t dev;{	return (0);}/****************************************************************************//*                            fdread/fdwrite                                *//****************************************************************************//* * Routines to do raw IO for a unit.

⌨️ 快捷键说明

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