📄 rx.c
字号:
while ((rxaddr->rxcs&RX_TREQ) == 0) ; rxaddr->rxdb = (u_short) bp->b_bcount >> 1; } while ((rxaddr->rxcs&RX_TREQ) == 0) ; rxaddr->rxdb = (u_short) ubinfo;}rxintr(ctlr) int ctlr;{ int unit, sector, track; struct uba_ctlr *um = rxminfo[ctlr]; register struct rxdevice *rxaddr; register struct buf *bp, *dp; register struct rx_softc *sc; struct uba_device *ui; struct rxerr *er; struct rx_ctlr *rxc; if (!um->um_tab.b_active) return; dp = um->um_tab.b_actf; if (!dp->b_active) return; bp = dp->b_actf; unit = RXUNIT(bp->b_dev); sc = &rx_softc[unit]; ui = rxdinfo[unit]; rxaddr = (struct rxdevice *)um->um_addr; rxc = &rx_ctlr[um->um_ctlr]; rxc->rxc_tocnt = 0; er = &rxerr[unit];#ifdef RXDEBUG printf("rxint: dev=%x, st=%d, cs=0x%x, db=0x%x\n", bp->b_dev, rxc->rxc_state, rxaddr->rxcs, rxaddr->rxdb);#endif if ((rxaddr->rxcs & RX_ERR) && (rxc->rxc_state != RXS_RDSTAT) && (rxc->rxc_state != RXS_RDERR)) goto error; switch (rxc->rxc_state) { /* * Incomplete commands. Perform next step * and return. Note that b_active is set on * entrance and, therefore, also on exit. */ case RXS_READ: if (rxaddr->rxdb & RXES_DDMARK) sc->sc_flags |= RXF_DDMK; else sc->sc_flags &= ~RXF_DDMK; rxc->rxc_state = RXS_EMPTY; um->um_cmd = RX_EMPTY; (void) ubago(ui); return; case RXS_FILL: rxc->rxc_state = RXS_WRITE; if (sc->sc_flags & RXF_USEWDDS) { rxaddr->rxcs = RX_WDDS | sc->sc_csbits; sc->sc_flags &= ~RXF_USEWDDS; } else rxaddr->rxcs = RX_WRITE | sc->sc_csbits; rxmap(bp, §or, &track); while ((rxaddr->rxcs&RX_TREQ) == 0) ; rxaddr->rxdb = sector; while ((rxaddr->rxcs&RX_TREQ) == 0) ; rxaddr->rxdb = track; return; /* * Possibly completed command. */ case RXS_RDSTAT: if (bp->b_flags & B_RDSTAT) { if ((rxaddr->rxdb&RXES_READY) == 0) { bp->b_flags |= B_ERROR; bp->b_error = ENODEV; } else { sc->sc_csbits |= rxaddr->rxdb&RXES_DBLDEN ? RX_DDEN : RX_SDEN; } goto rdone; } if (rxaddr->rxdb&RXES_READY) goto rderr; bp->b_error = ENODEV; bp->b_flags |= B_ERROR; goto done; /* * Command completed. */ case RXS_EMPTY: case RXS_WRITE: goto done; case RXS_FORMAT: goto rdone; case RXS_RDERR: bp = savebp; rxmap(bp, §or, &track); printf("rx%d: hard error, trk %d psec %d ", unit, track, sector); printf("cs=%b, db=%b, err=", MASKREG(er->rxcs), RXCS_BITS, MASKREG(er->rxdb), RXES_BITS); printf("%x, %x, %x, %x\n", MASKREG(er->rxxt[0]), MASKREG(er->rxxt[1]), MASKREG(er->rxxt[2]), MASKREG(er->rxxt[3])); goto done; default: printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state); rxreset(um->um_ubanum); return; }error: /* * In case of an error: * (a) Give up now if a format (ioctl) was in progress, if a * density error was detected, or if the drive went offline * (b) Retry up to nine times if a CRC (data) error was detected, * then give up if the error persists. * (c) In all other cases, reinitialize the drive and try the * operation once more before giving up. */ if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR)) goto giveup; if (rxaddr->rxdb & RXES_CRCERR) { if (++um->um_tab.b_errcnt >= 10) goto giveup; goto retry; } um->um_tab.b_errcnt += 9; if (um->um_tab.b_errcnt >= 10) goto giveup; rxaddr->rxcs = RX_INIT; /* no way to get an interrupt for "init done", so just wait */ while ((rxaddr->rxcs&RX_DONE) == 0) ; /* if someone opened the drive: give up */ if ((rxaddr->rxdb&RXES_READY) == 0) goto giveup;retry: /* * In case we already have UNIBUS resources, give * them back since we reallocate things in rxstart. */ if (um->um_ubinfo) ubadone(um); um->um_tab.b_active = 0; rxstart(um); return;giveup: /* * Hard I/O error -- * ALL errors are considered fatal and will abort the * transfer and purge the i/o request queue */ sc->sc_flags |= RXF_BAD; sc->sc_resid = 0; /* make sure the transfer is terminated */ rxc->rxc_state = RXS_RDSTAT; rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits; return;rderr: /* * A hard error (other than not ready) has occurred. * Read the extended error status information. * Before doing this, save the current CS and DB register values, * because the read error status operation may modify them. * Insert buffer with request at the head of the queue. */ bp->b_error = EIO; bp->b_flags |= B_ERROR; if (um->um_ubinfo) ubadone(um); savebp = bp; er->rxcs = rxaddr->rxcs; er->rxdb = rxaddr->rxdb; bp = &erxbuf[unit]; bp->b_un.b_addr = (caddr_t)er->rxxt; bp->b_bcount = sizeof (er->rxxt); bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET); if (dp->b_actf == NULL) dp->b_actl = bp; bp->b_forw = dp->b_actf; dp->b_actf = bp; rxc->rxc_state = RXS_RDERR; um->um_cmd = RX_RDERR; (void) ubago(ui); return;done: ubadone(um);rdone: um->um_tab.b_active = 0; um->um_tab.b_errcnt = 0; if ((sc->sc_resid -= NBPS) > 0) { bp->b_un.b_addr += NBPS; rxstart(um); return; } bp->b_un.b_addr = sc->sc_uaddr; bp->b_resid = 0; bp->b_bcount = sc->sc_bcnt; dp->b_actf = bp->av_forw; iodone(bp); sc->sc_offset = 0; rxc->rxc_state = RXS_IDLE; um->um_tab.b_actf = dp->b_forw; dp->b_active = 0; dp->b_errcnt = 0;#ifdef RXDEBUG printf(".. bp=%x, new=%x\n", bp, dp->b_actf);#endif /* * If this unit has more work to do, * start it up right away */ if (dp->b_actf) rxustart(ui); rxstart(um);}/*ARGSUSED*/rxwatch(){ register struct uba_device *ui; register struct uba_ctlr *um; register struct rx_softc *sc; struct rx_ctlr *rxc; int i, dopen = 0; for (i=0; i<nNURX; i++) { ui = rxdinfo[i]; if (ui == 0 || ui->ui_alive == 0) continue; sc = &rx_softc[i]; if ((sc->sc_open == 0) && (rxutab[i].b_active == 0)) { sc->sc_csbits = 0; continue; } dopen++; um = ui->ui_mi; rxc = &rx_ctlr[um->um_ctlr]; if (++rxc->rxc_tocnt >= RX_MAXTIMEOUT) { rxc->rxc_tocnt = 0; if (um->um_tab.b_active) { printf("rx%d: timeout\n", i);/* for debugging */ rxintr(um->um_ctlr); } } } if (dopen) timeout(rxwatch, (caddr_t)0, hz); else rxwstart = 0;}rxreset(uban) int uban;{ register struct uba_ctlr *um; register struct rxdevice *rxaddr; register int ctlr; for (ctlr = 0; ctlr < nNFX; ctlr++) { if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban || um->um_alive == 0) continue; if (um->um_ubinfo) um->um_ubinfo = 0; rx_ctlr[ctlr].rxc_state = RXS_IDLE; rxaddr = (struct rxdevice *)um->um_addr; rxaddr->rxcs = RX_INIT; while ((rxaddr->rxcs&RX_DONE) == 0) ; rxstart(um); }}rxread(dev, uio) dev_t dev; struct uio *uio;{ int unit = RXUNIT(dev); struct rx_softc *sc = &rx_softc[unit]; if (uio->uio_offset + uio->uio_resid > RXSIZE) return (ENXIO); if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0) return (ENXIO); sc->sc_offset = uio->uio_offset % DEV_BSIZE; return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));}rxwrite(dev, uio) dev_t dev; struct uio *uio;{ int unit = RXUNIT(dev); struct rx_softc *sc = &rx_softc[unit]; if (uio->uio_offset + uio->uio_resid > RXSIZE) return (ENXIO); if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0) return (ENXIO); sc->sc_offset = uio->uio_offset % DEV_BSIZE; return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));}/* * Control routine: * processes four kinds of requests: * * (1) Set density (i.e., format the diskette) according to * that specified data parameter * (2) Arrange for the next sector to be written with a deleted- * data mark. * (3) Report whether the last sector read had a deleted-data mark * (4) Report the density of the diskette in the indicated drive * (since the density it automatically determined by the driver, * this is the only way to let an application program know the * density) * * Requests relating to deleted-data marks can be handled right here. * A "set density" (format) request, however, must additionally be * processed through "rxstart", just like a read or write request. *//*ARGSUSED3*/rxioctl(dev, cmd, data, flag) dev_t dev; caddr_t data;{ int unit = RXUNIT(dev); struct rx_softc *sc = &rx_softc[unit]; switch (cmd) { case RXIOC_FORMAT: if ((flag&FWRITE) == 0) return (EBADF); if (sc->sc_open > 1) return (EBUSY); if (*(int *)data) sc->sc_csbits |= RX_DDEN; else sc->sc_csbits &= ~RX_DDEN; return (rxformat(dev)); case RXIOC_WDDS: sc->sc_flags |= RXF_USEWDDS; return (0); case RXIOC_RDDSMK: *(int *)data = sc->sc_flags & RXF_DDMK; return (0); case RXIOC_GDENS: *(int *)data = sc->sc_csbits & RX_DDEN; return (0); } return (ENXIO);}/* * Initiate a format command. */rxformat(dev) dev_t dev;{ int unit = RXUNIT(dev); struct buf *bp; struct rx_softc *sc = &rx_softc[unit]; int s, error = 0; bp = &rrxbuf[unit]; bp->b_flags = B_BUSY | B_CTRL; sc->sc_flags = RXF_FORMAT | RXF_LOCK; bp->b_dev = dev; bp->b_error = 0; bp->b_blkno = 0; rxstrategy(bp); iowait(bp); if (bp->b_flags & B_ERROR) error = bp->b_error; bp->b_flags &= ~B_BUSY; sc->sc_flags &= ~RXF_LOCK; return (error);}/* * A permanent hard error condition has occured, * purge the buffer queue */rxpurge(um) register struct uba_ctlr *um;{ register struct buf *bp, *dp; dp = um->um_tab.b_actf; while (dp->b_actf) { dp->b_errcnt++; bp = dp->b_actf; bp->b_error = EIO; bp->b_flags |= B_ERROR; iodone(bp); dp->b_actf = bp->av_forw; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -