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

📄 rx.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef	lintstatic char *sccsid = "@(#)rx.c	4.1	ULTRIX	7/2/90";#endif	lint/************************************************************************ *									* *			Copyright (c) 1985 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//*	rx.c	6.1	83/07/29	*/#include "rx.h"#if NFX > 0 || defined(BINARY)/* * RX02 floppy disk device driver * * 18-mar-86  -- jaw     br/cvec changed to NOT use registers. * *//* * TODO: *	- clean up the code for multisector transfers using *	  a 'transfer in progress' flag *	- Test Deleted Data read/write  *	- Test error handling/reporting and 'volume valid' stuff * * 	Note: If the drive subsystem is * 	powered off at boot time, the controller won't interrupt! */#include "../data/rx_data.c"#define b_cylin	b_resid#define	RXS_READ	1	/* read started	*/#define	RXS_EMPTY	2	/* empty started */#define	RXS_FILL	3	/* fill started	*/#define	RXS_WRITE	4	/* write started */#define	RXS_FORMAT	5	/* format started */#define	RXS_RDSTAT	6	/* status read started */#define	RXS_RDERR	7	/* error read started */#define	RXS_IDLE	8	/* device is idle */#define	RXF_DIRECT	0x01	/* if set: use direct sector mapping */#define	RXF_TRKONE	0x02	/* if set: start mapping on track 1 */#define	RXF_DBLDEN	0x04	/* use double density */#define	RXF_DEVTYPE	0x07	/* mapping flags */#define	RXF_LOCK	0x10	/* exclusive use */#define	RXF_DDMK	0x20	/* deleted-data mark detected */#define	RXF_USEWDDS	0x40	/* write deleted-data sector */#define	RXF_FORMAT	0x80	/* format in progress */#define	RXF_BAD		0x100	/* drive bad, cannot be used */#define	RX_MAXTIMEOUT	30	/* # seconds to wait before giving up */struct buf *savebp;int rxprobe(), rxslave(), rxattach(), rxdgo(), rxintr(), rxwatch(), rxphys();u_short rxstd[] = { 0177170, 0177150, 0 };struct uba_driver fxdriver =  { rxprobe, rxslave, rxattach, rxdgo, rxstd, "rx", rxdinfo, "fx", rxminfo };int	rxwstart;#define	RXUNIT(dev)	(minor(dev)>>3)#define	MASKREG(reg)	(reg&0xffff)/* constants related to floppy data capacity */#define	RXSECS	2002				/* # sectors on a floppy */#define	DDSTATE	(sc->sc_csbits&RX_DDEN)#define	NBPS	(DDSTATE ? 256 : 128)		/* # bytes per sector */#define	RXSIZE	(DDSTATE ? 512512 : 256256)	/* # bytes per disk */#define	SECMASK	(DDSTATE ? 0xff : 0x7f)		/* shifted-out bits of offset */#define	B_CTRL		0x80000000		/* control (format) request */#define B_RDSTAT	0x40000000		/* read drive status (open) *//*ARGSUSED*/rxprobe (reg)	caddr_t reg;{	struct rxdevice *rxaddr = (struct rxdevice *)reg;#ifdef lint	rxintr(0);#endif lint	rxaddr->rxcs = RX_INTR;	DELAY(10);	rxaddr->rxcs = 0;	return (sizeof (*rxaddr));}rxslave(ui, reg)	struct uba_device *ui;	caddr_t reg;{	ui->ui_dk = 1;	return (ui->ui_slave == 0 || ui->ui_slave == 1);}/*ARGSUSED*/rxattach(ui)	struct uba_device *ui;{}/*ARGSUSED1*/rxopen(dev, flag)	dev_t dev;{ 	register int unit = RXUNIT(dev);	register struct rx_softc *sc;	register struct uba_device *ui;	struct rx_ctlr *rxc; 	if (unit >= nNURX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)		return (ENXIO);	sc = &rx_softc[unit];	if (sc->sc_open == 0 && sc->sc_csbits == 0) {		struct buf *bp = &erxbuf[unit];		/*		 * lock the device while an open 		 * is in progress		 */		sc->sc_flags = (minor(dev) & RXF_DEVTYPE) | RXF_LOCK;		sc->sc_csbits = RX_INTR;		sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;		bp->b_dev = dev;		bp->b_flags = B_RDSTAT | B_BUSY;		bp->b_error = 0;		bp->b_blkno = 0;		sc->sc_offset = 0;		sc->sc_resid  = 0;		/*		 * read device status to determine if		 * a floppy is present in the drive and		 * what density it is		 */		rxstrategy(bp);		iowait(bp);		if (bp->b_flags & B_ERROR) {			sc->sc_csbits = 0;			return (bp->b_error);		}		if (rxwstart++ == 0) {			rxc = &rx_ctlr[ui->ui_mi->um_ctlr];			rxc->rxc_tocnt = 0;			timeout(rxwatch, (caddr_t)0, hz);  /* start watchdog */		}#ifdef RXDEBUG		printf("rxopen: csbits=0x%x\n", sc->sc_csbits);#endif		sc->sc_flags &= ~RXF_LOCK;	} else	{		if (sc->sc_flags & RXF_LOCK)			return(EBUSY);	}	sc->sc_open++;	return (0);}/*ARGSUSED1*/rxclose(dev, flag)	dev_t dev;{	register struct rx_softc *sc = &rx_softc[RXUNIT(dev)];	--sc->sc_open;#ifdef RXDEBUG	printf("rxclose: dev=0x%x, sc_open=%d\n", dev, sc->sc_open);#endif}rxstrategy(bp)	register struct buf *bp;{	struct uba_device *ui;	register struct buf *dp;	struct rx_softc *sc;	int s, unit = RXUNIT(bp->b_dev);	if (unit >= nNURX)		goto bad;	ui = rxdinfo[unit];	if (ui == 0 || ui->ui_alive == 0) 		goto bad;	sc = &rx_softc[unit];	if (bp->b_blkno < 0 || dbtob(bp->b_blkno) > RXSIZE)		goto bad;	if (sc->sc_flags & RXF_BAD) {		bp->b_error = EIO;		goto dbad;	}	s = spl5();#ifdef RXDEBUG	printf("rxstrat: bp=0x%x, fl=0x%x, un=%d, bl=%d, cnt=%d\n", 		bp, bp->b_flags, unit, bp->b_blkno, bp->b_bcount);#endif	bp->b_cylin = bp->b_blkno;	/* don't care to calculate trackno */	dp = &rxutab[unit];	disksort(dp, bp);	if (dp->b_active == 0) {		rxustart(ui);		bp = &ui->ui_mi->um_tab;		if (bp->b_actf && bp->b_active == 0)			rxstart(ui->ui_mi);	}	splx(s);	return;bad:	bp->b_error = ENXIO;dbad:	bp->b_flags |= B_ERROR;	iodone(bp);	return;}/* * Unit start routine. * Put this unit on the ready queue for the controller */rxustart(ui)	register struct uba_device *ui;{	struct buf *dp = &rxutab[ui->ui_unit];	struct uba_ctlr *um = ui->ui_mi;		dp->b_forw = NULL;	if (um->um_tab.b_actf == NULL)		um->um_tab.b_actf = dp;	else		um->um_tab.b_actl->b_forw = dp;	um->um_tab.b_actl = dp;	dp->b_active++;}/* * Sector mapping routine. * Two independent sets of choices are available: * * (a) The first logical sector may either be on track 1 or track 0. * (b) The sectors on a track may either be taken in 2-for-1 interleaved *	 fashion or directly. * This gives a total of four possible mapping schemes. * * Physical tracks on the RX02 are numbered 0-76.  Physical sectors on * each track are numbered 1-26. * * When interleaving is used, sectors on the first logical track are * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26.  A skew of * six sectors per track is also used (to allow time for the heads to * move); hence, the sectors on the second logical track are taken in * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6; * the third logical track starts with sector 13; and so on. * * When the mapping starts with track 1, track 0 is the last logical * track, and this track is always handled directly (without inter- * leaving), even when the rest of the disk is interleaved.  (This is * still compatible with DEC RT-11, which does not use track 0 at all.) */rxmap(bp, psector, ptrack)	struct buf *bp;	int *psector, *ptrack;{	register int lt, ls, ptoff;	struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];	ls = (dbtob(bp->b_blkno) + (sc->sc_offset - sc->sc_resid)) / NBPS;	lt = ls / 26;	ls %= 26;	/*	 * The "physical track offset" (ptoff) takes the	 * starting physical track (0 or 1) and the desired	 * interleaving into account.  If lt+ptoff >= 77,	 * then interleaving is not performed.	 */	ptoff = 0;	if (sc->sc_flags & RXF_DIRECT)		ptoff = 77;	if (sc->sc_flags & RXF_TRKONE)		ptoff++;	if (lt + ptoff < 77)		ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;	*ptrack = (lt + ptoff) % 77;	*psector = ls + 1;}/* * Controller start routine. * Start a new transfer or continue a multisector * transfer. If this is a new transfer (dp->b_active == 1) * save the start address of the data buffer and the total * byte count in the soft control structure. These are * restored into the buffer structure when the transfer has * been completed, before calling 'iodone'. */rxstart(um)	register struct uba_ctlr *um;{	register struct rxdevice *rxaddr;	register struct rx_ctlr *rxc;	register struct rx_softc *sc;	struct buf *dp, *bp;	int unit, sector, track;	if (um->um_tab.b_active)		return;loop:	if ((dp = um->um_tab.b_actf) == NULL)		return;	if ((bp = dp->b_actf) == NULL) {		um->um_tab.b_actf = dp->b_forw;		goto loop;	}	um->um_tab.b_active++;	unit = RXUNIT(bp->b_dev);	sc = &rx_softc[unit];	if (sc->sc_flags & RXF_BAD) {		rxpurge(um);		return;	}	if (dp->b_active == 1) {		sc->sc_resid = bp->b_bcount;		sc->sc_uaddr = bp->b_un.b_addr;		sc->sc_bcnt = bp->b_bcount;		sc->sc_offset += sc->sc_bcnt;		dp->b_active++;	}	rxaddr = (struct rxdevice *)um->um_addr;	rxc = &rx_ctlr[um->um_ctlr];	bp->b_bcount = sc->sc_resid;	if (bp->b_bcount > NBPS)		bp->b_bcount = NBPS;	rxc->rxc_tocnt = 0;#ifdef RXDEBUG	printf("rxstart: ");#endif	if (rxaddr->rxcs == 0x800) {		/*		 * 'Volume valid'? (check if the 		 * drive unit has been powered down)		 */		rxaddr->rxcs = RX_INIT;		while((rxaddr->rxcs&RX_DONE) == 0)			;	}	if (bp->b_flags & B_CTRL) {				/* format */		rxc->rxc_state = RXS_FORMAT;		rxaddr->rxcs = RX_FORMAT | sc->sc_csbits;		while ((rxaddr->rxcs&RX_TREQ) == 0)			;		rxaddr->rxdb = 'I';		return;	}	if (bp->b_flags & B_RDSTAT) {			/* read drive status */		rxc->rxc_state = RXS_RDSTAT;		rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;		return;	}	if (bp->b_flags & B_READ) {		rxmap(bp, &sector, &track);			/* read */#ifdef RXDEBUG		printf("read tr=%d, sc=%d", track, sector);#endif		rxc->rxc_state = RXS_READ;		rxaddr->rxcs = RX_READ | sc->sc_csbits;		while ((rxaddr->rxcs&RX_TREQ) == 0)			;		rxaddr->rxdb = (u_short)sector;		while ((rxaddr->rxcs&RX_TREQ) == 0)			;		rxaddr->rxdb = (u_short)track;	} else {#ifdef RXDEBUG		printf("write");#endif		rxc->rxc_state = RXS_FILL;			/* write */		um->um_cmd = RX_FILL;		(void) ubago(rxdinfo[unit]);	}#ifdef RXDEBUG	printf("\n");#endif}rxdgo(um)	struct uba_ctlr *um;{	register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;	int ubinfo = um->um_ubinfo;	struct buf *bp = um->um_tab.b_actf->b_actf;	struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];	struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];	rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;	if (rxc->rxc_state != RXS_RDERR) {

⌨️ 快捷键说明

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