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