Annotation of 43BSD/sys/vaxuba/rx.c, revision 1.1.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.1 (Berkeley) 6/5/86
                      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: rxslave(ui, reg)
                    147:        struct uba_device *ui;
                    148:        caddr_t reg;
                    149: {
                    150: 
                    151:        ui->ui_dk = 1;
                    152:        return (ui->ui_slave == 0 || ui->ui_slave == 1);
                    153: }
                    154: 
                    155: /*ARGSUSED*/
                    156: rxattach(ui)
                    157:        struct uba_device *ui;
                    158: {
                    159: 
                    160: }
                    161: 
                    162: /*ARGSUSED1*/
                    163: rxopen(dev, flag)
                    164:        dev_t dev;
                    165: { 
                    166:        register int unit = RXUNIT(dev);
                    167:        register struct rx_softc *sc;
                    168:        register struct uba_device *ui;
                    169:        struct rx_ctlr *rxc;
                    170: 
                    171:        if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)
                    172:                return (ENXIO);
                    173:        sc = &rx_softc[unit];
                    174:        if (sc->sc_open == 0 && sc->sc_csbits == 0) {
                    175:                struct buf *bp = &erxbuf[unit];
                    176:                /*
                    177:                 * lock the device while an open 
                    178:                 * is in progress
                    179:                 */
                    180:                sc->sc_flags = (minor(dev) & RXF_DEVTYPE) | RXF_LOCK;
                    181:                sc->sc_csbits = RX_INTR;
                    182:                sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;
                    183: 
                    184:                bp->b_dev = dev;
                    185:                bp->b_flags = B_RDSTAT | B_BUSY;
                    186:                bp->b_error = 0;
                    187:                bp->b_blkno = 0;
                    188:                sc->sc_offset = 0;
                    189:                sc->sc_resid  = 0;
                    190:                /*
                    191:                 * read device status to determine if
                    192:                 * a floppy is present in the drive and
                    193:                 * what density it is
                    194:                 */
                    195:                rxstrategy(bp);
                    196:                iowait(bp);
                    197:                if (bp->b_flags & B_ERROR) {
                    198:                        sc->sc_csbits = 0;
                    199:                        sc->sc_flags &= ~RXF_LOCK;
                    200:                        return (bp->b_error);
                    201:                }
                    202:                if (rxwstart++ == 0) {
                    203:                        rxc = &rx_ctlr[ui->ui_mi->um_ctlr];
                    204:                        rxc->rxc_tocnt = 0;
                    205:                        timeout(rxwatch, (caddr_t)0, hz);  /* start watchdog */
                    206:                }
                    207: #ifdef RXDEBUG
                    208:                printf("rxopen: csbits=0x%x\n", sc->sc_csbits);
                    209: #endif
                    210:                sc->sc_flags &= ~RXF_LOCK;
                    211:        } else  {
                    212:                if (sc->sc_flags & RXF_LOCK)
                    213:                        return(EBUSY);
                    214:        }
                    215:        sc->sc_open = 1;
                    216:        return (0);
                    217: }
                    218: 
                    219: /*ARGSUSED1*/
                    220: rxclose(dev, flag)
                    221:        dev_t dev;
                    222: {
                    223:        register struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
                    224: 
                    225:        sc->sc_open = 0;
                    226: #ifdef RXDEBUG
                    227:        printf("rxclose: dev=0x%x, sc_open=%d\n", dev, sc->sc_open);
                    228: #endif
                    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:                if (um->um_ubinfo)
                    735:                        um->um_ubinfo = 0;
                    736:                rx_ctlr[ctlr].rxc_state = RXS_IDLE;
                    737:                rxaddr = (struct rxdevice *)um->um_addr;
                    738:                rxaddr->rxcs = RX_INIT;
                    739:                while ((rxaddr->rxcs&RX_DONE) == 0)
                    740:                        ;
                    741:                rxstart(um);
                    742:        }
                    743: }
                    744: 
                    745: rxread(dev, uio)
                    746:        dev_t dev;
                    747:        struct uio *uio;
                    748: {
                    749:        int unit = RXUNIT(dev);
                    750:        struct rx_softc *sc = &rx_softc[unit];
                    751: 
                    752:        if (uio->uio_offset + uio->uio_resid > RXSIZE)
                    753:                return (ENXIO);
                    754:        if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
                    755:                return (ENXIO);
                    756:        sc->sc_offset = uio->uio_offset % DEV_BSIZE;
                    757:        return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
                    758: }
                    759: 
                    760: rxwrite(dev, uio)
                    761:        dev_t dev;
                    762:        struct uio *uio;
                    763: {
                    764:        int unit = RXUNIT(dev);
                    765:        struct rx_softc *sc = &rx_softc[unit];
                    766: 
                    767:        if (uio->uio_offset + uio->uio_resid > RXSIZE)
                    768:                return (ENXIO);
                    769:        if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
                    770:                return (ENXIO);
                    771:        sc->sc_offset = uio->uio_offset % DEV_BSIZE;
                    772:        return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
                    773: }
                    774: 
                    775: /*
                    776:  * Control routine:
                    777:  * processes four kinds of requests:
                    778:  *
                    779:  *     (1) Set density (i.e., format the diskette) according to 
                    780:  *               that specified data parameter
                    781:  *     (2) Arrange for the next sector to be written with a deleted-
                    782:  *               data mark.
                    783:  *     (3) Report whether the last sector read had a deleted-data mark
                    784:  *     (4) Report the density of the diskette in the indicated drive
                    785:  *         (since the density it automatically determined by the driver,
                    786:  *          this is the only way to let an application program know the
                    787:  *          density)
                    788:  *
                    789:  * Requests relating to deleted-data marks can be handled right here.
                    790:  * A "set density" (format) request, however, must additionally be 
                    791:  * processed through "rxstart", just like a read or write request.
                    792:  */
                    793: 
                    794: /*ARGSUSED3*/
                    795: rxioctl(dev, cmd, data, flag)
                    796:        dev_t dev;
                    797:        caddr_t data;
                    798: {   
                    799:        int unit = RXUNIT(dev);
                    800:        struct rx_softc *sc = &rx_softc[unit];
                    801: 
                    802:        switch (cmd) {
                    803: 
                    804:        case RXIOC_FORMAT:
                    805:                if ((flag&FWRITE) == 0)
                    806:                        return (EBADF);
                    807:                if (sc->sc_open > 1)
                    808:                        return (EBUSY);
                    809:                if (*(int *)data)
                    810:                        sc->sc_csbits |= RX_DDEN;
                    811:                else
                    812:                        sc->sc_csbits &= ~RX_DDEN;
                    813:                return (rxformat(dev));
                    814: 
                    815:        case RXIOC_WDDS:
                    816:                sc->sc_flags |= RXF_USEWDDS;
                    817:                return (0);
                    818: 
                    819:        case RXIOC_RDDSMK:
                    820:                *(int *)data = sc->sc_flags & RXF_DDMK;
                    821:                return (0);
                    822: 
                    823:        case RXIOC_GDENS:
                    824:                *(int *)data = sc->sc_csbits & RX_DDEN;
                    825:                return (0);
                    826:        }
                    827:        return (ENXIO);
                    828: }
                    829: 
                    830: /*
                    831:  * Initiate a format command.
                    832:  */
                    833: rxformat(dev)
                    834:        dev_t dev;
                    835: {
                    836:        int unit = RXUNIT(dev);
                    837:        struct buf *bp;
                    838:        struct rx_softc *sc = &rx_softc[unit];
                    839:        int s, error = 0;
                    840: 
                    841:        bp = &rrxbuf[unit];
                    842:        bp->b_flags = B_BUSY | B_CTRL;
                    843:        sc->sc_flags = RXF_FORMAT | RXF_LOCK;
                    844:        bp->b_dev = dev;
                    845:        bp->b_error = 0;
                    846:        bp->b_blkno = 0;
                    847:        rxstrategy(bp);
                    848:        iowait(bp);
                    849:        if (bp->b_flags & B_ERROR)
                    850:                error = bp->b_error;
                    851:        bp->b_flags &= ~B_BUSY;
                    852:        sc->sc_flags &= ~RXF_LOCK;
                    853:        return (error);
                    854: }
                    855: 
                    856: /*
                    857:  * A permanent hard error condition has occured,
                    858:  * purge the buffer queue
                    859:  */
                    860: rxpurge(um)
                    861:        register struct uba_ctlr *um;
                    862: {
                    863:        register struct buf *bp, *dp;
                    864: 
                    865:        dp = um->um_tab.b_actf;
                    866:        while (dp->b_actf) {
                    867:                dp->b_errcnt++;
                    868:                bp = dp->b_actf;
                    869:                bp->b_error = EIO;
                    870:                bp->b_flags |= B_ERROR;
                    871:                iodone(bp);
                    872:                dp->b_actf = bp->av_forw;
                    873:        }
                    874: }
                    875: #endif

unix.superglobalmegacorp.com

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