1 /* rk.c 4.30 81/03/17 */ 2 3 #include "rk.h" 4 #if NHK > 0 5 int rkpip; /* DEBUG */ 6 int rknosval; /* DEBUG */ 7 /* 8 * RK11/RK07 disk driver 9 * 10 * This driver mimics up.c; see it for an explanation of common code. 11 * 12 * TODO: 13 * Learn why we lose an interrupt sometime when spinning drives down 14 */ 15 #include "../h/param.h" 16 #include "../h/systm.h" 17 #include "../h/buf.h" 18 #include "../h/conf.h" 19 #include "../h/dir.h" 20 #include "../h/user.h" 21 #include "../h/pte.h" 22 #include "../h/map.h" 23 #include "../h/vm.h" 24 #include "../h/ubareg.h" 25 #include "../h/ubavar.h" 26 #include "../h/dk.h" 27 #include "../h/cpu.h" 28 #include "../h/cmap.h" 29 30 #include "../h/rkreg.h" 31 32 struct rk_softc { 33 int sc_softas; 34 int sc_ndrive; 35 int sc_wticks; 36 int sc_recal; 37 } rk_softc[NHK]; 38 39 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 40 struct size { 41 daddr_t nblocks; 42 int cyloff; 43 } rk7_sizes[] ={ 44 15884, 0, /* A=cyl 0 thru 240 */ 45 10032, 241, /* B=cyl 241 thru 392 */ 46 53790, 0, /* C=cyl 0 thru 814 */ 47 0, 0, 48 0, 0, 49 0, 0, 50 27786, 393, /* G=cyl 393 thru 813 */ 51 0, 0, 52 }; 53 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 54 55 int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 56 struct uba_ctlr *rkminfo[NHK]; 57 struct uba_device *rkdinfo[NRK]; 58 struct uba_device *rkip[NHK][4]; 59 60 u_short rkstd[] = { 0777440, 0 }; 61 struct uba_driver hkdriver = 62 { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 63 struct buf rkutab[NRK]; 64 short rkcyl[NRK]; 65 66 struct rkst { 67 short nsect; 68 short ntrak; 69 short nspc; 70 short ncyl; 71 struct size *sizes; 72 } rkst[] = { 73 NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 74 }; 75 76 u_char rk_offset[16] = 77 { P400,M400,P400,M400,P800,M800,P800,M800,P1200,M1200,P1200,M1200,0,0,0,0 }; 78 79 struct buf rrkbuf[NRK]; 80 81 #define b_cylin b_resid 82 83 #ifdef INTRLVE 84 daddr_t dkblock(); 85 #endif 86 87 int rkwstart, rkwatch(); 88 89 rkprobe(reg) 90 caddr_t reg; 91 { 92 register int br, cvec; 93 94 #ifdef lint 95 br = 0; cvec = br; br = cvec; 96 #endif 97 ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 98 DELAY(10); 99 ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 100 return (1); 101 } 102 103 rkslave(ui, reg) 104 struct uba_device *ui; 105 caddr_t reg; 106 { 107 register struct rkdevice *rkaddr = (struct rkdevice *)reg; 108 109 rkaddr->rkcs1 = RK_CDT|RK_CCLR; 110 rkaddr->rkcs2 = ui->ui_slave; 111 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 112 rkwait(rkaddr); 113 DELAY(50); 114 if (rkaddr->rkcs2&RK_NED || (rkaddr->rkds&RK_SVAL) == 0) { 115 rkaddr->rkcs1 = RK_CDT|RK_CCLR; 116 return (0); 117 } 118 return (1); 119 } 120 121 rkattach(ui) 122 register struct uba_device *ui; 123 { 124 125 if (rkwstart == 0) { 126 timeout(rkwatch, (caddr_t)0, hz); 127 rkwstart++; 128 } 129 if (ui->ui_dk >= 0) 130 dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 131 rkip[ui->ui_ctlr][ui->ui_slave] = ui; 132 rk_softc[ui->ui_ctlr].sc_ndrive++; 133 rkcyl[ui->ui_unit] = -1; 134 } 135 136 rkstrategy(bp) 137 register struct buf *bp; 138 { 139 register struct uba_device *ui; 140 register struct rkst *st; 141 register int unit; 142 register struct buf *dp; 143 int xunit = minor(bp->b_dev) & 07; 144 long bn, sz; 145 146 sz = (bp->b_bcount+511) >> 9; 147 unit = dkunit(bp); 148 if (unit >= NRK) 149 goto bad; 150 ui = rkdinfo[unit]; 151 if (ui == 0 || ui->ui_alive == 0) 152 goto bad; 153 st = &rkst[ui->ui_type]; 154 if (bp->b_blkno < 0 || 155 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 156 goto bad; 157 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 158 (void) spl5(); 159 dp = &rkutab[ui->ui_unit]; 160 disksort(dp, bp); 161 if (dp->b_active == 0) { 162 (void) rkustart(ui); 163 bp = &ui->ui_mi->um_tab; 164 if (bp->b_actf && bp->b_active == 0) 165 (void) rkstart(ui->ui_mi); 166 } 167 (void) spl0(); 168 return; 169 170 bad: 171 bp->b_flags |= B_ERROR; 172 iodone(bp); 173 return; 174 } 175 176 rkustart(ui) 177 register struct uba_device *ui; 178 { 179 register struct buf *bp, *dp; 180 register struct uba_ctlr *um; 181 register struct rkdevice *rkaddr; 182 int didie = 0; 183 184 if (ui == 0) 185 return (0); 186 dk_busy &= ~(1<<ui->ui_dk); 187 dp = &rkutab[ui->ui_unit]; 188 um = ui->ui_mi; 189 rkaddr = (struct rkdevice *)um->um_addr; 190 if (um->um_tab.b_active) { 191 rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 192 return (0); 193 } 194 rkaddr->rkcs1 = RK_CDT|RK_CERR; 195 rkaddr->rkcs2 = ui->ui_slave; 196 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 197 rkwait(rkaddr); 198 if ((bp = dp->b_actf) == NULL) { 199 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 200 rkwait(rkaddr); 201 return (0); 202 } 203 if ((rkaddr->rkds & RK_VV) == 0) { 204 /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 205 rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO; 206 rkwait(rkaddr); 207 } 208 if (dp->b_active) 209 goto done; 210 dp->b_active = 1; 211 if ((rkaddr->rkds & RK_DREADY) != RK_DREADY) 212 goto done; 213 if (rk_softc[um->um_ctlr].sc_ndrive == 1) 214 goto done; 215 if (bp->b_cylin == rkcyl[ui->ui_unit]) 216 goto done; 217 rkaddr->rkcyl = bp->b_cylin; 218 rkcyl[ui->ui_unit] = bp->b_cylin; 219 rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 220 didie = 1; 221 if (ui->ui_dk >= 0) { 222 dk_busy |= 1<<ui->ui_dk; 223 dk_seek[ui->ui_dk]++; 224 } 225 goto out; 226 done: 227 if (dp->b_active != 2) { 228 dp->b_forw = NULL; 229 if (um->um_tab.b_actf == NULL) 230 um->um_tab.b_actf = dp; 231 else 232 um->um_tab.b_actl->b_forw = dp; 233 um->um_tab.b_actl = dp; 234 dp->b_active = 2; 235 } 236 out: 237 return (didie); 238 } 239 240 rkstart(um) 241 register struct uba_ctlr *um; 242 { 243 register struct buf *bp, *dp; 244 register struct uba_device *ui; 245 register struct rkdevice *rkaddr; 246 struct rkst *st; 247 daddr_t bn; 248 int sn, tn, cmd; 249 250 loop: 251 if ((dp = um->um_tab.b_actf) == NULL) 252 return (0); 253 if ((bp = dp->b_actf) == NULL) { 254 um->um_tab.b_actf = dp->b_forw; 255 goto loop; 256 } 257 um->um_tab.b_active++; 258 ui = rkdinfo[dkunit(bp)]; 259 bn = dkblock(bp); 260 st = &rkst[ui->ui_type]; 261 sn = bn%st->nspc; 262 tn = sn/st->nsect; 263 sn %= st->nsect; 264 rkaddr = (struct rkdevice *)ui->ui_addr; 265 retry: 266 rkaddr->rkcs1 = RK_CDT|RK_CERR; 267 rkaddr->rkcs2 = ui->ui_slave; 268 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 269 rkwait(rkaddr); 270 if ((rkaddr->rkds&RK_SVAL) == 0) { 271 rknosval++; 272 goto nosval; 273 } 274 if (rkaddr->rkds&RK_PIP) { 275 rkpip++; 276 goto retry; 277 } 278 if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 279 printf("rk%d: not ready", dkunit(bp)); 280 if ((rkaddr->rkds&RK_DREADY) != RK_DREADY) { 281 printf("\n"); 282 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 283 rkwait(rkaddr); 284 rkaddr->rkcs1 = RK_CDT|RK_CERR; 285 rkwait(rkaddr); 286 um->um_tab.b_active = 0; 287 um->um_tab.b_errcnt = 0; 288 dp->b_actf = bp->av_forw; 289 dp->b_active = 0; 290 bp->b_flags |= B_ERROR; 291 iodone(bp); 292 goto loop; 293 } 294 printf(" (came back!)\n"); 295 } 296 nosval: 297 rkaddr->rkcyl = bp->b_cylin; 298 rkcyl[ui->ui_unit] = bp->b_cylin; 299 rkaddr->rkda = (tn << 8) + sn; 300 rkaddr->rkwc = -bp->b_bcount / sizeof (short); 301 if (bp->b_flags & B_READ) 302 cmd = RK_CDT|RK_IE|RK_READ|RK_GO; 303 else 304 cmd = RK_CDT|RK_IE|RK_WRITE|RK_GO; 305 um->um_cmd = cmd; 306 (void) ubago(ui); 307 return (1); 308 } 309 310 rkdgo(um) 311 register struct uba_ctlr *um; 312 { 313 register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 314 315 rkaddr->rkba = um->um_ubinfo; 316 rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 317 } 318 319 rkintr(rk11) 320 int rk11; 321 { 322 register struct uba_ctlr *um = rkminfo[rk11]; 323 register struct uba_device *ui; 324 register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 325 register struct buf *bp, *dp; 326 int unit; 327 struct rk_softc *sc = &rk_softc[um->um_ctlr]; 328 int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 329 int needie = 1; 330 331 sc->sc_wticks = 0; 332 sc->sc_softas = 0; 333 if (um->um_tab.b_active) { 334 ubadone(um); 335 dp = um->um_tab.b_actf; 336 bp = dp->b_actf; 337 ui = rkdinfo[dkunit(bp)]; 338 dk_busy &= ~(1 << ui->ui_dk); 339 if (rkaddr->rkcs1 & RK_CERR) { 340 int recal; 341 u_short ds = rkaddr->rkds; 342 u_short cs2 = rkaddr->rkcs2; 343 u_short er = rkaddr->rker; 344 if (ds & RK_WLE) { 345 printf("rk%d: write locked\n", dkunit(bp)); 346 bp->b_flags |= B_ERROR; 347 } else if (++um->um_tab.b_errcnt > 28 || 348 ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 349 harderr(bp, "rk"); 350 printf("cs2=%b ds=%b er=%b\n", 351 cs2, RKCS2_BITS, ds, 352 RKDS_BITS, er, RKER_BITS); 353 bp->b_flags |= B_ERROR; 354 sc->sc_recal = 0; 355 } else 356 um->um_tab.b_active = 0; 357 if (cs2&RK_MDS) { 358 rkaddr->rkcs2 = RK_SCLR; 359 goto retry; 360 } 361 recal = 0; 362 if (ds&RK_DROT || er&(RK_OPI|RK_SKI|RK_UNS) || 363 (um->um_tab.b_errcnt&07) == 4) 364 recal = 1; 365 if ((er & (RK_DCK|RK_ECH)) == RK_DCK) 366 if (rkecc(ui)) 367 return; 368 rkaddr->rkcs1 = RK_CDT|RK_CCLR; 369 rkaddr->rkcs2 = ui->ui_slave; 370 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 371 rkwait(rkaddr); 372 if (recal && um->um_tab.b_active == 0) { 373 rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO; 374 rkcyl[ui->ui_unit] = -1; 375 sc->sc_recal = 0; 376 goto nextrecal; 377 } 378 } 379 retry: 380 switch (sc->sc_recal) { 381 382 case 1: 383 rkaddr->rkcyl = bp->b_cylin; 384 rkcyl[ui->ui_unit] = bp->b_cylin; 385 rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO; 386 goto nextrecal; 387 case 2: 388 if (um->um_tab.b_errcnt < 16 || 389 (bp->b_flags&B_READ) == 0) 390 goto donerecal; 391 rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 392 rkaddr->rkcs1 = RK_CDT|RK_IE|RK_OFFSET|RK_GO; 393 /* fall into ... */ 394 nextrecal: 395 sc->sc_recal++; 396 rkwait(rkaddr); 397 um->um_tab.b_active = 1; 398 return; 399 donerecal: 400 case 3: 401 sc->sc_recal = 0; 402 um->um_tab.b_active = 0; 403 break; 404 } 405 if (um->um_tab.b_active) { 406 um->um_tab.b_active = 0; 407 um->um_tab.b_errcnt = 0; 408 um->um_tab.b_actf = dp->b_forw; 409 dp->b_active = 0; 410 dp->b_errcnt = 0; 411 dp->b_actf = bp->av_forw; 412 bp->b_resid = -rkaddr->rkwc * sizeof(short); 413 iodone(bp); 414 if (dp->b_actf) 415 if (rkustart(ui)) 416 needie = 0; 417 } 418 as &= ~(1<<ui->ui_slave); 419 } 420 for (unit = 0; as; as >>= 1, unit++) 421 if (as & 1) { 422 ui = rkip[rk11][unit]; 423 if (ui) { 424 if (rkustart(rkip[rk11][unit])) 425 needie = 0; 426 } else { 427 rkaddr->rkcs1 = RK_CERR|RK_CDT; 428 rkaddr->rkcs2 = unit; 429 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 430 rkwait(rkaddr); 431 } 432 } 433 if (um->um_tab.b_actf && um->um_tab.b_active == 0) 434 if (rkstart(um)) 435 needie = 0; 436 if (needie) 437 rkaddr->rkcs1 = RK_CDT|RK_IE; 438 } 439 440 rkwait(addr) 441 register struct rkdevice *addr; 442 { 443 444 while ((addr->rkcs1 & RK_CRDY) == 0) 445 ; 446 } 447 448 rkread(dev) 449 dev_t dev; 450 { 451 register int unit = minor(dev) >> 3; 452 453 if (unit >= NRK) 454 u.u_error = ENXIO; 455 else 456 physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); 457 } 458 459 rkwrite(dev) 460 dev_t dev; 461 { 462 register int unit = minor(dev) >> 3; 463 464 if (unit >= NRK) 465 u.u_error = ENXIO; 466 else 467 physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); 468 } 469 470 rkecc(ui) 471 register struct uba_device *ui; 472 { 473 register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 474 register struct buf *bp = rkutab[ui->ui_unit].b_actf; 475 register struct uba_ctlr *um = ui->ui_mi; 476 register struct rkst *st; 477 struct uba_regs *ubp = ui->ui_hd->uh_uba; 478 register int i; 479 caddr_t addr; 480 int reg, bit, byte, npf, mask, o, cmd, ubaddr; 481 int bn, cn, tn, sn; 482 483 npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1; 484 reg = btop(um->um_ubinfo&0x3ffff) + npf; 485 o = (int)bp->b_un.b_addr & PGOFSET; 486 printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), 487 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 488 mask = rk->rkec2; 489 ubapurge(um); 490 i = rk->rkec1 - 1; /* -1 makes 0 origin */ 491 bit = i&07; 492 i = (i&~07)>>3; 493 byte = i + o; 494 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 495 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 496 (byte & PGOFSET); 497 putmemc(addr, getmemc(addr)^(mask<<bit)); 498 byte++; 499 i++; 500 bit -= 8; 501 } 502 um->um_tab.b_active++; /* Either complete or continuing... */ 503 if (rk->rkwc == 0) 504 return (0); 505 #ifdef notdef 506 rk->rkcs1 |= RK_GO; 507 #else 508 rk->rkcs1 = RK_CDT|RK_CCLR; 509 rk->rkcs2 = ui->ui_slave; 510 rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 511 rkwait(rk); 512 bn = dkblock(bp); 513 st = &rkst[ui->ui_type]; 514 cn = bp->b_cylin; 515 sn = bn%st->nspc + npf + 1; 516 tn = sn/st->nsect; 517 sn %= st->nsect; 518 cn += tn/st->ntrak; 519 tn %= st->ntrak; 520 rk->rkcyl = cn; 521 rk->rkda = (tn << 8) | sn; 522 ubaddr = (int)ptob(reg+1) + o; 523 rk->rkba = ubaddr; 524 cmd = (ubaddr >> 8) & 0x300; 525 cmd |= RK_CDT|RK_IE|RK_GO|RK_READ; 526 rk->rkcs1 = cmd; 527 #endif 528 return (1); 529 } 530 531 rkreset(uban) 532 int uban; 533 { 534 register struct uba_ctlr *um; 535 register struct uba_device *ui; 536 register rk11, unit; 537 538 for (rk11 = 0; rk11 < NHK; rk11++) { 539 if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 540 um->um_alive == 0) 541 continue; 542 printf(" hk%d", rk11); 543 um->um_tab.b_active = 0; 544 um->um_tab.b_actf = um->um_tab.b_actl = 0; 545 rk_softc[um->um_ctlr].sc_recal = 0; 546 if (um->um_ubinfo) { 547 printf("<%d>", (um->um_ubinfo>>28)&0xf); 548 ubadone(um); 549 } 550 for (unit = 0; unit < NHK; unit++) { 551 if ((ui = rkdinfo[unit]) == 0) 552 continue; 553 if (ui->ui_alive == 0) 554 continue; 555 rkutab[unit].b_active = 0; 556 (void) rkustart(ui); 557 } 558 (void) rkstart(um); 559 } 560 } 561 562 rkwatch() 563 { 564 register struct uba_ctlr *um; 565 register rk11, unit; 566 register struct rk_softc *sc; 567 568 timeout(rkwatch, (caddr_t)0, hz); 569 for (rk11 = 0; rk11 < NHK; rk11++) { 570 um = rkminfo[rk11]; 571 if (um == 0 || um->um_alive == 0) 572 continue; 573 sc = &rk_softc[rk11]; 574 if (um->um_tab.b_active == 0) { 575 for (unit = 0; unit < NRK; unit++) 576 if (rkutab[unit].b_active && 577 rkdinfo[unit]->ui_mi == um) 578 goto active; 579 sc->sc_wticks = 0; 580 continue; 581 } 582 active: 583 sc->sc_wticks++; 584 if (sc->sc_wticks >= 20) { 585 sc->sc_wticks = 0; 586 printf("hk%d: lost interrupt\n", rk11); 587 ubareset(um->um_ubanum); 588 } 589 } 590 } 591 592 #define DBSIZE 20 593 594 rkdump(dev) 595 dev_t dev; 596 { 597 struct rkdevice *rkaddr; 598 char *start; 599 int num, blk, unit; 600 struct size *sizes; 601 register struct uba_regs *uba; 602 register struct uba_device *ui; 603 register short *rp; 604 struct rkst *st; 605 606 unit = minor(dev) >> 3; 607 if (unit >= NRK) 608 return (ENXIO); 609 #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 610 ui = phys(struct uba_device *, rkdinfo[unit]); 611 if (ui->ui_alive == 0) 612 return (ENXIO); 613 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 614 #if VAX780 615 if (cpu == VAX_780) 616 ubainit(uba); 617 #endif 618 rkaddr = (struct rkdevice *)ui->ui_physaddr; 619 num = maxfree; 620 start = 0; 621 rkaddr->rkcs1 = RK_CDT|RK_CERR; 622 rkaddr->rkcs2 = unit; 623 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 624 rkwait(rkaddr); 625 if ((rkaddr->rkds & RK_VV) == 0) { 626 rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO; 627 rkwait(rkaddr); 628 } 629 st = &rkst[ui->ui_type]; 630 sizes = phys(struct size *, st->sizes); 631 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 632 return (EINVAL); 633 while (num > 0) { 634 register struct pte *io; 635 register int i; 636 int cn, sn, tn; 637 daddr_t bn; 638 639 blk = num > DBSIZE ? DBSIZE : num; 640 io = uba->uba_map; 641 for (i = 0; i < blk; i++) 642 *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 643 *(int *)io = 0; 644 bn = dumplo + btop(start); 645 cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 646 sn = bn%st->nspc; 647 tn = sn/st->nsect; 648 sn = sn%st->nsect; 649 rkaddr->rkcyl = cn; 650 rp = (short *) &rkaddr->rkda; 651 *rp = (tn << 8) + sn; 652 *--rp = 0; 653 *--rp = -blk*NBPG / sizeof (short); 654 *--rp = RK_CDT|RK_GO|RK_WRITE; 655 rkwait(rkaddr); 656 if (rkaddr->rkcs1 & RK_CERR) 657 return (EIO); 658 start += blk*NBPG; 659 num -= blk; 660 } 661 return (0); 662 } 663 #endif 664