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