Annotation of 43BSDTahoe/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.2 (Berkeley) 1/28/88
                      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: }
                    229: 
                    230: rxstrategy(bp)
                    231:        register struct buf *bp;
                    232: {
                    233:        struct uba_device *ui;
                    234:        register struct buf *dp;
                    235:        struct rx_softc *sc;
                    236:        int s, unit = RXUNIT(bp->b_dev);
                    237: 
                    238:        if (unit >= NRX)
                    239:                goto bad;
                    240:        ui = rxdinfo[unit];
                    241:        if (ui == 0 || ui->ui_alive == 0) 
                    242:                goto bad;
                    243:        sc = &rx_softc[unit];
                    244:        if (bp->b_blkno < 0 || dbtob(bp->b_blkno) > RXSIZE)
                    245:                goto bad;
                    246:        if (sc->sc_flags & RXF_BAD) {
                    247:                bp->b_error = EIO;
                    248:                goto dbad;
                    249:        }
                    250:        s = spl5();
                    251: #ifdef RXDEBUG
                    252:        printf("rxstrat: bp=0x%x, fl=0x%x, un=%d, bl=%d, cnt=%d\n", 
                    253:                bp, bp->b_flags, unit, bp->b_blkno, bp->b_bcount);
                    254: #endif
                    255:        bp->b_cylin = bp->b_blkno;      /* don't care to calculate trackno */
                    256:        dp = &rxutab[unit];
                    257:        disksort(dp, bp);
                    258:        if (dp->b_active == 0) {
                    259:                rxustart(ui);
                    260:                bp = &ui->ui_mi->um_tab;
                    261:                if (bp->b_actf && bp->b_active == 0)
                    262:                        rxstart(ui->ui_mi);
                    263:        }
                    264:        splx(s);
                    265:        return;
                    266: 
                    267: bad:
                    268:        bp->b_error = ENXIO;
                    269: dbad:
                    270:        bp->b_flags |= B_ERROR;
                    271:        iodone(bp);
                    272:        return;
                    273: }
                    274: 
                    275: /*
                    276:  * Unit start routine.
                    277:  * Put this unit on the ready queue for the controller
                    278:  */
                    279: rxustart(ui)
                    280:        register struct uba_device *ui;
                    281: {
                    282:        struct buf *dp = &rxutab[ui->ui_unit];
                    283:        struct uba_ctlr *um = ui->ui_mi;
                    284:        
                    285:        dp->b_forw = NULL;
                    286:        if (um->um_tab.b_actf == NULL)
                    287:                um->um_tab.b_actf = dp;
                    288:        else
                    289:                um->um_tab.b_actl->b_forw = dp;
                    290:        um->um_tab.b_actl = dp;
                    291:        dp->b_active++;
                    292: }
                    293: /*
                    294:  * Sector mapping routine.
                    295:  * Two independent sets of choices are available:
                    296:  *
                    297:  * (a) The first logical sector may either be on track 1 or track 0.
                    298:  * (b) The sectors on a track may either be taken in 2-for-1 interleaved
                    299:  *      fashion or directly.
                    300:  * This gives a total of four possible mapping schemes.
                    301:  *
                    302:  * Physical tracks on the RX02 are numbered 0-76.  Physical sectors on
                    303:  * each track are numbered 1-26.
                    304:  *
                    305:  * When interleaving is used, sectors on the first logical track are
                    306:  * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26.  A skew of
                    307:  * six sectors per track is also used (to allow time for the heads to
                    308:  * move); hence, the sectors on the second logical track are taken in
                    309:  * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6;
                    310:  * the third logical track starts with sector 13; and so on.
                    311:  *
                    312:  * When the mapping starts with track 1, track 0 is the last logical
                    313:  * track, and this track is always handled directly (without inter-
                    314:  * leaving), even when the rest of the disk is interleaved.  (This is
                    315:  * still compatible with DEC RT-11, which does not use track 0 at all.)
                    316:  */
                    317: rxmap(bp, psector, ptrack)
                    318:        struct buf *bp;
                    319:        int *psector, *ptrack;
                    320: {
                    321:        register int lt, ls, ptoff;
                    322:        struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
                    323: 
                    324:        ls = (dbtob(bp->b_blkno) + (sc->sc_offset - sc->sc_resid)) / NBPS;
                    325:        lt = ls / 26;
                    326:        ls %= 26;
                    327:        /*
                    328:         * The "physical track offset" (ptoff) takes the
                    329:         * starting physical track (0 or 1) and the desired
                    330:         * interleaving into account.  If lt+ptoff >= 77,
                    331:         * then interleaving is not performed.
                    332:         */
                    333:        ptoff = 0;
                    334:        if (sc->sc_flags & RXF_DIRECT)
                    335:                ptoff = 77;
                    336:        if (sc->sc_flags & RXF_TRKONE)
                    337:                ptoff++;
                    338:        if (lt + ptoff < 77)
                    339:                ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
                    340:        *ptrack = (lt + ptoff) % 77;
                    341:        *psector = ls + 1;
                    342: }
                    343: 
                    344: /*
                    345:  * Controller start routine.
                    346:  * Start a new transfer or continue a multisector
                    347:  * transfer. If this is a new transfer (dp->b_active == 1)
                    348:  * save the start address of the data buffer and the total
                    349:  * byte count in the soft control structure. These are
                    350:  * restored into the buffer structure when the transfer has
                    351:  * been completed, before calling 'iodone'.
                    352:  */
                    353: rxstart(um)
                    354:        register struct uba_ctlr *um;
                    355: {
                    356:        register struct rxdevice *rxaddr;
                    357:        register struct rx_ctlr *rxc;
                    358:        register struct rx_softc *sc;
                    359:        struct buf *dp, *bp;
                    360:        int unit, sector, track;
                    361: 
                    362:        if (um->um_tab.b_active)
                    363:                return;
                    364: loop:
                    365:        if ((dp = um->um_tab.b_actf) == NULL)
                    366:                return;
                    367:        if ((bp = dp->b_actf) == NULL) {
                    368:                um->um_tab.b_actf = dp->b_forw;
                    369:                goto loop;
                    370:        }
                    371:        um->um_tab.b_active++;
                    372:        unit = RXUNIT(bp->b_dev);
                    373:        sc = &rx_softc[unit];
                    374:        if (sc->sc_flags & RXF_BAD) {
                    375:                rxpurge(um);
                    376:                return;
                    377:        }
                    378:        if (dp->b_active == 1) {
                    379:                sc->sc_resid = bp->b_bcount;
                    380:                sc->sc_uaddr = bp->b_un.b_addr;
                    381:                sc->sc_bcnt = bp->b_bcount;
                    382:                sc->sc_offset += sc->sc_bcnt;
                    383:                dp->b_active++;
                    384:        }
                    385:        rxaddr = (struct rxdevice *)um->um_addr;
                    386:        rxc = &rx_ctlr[um->um_ctlr];
                    387:        bp->b_bcount = sc->sc_resid;
                    388:        if (bp->b_bcount > NBPS)
                    389:                bp->b_bcount = NBPS;
                    390:        rxc->rxc_tocnt = 0;
                    391: #ifdef RXDEBUG
                    392:        printf("rxstart: ");
                    393: #endif
                    394:        if (rxaddr->rxcs == 0x800) {
                    395:                /*
                    396:                 * 'Volume valid'? (check if the 
                    397:                 * drive unit has been powered down)
                    398:                 */
                    399:                rxaddr->rxcs = RX_INIT;
                    400:                while((rxaddr->rxcs&RX_DONE) == 0)
                    401:                        ;
                    402:        }
                    403:        if (bp->b_flags & B_CTRL) {                             /* format */
                    404:                rxc->rxc_state = RXS_FORMAT;
                    405:                rxaddr->rxcs = RX_FORMAT | sc->sc_csbits;
                    406:                while ((rxaddr->rxcs&RX_TREQ) == 0)
                    407:                        ;
                    408:                rxaddr->rxdb = 'I';
                    409:                return;
                    410:        }
                    411:        if (bp->b_flags & B_RDSTAT) {                   /* read drive status */
                    412:                rxc->rxc_state = RXS_RDSTAT;
                    413:                rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
                    414:                return;
                    415:        }
                    416: 
                    417:        if (bp->b_flags & B_READ) {
                    418:                rxmap(bp, &sector, &track);                     /* read */
                    419: #ifdef RXDEBUG
                    420:                printf("read tr=%d, sc=%d", track, sector);
                    421: #endif
                    422:                rxc->rxc_state = RXS_READ;
                    423:                rxaddr->rxcs = RX_READ | sc->sc_csbits;
                    424:                while ((rxaddr->rxcs&RX_TREQ) == 0)
                    425:                        ;
                    426:                rxaddr->rxdb = (u_short)sector;
                    427:                while ((rxaddr->rxcs&RX_TREQ) == 0)
                    428:                        ;
                    429:                rxaddr->rxdb = (u_short)track;
                    430:        } else {
                    431: #ifdef RXDEBUG
                    432:                printf("write");
                    433: #endif
                    434:                rxc->rxc_state = RXS_FILL;                      /* write */
                    435:                um->um_cmd = RX_FILL;
                    436:                (void) ubago(rxdinfo[unit]);
                    437:        }
                    438: #ifdef RXDEBUG
                    439:        printf("\n");
                    440: #endif
                    441: }
                    442: 
                    443: rxdgo(um)
                    444:        struct uba_ctlr *um;
                    445: {
                    446:        register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
                    447:        int ubinfo = um->um_ubinfo;
                    448:        struct buf *bp = um->um_tab.b_actf->b_actf;
                    449:        struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
                    450:        struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
                    451: 
                    452:        rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
                    453:        if (rxc->rxc_state != RXS_RDERR) {
                    454:                while ((rxaddr->rxcs&RX_TREQ) == 0)
                    455:                        ;
                    456:                rxaddr->rxdb = (u_short) bp->b_bcount >> 1;
                    457:        }
                    458:        while ((rxaddr->rxcs&RX_TREQ) == 0)
                    459:                ;
                    460:        rxaddr->rxdb = (u_short) ubinfo;
                    461: }
                    462: 
                    463: rxintr(ctlr)
                    464:        int ctlr;
                    465: {
                    466:        int unit, sector, track;
                    467:        struct uba_ctlr *um = rxminfo[ctlr];
                    468:        register struct rxdevice *rxaddr;
                    469:        register struct buf *bp, *dp;
                    470:        register struct rx_softc *sc;
                    471:        struct uba_device *ui;
                    472:        struct rxerr *er;
                    473:        struct rx_ctlr *rxc;
                    474: 
                    475:        if (!um->um_tab.b_active)
                    476:                return;
                    477:        dp = um->um_tab.b_actf;
                    478:        if (!dp->b_active)
                    479:                return;
                    480:        bp = dp->b_actf;
                    481:        unit = RXUNIT(bp->b_dev);
                    482:        sc = &rx_softc[unit];
                    483:        ui = rxdinfo[unit];
                    484:        rxaddr = (struct rxdevice *)um->um_addr;
                    485:        rxc = &rx_ctlr[um->um_ctlr];
                    486:        rxc->rxc_tocnt = 0;
                    487:        er = &rxerr[unit];
                    488: #ifdef RXDEBUG
                    489:        printf("rxint: dev=%x, st=%d, cs=0x%x, db=0x%x\n", 
                    490:                bp->b_dev, rxc->rxc_state, rxaddr->rxcs, rxaddr->rxdb);
                    491: #endif
                    492:        if ((rxaddr->rxcs & RX_ERR) &&
                    493:            (rxc->rxc_state != RXS_RDSTAT) && (rxc->rxc_state != RXS_RDERR))
                    494:                goto error;
                    495:        switch (rxc->rxc_state) {
                    496: 
                    497:        /*
                    498:         * Incomplete commands.  Perform next step
                    499:         * and return.  Note that b_active is set on
                    500:         * entrance and, therefore, also on exit.
                    501:         */
                    502:        case RXS_READ:
                    503:                if (rxaddr->rxdb & RXES_DDMARK)
                    504:                        sc->sc_flags |= RXF_DDMK;
                    505:                else
                    506:                        sc->sc_flags &= ~RXF_DDMK;
                    507:                rxc->rxc_state = RXS_EMPTY;
                    508:                um->um_cmd = RX_EMPTY;
                    509:                (void) ubago(ui);
                    510:                return;
                    511: 
                    512:        case RXS_FILL:
                    513:                rxc->rxc_state = RXS_WRITE;
                    514:                if (sc->sc_flags & RXF_USEWDDS) {
                    515:                        rxaddr->rxcs = RX_WDDS | sc->sc_csbits;
                    516:                        sc->sc_flags &= ~RXF_USEWDDS;
                    517:                } else
                    518:                        rxaddr->rxcs = RX_WRITE | sc->sc_csbits;
                    519:                rxmap(bp, &sector, &track);
                    520:                while ((rxaddr->rxcs&RX_TREQ) == 0)
                    521:                        ;
                    522:                rxaddr->rxdb = sector;
                    523:                while ((rxaddr->rxcs&RX_TREQ) == 0)
                    524:                        ;
                    525:                rxaddr->rxdb = track;
                    526:                return;
                    527: 
                    528:        /*
                    529:         * Possibly completed command.
                    530:         */
                    531:        case RXS_RDSTAT:
                    532:                if (bp->b_flags & B_RDSTAT) {
                    533:                        if ((rxaddr->rxdb&RXES_READY) == 0) {
                    534:                                bp->b_flags |= B_ERROR;
                    535:                                bp->b_error = ENODEV;
                    536:                        } else {
                    537:                                sc->sc_csbits |= rxaddr->rxdb&RXES_DBLDEN ?
                    538:                                        RX_DDEN : RX_SDEN;
                    539:                        }
                    540:                        goto rdone;
                    541:                }
                    542:                if (rxaddr->rxdb&RXES_READY)
                    543:                        goto rderr;
                    544:                bp->b_error = ENODEV;
                    545:                bp->b_flags |= B_ERROR;
                    546:                goto done;
                    547: 
                    548:        /*
                    549:         * Command completed.
                    550:         */
                    551:        case RXS_EMPTY:
                    552:        case RXS_WRITE: 
                    553:                goto done;
                    554: 
                    555:        case RXS_FORMAT:
                    556:                goto rdone;
                    557: 
                    558:        case RXS_RDERR:
                    559:                bp = savebp;
                    560:                rxmap(bp, &sector, &track);
                    561:                printf("rx%d: hard error, trk %d psec %d ",
                    562:                        unit, track, sector);
                    563:                printf("cs=%b, db=%b, err=", MASKREG(er->rxcs), 
                    564:                        RXCS_BITS, MASKREG(er->rxdb), RXES_BITS);
                    565:                printf("%x, %x, %x, %x\n", MASKREG(er->rxxt[0]),
                    566:                        MASKREG(er->rxxt[1]), MASKREG(er->rxxt[2]), 
                    567:                        MASKREG(er->rxxt[3]));
                    568:                goto done;
                    569: 
                    570:        default:
                    571:                printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state);
                    572:                rxreset(um->um_ubanum);
                    573:                return;
                    574:        }
                    575: error:
                    576:        /*
                    577:         * In case of an error:
                    578:         *  (a) Give up now if a format (ioctl) was in progress, if a
                    579:         *        density error was detected, or if the drive went offline
                    580:         *  (b) Retry up to nine times if a CRC (data) error was detected,
                    581:         *        then give up if the error persists.
                    582:         *  (c) In all other cases, reinitialize the drive and try the
                    583:         *        operation once more before giving up.
                    584:         */
                    585:        if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR))
                    586:                goto giveup;
                    587:        if (rxaddr->rxdb & RXES_CRCERR) {
                    588:                if (++um->um_tab.b_errcnt >= 10)
                    589:                        goto giveup;
                    590:                goto retry;
                    591:        }
                    592:        um->um_tab.b_errcnt += 9;
                    593:        if (um->um_tab.b_errcnt >= 10)
                    594:                goto giveup;
                    595:        rxaddr->rxcs = RX_INIT;
                    596:        /* no way to get an interrupt for "init done", so just wait */
                    597:        while ((rxaddr->rxcs&RX_DONE) == 0)
                    598:                ;
                    599:        /* if someone opened the drive: give up */
                    600:        if ((rxaddr->rxdb&RXES_READY) == 0)
                    601:                goto giveup;
                    602: retry:
                    603:        /*
                    604:         * In case we already have UNIBUS resources, give
                    605:         * them back since we reallocate things in rxstart.
                    606:         */
                    607:        if (um->um_ubinfo)
                    608:                ubadone(um);
                    609:        um->um_tab.b_active = 0;
                    610:        rxstart(um);
                    611:        return;
                    612: 
                    613: giveup:
                    614:        /*
                    615:         * Hard I/O error --
                    616:         * ALL errors are considered fatal and will abort the
                    617:         * transfer and purge the i/o request queue
                    618:         */
                    619:        sc->sc_flags |= RXF_BAD;
                    620:        sc->sc_resid = 0;       /* make sure the transfer is terminated */
                    621:        rxc->rxc_state = RXS_RDSTAT;
                    622:        rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
                    623:        return;
                    624: 
                    625: rderr:
                    626:        /*
                    627:         * A hard error (other than not ready) has occurred.
                    628:         * Read the extended error status information.
                    629:         * Before doing this, save the current CS and DB register values,
                    630:         * because the read error status operation may modify them.
                    631:         * Insert buffer with request at the head of the queue.
                    632:         */
                    633:        bp->b_error = EIO;
                    634:        bp->b_flags |= B_ERROR;
                    635:        if (um->um_ubinfo)
                    636:                ubadone(um);
                    637:        savebp = bp;
                    638:        er->rxcs = rxaddr->rxcs;
                    639:        er->rxdb = rxaddr->rxdb;
                    640:        bp = &erxbuf[unit];
                    641:        bp->b_un.b_addr = (caddr_t)er->rxxt;
                    642:        bp->b_bcount = sizeof (er->rxxt);
                    643:        bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
                    644:        if (dp->b_actf == NULL)
                    645:                dp->b_actl = bp;
                    646:        bp->b_forw = dp->b_actf;
                    647:        dp->b_actf = bp;
                    648:        rxc->rxc_state = RXS_RDERR;
                    649:        um->um_cmd = RX_RDERR;
                    650:        (void) ubago(ui);
                    651:        return;
                    652: 
                    653: done:
                    654:        ubadone(um);
                    655: rdone:
                    656:        um->um_tab.b_active = 0;
                    657:        um->um_tab.b_errcnt = 0;
                    658:        if ((sc->sc_resid -= NBPS) > 0) {
                    659:                bp->b_un.b_addr += NBPS;
                    660:                rxstart(um);
                    661:                return;
                    662:        }
                    663:        bp->b_un.b_addr = sc->sc_uaddr;
                    664:        bp->b_resid = 0;
                    665:        bp->b_bcount = sc->sc_bcnt;
                    666:        dp->b_actf = bp->av_forw;
                    667:        iodone(bp);
                    668:        sc->sc_offset = 0;
                    669:        rxc->rxc_state = RXS_IDLE;
                    670:        um->um_tab.b_actf = dp->b_forw;
                    671:        dp->b_active = 0;
                    672:        dp->b_errcnt = 0;
                    673: #ifdef RXDEBUG
                    674:        printf(".. bp=%x, new=%x\n", bp, dp->b_actf);
                    675: #endif
                    676:        /*
                    677:         * If this unit has more work to do,
                    678:         * start it up right away
                    679:         */
                    680:        if (dp->b_actf)
                    681:                rxustart(ui);
                    682: 
                    683:        rxstart(um);
                    684: }
                    685: 
                    686: /*ARGSUSED*/
                    687: 
                    688: rxwatch()
                    689: {
                    690:        register struct uba_device *ui;
                    691:        register struct uba_ctlr *um;
                    692:        register struct rx_softc *sc;
                    693:        struct rx_ctlr *rxc;
                    694:        int i, dopen = 0;
                    695: 
                    696:        for (i=0; i<NRX; i++) {
                    697:                ui = rxdinfo[i];
                    698:                if (ui == 0 || ui->ui_alive == 0)
                    699:                        continue;
                    700:                sc = &rx_softc[i];
                    701:                if ((sc->sc_open == 0) && (rxutab[i].b_active == 0)) {
                    702:                        sc->sc_csbits = 0;
                    703:                        continue;
                    704:                }
                    705:                dopen++;
                    706:                um = ui->ui_mi;
                    707:                rxc = &rx_ctlr[um->um_ctlr];
                    708:                if (++rxc->rxc_tocnt >= RX_MAXTIMEOUT) {
                    709:                        rxc->rxc_tocnt = 0;
                    710:                        if (um->um_tab.b_active) {      
                    711:                                printf("rx%d: timeout\n", i);/* for debugging */
                    712:                                rxintr(um->um_ctlr);
                    713:                        }
                    714:                }
                    715:        }
                    716:        if (dopen)
                    717:                timeout(rxwatch, (caddr_t)0, hz);
                    718:        else
                    719:                rxwstart = 0;
                    720: }
                    721: 
                    722: rxreset(uban)
                    723:        int uban;
                    724: {
                    725:        register struct uba_ctlr *um;
                    726:        register struct rxdevice *rxaddr;
                    727:        register int ctlr;
                    728: 
                    729:        for (ctlr = 0; ctlr < NFX; ctlr++) {
                    730:                if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
                    731:                    um->um_alive == 0)
                    732:                        continue;
                    733:                printf(" fx%d", ctlr);
                    734:                if (um->um_ubinfo) {
                    735:                        printf("<%d>", UBAI_BDP(um->um_ubinfo));
                    736:                        um->um_ubinfo = 0;
                    737:                }
                    738:                rx_ctlr[ctlr].rxc_state = RXS_IDLE;
                    739:                rxaddr = (struct rxdevice *)um->um_addr;
                    740:                rxaddr->rxcs = RX_INIT;
                    741:                while ((rxaddr->rxcs&RX_DONE) == 0)
                    742:                        ;
                    743:                rxstart(um);
                    744:        }
                    745: }
                    746: 
                    747: rxread(dev, uio)
                    748:        dev_t dev;
                    749:        struct uio *uio;
                    750: {
                    751:        int unit = RXUNIT(dev);
                    752:        struct rx_softc *sc = &rx_softc[unit];
                    753: 
                    754:        if (uio->uio_offset + uio->uio_resid > RXSIZE)
                    755:                return (ENXIO);
                    756:        if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
                    757:                return (ENXIO);
                    758:        sc->sc_offset = uio->uio_offset % DEV_BSIZE;
                    759:        return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
                    760: }
                    761: 
                    762: rxwrite(dev, uio)
                    763:        dev_t dev;
                    764:        struct uio *uio;
                    765: {
                    766:        int unit = RXUNIT(dev);
                    767:        struct rx_softc *sc = &rx_softc[unit];
                    768: 
                    769:        if (uio->uio_offset + uio->uio_resid > RXSIZE)
                    770:                return (ENXIO);
                    771:        if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
                    772:                return (ENXIO);
                    773:        sc->sc_offset = uio->uio_offset % DEV_BSIZE;
                    774:        return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
                    775: }
                    776: 
                    777: /*
                    778:  * Control routine:
                    779:  * processes four kinds of requests:
                    780:  *
                    781:  *     (1) Set density (i.e., format the diskette) according to 
                    782:  *               that specified data parameter
                    783:  *     (2) Arrange for the next sector to be written with a deleted-
                    784:  *               data mark.
                    785:  *     (3) Report whether the last sector read had a deleted-data mark
                    786:  *     (4) Report the density of the diskette in the indicated drive
                    787:  *         (since the density it automatically determined by the driver,
                    788:  *          this is the only way to let an application program know the
                    789:  *          density)
                    790:  *
                    791:  * Requests relating to deleted-data marks can be handled right here.
                    792:  * A "set density" (format) request, however, must additionally be 
                    793:  * processed through "rxstart", just like a read or write request.
                    794:  */
                    795: 
                    796: /*ARGSUSED3*/
                    797: rxioctl(dev, cmd, data, flag)
                    798:        dev_t dev;
                    799:        caddr_t data;
                    800: {   
                    801:        int unit = RXUNIT(dev);
                    802:        struct rx_softc *sc = &rx_softc[unit];
                    803: 
                    804:        switch (cmd) {
                    805: 
                    806:        case RXIOC_FORMAT:
                    807:                if ((flag&FWRITE) == 0)
                    808:                        return (EBADF);
                    809:                if (sc->sc_open > 1)
                    810:                        return (EBUSY);
                    811:                if (*(int *)data)
                    812:                        sc->sc_csbits |= RX_DDEN;
                    813:                else
                    814:                        sc->sc_csbits &= ~RX_DDEN;
                    815:                return (rxformat(dev));
                    816: 
                    817:        case RXIOC_WDDS:
                    818:                sc->sc_flags |= RXF_USEWDDS;
                    819:                return (0);
                    820: 
                    821:        case RXIOC_RDDSMK:
                    822:                *(int *)data = sc->sc_flags & RXF_DDMK;
                    823:                return (0);
                    824: 
                    825:        case RXIOC_GDENS:
                    826:                *(int *)data = sc->sc_csbits & RX_DDEN;
                    827:                return (0);
                    828:        }
                    829:        return (ENXIO);
                    830: }
                    831: 
                    832: /*
                    833:  * Initiate a format command.
                    834:  */
                    835: rxformat(dev)
                    836:        dev_t dev;
                    837: {
                    838:        int unit = RXUNIT(dev);
                    839:        struct buf *bp;
                    840:        struct rx_softc *sc = &rx_softc[unit];
                    841:        int error = 0;
                    842: 
                    843:        bp = &rrxbuf[unit];
                    844:        bp->b_flags = B_BUSY | B_CTRL;
                    845:        sc->sc_flags = RXF_FORMAT | RXF_LOCK;
                    846:        bp->b_dev = dev;
                    847:        bp->b_error = 0;
                    848:        bp->b_blkno = 0;
                    849:        rxstrategy(bp);
                    850:        iowait(bp);
                    851:        if (bp->b_flags & B_ERROR)
                    852:                error = bp->b_error;
                    853:        bp->b_flags &= ~B_BUSY;
                    854:        sc->sc_flags &= ~RXF_LOCK;
                    855:        return (error);
                    856: }
                    857: 
                    858: /*
                    859:  * A permanent hard error condition has occured,
                    860:  * purge the buffer queue
                    861:  */
                    862: rxpurge(um)
                    863:        register struct uba_ctlr *um;
                    864: {
                    865:        register struct buf *bp, *dp;
                    866: 
                    867:        dp = um->um_tab.b_actf;
                    868:        while (dp->b_actf) {
                    869:                dp->b_errcnt++;
                    870:                bp = dp->b_actf;
                    871:                bp->b_error = EIO;
                    872:                bp->b_flags |= B_ERROR;
                    873:                iodone(bp);
                    874:                dp->b_actf = bp->av_forw;
                    875:        }
                    876: }
                    877: #endif

unix.superglobalmegacorp.com

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