Annotation of 42BSD/sys/vaxuba/rx.c, revision 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.