Annotation of 42BSD/sys/vaxuba/rx.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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