📄 rx.c
字号:
#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, §or, &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 + -