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