Annotation of researchv9/sys/boot/stand/ar.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)ar.c       1.1 86/02/03    Copyr 1983 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1983 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * Standalone Driver for Archive Intelligent Streaming Tape
        !            11:  */
        !            12: #include "saio.h"
        !            13: #include "param.h"
        !            14: #include "../sundev/arreg.h"
        !            15: #include "ardef.h"
        !            16: 
        !            17: #define        min(a,b)        ((a) < (b) ? (a) : (b))
        !            18: 
        !            19: int ardebug = 0;
        !            20: #define Dprintf  if (ardebug) printf
        !            21: 
        !            22: /* Trace all writes to control reg */
        !            23: #define DebugTrace Dprintf(ar_ctrl_hdr, *(long*)(2+(char*)araddr), ar_bits)
        !            24: 
        !            25: /* Define assorted debugging strings to save repeating them N times */
        !            26: #ifdef DEBUG
        !            27: char ar_bits[] = ARCH_LONG_CTRL_BITS;
        !            28: char ar_ctrl_hdr[] = "ar* Bits: %b\n";
        !            29: char ar_set_hdr[] = "ar* CMD: %x\n";
        !            30: #endif DEBUG
        !            31: char ar_stat_bits[] = ARCH_BITS;
        !            32: 
        !            33: /*
        !            34:  * Standard I/O addresses.
        !            35:  */
        !            36: #define NARADDR        2
        !            37: u_long araddrs[] = { 0x200, 0x208};
        !            38: 
        !            39: /*
        !            40:  * What resources we need to run
        !            41:  */
        !            42: struct devinfo arinfo = {
        !            43:        sizeof (struct ardevice),       /* I/O regs */
        !            44:        0,                              /* no DMA */
        !            45:        sizeof (struct ar_softc),       /* work area */
        !            46:        NARADDR,
        !            47:        araddrs,
        !            48:        MAP_MBIO,
        !            49:        DEV_BSIZE,                      /* transfer size */
        !            50: };
        !            51: 
        !            52: /*
        !            53:  * What facilities we export to the world
        !            54:  */
        !            55: int    aropen(), arclose(), arstrategy();
        !            56: extern int     xxboot(), xxprobe();
        !            57: 
        !            58: struct boottab ardriver = {
        !            59:        "ar",   xxprobe, xxboot, aropen, arclose, arstrategy,
        !            60:        "ar: Multibus Archive tape controller", &arinfo,
        !            61: }; 
        !            62: 
        !            63: /*
        !            64:  * Translation between generic tape commands and initial states of
        !            65:  * the Archive state machine.
        !            66:  */
        !            67: enum ARstates ar_cmds[] = {
        !            68:        /* CLOSE */     CLOSEinit,
        !            69:        /* REWIND */    REWinit,
        !            70:        /* STATUS */    RDSTinit,
        !            71:        /* READ */      READinit,
        !            72:        /* WRITE */     WRinit,
        !            73:        /* WEOF */      WFMinit,
        !            74:        /* ERASE */     ERASEinit,
        !            75:        /* SELECT */    SELinit,
        !            76:        /* DELSELECT */ DESELinit,
        !            77:        /* TENSE */     TENSEinit,
        !            78:        /* SKIPFILE */  RFMinit,
        !            79:        /* CMD OK? */   CMDOKinit,
        !            80: };
        !            81: 
        !            82: 
        !            83: #define SPININIT 1000000
        !            84: /*
        !            85:  * Initialize a controller
        !            86:  */
        !            87: aropen(sip)
        !            88:        register struct saioreq *sip;
        !            89: {
        !            90:        register struct ar_softc *sc;
        !            91:        register int count;
        !            92:        register struct ardevice *araddr;
        !            93:        int skip;
        !            94:        
        !            95:        sc = (struct ar_softc *)sip->si_devdata;
        !            96:        araddr = sc->sc_addr = (struct ardevice *)sip->si_devaddr;
        !            97: 
        !            98:        sc->sc_lastiow = 0;
        !            99:        sc->sc_state = IDLEstate;
        !           100: /*     sc->sc_status = 0;  Doesn't work, so leave it alone. */
        !           101:        sc->sc_size = 0;
        !           102:        sc->sc_bufptr = (char *) 0x1ff001;      /* very funny buf addr */
        !           103: /*     sc->sc_attached had better already be 1. */
        !           104:        sc->sc_initted = 0;                     /* until later */
        !           105:        sc->sc_opened = 0;                      /* until later */
        !           106:        sc->sc_drive = 0;
        !           107:        sc->sc_histate = 0;
        !           108: /*     sc->sc_addr had better already be initialized. */
        !           109:        sc->sc_qidle = 1;
        !           110:        sc->sc_eoflag = 0;
        !           111:        sc->sc_cmdok = 0;
        !           112:        sc->sc_selecteddev = -1;
        !           113: /* When adding new fields to softc, be sure to initialize them here. */
        !           114: /* FIXME, should initialize buffer headers here too */
        !           115: 
        !           116:        araddr->arunwedge = 1;          /* Take it out of burst mode wedge */
        !           117:        araddr->arburst = 0;
        !           118:        araddr->arreq = 0;
        !           119:        araddr->arxfer = 0;
        !           120:        araddr->arcatch = 0;
        !           121:        araddr->arexcie = 0;
        !           122:        araddr->arrdyie = 0;
        !           123: 
        !           124:        /*
        !           125:         * If tape is up from previous system operation,
        !           126:         * take it down gently.
        !           127:         */
        !           128:        if (araddr->aronline) {
        !           129: Dprintf("ar*init tape online\n");
        !           130:                araddr->aronline = 0;   /* Writes TM (if writing) & rewinds */
        !           131:        }
        !           132: 
        !           133:        count = SPININIT;
        !           134:        while (!araddr->arrdy && !araddr->arexc && count)
        !           135:                count--;
        !           136: if (count == 0) Dprintf("ar: Timeout waiting for Ready at %x\n", araddr);
        !           137: 
        !           138: if (araddr->arrdy) Dprintf("ar*init arrdy on before reset\n");
        !           139: if (araddr->arexc) Dprintf("ar*init arexc on before reset\n");
        !           140: 
        !           141:        /* Tape is ready or exceptional.  Reset it for good measure. */
        !           142: #ifdef PRF
        !           143: Dprintf("ar*init about to arreset\n");
        !           144: #endif PRF
        !           145:        araddr->arreset = 1;
        !           146: #ifdef PRF
        !           147: Dprintf("ar*init asserted arreset\n");
        !           148: #endif PRF
        !           149:        DELAY(25);      /* at least 13 usec */
        !           150:        araddr->arreset = 0;
        !           151: #ifdef PRF
        !           152: Dprintf("ar*init Reset complete\n");
        !           153: #endif PRF
        !           154: 
        !           155:        count = SPININIT;
        !           156:        while (!araddr->arexc && count)
        !           157:                count--;
        !           158:        if (count == 0) {
        !           159: Dprintf("ar: Timeout waiting for Exception after reset\n");
        !           160:                return (-1);
        !           161:        }
        !           162: 
        !           163:        /* Now read back status from the reset. */
        !           164:        sc->sc_initted = 1;     /* Must do first so interrupt OK */
        !           165:        sc->sc_opened = 1;      /* Must do first so interrupt OK */
        !           166:        araddr->aronline = 1;   /* Must do first so RDST microcode doesn't
        !           167:                                   play games with arrdy line.  See comments
        !           168:                                   in open(). */
        !           169:        if (arcmd(sc, AR_STATUS)) {
        !           170: Dprintf("ar*init Error from command STATUS\n");
        !           171:                araddr->aronline = 0;
        !           172:                sc->sc_initted = 0;     /* Try again on next open */
        !           173:                sc->sc_opened = 0;      /* Try again on next open */
        !           174:                return (-1);
        !           175:        }
        !           176: 
        !           177:        /*
        !           178:         * FIXME, this is a kludge.  open() won't select the drive unless
        !           179:         * the in-core status claims we are at BOT, since the tape drive
        !           180:         * will reject the command if indeed a tape was in use and is not
        !           181:         * at BOT.  However, tapes at BOT after a Reset do not necessarily
        !           182:         * indicate BOT in their status.  We should probably do a rewind
        !           183:         * here instead, if the tape exists.
        !           184:         */
        !           185:        sc->sc_status.BOT = 1;  /* Pretend we're at BOT for open() */
        !           186: 
        !           187:        /*
        !           188:         * There is a problem in the Archive in that after each command,
        !           189:         * it goes thru a cleanup routine.  If aronline is not asserted,
        !           190:         * this cleanup routine drops arrdy while it rewinds the tape
        !           191:         * to BOT.  It deasserts arrdy for 90 us even if the tape is
        !           192:         * already at BOT.  This causes us problems because we get a arrdy
        !           193:         * interrupt and then discover that arrdy is gone.
        !           194:         *
        !           195:         * The problem has been circumvented at the low level by checking
        !           196:         * for arrdy in the interrupt routine, and looping until it (or
        !           197:         * arexc) comes on.  We attempt to fix the problem here, to avoid
        !           198:         * looping at SPL(), by having aronline always on when we are doing
        !           199:         * anything.
        !           200:         *
        !           201:         * The problem seems especially a problem for us on Select and Read
        !           202:         * Status commands. (That's because those are the only commands we
        !           203:         * do with aronline deasserted.)
        !           204:         *
        !           205:         * This info was obtained from Lou Domshy, Mgr. of Product Mgmt and
        !           206:         * Applications Engineering(?) at the Archive factory, 714-641-0279,
        !           207:         * on 1 December 1982, by John Gilmore of Sun Microsystems.
        !           208:         */
        !           209:        araddr->aronline = 1;           /* Let ctrlr know we are doing a series */
        !           210: 
        !           211:        /*
        !           212:         * First select the drive we're interested in.
        !           213:         *
        !           214:         * Since the select command doesn't work when we aren't at BOT,
        !           215:         * we just have to hope the same drive is still selected as last
        !           216:         * time.  FIXME.  We should record this info in softc and keep it
        !           217:         * up to date.  FIXME: also, I'm not happy about using status.BOT
        !           218:         * here, even tho it should always be up to date. -- JCGnu 22Nov82
        !           219:         */
        !           220:        sc->sc_cmdok = 0;
        !           221:        (void) arcmd(sc, AR_CMDOK);     /* See if OK to issue cmds */
        !           222:        /*
        !           223:         * Now get its status and check on a few things.
        !           224:         */
        !           225:        if (sc->sc_cmdok) {
        !           226:                if (arcmd(sc, AR_STATUS)) {     /* interrupted */
        !           227: Dprintf("ar*open command STATUS error\n");
        !           228:                        goto err;
        !           229:                }
        !           230:                if (sc->sc_status.NoDrive) {
        !           231:                        printf("ar: no drive\n");
        !           232:                        goto err;
        !           233:                }       
        !           234:                if (sc->sc_status.NoCart) {
        !           235:                        printf("ar: no cartridge in drive\n");
        !           236:                        goto err;
        !           237:                }
        !           238:        }
        !           239: 
        !           240:        if ((sip->si_flgs&F_WRITE) && sc->sc_status.WriteProt) {
        !           241:                printf("ar: cartridge is write protected\n");
        !           242:                goto err;
        !           243:        }
        !           244:        sc->sc_lastiow = 0;
        !           245: 
        !           246:        skip = sip->si_boff;
        !           247:        while (skip--) {
        !           248:                arcmd(sc, AR_SKIPFILE);
        !           249:                arcmd(sc, AR_STATUS);
        !           250:        }
        !           251:        sc->sc_eoflag = 0;
        !           252: Dprintf("ar*open exiting\n");
        !           253:        return (0);
        !           254: 
        !           255: err:
        !           256:        arcmd(sc, AR_DESELECT);
        !           257:        araddr->aronline = 0;
        !           258:        sc->sc_opened = 0;
        !           259:        return (-1);
        !           260: }
        !           261: 
        !           262: /*
        !           263:  * Close tape device.
        !           264:  *
        !           265:  * If tape was open for writing or last operation was
        !           266:  * a write, then write two EOF's and backspace over the last one.
        !           267:  * Unless this is a non-rewinding special file, rewind the tape.
        !           268:  * Make the tape available to others.
        !           269:  */
        !           270: arclose(sip)
        !           271:        struct saioreq *sip;
        !           272: {
        !           273:        register struct ar_softc *sc = (struct ar_softc *)sip->si_devdata;
        !           274:        register struct ardevice *araddr = sc->sc_addr;
        !           275: 
        !           276:        /*
        !           277:         * Write file mark and rewind, by dropping aronline.
        !           278:         * FIXME.  These 3 commands should be moved into AR_CLOSE
        !           279:         * in order that the user program can continue while the
        !           280:         * tape is rewinding.
        !           281:         */
        !           282:        arcmd(sc, AR_CLOSE);    /* Shut down things */
        !           283:        araddr->aronline = 1;           /* After rewind, set aronline */
        !           284:        /* See comments in open() about aronline and read status cmds */
        !           285:        /* FIXME, this might screw low level code if it affects arrdy */
        !           286:        arcmd(sc, AR_STATUS);   /* Read block counts */
        !           287:        arcmd(sc, AR_DESELECT); /* Turn LED off */
        !           288:        sc->sc_selecteddev = -1;
        !           289:        sc->sc_eoflag = 0;      /* Not at eof after rewind */
        !           290:        sc->sc_opened = 0;      /* Available to be opened again */
        !           291: Dprintf("ar*close exiting\n");
        !           292: }
        !           293: 
        !           294: arstrategy(sip, rw)
        !           295:        register struct saioreq *sip;
        !           296:        int rw;
        !           297: {
        !           298:        register struct ar_softc *sc = (struct ar_softc *)sip->si_devdata;
        !           299:        int func = (rw == WRITE) ? AR_WRITE : AR_READ;
        !           300: 
        !           301:        if (sc->sc_eoflag) {
        !           302:                sc->sc_eoflag = 0;
        !           303:                return (0);
        !           304:        }
        !           305:        sc->sc_size = sip->si_cc;
        !           306:        sc->sc_bufptr = sip->si_ma;
        !           307:        if (arcmd(sc, func))
        !           308:                return (-1);
        !           309:        return (sip->si_cc);
        !           310: }
        !           311: 
        !           312: /*
        !           313:  * Begin execution of a device command for the device pointed to by
        !           314:  * sc.  The command begins execution in state newstate.
        !           315:  *
        !           316:  * This is HARDWARE oriented software.  It doesn't know or care of
        !           317:  * state of buffers, etc.  Its result reflects what the hardware is
        !           318:  * doing, not what the software is doing.
        !           319:  *
        !           320:  * The device is assumed to be in one of the FIN or IDLE states:
        !           321:  *     IDLEstate, FINstate, READfin, READidle, WRfin, or WRidle.
        !           322:  * This is a requirement, since various fields in sc have already
        !           323:  * been set up for us, and the use of those fields would conflict
        !           324:  * with their use by the interrupt routine if we weren't idle or fin.
        !           325:  *
        !           326:  * Our result is:
        !           327:  *     0       if the operation completed normally
        !           328:  *     1       if the operation completed abnormally
        !           329:  *
        !           330:  */
        !           331: arcmd(sc, cmd)
        !           332:        register struct ar_softc *sc;
        !           333: {
        !           334:        struct ardevice *araddr = sc->sc_addr;
        !           335: 
        !           336:        if (!sc->sc_opened)
        !           337:                return (-1);
        !           338: 
        !           339:        sc->sc_state = ar_cmds[cmd];
        !           340: 
        !           341:        for (;;) {
        !           342:                if (araddr->arexc) {
        !           343:                        /*
        !           344:                         * This interrupt is from the true level of arexc.
        !           345:                         *
        !           346:                         * An error has occurred.  Deal with it somehow.
        !           347:                         * If we are reading status, just do it; else do our own
        !           348:                         * RDST to find out the problem, and cancel the current
        !           349:                         * operation.
        !           350:                         */
        !           351:                        if (sc->sc_state == RDSTinit)
        !           352:                                goto doit;
        !           353:        Dprintf("ar*intr arexc set, old state %x\n", sc->sc_state);
        !           354:                        sc->sc_oldstate = sc->sc_state;
        !           355:                        sc->sc_state = RDSTinit;
        !           356:                        /*
        !           357:                         * Clear EdgeReady and enable it so the next arrdy
        !           358:                         * edge will be caught (possibly inside armachine()).
        !           359:                         */
        !           360:                        araddr->arcatch = 0;
        !           361:                        araddr->arcatch = 1;
        !           362:                        while (!armachine(sc)) {
        !           363:                                /* Shouldn't happen! */
        !           364:                                printf("ar*intr RDST did not return 1\n");
        !           365:                        }
        !           366:                        if (!sc->sc_status.FileMark) {
        !           367:                                printf("ar: error %x\n",
        !           368:                                        *(u_short *)&sc->sc_status);
        !           369:                                return (1);
        !           370:                        }
        !           371:                        /* Eof signaled now means that NEXT block is an EOF. */
        !           372:                        sc->sc_eoflag = 1;
        !           373:                        return (0);
        !           374:                }
        !           375:                if (araddr->arrdy) {
        !           376: 
        !           377:        doit:
        !           378:                        araddr->arcatch = 0;
        !           379:                        araddr->arcatch = 1;
        !           380:                        if (armachine(sc))
        !           381:                                return (0);
        !           382:                }
        !           383:        }
        !           384: }
        !           385: 
        !           386: /*
        !           387:  * State machine for archive tape drive controller.
        !           388:  * This actually accomplishes things w.r.t. the tape drive.
        !           389:  * Returns 0 if operation still in progress, 1 if finished.
        !           390:  * Note that we may take further interrupts after claiming that an
        !           391:  * operation is "finished".  For example, we say a write is done when
        !           392:  * we have transferred the last byte of the block; but there will be
        !           393:  * an interrupt 5.5ms later to tell us it's ok to send the next block.
        !           394:  * Eventually, we will rewind the tape asynchronously after the file is
        !           395:  * closed, letting the user go free while it spins.  FIXME: THIS CANNOT
        !           396:  * BE DONE until we clean up the high level code so it doesn't clobber
        !           397:  * our variables as it is setting up to call arstart_cmd().
        !           398:  */
        !           399: armachine(sc)
        !           400:        register struct ar_softc *sc;
        !           401: {
        !           402:        register struct ardevice *araddr = sc->sc_addr;
        !           403:        register int count, i, x;
        !           404:        register char *byteptr;
        !           405: 
        !           406: Dprintf("ar*machine(%x, %x) state %x\n", sc, araddr, sc->sc_state);
        !           407: 
        !           408:        switch (sc->sc_state) {
        !           409: 
        !           410:        case CMDOKinit:
        !           411:                /*
        !           412:                 * If we got here the command state is ok,
        !           413:                 * i.e., not in the middle of a read or write.
        !           414:                 */
        !           415:                sc->sc_state = IDLEstate;
        !           416:                sc->sc_cmdok = 1;
        !           417:                return (1);
        !           418: 
        !           419:        case CLOSEinit:
        !           420:                /* FIXME, this is time dependent and not documented in
        !           421:                   the Archive manual */
        !           422:                araddr->aronline = 0;           /* Drop online; we're done. */
        !           423:                if (araddr->arrdy)
        !           424:                        goto IdleState; /* No interrupt will occur. */
        !           425:                else
        !           426:                        goto FinState;  /* Rewinding; wait for interrupt. */
        !           427: 
        !           428: #ifdef FIXME
        !           429:        case CLOSEend:
        !           430:                /* This is entered from READidle or WRidle. */
        !           431:                araddr->aronline = 0;           /* Drop it, causing rewind. */
        !           432:                goto FinState;          /* Interrupt will signal end of rew. */
        !           433: #endif
        !           434: 
        !           435:        case WFMinit:
        !           436:                sc->sc_status.BOT = 0;
        !           437:                araddr->ardata = ARCMD_WREOF;
        !           438:                araddr->arreq = 1;
        !           439:                goto CmdState;
        !           440: 
        !           441:        case RFMinit:
        !           442:                araddr->ardata = ARCMD_RDEOF;
        !           443:                araddr->arreq = 1;
        !           444:                goto CmdState;
        !           445: 
        !           446:        case REWinit:
        !           447:                araddr->ardata = ARCMD_REWIND;
        !           448:                araddr->arreq = 1;
        !           449:                goto CmdState;
        !           450: 
        !           451:        case TENSEinit:
        !           452:                araddr->ardata = ARCMD_TENSION;
        !           453:                araddr->arreq = 1;
        !           454:                goto CmdState;
        !           455: 
        !           456:        case ERASEinit:
        !           457:                araddr->ardata = ARCMD_ERASE;
        !           458:                araddr->arreq = 1;
        !           459:                goto CmdState;
        !           460: 
        !           461:        case SELinit:
        !           462:                araddr->ardata = ARCMD_LED | (1 << sc->sc_drive);
        !           463:                araddr->arreq = 1;
        !           464:                goto CmdState;
        !           465: 
        !           466:        case DESELinit:
        !           467:                araddr->ardata = 1 << sc->sc_drive;
        !           468:                araddr->arreq = 1;
        !           469:                goto CmdState;
        !           470: 
        !           471:        RDSTagain:
        !           472:                printf("ar: RDST gave Exception, retrying\n");
        !           473:                /* Fall thru... */
        !           474: 
        !           475:        case RDSTinit:
        !           476:                byteptr = (char *) &sc->sc_status;
        !           477: 
        !           478:                /* We could have either arrdy or arexc; remember which */
        !           479:                count = 0;
        !           480:                if (araddr->arrdy)
        !           481:                        count = 1;
        !           482:                araddr->ardata = ARCMD_RDSTAT;
        !           483:                araddr->arreq = 1;
        !           484: 
        !           485:                /*
        !           486:                 * Now wait for arrdy indicating command accepted.
        !           487:                 * Check for Exception, if we started with arrdy.  
        !           488:                 * (It's not legal to do RDST all the time(!).)
        !           489:                 */
        !           490:                while (!araddr->arrdy)
        !           491:                        if (count && araddr->arexc)
        !           492:                                goto RDSTagain;
        !           493: 
        !           494:                /* Negate arreq, wait for arrdy to drop. */
        !           495:                araddr->arcatch = 0;    /* Clear arrdyedge */
        !           496:                araddr->arcatch = 1;    /* Catch edge */
        !           497:                araddr->arreq = 0;
        !           498: 
        !           499:                /* Now xfer a byte or six. */
        !           500:                do {
        !           501:                        /* Wait for edge of arrdy */
        !           502:                        while (!araddr->arrdyedge)
        !           503:                                if (araddr->arexc)
        !           504:                                        goto RDSTagain;
        !           505:                        *byteptr++ = araddr->ardata;
        !           506:                        araddr->arcatch = 0;    /* Clear edge indicator */
        !           507:                        araddr->arcatch = 1;    /* Catch next one */
        !           508:                        araddr->arreq = 1;      /* Tell controller we have it */
        !           509:                        /* Ready will fall within 250ns of our arreq, but
        !           510:                           we're supposed to keep it high for 20us */
        !           511:                        DELAY(30);      /* at least 20 usec */
        !           512:                        araddr->arreq = 0;
        !           513:                } while (byteptr <
        !           514:                        (char *)(&sc->sc_status) + sizeof (sc->sc_status));
        !           515:                /*
        !           516:                 * On exit from this loop, arcatch has been negated and
        !           517:                 * asserted, so it will correctly reflect the leading edge
        !           518:                 * of arrdy for the next command.
        !           519:                 */
        !           520:                sc->sc_oldstate = sc->sc_state;
        !           521:                sc->sc_state = FINstate;        /* Awaiting final interrupt */
        !           522: 
        !           523: /* Dump status bytes after a command AR_STATUS */
        !           524: 
        !           525: Dprintf("ar*RDST %b %d %d\n", *(unsigned short*)&sc->sc_status,
        !           526:        ar_stat_bits, sc->sc_status.SoftErrs, sc->sc_status.TapeStops);
        !           527: 
        !           528: /* This code is obsolete since sc_qidle, and should be replaceable
        !           529:    by a simple branch to RdWrFin.  However, that doesn't work, so
        !           530:    try this.  JCGnu, 23Nov82 */
        !           531:                while (!araddr->arrdy)
        !           532:                        if (araddr->arexc)
        !           533:                                goto RDSTagain;
        !           534: /* We leave the edge of Ready caught in EdgeReady, but IdleState will
        !           535:    disable interrupts on it. */
        !           536:                goto IdleState;
        !           537: 
        !           538:        case READcmd:
        !           539:        case WRcmd:
        !           540:                araddr->arreq = 0;
        !           541:                goto next;
        !           542: 
        !           543:        case READinit:
        !           544:                araddr->ardata = ARCMD_RDDATA;
        !           545:                araddr->arreq = 1;
        !           546:                goto next;
        !           547: 
        !           548:        case READburst:
        !           549:                /* Read a block of data from the tape drive. */
        !           550: Dprintf("ar*READ addr %x count %x\n", sc->sc_bufptr, sc->sc_size);
        !           551:                sc->sc_status.BOT = 0;
        !           552:                while (!araddr->arrdy) {
        !           553:                        if (araddr->arexc)
        !           554:                                return (0);    /* Not yet done */
        !           555:                        Dprintf("ar*Read no READY\n");
        !           556:                }
        !           557:                araddr->arburst = 1;                    /* Begin block xfer */
        !           558:                count = min(sc->sc_size, AR_BSIZE);
        !           559:                byteptr = sc->sc_bufptr;
        !           560:                for (i=0; i<count; i++)
        !           561:                        *byteptr++ = araddr->ardata; /* read data */
        !           562:                for (; i<AR_BSIZE; i++)
        !           563:                        x = araddr->ardata;     /* read junk */
        !           564:                araddr->arburst = 0;
        !           565:                sc->sc_oldstate = sc->sc_state;
        !           566:                sc->sc_state = READfin;         /* Like FINstate sorta */
        !           567:                break;
        !           568: 
        !           569:        case WRinit:
        !           570:                araddr->ardata = ARCMD_WRDATA;
        !           571:                araddr->arreq = 1;
        !           572:                goto next;
        !           573: 
        !           574:        case WRburst:
        !           575:                /* Write a block of data to the tape drive. */
        !           576: Dprintf("ar*WRITE addr %x count %x\n", sc->sc_bufptr, sc->sc_size);
        !           577:                while (!araddr->arrdy) {
        !           578:                        if (araddr->arexc)
        !           579:                                return (0);             /* Not done yet */
        !           580:                        Dprintf("ar*Write no READY\n");
        !           581:                }
        !           582:                araddr->arburst = 1;                    /* Begin block xfer */
        !           583:                count = AR_BSIZE;
        !           584:                byteptr = sc->sc_bufptr;
        !           585:                while (count--)
        !           586:                        araddr->ardata = *byteptr++;
        !           587:                araddr->arburst = 0;
        !           588:                sc->sc_oldstate = sc->sc_state;
        !           589:                sc->sc_state = WRfin;           /* Like FINstate sorta */
        !           590: Dprintf("ar*machine exiting done in state %x\n", sc->sc_state);
        !           591:                /*
        !           592:                 * This code is a copy of the code at the end of this
        !           593:                 * switch statement, except that it returns 1 (operation
        !           594:                 * completed) instead of 0 (more needs doing)
        !           595:                 */
        !           596:                araddr->arrdyie = 1;
        !           597:                araddr->arexcie = 1;
        !           598:                return (1);
        !           599: 
        !           600:        case CMDstate:
        !           601:                /* All commands that stop interacting once you say "do it" */
        !           602:                araddr->arreq = 0;      /* Done with command */
        !           603:                goto FinState;          /* Final interaction for this cmd */
        !           604: 
        !           605:        IdleState:              /* Drive is idle; set IDLEstate and disable */
        !           606:                sc->sc_oldstate = sc->sc_state;
        !           607:                sc->sc_state = IDLEstate;
        !           608:                goto DisAble;
        !           609: 
        !           610:        case WRfin:             /* Entry after writing a block */
        !           611:        case READfin:           /* Entry after reading a block */
        !           612:        case FINstate:          /* Entry after any other command */
        !           613:                /*
        !           614:                 * Go to next sequential state - WRidle, READidle, IDLEstate.
        !           615:                 * Disable interrupts, and return.  arstart_cmd() will later
        !           616:                 * put us into READ/WRburst or some commandinit state.
        !           617:                 */
        !           618:                sc->sc_oldstate = sc->sc_state;
        !           619:                sc->sc_state = (enum ARstates)(1 +(int)sc->sc_state);
        !           620: DisAble:
        !           621: Dprintf("ar*machine idling\n");
        !           622:                araddr->arrdyie = 0;            /* Negate arrdy interrupt */
        !           623:                return (1);                     /* Tell caller op is done */
        !           624: 
        !           625:        case WRidle:            /* Writing blocks, but none to write now */
        !           626:        case READidle:          /* Reading blocks, but don't need one now */
        !           627:        case IDLEstate:         /* Issuing commands, but don't have one now */
        !           628:                /* This can only happen if software triggers us. */
        !           629:                printf("ar: triggerred at idle %x\n", sc->sc_state);
        !           630:                goto DisAble;   /* Turn off interrupt enable again */
        !           631: 
        !           632:        default:
        !           633:                printf("ar: invalid state %d\n", sc->sc_state);
        !           634:                goto FinState;          /* Is this reasonable? */
        !           635: 
        !           636:        next:
        !           637:                /* Go to next sequential state */
        !           638:                sc->sc_oldstate = sc->sc_state;
        !           639:                sc->sc_state = (enum ARstates)(1 +(int)sc->sc_state);
        !           640:                break;
        !           641: 
        !           642:        FinState:
        !           643:                sc->sc_oldstate = sc->sc_state;
        !           644:                sc->sc_state = FINstate;
        !           645:                break;
        !           646: 
        !           647:        CmdState:
        !           648:                sc->sc_oldstate = sc->sc_state;
        !           649:                sc->sc_state = CMDstate;
        !           650:                break;
        !           651: 
        !           652:        }
        !           653: 
        !           654: Dprintf("ar*machine exiting in state %x\n", sc->sc_state);
        !           655: 
        !           656:        /* Go to next state on the next leading edge of arrdy. */
        !           657:        araddr->arrdyie = 1;    /* Interrupt on arrdy leading edge */
        !           658:        araddr->arexcie = 1;    /* Interrupt on arexc too */
        !           659: /* FIXME.  Figure out where to set and unset, leave alone otherwise. */
        !           660: 
        !           661:        return (0);
        !           662: }

unix.superglobalmegacorp.com

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