Annotation of researchv9/sys/boot/stand/ar.c, revision 1.1.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.