|
|
1.1 ! root 1: /* idc.c 6.1 83/07/29 */ ! 2: ! 3: #include "rb.h" ! 4: #if NIDC > 0 ! 5: int idcdebug = 0; ! 6: #define printd if(idcdebug)printf ! 7: int idctrb[1000]; ! 8: int *trp = idctrb; ! 9: #define trace(a,b) {*trp++ = *(int*)a; *trp++ = (int)b; if(trp>&idctrb[998])trp=idctrb;} ! 10: /* ! 11: * IDC (RB730) disk driver ! 12: * ! 13: * There can only ever be one IDC on a machine, ! 14: * and only on a VAX-11/730. We take advantage ! 15: * of that to simplify the driver. ! 16: * ! 17: * TODO: ! 18: * dk_busy ! 19: * ecc ! 20: */ ! 21: #include "../machine/pte.h" ! 22: ! 23: #include "../h/param.h" ! 24: #include "../h/systm.h" ! 25: #include "../h/buf.h" ! 26: #include "../h/conf.h" ! 27: #include "../h/dir.h" ! 28: #include "../h/user.h" ! 29: #include "../h/map.h" ! 30: #include "../h/vm.h" ! 31: #include "../h/dk.h" ! 32: #include "../h/cmap.h" ! 33: #include "../h/dkbad.h" ! 34: #include "../h/uio.h" ! 35: #include "../h/kernel.h" ! 36: ! 37: #include "../vax/cpu.h" ! 38: #include "../vaxuba/ubareg.h" ! 39: #include "../vaxuba/ubavar.h" ! 40: #include "../vaxuba/idcreg.h" ! 41: ! 42: struct idc_softc { ! 43: int sc_bcnt; /* number of bytes to transfer */ ! 44: int sc_resid; /* total number of bytes to transfer */ ! 45: int sc_ubaddr; /* Unibus address of data */ ! 46: short sc_unit; /* unit doing transfer */ ! 47: short sc_softas; /* software attention summary bits */ ! 48: union idc_dar { ! 49: long dar_l; ! 50: u_short dar_w[2]; ! 51: u_char dar_b[4]; ! 52: } sc_un; /* prototype disk address register */ ! 53: } idc_softc; ! 54: ! 55: #define dar_dar dar_l /* the whole disk address */ ! 56: #define dar_cyl dar_w[1] /* cylinder address */ ! 57: #define dar_trk dar_b[1] /* track */ ! 58: #define dar_sect dar_b[0] /* sector */ ! 59: #define sc_dar sc_un.dar_dar ! 60: #define sc_cyl sc_un.dar_cyl ! 61: #define sc_trk sc_un.dar_trk ! 62: #define sc_sect sc_un.dar_sect ! 63: ! 64: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 65: struct size { ! 66: daddr_t nblocks; ! 67: int cyloff; ! 68: } rb02_sizes[8] ={ ! 69: 15884, 0, /* A=cyl 0 thru 399 */ ! 70: 4480, 400, /* B=cyl 400 thru 510 */ ! 71: 20480, 0, /* C=cyl 0 thru 511 */ ! 72: 0, 0, ! 73: 0, 0, ! 74: 0, 0, ! 75: 0, 0, ! 76: 0, 0, ! 77: }, rb80_sizes[8] ={ ! 78: 15884, 0, /* A=cyl 0 thru 36 */ ! 79: 33440, 37, /* B=cyl 37 thru 114 */ ! 80: 242606, 0, /* C=cyl 0 thru 558 */ ! 81: 0, 0, ! 82: 0, 0, ! 83: 0, 0, ! 84: 82080, 115, /* G=cyl 115 thru 304 */ ! 85: 110143, 305, /* H=cyl 305 thru 558 */ ! 86: }; ! 87: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 88: ! 89: int idcprobe(), idcslave(), idcattach(), idcdgo(), idcintr(); ! 90: struct uba_ctlr *idcminfo[NIDC]; ! 91: struct uba_device *idcdinfo[NRB]; ! 92: ! 93: u_short idcstd[] = { 0174400, 0}; ! 94: struct uba_driver idcdriver = ! 95: { idcprobe, idcslave, idcattach, idcdgo, idcstd, "rb", idcdinfo, "idc", idcminfo, 0 }; ! 96: struct buf idcutab[NRB]; ! 97: union idc_dar idccyl[NRB]; ! 98: ! 99: struct idcst { ! 100: short nbps; ! 101: short nsect; ! 102: short ntrak; ! 103: short nspc; ! 104: short ncyl; ! 105: struct size *sizes; ! 106: } idcst[] = { ! 107: 256, NRB02SECT, NRB02TRK, NRB02SECT*NRB02TRK, NRB02CYL, rb02_sizes, ! 108: 512, NRB80SECT, NRB80TRK, NRB80SECT*NRB80TRK, NRB80CYL, rb80_sizes, ! 109: }; ! 110: ! 111: struct buf ridcbuf[NRB]; ! 112: ! 113: #define b_cylin b_resid ! 114: ! 115: #ifdef INTRLVE ! 116: daddr_t dkblock(); ! 117: #endif ! 118: ! 119: int idcwstart, idcwticks, idcwatch(); ! 120: ! 121: /*ARGSUSED*/ ! 122: idcprobe(reg) ! 123: caddr_t reg; ! 124: { ! 125: register int br, cvec; ! 126: register struct idcdevice *idcaddr; ! 127: ! 128: #ifdef lint ! 129: br = 0; cvec = br; br = cvec; ! 130: #endif ! 131: idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200); ! 132: idcaddr->idccsr = IDC_ATTN|IDC_IE; ! 133: while ((idcaddr->idccsr & IDC_CRDY) == 0) ! 134: ; ! 135: idcaddr->idccsr = IDC_ATTN|IDC_CRDY; ! 136: return (sizeof (struct idcdevice)); ! 137: } ! 138: ! 139: /*ARGSUSED*/ ! 140: idcslave(ui, reg) ! 141: struct uba_device *ui; ! 142: caddr_t reg; ! 143: { ! 144: register struct idcdevice *idcaddr; ! 145: register int i; ! 146: ! 147: idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200); ! 148: ui->ui_type = 0; ! 149: idcaddr->idcmpr = IDCGS_GETSTAT; ! 150: idcaddr->idccsr = IDC_GETSTAT|(ui->ui_slave<<8); ! 151: (void) idcwait(idcaddr, 0); ! 152: i = idcaddr->idcmpr; ! 153: idcaddr->idccsr = IDC_CRDY|(1<<(ui->ui_slave+16)); ! 154: /* read header to synchronize microcode */ ! 155: (void) idcwait(idcaddr, 0); ! 156: idcaddr->idccsr = (ui->ui_slave<<8)|IDC_RHDR; ! 157: (void) idcwait(idcaddr, 0); ! 158: if (idcaddr->idccsr & IDC_ERR) ! 159: return (0); ! 160: i = idcaddr->idcmpr; /* read header word 1 */ ! 161: i = idcaddr->idcmpr; /* read header word 2 */ ! 162: #ifdef lint ! 163: i = i; ! 164: #endif ! 165: if (idcaddr->idccsr&IDC_R80) ! 166: ui->ui_type = 1; ! 167: return (1); ! 168: } ! 169: ! 170: idcattach(ui) ! 171: register struct uba_device *ui; ! 172: { ! 173: ! 174: /* ! 175: * Fix all addresses to correspond ! 176: * to the "real" IDC address. ! 177: */ ! 178: ui->ui_mi->um_addr = ui->ui_addr = (caddr_t)uba_hd[0].uh_uba + 0x200; ! 179: ui->ui_physaddr = (caddr_t)uba_hd[0].uh_physuba + 0x200; ! 180: if (idcwstart == 0) { ! 181: timeout(idcwatch, (caddr_t)0, hz); ! 182: idcwstart++; ! 183: } ! 184: if (ui->ui_dk >= 0) ! 185: if (ui->ui_type) ! 186: dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB80SECT * 256); ! 187: else ! 188: dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB02SECT * 128); ! 189: idccyl[ui->ui_unit].dar_dar = -1; ! 190: ui->ui_flags = 0; ! 191: } ! 192: ! 193: idcopen(dev) ! 194: dev_t dev; ! 195: { ! 196: register int unit = minor(dev) >> 3; ! 197: register struct uba_device *ui; ! 198: ! 199: if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0) ! 200: return (ENXIO); ! 201: return (0); ! 202: } ! 203: ! 204: idcstrategy(bp) ! 205: register struct buf *bp; ! 206: { ! 207: register struct uba_device *ui; ! 208: register struct idcst *st; ! 209: register int unit; ! 210: register struct buf *dp; ! 211: int xunit = minor(bp->b_dev) & 07; ! 212: long bn, sz; ! 213: ! 214: sz = (bp->b_bcount+511) >> 9; ! 215: unit = dkunit(bp); ! 216: if (unit >= NRB) ! 217: goto bad; ! 218: ui = idcdinfo[unit]; ! 219: if (ui == 0 || ui->ui_alive == 0) ! 220: goto bad; ! 221: st = &idcst[ui->ui_type]; ! 222: if (bp->b_blkno < 0 || ! 223: (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) ! 224: goto bad; ! 225: if (ui->ui_type == 0) ! 226: bn *= 2; ! 227: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; ! 228: (void) spl5(); ! 229: trace("strt",bp); ! 230: dp = &idcutab[ui->ui_unit]; ! 231: disksort(dp, bp); ! 232: if (dp->b_active == 0) { ! 233: trace("!act",dp); ! 234: (void) idcustart(ui); ! 235: bp = &ui->ui_mi->um_tab; ! 236: if (bp->b_actf && bp->b_active == 0) ! 237: (void) idcstart(ui->ui_mi); ! 238: } ! 239: (void) spl0(); ! 240: return; ! 241: ! 242: bad: ! 243: bp->b_flags |= B_ERROR; ! 244: iodone(bp); ! 245: return; ! 246: } ! 247: ! 248: idcustart(ui) ! 249: register struct uba_device *ui; ! 250: { ! 251: register struct buf *bp, *dp; ! 252: register struct uba_ctlr *um; ! 253: register struct idcdevice *idcaddr; ! 254: register struct idcst *st; ! 255: union idc_dar cyltrk; ! 256: daddr_t bn; ! 257: int unit; ! 258: ! 259: if (ui == 0) ! 260: return (0); ! 261: dk_busy &= ~(1<<ui->ui_dk); ! 262: dp = &idcutab[ui->ui_unit]; ! 263: um = ui->ui_mi; ! 264: unit = ui->ui_slave; ! 265: trace("ust", dp); ! 266: idcaddr = (struct idcdevice *)um->um_addr; ! 267: if (um->um_tab.b_active) { ! 268: idc_softc.sc_softas |= 1<<unit; ! 269: trace("umac",idc_softc.sc_softas); ! 270: return (0); ! 271: } ! 272: if ((bp = dp->b_actf) == NULL) { ! 273: trace("!bp",0); ! 274: return (0); ! 275: } ! 276: if (dp->b_active) { ! 277: trace("dpac",dp->b_active); ! 278: goto done; ! 279: } ! 280: dp->b_active = 1; ! 281: /* CHECK DRIVE READY? */ ! 282: bn = dkblock(bp); ! 283: trace("seek", bn); ! 284: if (ui->ui_type == 0) ! 285: bn *= 2; ! 286: st = &idcst[ui->ui_type]; ! 287: cyltrk.dar_cyl = bp->b_cylin; ! 288: cyltrk.dar_trk = (bn / st->nsect) % st->ntrak; ! 289: cyltrk.dar_sect = 0; ! 290: printd("idcustart, unit %d, cyltrk 0x%x\n", unit, cyltrk.dar_dar); ! 291: /* ! 292: * If on cylinder, no need to seek. ! 293: */ ! 294: if (cyltrk.dar_dar == idccyl[ui->ui_unit].dar_dar) ! 295: goto done; ! 296: /* ! 297: * RB80 can change heads (tracks) just by loading ! 298: * the disk address register, perform optimization ! 299: * here instead of doing a full seek. ! 300: */ ! 301: if (ui->ui_type && cyltrk.dar_cyl == idccyl[ui->ui_unit].dar_cyl) { ! 302: idcaddr->idccsr = IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8); ! 303: idcaddr->idcdar = cyltrk.dar_dar; ! 304: idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar; ! 305: goto done; ! 306: } ! 307: /* ! 308: * Need to do a full seek. Select the unit, clear ! 309: * its attention bit, set the command, load the ! 310: * disk address register, and then go. ! 311: */ ! 312: idcaddr->idccsr = ! 313: IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16)); ! 314: idcaddr->idcdar = cyltrk.dar_dar; ! 315: idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar; ! 316: printd(" seek"); ! 317: idcaddr->idccsr = IDC_IE|IDC_SEEK|(unit<<8); ! 318: if (ui->ui_dk >= 0) { ! 319: dk_busy |= 1<<ui->ui_dk; ! 320: dk_seek[ui->ui_dk]++; ! 321: } ! 322: /* ! 323: * RB80's initiate seeks very quickly. Wait for it ! 324: * to come ready rather than taking the interrupt. ! 325: */ ! 326: if (ui->ui_type) { ! 327: if (idcwait(idcaddr, 10) == 0) ! 328: return (1); ! 329: idcaddr->idccsr &= ~IDC_ATTN; ! 330: /* has the seek completed? */ ! 331: if (idcaddr->idccsr & IDC_DRDY) { ! 332: printd(", drdy"); ! 333: idcaddr->idccsr = ! 334: IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16)); ! 335: goto done; ! 336: } ! 337: } ! 338: printd(", idccsr = 0x%x\n", idcaddr->idccsr); ! 339: return (1); ! 340: done: ! 341: if (dp->b_active != 2) { ! 342: trace("!=2",dp->b_active); ! 343: dp->b_forw = NULL; ! 344: if (um->um_tab.b_actf == NULL) ! 345: um->um_tab.b_actf = dp; ! 346: else { ! 347: trace("!NUL",um->um_tab.b_actl); ! 348: um->um_tab.b_actl->b_forw = dp; ! 349: } ! 350: um->um_tab.b_actl = dp; ! 351: dp->b_active = 2; ! 352: } ! 353: return (0); ! 354: } ! 355: ! 356: idcstart(um) ! 357: register struct uba_ctlr *um; ! 358: { ! 359: register struct buf *bp, *dp; ! 360: register struct uba_device *ui; ! 361: register struct idcdevice *idcaddr; ! 362: register struct idc_softc *sc; ! 363: struct idcst *st; ! 364: daddr_t bn; ! 365: int sn, tn, cmd; ! 366: ! 367: loop: ! 368: if ((dp = um->um_tab.b_actf) == NULL) { ! 369: trace("nodp",um); ! 370: return (0); ! 371: } ! 372: if ((bp = dp->b_actf) == NULL) { ! 373: trace("nobp", dp); ! 374: um->um_tab.b_actf = dp->b_forw; ! 375: goto loop; ! 376: } ! 377: um->um_tab.b_active = 1; ! 378: ui = idcdinfo[dkunit(bp)]; ! 379: bn = dkblock(bp); ! 380: trace("star",bp); ! 381: if (ui->ui_type == 0) ! 382: bn *= 2; ! 383: sc = &idc_softc; ! 384: st = &idcst[ui->ui_type]; ! 385: sn = bn%st->nspc; ! 386: tn = sn/st->nsect; ! 387: sn %= st->nsect; ! 388: sc->sc_sect = sn; ! 389: sc->sc_trk = tn; ! 390: sc->sc_cyl = bp->b_cylin; ! 391: idcaddr = (struct idcdevice *)ui->ui_addr; ! 392: printd("idcstart, unit %d, dar 0x%x", ui->ui_slave, sc->sc_dar); ! 393: if (bp->b_flags & B_READ) ! 394: cmd = IDC_IE|IDC_READ|(ui->ui_slave<<8); ! 395: else ! 396: cmd = IDC_IE|IDC_WRITE|(ui->ui_slave<<8); ! 397: idcaddr->idccsr = IDC_CRDY|cmd; ! 398: if ((idcaddr->idccsr&IDC_DRDY) == 0) { ! 399: printf("rb%d: not ready\n", dkunit(bp)); ! 400: um->um_tab.b_active = 0; ! 401: um->um_tab.b_errcnt = 0; ! 402: dp->b_actf = bp->av_forw; ! 403: dp->b_active = 0; ! 404: bp->b_flags |= B_ERROR; ! 405: iodone(bp); ! 406: goto loop; ! 407: } ! 408: idccyl[ui->ui_unit].dar_dar = sc->sc_dar; ! 409: idccyl[ui->ui_unit].dar_sect = 0; ! 410: sn = (st->nsect - sn) * st->nbps; ! 411: if (sn > bp->b_bcount) ! 412: sn = bp->b_bcount; ! 413: sc->sc_bcnt = sn; ! 414: sc->sc_resid = bp->b_bcount; ! 415: sc->sc_unit = ui->ui_slave; ! 416: printd(", bcr 0x%x, cmd 0x%x\n", sn, cmd); ! 417: um->um_cmd = cmd; ! 418: (void) ubago(ui); ! 419: return (1); ! 420: } ! 421: ! 422: idcdgo(um) ! 423: register struct uba_ctlr *um; ! 424: { ! 425: register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr; ! 426: register struct idc_softc *sc = &idc_softc; ! 427: ! 428: /* ! 429: * VERY IMPORTANT: must load registers in this order. ! 430: */ ! 431: idcaddr->idcbar = sc->sc_ubaddr = um->um_ubinfo&0x3ffff; ! 432: idcaddr->idcbcr = -sc->sc_bcnt; ! 433: idcaddr->idcdar = sc->sc_dar; ! 434: printd("idcdgo, ubinfo 0x%x, cmd 0x%x\n", um->um_ubinfo, um->um_cmd); ! 435: idcaddr->idccsr = um->um_cmd; ! 436: trace("go", um); ! 437: um->um_tab.b_active = 2; ! 438: /*** CLEAR SPURIOUS ATTN ON R80? ***/ ! 439: } ! 440: ! 441: idcintr(idc) ! 442: int idc; ! 443: { ! 444: register struct uba_ctlr *um = idcminfo[idc]; ! 445: register struct uba_device *ui; ! 446: register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr; ! 447: register struct idc_softc *sc = &idc_softc; ! 448: register struct buf *bp, *dp; ! 449: struct idcst *st; ! 450: int unit, as, er, cmd, ds = 0; ! 451: ! 452: printd("idcintr, idccsr 0x%x", idcaddr->idccsr); ! 453: top: ! 454: idcwticks = 0; ! 455: trace("intr", um->um_tab.b_active); ! 456: if (um->um_tab.b_active == 2) { ! 457: /* ! 458: * Process a data transfer complete interrupt. ! 459: */ ! 460: um->um_tab.b_active = 1; ! 461: dp = um->um_tab.b_actf; ! 462: bp = dp->b_actf; ! 463: ui = idcdinfo[dkunit(bp)]; ! 464: unit = ui->ui_slave; ! 465: st = &idcst[ui->ui_type]; ! 466: idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8); ! 467: if ((er = idcaddr->idccsr) & IDC_ERR) { ! 468: if (er & IDC_DE) { ! 469: idcaddr->idcmpr = IDCGS_GETSTAT; ! 470: idcaddr->idccsr = IDC_GETSTAT|(unit<<8); ! 471: (void) idcwait(idcaddr, 0); ! 472: ds = idcaddr->idcmpr; ! 473: idcaddr->idccsr = ! 474: IDC_IE|IDC_CRDY|(1<<(unit+16)); ! 475: } ! 476: printd(", er 0x%x, ds 0x%x", er, ds); ! 477: if (ds & IDCDS_WL) { ! 478: printf("rb%d: write locked\n", dkunit(bp)); ! 479: bp->b_flags |= B_ERROR; ! 480: } else if (++um->um_tab.b_errcnt > 28 || er&IDC_HARD) { ! 481: hard: ! 482: harderr(bp, "rb"); ! 483: printf("csr=%b ds=%b\n", er, IDCCSR_BITS, ds, ! 484: ui->ui_type?IDCRB80DS_BITS:IDCRB02DS_BITS); ! 485: bp->b_flags |= B_ERROR; ! 486: } else if (er & IDC_DCK) { ! 487: switch (er & IDC_ECS) { ! 488: case IDC_ECS_NONE: ! 489: break; ! 490: case IDC_ECS_SOFT: ! 491: idcecc(ui); ! 492: break; ! 493: case IDC_ECS_HARD: ! 494: default: ! 495: goto hard; ! 496: } ! 497: } else ! 498: /* recoverable error, set up for retry */ ! 499: goto seek; ! 500: } ! 501: if ((sc->sc_resid -= sc->sc_bcnt) != 0) { ! 502: sc->sc_ubaddr += sc->sc_bcnt; ! 503: /* ! 504: * Current transfer is complete, have ! 505: * we overflowed to the next track? ! 506: */ ! 507: if ((sc->sc_sect += sc->sc_bcnt/st->nbps) == st->nsect) { ! 508: sc->sc_sect = 0; ! 509: if (++sc->sc_trk == st->ntrak) { ! 510: sc->sc_trk = 0; ! 511: sc->sc_cyl++; ! 512: } else if (ui->ui_type) { ! 513: /* ! 514: * RB80 can change heads just by ! 515: * loading the disk address register. ! 516: */ ! 517: idcaddr->idccsr = IDC_SEEK|IDC_CRDY| ! 518: IDC_IE|(unit<<8); ! 519: printd(", change to track 0x%x", sc->sc_dar); ! 520: idcaddr->idcdar = sc->sc_dar; ! 521: idccyl[ui->ui_unit].dar_dar = sc->sc_dar; ! 522: idccyl[ui->ui_unit].dar_sect = 0; ! 523: goto cont; ! 524: } ! 525: /* ! 526: * Changing tracks on RB02 or cylinders ! 527: * on RB80, start a seek. ! 528: */ ! 529: seek: ! 530: cmd = IDC_IE|IDC_SEEK|(unit<<8); ! 531: idcaddr->idccsr = cmd|IDC_CRDY; ! 532: idcaddr->idcdar = sc->sc_dar; ! 533: printd(", seek to 0x%x\n", sc->sc_dar); ! 534: idccyl[ui->ui_unit].dar_dar = sc->sc_dar; ! 535: idccyl[ui->ui_unit].dar_sect = 0; ! 536: sc->sc_bcnt = 0; ! 537: idcaddr->idccsr = cmd; ! 538: if (ui->ui_type) { ! 539: if (idcwait(idcaddr, 10) == 0) ! 540: return; ! 541: idcaddr->idccsr &= ~IDC_ATTN; ! 542: if (idcaddr->idccsr & IDC_DRDY) ! 543: goto top; ! 544: } ! 545: } else { ! 546: /* ! 547: * Continue transfer on current track. ! 548: */ ! 549: cont: ! 550: sc->sc_bcnt = (st->nsect-sc->sc_sect)*st->nbps; ! 551: if (sc->sc_bcnt > sc->sc_resid) ! 552: sc->sc_bcnt = sc->sc_resid; ! 553: if (bp->b_flags & B_READ) ! 554: cmd = IDC_IE|IDC_READ|(unit<<8); ! 555: else ! 556: cmd = IDC_IE|IDC_WRITE|(unit<<8); ! 557: idcaddr->idccsr = cmd|IDC_CRDY; ! 558: idcaddr->idcbar = sc->sc_ubaddr; ! 559: idcaddr->idcbcr = -sc->sc_bcnt; ! 560: idcaddr->idcdar = sc->sc_dar; ! 561: printd(", continue I/O 0x%x, 0x%x\n", sc->sc_dar, sc->sc_bcnt); ! 562: idcaddr->idccsr = cmd; ! 563: um->um_tab.b_active = 2; ! 564: } ! 565: return; ! 566: } ! 567: /* ! 568: * Entire transfer is done, clean up. ! 569: */ ! 570: ubadone(um); ! 571: dk_busy &= ~(1 << ui->ui_dk); ! 572: um->um_tab.b_active = 0; ! 573: um->um_tab.b_errcnt = 0; ! 574: um->um_tab.b_actf = dp->b_forw; ! 575: dp->b_active = 0; ! 576: dp->b_errcnt = 0; ! 577: dp->b_actf = bp->av_forw; ! 578: trace("done", dp); trace(&um->um_tab.b_actf, dp->b_actf); ! 579: bp->b_resid = sc->sc_resid; ! 580: printd(", iodone, resid 0x%x\n", bp->b_resid); ! 581: iodone(bp); ! 582: if (dp->b_actf) ! 583: if (idcustart(ui)) ! 584: return; ! 585: } else if (um->um_tab.b_active == 1) { ! 586: /* ! 587: * Got an interrupt while setting up for a command ! 588: * or doing a mid-transfer seek. Save any attentions ! 589: * for later and process a mid-transfer seek complete. ! 590: */ ! 591: as = idcaddr->idccsr; ! 592: idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN); ! 593: as = (as >> 16) & 0xf; ! 594: unit = sc->sc_unit; ! 595: sc->sc_softas |= as & ~(1<<unit); ! 596: if (as & (1<<unit)) { ! 597: printd(", seek1 complete"); ! 598: um->um_tab.b_active = 2; ! 599: goto top; ! 600: } ! 601: printd(", as1 %o\n", as); ! 602: return; ! 603: } ! 604: /* ! 605: * Process any seek initiated or complete interrupts. ! 606: */ ! 607: as = idcaddr->idccsr; ! 608: idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN); ! 609: as = ((as >> 16) & 0xf) | sc->sc_softas; ! 610: sc->sc_softas = 0; ! 611: trace("as", as); ! 612: printd(", as %o", as); ! 613: for (unit = 0; unit < NRB; unit++) ! 614: if (as & (1<<unit)) { ! 615: as &= ~(1<<unit); ! 616: idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8); ! 617: ui = idcdinfo[unit]; ! 618: if (ui) { ! 619: printd(", attn unit %d", unit); ! 620: if (idcaddr->idccsr & IDC_DRDY) ! 621: if (idcustart(ui)) { ! 622: sc->sc_softas = as; ! 623: return; ! 624: } ! 625: } else { ! 626: printd(", unsol. intr. unit %d", unit); ! 627: } ! 628: } ! 629: printd("\n"); ! 630: if (um->um_tab.b_actf && um->um_tab.b_active == 0) { ! 631: trace("stum",um->um_tab.b_actf); ! 632: (void) idcstart(um); ! 633: } ! 634: } ! 635: ! 636: idcwait(addr, n) ! 637: register struct idcdevice *addr; ! 638: register int n; ! 639: { ! 640: register int i; ! 641: ! 642: while (--n && (addr->idccsr & IDC_CRDY) == 0) ! 643: for (i = 10; i; i--) ! 644: ; ! 645: return (n); ! 646: } ! 647: ! 648: idcread(dev, uio) ! 649: dev_t dev; ! 650: struct uio *uio; ! 651: { ! 652: register int unit = minor(dev) >> 3; ! 653: ! 654: if (unit >= NRB) ! 655: return (ENXIO); ! 656: return (physio(idcstrategy, &ridcbuf[unit], dev, B_READ, minphys, uio)); ! 657: } ! 658: ! 659: idcwrite(dev, uio) ! 660: dev_t dev; ! 661: struct uio *uio; ! 662: { ! 663: register int unit = minor(dev) >> 3; ! 664: ! 665: if (unit >= NRB) ! 666: return (ENXIO); ! 667: return (physio(idcstrategy, &ridcbuf[unit], dev, B_WRITE, minphys, uio)); ! 668: } ! 669: ! 670: idcecc(ui) ! 671: register struct uba_device *ui; ! 672: { ! 673: register struct idcdevice *idc = (struct idcdevice *)ui->ui_addr; ! 674: register struct buf *bp = idcutab[ui->ui_unit].b_actf; ! 675: register struct uba_ctlr *um = ui->ui_mi; ! 676: register struct idcst *st; ! 677: register int i; ! 678: struct uba_regs *ubp = ui->ui_hd->uh_uba; ! 679: int bit, byte, mask; ! 680: caddr_t addr; ! 681: int reg, npf, o; ! 682: int cn, tn, sn; ! 683: ! 684: printf("idcecc: HELP!\n"); ! 685: npf = btop(idc->idcbcr + idc_softc.sc_bcnt) - 1;; ! 686: reg = btop(idc_softc.sc_ubaddr) + npf; ! 687: o = (int)bp->b_un.b_addr & PGOFSET; ! 688: st = &idcst[ui->ui_type]; ! 689: cn = idc_softc.sc_cyl; ! 690: tn = idc_softc.sc_trk; ! 691: sn = idc_softc.sc_sect; ! 692: um->um_tab.b_active = 1; /* Either complete or continuing... */ ! 693: printf("rb%d%c: soft ecc sn%d\n", dkunit(bp), ! 694: 'a'+(minor(bp->b_dev)&07), ! 695: (cn*st->ntrak + tn) * st->nsect + sn + npf); ! 696: mask = idc->idceccpat; ! 697: i = idc->idceccpos - 1; /* -1 makes 0 origin */ ! 698: bit = i&07; ! 699: i = (i&~07)>>3; ! 700: byte = i + o; ! 701: while (i < 512 && (int)ptob(npf)+i < idc_softc.sc_bcnt && bit > -11) { ! 702: addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ ! 703: (byte & PGOFSET); ! 704: putmemc(addr, getmemc(addr)^(mask<<bit)); ! 705: byte++; ! 706: i++; ! 707: bit -= 8; ! 708: } ! 709: idc_softc.sc_bcnt += idc->idcbcr; ! 710: um->um_tab.b_errcnt = 0; /* error has been corrected */ ! 711: return; ! 712: } ! 713: ! 714: idcreset(uban) ! 715: int uban; ! 716: { ! 717: register struct uba_ctlr *um; ! 718: register struct uba_device *ui; ! 719: register unit; ! 720: ! 721: if ((um = idcminfo[0]) == 0 || um->um_ubanum != uban || ! 722: um->um_alive == 0) ! 723: return; ! 724: printf(" idc0"); ! 725: um->um_tab.b_active = 0; ! 726: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 727: if (um->um_ubinfo) { ! 728: printf("<%d>", (um->um_ubinfo>>28)&0xf); ! 729: um->um_ubinfo = 0; ! 730: } ! 731: for (unit = 0; unit < NRB; unit++) { ! 732: if ((ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0) ! 733: continue; ! 734: idcutab[unit].b_active = 0; ! 735: (void) idcustart(ui); ! 736: } ! 737: (void) idcstart(um); ! 738: } ! 739: ! 740: idcwatch() ! 741: { ! 742: register struct uba_ctlr *um; ! 743: register unit; ! 744: ! 745: timeout(idcwatch, (caddr_t)0, hz); ! 746: um = idcminfo[0]; ! 747: if (um == 0 || um->um_alive == 0) ! 748: return; ! 749: if (um->um_tab.b_active == 0) { ! 750: for (unit = 0; unit < NRB; unit++) ! 751: if (idcutab[unit].b_active) ! 752: goto active; ! 753: idcwticks = 0; ! 754: return; ! 755: } ! 756: active: ! 757: idcwticks++; ! 758: if (idcwticks >= 20) { ! 759: idcwticks = 0; ! 760: printf("idc0: lost interrupt\n"); ! 761: idcintr(0); ! 762: } ! 763: } ! 764: ! 765: /*ARGSUSED*/ ! 766: idcdump(dev) ! 767: dev_t dev; ! 768: { ! 769: struct idcdevice *idcaddr; ! 770: char *start; ! 771: int num, blk, unit; ! 772: struct size *sizes; ! 773: register struct uba_regs *uba; ! 774: register struct uba_device *ui; ! 775: struct idcst *st; ! 776: union idc_dar dar; ! 777: int nspg; ! 778: ! 779: unit = minor(dev) >> 3; ! 780: if (unit >= NRB) ! 781: return (ENXIO); ! 782: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ! 783: ui = phys(struct uba_device *, idcdinfo[unit]); ! 784: if (ui->ui_alive == 0) ! 785: return (ENXIO); ! 786: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ! 787: ubainit(uba); ! 788: idcaddr = (struct idcdevice *)ui->ui_physaddr; ! 789: if (idcwait(idcaddr, 100) == 0) ! 790: return (EFAULT); ! 791: /* ! 792: * Since we can only transfer one track at a time, and ! 793: * the rl02 has 256 byte sectors, all the calculations ! 794: * are done in terms of physical sectors (i.e. num and blk ! 795: * are in sectors not NBPG blocks. ! 796: */ ! 797: st = phys(struct idcst *, &idcst[ui->ui_type]); ! 798: sizes = phys(struct size *, st->sizes); ! 799: if (dumplo < 0 || dumplo + maxfree >= sizes[minor(dev)&07].nblocks) ! 800: return (EINVAL); ! 801: nspg = NBPG / st->nbps; ! 802: num = maxfree * nspg; ! 803: start = 0; ! 804: ! 805: while (num > 0) { ! 806: register struct pte *io; ! 807: register int i; ! 808: daddr_t bn; ! 809: ! 810: bn = (dumplo + btop(start)) * nspg; ! 811: dar.dar_cyl = bn / st->nspc + sizes[minor(dev)&07].cyloff; ! 812: bn %= st->nspc; ! 813: dar.dar_trk = bn / st->nsect; ! 814: dar.dar_sect = bn % st->nsect; ! 815: blk = st->nsect - dar.dar_sect; ! 816: if (num < blk) ! 817: blk = num; ! 818: ! 819: io = uba->uba_map; ! 820: for (i = 0; i < (blk + nspg - 1) / nspg; i++) ! 821: *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; ! 822: *(int *)io = 0; ! 823: ! 824: idcaddr->idccsr = IDC_CRDY | IDC_SEEK | unit<<8; ! 825: if ((idcaddr->idccsr&IDC_DRDY) == 0) ! 826: return (EFAULT); ! 827: idcaddr->idcdar = dar.dar_dar; ! 828: idcaddr->idccsr = IDC_SEEK | unit << 8; ! 829: while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY)) ! 830: != (IDC_CRDY|IDC_DRDY)) ! 831: ; ! 832: if (idcaddr->idccsr & IDC_ERR) { ! 833: printf("rb%d: seek, csr=%b\n", ! 834: unit, idcaddr->idccsr, IDCCSR_BITS); ! 835: return (EIO); ! 836: } ! 837: ! 838: idcaddr->idccsr = IDC_CRDY | IDC_WRITE | unit<<8; ! 839: if ((idcaddr->idccsr&IDC_DRDY) == 0) ! 840: return (EFAULT); ! 841: idcaddr->idcbar = 0; /* start addr 0 */ ! 842: idcaddr->idcbcr = - (blk * st->nbps); ! 843: idcaddr->idcdar = dar.dar_dar; ! 844: idcaddr->idccsr = IDC_WRITE | unit << 8; ! 845: while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY)) ! 846: != (IDC_CRDY|IDC_DRDY)) ! 847: ; ! 848: if (idcaddr->idccsr & IDC_ERR) { ! 849: printf("rb%d: write, csr=%b\n", ! 850: unit, idcaddr->idccsr, IDCCSR_BITS); ! 851: return (EIO); ! 852: } ! 853: ! 854: start += blk * st->nbps; ! 855: num -= blk; ! 856: } ! 857: return (0); ! 858: } ! 859: ! 860: idcsize(dev) ! 861: dev_t dev; ! 862: { ! 863: int unit = minor(dev) >> 3; ! 864: struct uba_device *ui; ! 865: struct idcst *st; ! 866: ! 867: if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0) ! 868: return (-1); ! 869: st = &idcst[ui->ui_type]; ! 870: return (st->sizes[minor(dev) & 07].nblocks); ! 871: } ! 872: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.