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