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