|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.