Annotation of 43BSDReno/sys/vaxuba/rx.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  *
        !             6:  *     @(#)rx.c        7.4 (Berkeley) 4/3/90
        !             7:  */
        !             8: 
        !             9: #include "rx.h"
        !            10: #if NFX > 0
        !            11: /*
        !            12:  * RX02 floppy disk device driver
        !            13:  *
        !            14:  */
        !            15: 
        !            16: /*
        !            17:  * TODO:
        !            18:  *     - clean up the code for multisector transfers using
        !            19:  *       a 'transfer in progress' flag
        !            20:  *     - Test Deleted Data read/write 
        !            21:  *     - Test error handling/reporting and 'volume valid' stuff
        !            22:  *
        !            23:  *     Note: If the drive subsystem is
        !            24:  *     powered off at boot time, the controller won't interrupt!
        !            25:  */
        !            26: 
        !            27: #include "machine/pte.h"
        !            28: 
        !            29: #include "param.h"
        !            30: #include "buf.h"
        !            31: #include "systm.h"
        !            32: #include "conf.h"
        !            33: #include "errno.h"
        !            34: #include "time.h"
        !            35: #include "kernel.h"
        !            36: #include "uio.h"
        !            37: #include "file.h"
        !            38: 
        !            39: #include "../vax/cpu.h"
        !            40: #include "../vax/nexus.h"
        !            41: 
        !            42: #include "ubavar.h"
        !            43: #include "ubareg.h"
        !            44: #include "rxreg.h"
        !            45: 
        !            46: #define b_cylin        b_resid
        !            47: 
        !            48: /* per-controller data */
        !            49: struct rx_ctlr {
        !            50:        int     rxc_state;      /* controller state */
        !            51: #define        RXS_READ        1       /* read started */
        !            52: #define        RXS_EMPTY       2       /* empty started */
        !            53: #define        RXS_FILL        3       /* fill started */
        !            54: #define        RXS_WRITE       4       /* write started */
        !            55: #define        RXS_FORMAT      5       /* format started */
        !            56: #define        RXS_RDSTAT      6       /* status read started */
        !            57: #define        RXS_RDERR       7       /* error read started */
        !            58: #define        RXS_IDLE        8       /* device is idle */
        !            59:        u_short rxc_rxcs;       /* extended error status */
        !            60:        u_short rxc_rxdb;
        !            61:        u_short rxc_rxxt[4];
        !            62:        int     rxc_tocnt;      /* for watchdog routine */
        !            63: #define        RX_MAXTIMEOUT   30      /* # seconds to wait before giving up */
        !            64: } rx_ctlr[NFX];
        !            65: 
        !            66: /* per-drive buffers */
        !            67: struct buf     rrxbuf[NRX];    /* buffers for raw I/O */
        !            68: struct buf     erxbuf[NRX];    /* buffers for reading error status */
        !            69: struct buf     rxutab[NRX];    /* per drive buffers */
        !            70: 
        !            71: /* per-drive data */
        !            72: struct rx_softc {
        !            73:        int     sc_flags;       /* drive status flags */
        !            74: #define        RXF_DIRECT      0x01    /* if set: use direct sector mapping */
        !            75: #define        RXF_TRKONE      0x02    /* if set: start mapping on track 1 */
        !            76: #define        RXF_DBLDEN      0x04    /* use double density */
        !            77: #define        RXF_DEVTYPE     0x07    /* mapping flags */
        !            78: #define        RXF_LOCK        0x10    /* exclusive use */
        !            79: #define        RXF_DDMK        0x20    /* deleted-data mark detected */
        !            80: #define        RXF_USEWDDS     0x40    /* write deleted-data sector */
        !            81: #define        RXF_FORMAT      0x80    /* format in progress */
        !            82: #define        RXF_BAD         0x100   /* drive bad, cannot be used */
        !            83:        int     sc_csbits;      /* constant bits for CS register */
        !            84:        int     sc_open;        /* count number of opens */
        !            85:        int     sc_offset;      /* raw mode kludge to avoid restricting */
        !            86:                                /* single sector transfers to start on */
        !            87:                                /* DEV_BSIZE boundaries */
        !            88:        /*
        !            89:         * The rest of this structure is used to 
        !            90:         * store temporaries while simulating multi 
        !            91:         * sector transfers
        !            92:         */
        !            93:        caddr_t sc_uaddr;       /* unibus base address */
        !            94:        long    sc_bcnt;        /* total transfer count */
        !            95:        long    sc_resid;       /* no. of bytes left to transfer */
        !            96: } rx_softc[NRX];
        !            97: 
        !            98: struct rxerr {
        !            99:        short   rxcs;
        !           100:        short   rxdb;
        !           101:        short   rxxt[4];        /* error code dump from controller */
        !           102: } rxerr[NRX];
        !           103: /* End of per-drive data */
        !           104: 
        !           105: struct uba_device *rxdinfo[NRX];
        !           106: struct uba_ctlr *rxminfo[NFX];
        !           107: 
        !           108: struct buf *savebp;
        !           109: 
        !           110: int rxprobe(), rxslave(), rxattach(), rxdgo(), rxintr(), rxwatch(), rxphys();
        !           111: u_short rxstd[] = { 0177170, 0177150, 0 };
        !           112: struct uba_driver fxdriver =
        !           113:   { rxprobe, rxslave, rxattach, rxdgo, rxstd, "rx", rxdinfo, "fx", rxminfo };
        !           114: 
        !           115: int    rxwstart;
        !           116: #define        RXUNIT(dev)     (minor(dev)>>3)
        !           117: #define        MASKREG(reg)    (reg&0xffff)
        !           118: 
        !           119: /* constants related to floppy data capacity */
        !           120: #define        RXSECS  2002                            /* # sectors on a floppy */
        !           121: #define        DDSTATE (sc->sc_csbits&RX_DDEN)
        !           122: #define        NBPS    (DDSTATE ? 256 : 128)           /* # bytes per sector */
        !           123: #define        RXSIZE  (DDSTATE ? 512512 : 256256)     /* # bytes per disk */
        !           124: #define        SECMASK (DDSTATE ? 0xff : 0x7f)         /* shifted-out bits of offset */
        !           125: 
        !           126: #define        B_CTRL          0x80000000              /* control (format) request */
        !           127: #define B_RDSTAT       0x40000000              /* read drive status (open) */
        !           128: 
        !           129: /*ARGSUSED*/
        !           130: rxprobe (reg)
        !           131:        caddr_t reg;
        !           132: {
        !           133:        register int br, cvec;                  /* value-result */
        !           134:        struct rxdevice *rxaddr = (struct rxdevice *)reg;
        !           135: 
        !           136: #ifdef lint
        !           137:        br = 0; cvec = br; br = cvec;
        !           138:        rxintr(0);
        !           139: #endif lint
        !           140:        rxaddr->rxcs = RX_INTR;
        !           141:        DELAY(10);
        !           142:        rxaddr->rxcs = 0;
        !           143:        return (sizeof (*rxaddr));
        !           144: }
        !           145: 
        !           146: /*ARGSUSED*/
        !           147: rxslave(ui, reg)
        !           148:        struct uba_device *ui;
        !           149:        caddr_t reg;
        !           150: {
        !           151:        return (ui->ui_slave == 0 || ui->ui_slave == 1);
        !           152: }
        !           153: 
        !           154: /*ARGSUSED*/
        !           155: rxattach(ui)
        !           156:        struct uba_device *ui;
        !           157: {
        !           158: 
        !           159: }
        !           160: 
        !           161: /*ARGSUSED1*/
        !           162: rxopen(dev, flag)
        !           163:        dev_t dev;
        !           164: { 
        !           165:        register int unit = RXUNIT(dev);
        !           166:        register struct rx_softc *sc;
        !           167:        register struct uba_device *ui;
        !           168:        struct rx_ctlr *rxc;
        !           169: 
        !           170:        if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)
        !           171:                return (ENXIO);
        !           172:        sc = &rx_softc[unit];
        !           173:        if (sc->sc_open == 0 && sc->sc_csbits == 0) {
        !           174:                struct buf *bp = &erxbuf[unit];
        !           175:                /*
        !           176:                 * lock the device while an open 
        !           177:                 * is in progress
        !           178:                 */
        !           179:                sc->sc_flags = (minor(dev) & RXF_DEVTYPE) | RXF_LOCK;
        !           180:                sc->sc_csbits = RX_INTR;
        !           181:                sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;
        !           182: 
        !           183:                bp->b_dev = dev;
        !           184:                bp->b_flags = B_RDSTAT | B_BUSY;
        !           185:                bp->b_error = 0;
        !           186:                bp->b_blkno = 0;
        !           187:                sc->sc_offset = 0;
        !           188:                sc->sc_resid  = 0;
        !           189:                /*
        !           190:                 * read device status to determine if
        !           191:                 * a floppy is present in the drive and
        !           192:                 * what density it is
        !           193:                 */
        !           194:                rxstrategy(bp);
        !           195:                iowait(bp);
        !           196:                if (bp->b_flags & B_ERROR) {
        !           197:                        sc->sc_csbits = 0;
        !           198:                        sc->sc_flags &= ~RXF_LOCK;
        !           199:                        return (bp->b_error);
        !           200:                }
        !           201:                if (rxwstart++ == 0) {
        !           202:                        rxc = &rx_ctlr[ui->ui_mi->um_ctlr];
        !           203:                        rxc->rxc_tocnt = 0;
        !           204:                        timeout(rxwatch, (caddr_t)0, hz);  /* start watchdog */
        !           205:                }
        !           206: #ifdef RXDEBUG
        !           207:                printf("rxopen: csbits=0x%x\n", sc->sc_csbits);
        !           208: #endif
        !           209:                sc->sc_flags &= ~RXF_LOCK;
        !           210:        } else  {
        !           211:                if (sc->sc_flags & RXF_LOCK)
        !           212:                        return(EBUSY);
        !           213:        }
        !           214:        sc->sc_open = 1;
        !           215:        return (0);
        !           216: }
        !           217: 
        !           218: /*ARGSUSED1*/
        !           219: rxclose(dev, flag)
        !           220:        dev_t dev;
        !           221: {
        !           222:        register struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
        !           223: 
        !           224:        sc->sc_open = 0;
        !           225: #ifdef RXDEBUG
        !           226:        printf("rxclose: dev=0x%x, sc_open=%d\n", dev, sc->sc_open);
        !           227: #endif
        !           228:        return (0);
        !           229: }
        !           230: 
        !           231: rxstrategy(bp)
        !           232:        register struct buf *bp;
        !           233: {
        !           234:        struct uba_device *ui;
        !           235:        register struct buf *dp;
        !           236:        struct rx_softc *sc;
        !           237:        int s, unit = RXUNIT(bp->b_dev);
        !           238: 
        !           239:        if (unit >= NRX)
        !           240:                goto bad;
        !           241:        ui = rxdinfo[unit];
        !           242:        if (ui == 0 || ui->ui_alive == 0) 
        !           243:                goto bad;
        !           244:        sc = &rx_softc[unit];
        !           245:        if (bp->b_blkno < 0 || dbtob(bp->b_blkno) > RXSIZE)
        !           246:                goto bad;
        !           247:        if (sc->sc_flags & RXF_BAD) {
        !           248:                bp->b_error = EIO;
        !           249:                goto dbad;
        !           250:        }
        !           251:        s = spl5();
        !           252: #ifdef RXDEBUG
        !           253:        printf("rxstrat: bp=0x%x, fl=0x%x, un=%d, bl=%d, cnt=%d\n", 
        !           254:                bp, bp->b_flags, unit, bp->b_blkno, bp->b_bcount);
        !           255: #endif
        !           256:        bp->b_cylin = bp->b_blkno;      /* don't care to calculate trackno */
        !           257:        dp = &rxutab[unit];
        !           258:        disksort(dp, bp);
        !           259:        if (dp->b_active == 0) {
        !           260:                rxustart(ui);
        !           261:                bp = &ui->ui_mi->um_tab;
        !           262:                if (bp->b_actf && bp->b_active == 0)
        !           263:                        rxstart(ui->ui_mi);
        !           264:        }
        !           265:        splx(s);
        !           266:        return;
        !           267: 
        !           268: bad:
        !           269:        bp->b_error = ENXIO;
        !           270: dbad:
        !           271:        bp->b_flags |= B_ERROR;
        !           272:        iodone(bp);
        !           273:        return;
        !           274: }
        !           275: 
        !           276: /*
        !           277:  * Unit start routine.
        !           278:  * Put this unit on the ready queue for the controller
        !           279:  */
        !           280: rxustart(ui)
        !           281:        register struct uba_device *ui;
        !           282: {
        !           283:        struct buf *dp = &rxutab[ui->ui_unit];
        !           284:        struct uba_ctlr *um = ui->ui_mi;
        !           285:        
        !           286:        dp->b_forw = NULL;
        !           287:        if (um->um_tab.b_actf == NULL)
        !           288:                um->um_tab.b_actf = dp;
        !           289:        else
        !           290:                um->um_tab.b_actl->b_forw = dp;
        !           291:        um->um_tab.b_actl = dp;
        !           292:        dp->b_active++;
        !           293: }
        !           294: /*
        !           295:  * Sector mapping routine.
        !           296:  * Two independent sets of choices are available:
        !           297:  *
        !           298:  * (a) The first logical sector may either be on track 1 or track 0.
        !           299:  * (b) The sectors on a track may either be taken in 2-for-1 interleaved
        !           300:  *      fashion or directly.
        !           301:  * This gives a total of four possible mapping schemes.
        !           302:  *
        !           303:  * Physical tracks on the RX02 are numbered 0-76.  Physical sectors on
        !           304:  * each track are numbered 1-26.
        !           305:  *
        !           306:  * When interleaving is used, sectors on the first logical track are
        !           307:  * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26.  A skew of
        !           308:  * six sectors per track is also used (to allow time for the heads to
        !           309:  * move); hence, the sectors on the second logical track are taken in
        !           310:  * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6;
        !           311:  * the third logical track starts with sector 13; and so on.
        !           312:  *
        !           313:  * When the mapping starts with track 1, track 0 is the last logical
        !           314:  * track, and this track is always handled directly (without inter-
        !           315:  * leaving), even when the rest of the disk is interleaved.  (This is
        !           316:  * still compatible with DEC RT-11, which does not use track 0 at all.)
        !           317:  */
        !           318: rxmap(bp, psector, ptrack)
        !           319:        struct buf *bp;
        !           320:        int *psector, *ptrack;
        !           321: {
        !           322:        register int lt, ls, ptoff;
        !           323:        struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
        !           324: 
        !           325:        ls = (dbtob(bp->b_blkno) + (sc->sc_offset - sc->sc_resid)) / NBPS;
        !           326:        lt = ls / 26;
        !           327:        ls %= 26;
        !           328:        /*
        !           329:         * The "physical track offset" (ptoff) takes the
        !           330:         * starting physical track (0 or 1) and the desired
        !           331:         * interleaving into account.  If lt+ptoff >= 77,
        !           332:         * then interleaving is not performed.
        !           333:         */
        !           334:        ptoff = 0;
        !           335:        if (sc->sc_flags & RXF_DIRECT)
        !           336:                ptoff = 77;
        !           337:        if (sc->sc_flags & RXF_TRKONE)
        !           338:                ptoff++;
        !           339:        if (lt + ptoff < 77)
        !           340:                ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
        !           341:        *ptrack = (lt + ptoff) % 77;
        !           342:        *psector = ls + 1;
        !           343: }
        !           344: 
        !           345: /*
        !           346:  * Controller start routine.
        !           347:  * Start a new transfer or continue a multisector
        !           348:  * transfer. If this is a new transfer (dp->b_active == 1)
        !           349:  * save the start address of the data buffer and the total
        !           350:  * byte count in the soft control structure. These are
        !           351:  * restored into the buffer structure when the transfer has
        !           352:  * been completed, before calling 'iodone'.
        !           353:  */
        !           354: rxstart(um)
        !           355:        register struct uba_ctlr *um;
        !           356: {
        !           357:        register struct rxdevice *rxaddr;
        !           358:        register struct rx_ctlr *rxc;
        !           359:        register struct rx_softc *sc;
        !           360:        struct buf *dp, *bp;
        !           361:        int unit, sector, track;
        !           362: 
        !           363:        if (um->um_tab.b_active)
        !           364:                return;
        !           365: loop:
        !           366:        if ((dp = um->um_tab.b_actf) == NULL)
        !           367:                return;
        !           368:        if ((bp = dp->b_actf) == NULL) {
        !           369:                um->um_tab.b_actf = dp->b_forw;
        !           370:                goto loop;
        !           371:        }
        !           372:        um->um_tab.b_active++;
        !           373:        unit = RXUNIT(bp->b_dev);
        !           374:        sc = &rx_softc[unit];
        !           375:        if (sc->sc_flags & RXF_BAD) {
        !           376:                rxpurge(um);
        !           377:                return;
        !           378:        }
        !           379:        if (dp->b_active == 1) {
        !           380:                sc->sc_resid = bp->b_bcount;
        !           381:                sc->sc_uaddr = bp->b_un.b_addr;
        !           382:                sc->sc_bcnt = bp->b_bcount;
        !           383:                sc->sc_offset += sc->sc_bcnt;
        !           384:                dp->b_active++;
        !           385:        }
        !           386:        rxaddr = (struct rxdevice *)um->um_addr;
        !           387:        rxc = &rx_ctlr[um->um_ctlr];
        !           388:        bp->b_bcount = sc->sc_resid;
        !           389:        if (bp->b_bcount > NBPS)
        !           390:                bp->b_bcount = NBPS;
        !           391:        rxc->rxc_tocnt = 0;
        !           392: #ifdef RXDEBUG
        !           393:        printf("rxstart: ");
        !           394: #endif
        !           395:        if (rxaddr->rxcs == 0x800) {
        !           396:                /*
        !           397:                 * 'Volume valid'? (check if the 
        !           398:                 * drive unit has been powered down)
        !           399:                 */
        !           400:                rxaddr->rxcs = RX_INIT;
        !           401:                while((rxaddr->rxcs&RX_DONE) == 0)
        !           402:                        ;
        !           403:        }
        !           404:        if (bp->b_flags & B_CTRL) {                             /* format */
        !           405:                rxc->rxc_state = RXS_FORMAT;
        !           406:                rxaddr->rxcs = RX_FORMAT | sc->sc_csbits;
        !           407:                while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           408:                        ;
        !           409:                rxaddr->rxdb = 'I';
        !           410:                return;
        !           411:        }
        !           412:        if (bp->b_flags & B_RDSTAT) {                   /* read drive status */
        !           413:                rxc->rxc_state = RXS_RDSTAT;
        !           414:                rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
        !           415:                return;
        !           416:        }
        !           417: 
        !           418:        if (bp->b_flags & B_READ) {
        !           419:                rxmap(bp, &sector, &track);                     /* read */
        !           420: #ifdef RXDEBUG
        !           421:                printf("read tr=%d, sc=%d", track, sector);
        !           422: #endif
        !           423:                rxc->rxc_state = RXS_READ;
        !           424:                rxaddr->rxcs = RX_READ | sc->sc_csbits;
        !           425:                while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           426:                        ;
        !           427:                rxaddr->rxdb = (u_short)sector;
        !           428:                while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           429:                        ;
        !           430:                rxaddr->rxdb = (u_short)track;
        !           431:        } else {
        !           432: #ifdef RXDEBUG
        !           433:                printf("write");
        !           434: #endif
        !           435:                rxc->rxc_state = RXS_FILL;                      /* write */
        !           436:                um->um_cmd = RX_FILL;
        !           437:                (void) ubago(rxdinfo[unit]);
        !           438:        }
        !           439: #ifdef RXDEBUG
        !           440:        printf("\n");
        !           441: #endif
        !           442: }
        !           443: 
        !           444: rxdgo(um)
        !           445:        struct uba_ctlr *um;
        !           446: {
        !           447:        register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
        !           448:        int ubinfo = um->um_ubinfo;
        !           449:        struct buf *bp = um->um_tab.b_actf->b_actf;
        !           450:        struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
        !           451:        struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
        !           452: 
        !           453:        rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
        !           454:        if (rxc->rxc_state != RXS_RDERR) {
        !           455:                while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           456:                        ;
        !           457:                rxaddr->rxdb = (u_short) bp->b_bcount >> 1;
        !           458:        }
        !           459:        while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           460:                ;
        !           461:        rxaddr->rxdb = (u_short) ubinfo;
        !           462: }
        !           463: 
        !           464: rxintr(ctlr)
        !           465:        int ctlr;
        !           466: {
        !           467:        int unit, sector, track;
        !           468:        struct uba_ctlr *um = rxminfo[ctlr];
        !           469:        register struct rxdevice *rxaddr;
        !           470:        register struct buf *bp, *dp;
        !           471:        register struct rx_softc *sc;
        !           472:        struct uba_device *ui;
        !           473:        struct rxerr *er;
        !           474:        struct rx_ctlr *rxc;
        !           475: 
        !           476:        if (!um->um_tab.b_active)
        !           477:                return;
        !           478:        dp = um->um_tab.b_actf;
        !           479:        if (!dp->b_active)
        !           480:                return;
        !           481:        bp = dp->b_actf;
        !           482:        unit = RXUNIT(bp->b_dev);
        !           483:        sc = &rx_softc[unit];
        !           484:        ui = rxdinfo[unit];
        !           485:        rxaddr = (struct rxdevice *)um->um_addr;
        !           486:        rxc = &rx_ctlr[um->um_ctlr];
        !           487:        rxc->rxc_tocnt = 0;
        !           488:        er = &rxerr[unit];
        !           489: #ifdef RXDEBUG
        !           490:        printf("rxint: dev=%x, st=%d, cs=0x%x, db=0x%x\n", 
        !           491:                bp->b_dev, rxc->rxc_state, rxaddr->rxcs, rxaddr->rxdb);
        !           492: #endif
        !           493:        if ((rxaddr->rxcs & RX_ERR) &&
        !           494:            (rxc->rxc_state != RXS_RDSTAT) && (rxc->rxc_state != RXS_RDERR))
        !           495:                goto error;
        !           496:        switch (rxc->rxc_state) {
        !           497: 
        !           498:        /*
        !           499:         * Incomplete commands.  Perform next step
        !           500:         * and return.  Note that b_active is set on
        !           501:         * entrance and, therefore, also on exit.
        !           502:         */
        !           503:        case RXS_READ:
        !           504:                if (rxaddr->rxdb & RXES_DDMARK)
        !           505:                        sc->sc_flags |= RXF_DDMK;
        !           506:                else
        !           507:                        sc->sc_flags &= ~RXF_DDMK;
        !           508:                rxc->rxc_state = RXS_EMPTY;
        !           509:                um->um_cmd = RX_EMPTY;
        !           510:                (void) ubago(ui);
        !           511:                return;
        !           512: 
        !           513:        case RXS_FILL:
        !           514:                rxc->rxc_state = RXS_WRITE;
        !           515:                if (sc->sc_flags & RXF_USEWDDS) {
        !           516:                        rxaddr->rxcs = RX_WDDS | sc->sc_csbits;
        !           517:                        sc->sc_flags &= ~RXF_USEWDDS;
        !           518:                } else
        !           519:                        rxaddr->rxcs = RX_WRITE | sc->sc_csbits;
        !           520:                rxmap(bp, &sector, &track);
        !           521:                while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           522:                        ;
        !           523:                rxaddr->rxdb = sector;
        !           524:                while ((rxaddr->rxcs&RX_TREQ) == 0)
        !           525:                        ;
        !           526:                rxaddr->rxdb = track;
        !           527:                return;
        !           528: 
        !           529:        /*
        !           530:         * Possibly completed command.
        !           531:         */
        !           532:        case RXS_RDSTAT:
        !           533:                if (bp->b_flags & B_RDSTAT) {
        !           534:                        if ((rxaddr->rxdb&RXES_READY) == 0) {
        !           535:                                bp->b_flags |= B_ERROR;
        !           536:                                bp->b_error = ENODEV;
        !           537:                        } else {
        !           538:                                sc->sc_csbits |= rxaddr->rxdb&RXES_DBLDEN ?
        !           539:                                        RX_DDEN : RX_SDEN;
        !           540:                        }
        !           541:                        goto rdone;
        !           542:                }
        !           543:                if (rxaddr->rxdb&RXES_READY)
        !           544:                        goto rderr;
        !           545:                bp->b_error = ENODEV;
        !           546:                bp->b_flags |= B_ERROR;
        !           547:                goto done;
        !           548: 
        !           549:        /*
        !           550:         * Command completed.
        !           551:         */
        !           552:        case RXS_EMPTY:
        !           553:        case RXS_WRITE: 
        !           554:                goto done;
        !           555: 
        !           556:        case RXS_FORMAT:
        !           557:                goto rdone;
        !           558: 
        !           559:        case RXS_RDERR:
        !           560:                bp = savebp;
        !           561:                rxmap(bp, &sector, &track);
        !           562:                printf("rx%d: hard error, trk %d psec %d ",
        !           563:                        unit, track, sector);
        !           564:                printf("cs=%b, db=%b, err=", MASKREG(er->rxcs), 
        !           565:                        RXCS_BITS, MASKREG(er->rxdb), RXES_BITS);
        !           566:                printf("%x, %x, %x, %x\n", MASKREG(er->rxxt[0]),
        !           567:                        MASKREG(er->rxxt[1]), MASKREG(er->rxxt[2]), 
        !           568:                        MASKREG(er->rxxt[3]));
        !           569:                goto done;
        !           570: 
        !           571:        default:
        !           572:                printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state);
        !           573:                rxreset(um->um_ubanum);
        !           574:                return;
        !           575:        }
        !           576: error:
        !           577:        /*
        !           578:         * In case of an error:
        !           579:         *  (a) Give up now if a format (ioctl) was in progress, if a
        !           580:         *        density error was detected, or if the drive went offline
        !           581:         *  (b) Retry up to nine times if a CRC (data) error was detected,
        !           582:         *        then give up if the error persists.
        !           583:         *  (c) In all other cases, reinitialize the drive and try the
        !           584:         *        operation once more before giving up.
        !           585:         */
        !           586:        if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR))
        !           587:                goto giveup;
        !           588:        if (rxaddr->rxdb & RXES_CRCERR) {
        !           589:                if (++um->um_tab.b_errcnt >= 10)
        !           590:                        goto giveup;
        !           591:                goto retry;
        !           592:        }
        !           593:        um->um_tab.b_errcnt += 9;
        !           594:        if (um->um_tab.b_errcnt >= 10)
        !           595:                goto giveup;
        !           596:        rxaddr->rxcs = RX_INIT;
        !           597:        /* no way to get an interrupt for "init done", so just wait */
        !           598:        while ((rxaddr->rxcs&RX_DONE) == 0)
        !           599:                ;
        !           600:        /* if someone opened the drive: give up */
        !           601:        if ((rxaddr->rxdb&RXES_READY) == 0)
        !           602:                goto giveup;
        !           603: retry:
        !           604:        /*
        !           605:         * In case we already have UNIBUS resources, give
        !           606:         * them back since we reallocate things in rxstart.
        !           607:         */
        !           608:        if (um->um_ubinfo)
        !           609:                ubadone(um);
        !           610:        um->um_tab.b_active = 0;
        !           611:        rxstart(um);
        !           612:        return;
        !           613: 
        !           614: giveup:
        !           615:        /*
        !           616:         * Hard I/O error --
        !           617:         * ALL errors are considered fatal and will abort the
        !           618:         * transfer and purge the i/o request queue
        !           619:         */
        !           620:        sc->sc_flags |= RXF_BAD;
        !           621:        sc->sc_resid = 0;       /* make sure the transfer is terminated */
        !           622:        rxc->rxc_state = RXS_RDSTAT;
        !           623:        rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
        !           624:        return;
        !           625: 
        !           626: rderr:
        !           627:        /*
        !           628:         * A hard error (other than not ready) has occurred.
        !           629:         * Read the extended error status information.
        !           630:         * Before doing this, save the current CS and DB register values,
        !           631:         * because the read error status operation may modify them.
        !           632:         * Insert buffer with request at the head of the queue.
        !           633:         */
        !           634:        bp->b_error = EIO;
        !           635:        bp->b_flags |= B_ERROR;
        !           636:        if (um->um_ubinfo)
        !           637:                ubadone(um);
        !           638:        savebp = bp;
        !           639:        er->rxcs = rxaddr->rxcs;
        !           640:        er->rxdb = rxaddr->rxdb;
        !           641:        bp = &erxbuf[unit];
        !           642:        bp->b_un.b_addr = (caddr_t)er->rxxt;
        !           643:        bp->b_bcount = sizeof (er->rxxt);
        !           644:        bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
        !           645:        if (dp->b_actf == NULL)
        !           646:                dp->b_actl = bp;
        !           647:        bp->b_forw = dp->b_actf;
        !           648:        dp->b_actf = bp;
        !           649:        rxc->rxc_state = RXS_RDERR;
        !           650:        um->um_cmd = RX_RDERR;
        !           651:        (void) ubago(ui);
        !           652:        return;
        !           653: 
        !           654: done:
        !           655:        ubadone(um);
        !           656: rdone:
        !           657:        um->um_tab.b_active = 0;
        !           658:        um->um_tab.b_errcnt = 0;
        !           659:        if ((sc->sc_resid -= NBPS) > 0) {
        !           660:                bp->b_un.b_addr += NBPS;
        !           661:                rxstart(um);
        !           662:                return;
        !           663:        }
        !           664:        bp->b_un.b_addr = sc->sc_uaddr;
        !           665:        bp->b_resid = 0;
        !           666:        bp->b_bcount = sc->sc_bcnt;
        !           667:        dp->b_actf = bp->av_forw;
        !           668:        iodone(bp);
        !           669:        sc->sc_offset = 0;
        !           670:        rxc->rxc_state = RXS_IDLE;
        !           671:        um->um_tab.b_actf = dp->b_forw;
        !           672:        dp->b_active = 0;
        !           673:        dp->b_errcnt = 0;
        !           674: #ifdef RXDEBUG
        !           675:        printf(".. bp=%x, new=%x\n", bp, dp->b_actf);
        !           676: #endif
        !           677:        /*
        !           678:         * If this unit has more work to do,
        !           679:         * start it up right away
        !           680:         */
        !           681:        if (dp->b_actf)
        !           682:                rxustart(ui);
        !           683: 
        !           684:        rxstart(um);
        !           685: }
        !           686: 
        !           687: /*ARGSUSED*/
        !           688: 
        !           689: rxwatch()
        !           690: {
        !           691:        register struct uba_device *ui;
        !           692:        register struct uba_ctlr *um;
        !           693:        register struct rx_softc *sc;
        !           694:        struct rx_ctlr *rxc;
        !           695:        int i, dopen = 0;
        !           696: 
        !           697:        for (i=0; i<NRX; i++) {
        !           698:                ui = rxdinfo[i];
        !           699:                if (ui == 0 || ui->ui_alive == 0)
        !           700:                        continue;
        !           701:                sc = &rx_softc[i];
        !           702:                if ((sc->sc_open == 0) && (rxutab[i].b_active == 0)) {
        !           703:                        sc->sc_csbits = 0;
        !           704:                        continue;
        !           705:                }
        !           706:                dopen++;
        !           707:                um = ui->ui_mi;
        !           708:                rxc = &rx_ctlr[um->um_ctlr];
        !           709:                if (++rxc->rxc_tocnt >= RX_MAXTIMEOUT) {
        !           710:                        rxc->rxc_tocnt = 0;
        !           711:                        if (um->um_tab.b_active) {      
        !           712:                                printf("rx%d: timeout\n", i);/* for debugging */
        !           713:                                rxintr(um->um_ctlr);
        !           714:                        }
        !           715:                }
        !           716:        }
        !           717:        if (dopen)
        !           718:                timeout(rxwatch, (caddr_t)0, hz);
        !           719:        else
        !           720:                rxwstart = 0;
        !           721: }
        !           722: 
        !           723: rxreset(uban)
        !           724:        int uban;
        !           725: {
        !           726:        register struct uba_ctlr *um;
        !           727:        register struct rxdevice *rxaddr;
        !           728:        register int ctlr;
        !           729: 
        !           730:        for (ctlr = 0; ctlr < NFX; ctlr++) {
        !           731:                if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
        !           732:                    um->um_alive == 0)
        !           733:                        continue;
        !           734:                printf(" fx%d", ctlr);
        !           735:                if (um->um_ubinfo) {
        !           736:                        printf("<%d>", UBAI_BDP(um->um_ubinfo));
        !           737:                        um->um_ubinfo = 0;
        !           738:                }
        !           739:                rx_ctlr[ctlr].rxc_state = RXS_IDLE;
        !           740:                rxaddr = (struct rxdevice *)um->um_addr;
        !           741:                rxaddr->rxcs = RX_INIT;
        !           742:                while ((rxaddr->rxcs&RX_DONE) == 0)
        !           743:                        ;
        !           744:                rxstart(um);
        !           745:        }
        !           746: }
        !           747: 
        !           748: rxread(dev, uio)
        !           749:        dev_t dev;
        !           750:        struct uio *uio;
        !           751: {
        !           752:        int unit = RXUNIT(dev);
        !           753:        struct rx_softc *sc = &rx_softc[unit];
        !           754: 
        !           755:        if (uio->uio_offset + uio->uio_resid > RXSIZE)
        !           756:                return (ENXIO);
        !           757:        if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
        !           758:                return (ENXIO);
        !           759:        sc->sc_offset = uio->uio_offset % DEV_BSIZE;
        !           760:        return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
        !           761: }
        !           762: 
        !           763: rxwrite(dev, uio)
        !           764:        dev_t dev;
        !           765:        struct uio *uio;
        !           766: {
        !           767:        int unit = RXUNIT(dev);
        !           768:        struct rx_softc *sc = &rx_softc[unit];
        !           769: 
        !           770:        if (uio->uio_offset + uio->uio_resid > RXSIZE)
        !           771:                return (ENXIO);
        !           772:        if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
        !           773:                return (ENXIO);
        !           774:        sc->sc_offset = uio->uio_offset % DEV_BSIZE;
        !           775:        return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
        !           776: }
        !           777: 
        !           778: /*
        !           779:  * Control routine:
        !           780:  * processes four kinds of requests:
        !           781:  *
        !           782:  *     (1) Set density (i.e., format the diskette) according to 
        !           783:  *               that specified data parameter
        !           784:  *     (2) Arrange for the next sector to be written with a deleted-
        !           785:  *               data mark.
        !           786:  *     (3) Report whether the last sector read had a deleted-data mark
        !           787:  *     (4) Report the density of the diskette in the indicated drive
        !           788:  *         (since the density it automatically determined by the driver,
        !           789:  *          this is the only way to let an application program know the
        !           790:  *          density)
        !           791:  *
        !           792:  * Requests relating to deleted-data marks can be handled right here.
        !           793:  * A "set density" (format) request, however, must additionally be 
        !           794:  * processed through "rxstart", just like a read or write request.
        !           795:  */
        !           796: 
        !           797: /*ARGSUSED3*/
        !           798: rxioctl(dev, cmd, data, flag)
        !           799:        dev_t dev;
        !           800:        caddr_t data;
        !           801: {   
        !           802:        int unit = RXUNIT(dev);
        !           803:        struct rx_softc *sc = &rx_softc[unit];
        !           804: 
        !           805:        switch (cmd) {
        !           806: 
        !           807:        case RXIOC_FORMAT:
        !           808:                if ((flag&FWRITE) == 0)
        !           809:                        return (EBADF);
        !           810:                if (sc->sc_open > 1)
        !           811:                        return (EBUSY);
        !           812:                if (*(int *)data)
        !           813:                        sc->sc_csbits |= RX_DDEN;
        !           814:                else
        !           815:                        sc->sc_csbits &= ~RX_DDEN;
        !           816:                return (rxformat(dev));
        !           817: 
        !           818:        case RXIOC_WDDS:
        !           819:                sc->sc_flags |= RXF_USEWDDS;
        !           820:                return (0);
        !           821: 
        !           822:        case RXIOC_RDDSMK:
        !           823:                *(int *)data = sc->sc_flags & RXF_DDMK;
        !           824:                return (0);
        !           825: 
        !           826:        case RXIOC_GDENS:
        !           827:                *(int *)data = sc->sc_csbits & RX_DDEN;
        !           828:                return (0);
        !           829:        }
        !           830:        return (ENXIO);
        !           831: }
        !           832: 
        !           833: /*
        !           834:  * Initiate a format command.
        !           835:  */
        !           836: rxformat(dev)
        !           837:        dev_t dev;
        !           838: {
        !           839:        int unit = RXUNIT(dev);
        !           840:        struct buf *bp;
        !           841:        struct rx_softc *sc = &rx_softc[unit];
        !           842:        int error = 0;
        !           843: 
        !           844:        bp = &rrxbuf[unit];
        !           845:        bp->b_flags = B_BUSY | B_CTRL;
        !           846:        sc->sc_flags = RXF_FORMAT | RXF_LOCK;
        !           847:        bp->b_dev = dev;
        !           848:        bp->b_error = 0;
        !           849:        bp->b_blkno = 0;
        !           850:        rxstrategy(bp);
        !           851:        iowait(bp);
        !           852:        if (bp->b_flags & B_ERROR)
        !           853:                error = bp->b_error;
        !           854:        bp->b_flags &= ~B_BUSY;
        !           855:        sc->sc_flags &= ~RXF_LOCK;
        !           856:        return (error);
        !           857: }
        !           858: 
        !           859: /*
        !           860:  * A permanent hard error condition has occured,
        !           861:  * purge the buffer queue
        !           862:  */
        !           863: rxpurge(um)
        !           864:        register struct uba_ctlr *um;
        !           865: {
        !           866:        register struct buf *bp, *dp;
        !           867: 
        !           868:        dp = um->um_tab.b_actf;
        !           869:        while (dp->b_actf) {
        !           870:                dp->b_errcnt++;
        !           871:                bp = dp->b_actf;
        !           872:                bp->b_error = EIO;
        !           873:                bp->b_flags |= B_ERROR;
        !           874:                iodone(bp);
        !           875:                dp->b_actf = bp->av_forw;
        !           876:        }
        !           877: }
        !           878: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.