1 /* idc.c 4.15 83/05/27 */ 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 873