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