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