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