1 /* up.c 4.62 82/12/05 */ 2 3 #include "up.h" 4 #if NSC > 0 5 /* 6 * UNIBUS disk driver with: 7 * overlapped seeks, 8 * ECC recovery, and 9 * bad sector forwarding. 10 * 11 * TODO: 12 * Check that offset recovery code works 13 */ 14 15 #include "../h/param.h" 16 #include "../h/systm.h" 17 #include "../h/dk.h" 18 #include "../h/dkbad.h" 19 #include "../h/buf.h" 20 #include "../h/conf.h" 21 #include "../h/dir.h" 22 #include "../h/user.h" 23 #include "../h/map.h" 24 #include "../h/pte.h" 25 #include "../h/vm.h" 26 #include "../h/cmap.h" 27 #include "../h/uio.h" 28 29 #include "../vax/cpu.h" 30 #include "../vax/nexus.h" 31 #include "../vaxuba/ubavar.h" 32 #include "../vaxuba/ubareg.h" 33 #include "../vaxuba/upreg.h" 34 35 struct up_softc { 36 int sc_softas; 37 int sc_ndrive; 38 int sc_wticks; 39 int sc_recal; 40 } up_softc[NSC]; 41 42 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 43 struct size 44 { 45 daddr_t nblocks; 46 int cyloff; 47 } up_sizes[8] = { 48 #ifdef ERNIE 49 49324, 0, /* A=cyl 0 thru 26 */ 50 #else 51 15884, 0, /* A=cyl 0 thru 26 */ 52 #endif 53 33440, 27, /* B=cyl 27 thru 81 */ 54 495520, 0, /* C=cyl 0 thru 814 */ 55 15884, 562, /* D=cyl 562 thru 588 */ 56 55936, 589, /* E=cyl 589 thru 680 */ 57 #ifndef NOBADSECT 58 81376, 681, /* F=cyl 681 thru 814 */ 59 153728, 562, /* G=cyl 562 thru 814 */ 60 #else 61 81472, 681, 62 153824, 562, 63 #endif 64 291346, 82, /* H=cyl 82 thru 561 */ 65 }, fj_sizes[8] = { 66 15884, 0, /* A=cyl 0 thru 49 */ 67 33440, 50, /* B=cyl 50 thru 154 */ 68 263360, 0, /* C=cyl 0 thru 822 */ 69 0, 0, 70 0, 0, 71 0, 0, 72 0, 0, 73 #ifndef NOBADSECT 74 213664, 155, /* H=cyl 155 thru 822 */ 75 #else 76 213760, 155, 77 #endif 78 }, upam_sizes[8] = { 79 15884, 0, /* A=cyl 0 thru 31 */ 80 33440, 32, /* B=cyl 32 thru 97 */ 81 524288, 0, /* C=cyl 0 thru 1023 */ 82 27786, 668, 83 27786, 723, 84 125440, 778, 85 181760, 668, /* G=cyl 668 thru 1022 */ 86 291346, 98, /* H=cyl 98 thru 667 */ 87 }; 88 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 89 90 /* 91 * On a 780 upSDIST could be 2, but 92 * in the interest of 750's... 93 */ 94 #define _upSDIST 3 /* 1.5 msec */ 95 #define _upRDIST 4 /* 2.0 msec */ 96 97 int upSDIST = _upSDIST; 98 int upRDIST = _upRDIST; 99 100 int upprobe(), upslave(), upattach(), updgo(), upintr(); 101 struct uba_ctlr *upminfo[NSC]; 102 struct uba_device *updinfo[NUP]; 103 #define UPIPUNITS 8 104 struct uba_device *upip[NSC][UPIPUNITS]; /* fuji w/fixed head gives n,n+4 */ 105 106 u_short upstd[] = { 0776700, 0774400, 0776300, 0 }; 107 struct uba_driver scdriver = 108 { upprobe, upslave, upattach, updgo, upstd, "up", updinfo, "sc", upminfo }; 109 struct buf uputab[NUP]; 110 char upinit[NUP]; 111 112 struct upst { 113 short nsect; 114 short ntrak; 115 short nspc; 116 short ncyl; 117 struct size *sizes; 118 } upst[] = { 119 32, 19, 32*19, 823, up_sizes, /* 9300/cdc */ 120 /* 9300 actually has 815 cylinders... */ 121 32, 10, 32*10, 823, fj_sizes, /* fujitsu 160m */ 122 32, 16, 32*16, 1024, upam_sizes, /* ampex capricorn */ 123 }; 124 125 u_char up_offset[16] = { 126 UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400, 127 UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800, 128 UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200, 129 0, 0, 0, 0 130 }; 131 132 struct buf rupbuf[NUP]; 133 #ifndef NOBADSECT 134 struct buf bupbuf[NUP]; 135 struct dkbad upbad[NUP]; 136 #endif 137 138 #define b_cylin b_resid 139 140 #ifdef INTRLVE 141 daddr_t dkblock(); 142 #endif 143 144 int upwstart, upwatch(); /* Have started guardian */ 145 int upseek; 146 int upwaitdry; 147 148 /*ARGSUSED*/ 149 upprobe(reg) 150 caddr_t reg; 151 { 152 register int br, cvec; 153 154 #ifdef lint 155 br = 0; cvec = br; br = cvec; 156 #endif 157 ((struct updevice *)reg)->upcs1 = UP_IE|UP_RDY; 158 DELAY(10); 159 ((struct updevice *)reg)->upcs1 = 0; 160 return (sizeof (struct updevice)); 161 } 162 163 upslave(ui, reg) 164 struct uba_device *ui; 165 caddr_t reg; 166 { 167 register struct updevice *upaddr = (struct updevice *)reg; 168 169 upaddr->upcs1 = 0; /* conservative */ 170 upaddr->upcs2 = ui->ui_slave; 171 upaddr->upcs1 = UP_NOP|UP_GO; 172 if (upaddr->upcs2&UPCS2_NED) { 173 upaddr->upcs1 = UP_DCLR|UP_GO; 174 return (0); 175 } 176 return (1); 177 } 178 179 upattach(ui) 180 register struct uba_device *ui; 181 { 182 register struct updevice *upaddr; 183 184 if (upwstart == 0) { 185 timeout(upwatch, (caddr_t)0, hz); 186 upwstart++; 187 } 188 if (ui->ui_dk >= 0) 189 dk_mspw[ui->ui_dk] = .0000020345; 190 upip[ui->ui_ctlr][ui->ui_slave] = ui; 191 up_softc[ui->ui_ctlr].sc_ndrive++; 192 upaddr = (struct updevice *)ui->ui_addr; 193 upaddr->upcs1 = 0; 194 upaddr->upcs2 = ui->ui_slave; 195 upaddr->uphr = UPHR_MAXTRAK; 196 if (upaddr->uphr == 9) 197 ui->ui_type = 1; /* fujitsu hack */ 198 else if (upaddr->uphr == 15) 199 ui->ui_type = 2; /* ampex hack */ 200 upaddr->upcs2 = UPCS2_CLR; 201 } 202 203 upopen(dev) 204 dev_t dev; 205 { 206 register int unit = minor(dev) >> 3; 207 register struct uba_device *ui; 208 209 if (unit >= NUP || (ui = updinfo[unit]) == 0 || ui->ui_alive == 0) 210 return (ENXIO); 211 return (0); 212 } 213 214 upstrategy(bp) 215 register struct buf *bp; 216 { 217 register struct uba_device *ui; 218 register struct upst *st; 219 register int unit; 220 register struct buf *dp; 221 int xunit = minor(bp->b_dev) & 07; 222 long bn, sz; 223 224 sz = (bp->b_bcount+511) >> 9; 225 unit = dkunit(bp); 226 if (unit >= NUP) 227 goto bad; 228 ui = updinfo[unit]; 229 if (ui == 0 || ui->ui_alive == 0) 230 goto bad; 231 st = &upst[ui->ui_type]; 232 if (bp->b_blkno < 0 || 233 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 234 goto bad; 235 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 236 (void) spl5(); 237 dp = &uputab[ui->ui_unit]; 238 disksort(dp, bp); 239 if (dp->b_active == 0) { 240 (void) upustart(ui); 241 bp = &ui->ui_mi->um_tab; 242 if (bp->b_actf && bp->b_active == 0) 243 (void) upstart(ui->ui_mi); 244 } 245 (void) spl0(); 246 return; 247 248 bad: 249 bp->b_flags |= B_ERROR; 250 iodone(bp); 251 return; 252 } 253 254 /* 255 * Unit start routine. 256 * Seek the drive to be where the data is 257 * and then generate another interrupt 258 * to actually start the transfer. 259 * If there is only one drive on the controller, 260 * or we are very close to the data, don't 261 * bother with the search. If called after 262 * searching once, don't bother to look where 263 * we are, just queue for transfer (to avoid 264 * positioning forever without transferrring.) 265 */ 266 upustart(ui) 267 register struct uba_device *ui; 268 { 269 register struct buf *bp, *dp; 270 register struct uba_ctlr *um; 271 register struct updevice *upaddr; 272 register struct upst *st; 273 daddr_t bn; 274 int sn, csn; 275 /* 276 * The SC21 cancels commands if you just say 277 * cs1 = UP_IE 278 * so we are cautious about handling of cs1. 279 * Also don't bother to clear as bits other than in upintr(). 280 */ 281 int didie = 0; 282 283 if (ui == 0) 284 return (0); 285 um = ui->ui_mi; 286 dk_busy &= ~(1<<ui->ui_dk); 287 dp = &uputab[ui->ui_unit]; 288 if ((bp = dp->b_actf) == NULL) 289 goto out; 290 /* 291 * If the controller is active, just remember 292 * that this device would like to be positioned... 293 * if we tried to position now we would confuse the SC21. 294 */ 295 if (um->um_tab.b_active) { 296 up_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 297 return (0); 298 } 299 /* 300 * If we have already positioned this drive, 301 * then just put it on the ready queue. 302 */ 303 if (dp->b_active) 304 goto done; 305 dp->b_active = 1; 306 upaddr = (struct updevice *)um->um_addr; 307 upaddr->upcs2 = ui->ui_slave; 308 /* 309 * If drive has just come up, 310 * setup the pack. 311 */ 312 if ((upaddr->upds & UPDS_VV) == 0 || upinit[ui->ui_unit] == 0) { 313 #ifndef NOBADSECT 314 struct buf *bbp = &bupbuf[ui->ui_unit]; 315 #endif 316 /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 317 upinit[ui->ui_unit] = 1; 318 upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO; 319 upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO; 320 upaddr->upof = UPOF_FMT22; 321 didie = 1; 322 #ifndef NOBADSECT 323 st = &upst[ui->ui_type]; 324 bbp->b_flags = B_READ|B_BUSY; 325 bbp->b_dev = bp->b_dev; 326 bbp->b_bcount = 512; 327 bbp->b_un.b_addr = (caddr_t)&upbad[ui->ui_unit]; 328 bbp->b_blkno = st->ncyl * st->nspc - st->nsect; 329 bbp->b_cylin = st->ncyl - 1; 330 dp->b_actf = bbp; 331 bbp->av_forw = bp; 332 bp = bbp; 333 #endif 334 } 335 /* 336 * If drive is offline, forget about positioning. 337 */ 338 if ((upaddr->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL)) 339 goto done; 340 /* 341 * If there is only one drive, 342 * dont bother searching. 343 */ 344 if (up_softc[um->um_ctlr].sc_ndrive == 1) 345 goto done; 346 /* 347 * Figure out where this transfer is going to 348 * and see if we are close enough to justify not searching. 349 */ 350 st = &upst[ui->ui_type]; 351 bn = dkblock(bp); 352 sn = bn%st->nspc; 353 sn = (sn + st->nsect - upSDIST) % st->nsect; 354 if (bp->b_cylin - upaddr->updc) 355 goto search; /* Not on-cylinder */ 356 else if (upseek) 357 goto done; /* Ok just to be on-cylinder */ 358 csn = (upaddr->upla>>6) - sn - 1; 359 if (csn < 0) 360 csn += st->nsect; 361 if (csn > st->nsect - upRDIST) 362 goto done; 363 search: 364 upaddr->updc = bp->b_cylin; 365 /* 366 * Not on cylinder at correct position, 367 * seek/search. 368 */ 369 if (upseek) 370 upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO; 371 else { 372 upaddr->upda = sn; 373 upaddr->upcs1 = UP_IE|UP_SEARCH|UP_GO; 374 } 375 didie = 1; 376 /* 377 * Mark unit busy for iostat. 378 */ 379 if (ui->ui_dk >= 0) { 380 dk_busy |= 1<<ui->ui_dk; 381 dk_seek[ui->ui_dk]++; 382 } 383 goto out; 384 done: 385 /* 386 * Device is ready to go. 387 * Put it on the ready queue for the controller 388 * (unless its already there.) 389 */ 390 if (dp->b_active != 2) { 391 dp->b_forw = NULL; 392 if (um->um_tab.b_actf == NULL) 393 um->um_tab.b_actf = dp; 394 else 395 um->um_tab.b_actl->b_forw = dp; 396 um->um_tab.b_actl = dp; 397 dp->b_active = 2; 398 } 399 out: 400 return (didie); 401 } 402 403 /* 404 * Start up a transfer on a drive. 405 */ 406 upstart(um) 407 register struct uba_ctlr *um; 408 { 409 register struct buf *bp, *dp; 410 register struct uba_device *ui; 411 register struct updevice *upaddr; 412 struct upst *st; 413 daddr_t bn; 414 int dn, sn, tn, cmd, waitdry; 415 416 loop: 417 /* 418 * Pull a request off the controller queue 419 */ 420 if ((dp = um->um_tab.b_actf) == NULL) 421 return (0); 422 if ((bp = dp->b_actf) == NULL) { 423 um->um_tab.b_actf = dp->b_forw; 424 goto loop; 425 } 426 /* 427 * Mark controller busy, and 428 * determine destination of this request. 429 */ 430 um->um_tab.b_active++; 431 ui = updinfo[dkunit(bp)]; 432 bn = dkblock(bp); 433 dn = ui->ui_slave; 434 st = &upst[ui->ui_type]; 435 sn = bn%st->nspc; 436 tn = sn/st->nsect; 437 sn %= st->nsect; 438 upaddr = (struct updevice *)ui->ui_addr; 439 /* 440 * Select drive if not selected already. 441 */ 442 if ((upaddr->upcs2&07) != dn) 443 upaddr->upcs2 = dn; 444 /* 445 * Check that it is ready and online 446 */ 447 waitdry = 0; 448 while ((upaddr->upds&UPDS_DRY) == 0) { 449 printf("up%d: ds wait ds=%o\n",dkunit(bp),upaddr->upds); 450 if (++waitdry > 512) 451 break; 452 upwaitdry++; 453 } 454 if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { 455 printf("up%d: not ready", dkunit(bp)); 456 if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { 457 printf("\n"); 458 um->um_tab.b_active = 0; 459 um->um_tab.b_errcnt = 0; 460 dp->b_actf = bp->av_forw; 461 dp->b_active = 0; 462 bp->b_flags |= B_ERROR; 463 iodone(bp); 464 goto loop; 465 } 466 /* 467 * Oh, well, sometimes this 468 * happens, for reasons unknown. 469 */ 470 printf(" (flakey)\n"); 471 } 472 /* 473 * Setup for the transfer, and get in the 474 * UNIBUS adaptor queue. 475 */ 476 upaddr->updc = bp->b_cylin; 477 upaddr->upda = (tn << 8) + sn; 478 upaddr->upwc = -bp->b_bcount / sizeof (short); 479 if (bp->b_flags & B_READ) 480 cmd = UP_IE|UP_RCOM|UP_GO; 481 else 482 cmd = UP_IE|UP_WCOM|UP_GO; 483 um->um_cmd = cmd; 484 (void) ubago(ui); 485 return (1); 486 } 487 488 /* 489 * Now all ready to go, stuff the registers. 490 */ 491 updgo(um) 492 struct uba_ctlr *um; 493 { 494 register struct updevice *upaddr = (struct updevice *)um->um_addr; 495 496 um->um_tab.b_active = 2; /* should now be 2 */ 497 upaddr->upba = um->um_ubinfo; 498 upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 499 } 500 501 /* 502 * Handle a disk interrupt. 503 */ 504 upintr(sc21) 505 register sc21; 506 { 507 register struct buf *bp, *dp; 508 register struct uba_ctlr *um = upminfo[sc21]; 509 register struct uba_device *ui; 510 register struct updevice *upaddr = (struct updevice *)um->um_addr; 511 register unit; 512 struct up_softc *sc = &up_softc[um->um_ctlr]; 513 int as = (upaddr->upas & 0377) | sc->sc_softas; 514 int needie = 1, waitdry; 515 516 sc->sc_wticks = 0; 517 sc->sc_softas = 0; 518 /* 519 * If controller wasn't transferring, then this is an 520 * interrupt for attention status on seeking drives. 521 * Just service them. 522 */ 523 if (um->um_tab.b_active != 2 && !sc->sc_recal) { 524 if (upaddr->upcs1 & UP_TRE) 525 upaddr->upcs1 = UP_TRE; 526 goto doattn; 527 } 528 um->um_tab.b_active = 1; 529 /* 530 * Get device and block structures, and a pointer 531 * to the uba_device for the drive. Select the drive. 532 */ 533 dp = um->um_tab.b_actf; 534 bp = dp->b_actf; 535 ui = updinfo[dkunit(bp)]; 536 dk_busy &= ~(1 << ui->ui_dk); 537 if ((upaddr->upcs2&07) != ui->ui_slave) 538 upaddr->upcs2 = ui->ui_slave; 539 #ifndef NOBADSECT 540 if (bp->b_flags&B_BAD) { 541 if (upecc(ui, CONT)) 542 return; 543 } 544 #endif 545 /* 546 * Check for and process errors on 547 * either the drive or the controller. 548 */ 549 if ((upaddr->upds&UPDS_ERR) || (upaddr->upcs1&UP_TRE)) { 550 waitdry = 0; 551 while ((upaddr->upds & UPDS_DRY) == 0) { 552 if (++waitdry > 512) 553 break; 554 upwaitdry++; 555 } 556 if (upaddr->uper1&UPER1_WLE) { 557 /* 558 * Give up on write locked devices 559 * immediately. 560 */ 561 printf("up%d: write locked\n", dkunit(bp)); 562 bp->b_flags |= B_ERROR; 563 } else if (++um->um_tab.b_errcnt > 27) { 564 /* 565 * After 28 retries (16 without offset, and 566 * 12 with offset positioning) give up. 567 */ 568 hard: 569 harderr(bp, "up"); 570 printf("cn=%d tn=%d sn=%d cs2=%b er1=%b er2=%b\n", 571 upaddr->updc, ((upaddr->upda)>>8)&077, 572 (upaddr->upda)&037, 573 upaddr->upcs2, UPCS2_BITS, 574 upaddr->uper1, UPER1_BITS, 575 upaddr->uper2, UPER2_BITS); 576 bp->b_flags |= B_ERROR; 577 } else if (upaddr->uper2 & UPER2_BSE) { 578 #ifndef NOBADSECT 579 if (upecc(ui, BSE)) 580 return; 581 else 582 #endif 583 goto hard; 584 } else { 585 /* 586 * Retriable error. 587 * If a soft ecc, correct it (continuing 588 * by returning if necessary. 589 * Otherwise fall through and retry the transfer 590 */ 591 if ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK) { 592 if (upecc(ui, ECC)) 593 return; 594 } else 595 um->um_tab.b_active = 0; /* force retry */ 596 } 597 /* 598 * Clear drive error and, every eight attempts, 599 * (starting with the fourth) 600 * recalibrate to clear the slate. 601 */ 602 upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO; 603 needie = 0; 604 if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) { 605 upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO; 606 sc->sc_recal = 0; 607 goto nextrecal; 608 } 609 } 610 /* 611 * Advance recalibration finite state machine 612 * if recalibrate in progress, through 613 * RECAL 614 * SEEK 615 * OFFSET (optional) 616 * RETRY 617 */ 618 switch (sc->sc_recal) { 619 620 case 1: 621 upaddr->updc = bp->b_cylin; 622 upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO; 623 goto nextrecal; 624 case 2: 625 if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0) 626 goto donerecal; 627 upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UPOF_FMT22; 628 upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO; 629 goto nextrecal; 630 nextrecal: 631 sc->sc_recal++; 632 um->um_tab.b_active = 1; 633 return; 634 donerecal: 635 case 3: 636 sc->sc_recal = 0; 637 um->um_tab.b_active = 0; 638 break; 639 } 640 /* 641 * If still ``active'', then don't need any more retries. 642 */ 643 if (um->um_tab.b_active) { 644 /* 645 * If we were offset positioning, 646 * return to centerline. 647 */ 648 if (um->um_tab.b_errcnt >= 16) { 649 upaddr->upof = UPOF_FMT22; 650 upaddr->upcs1 = UP_RTC|UP_GO|UP_IE; 651 while (upaddr->upds & UPDS_PIP) 652 DELAY(25); 653 needie = 0; 654 } 655 um->um_tab.b_active = 0; 656 um->um_tab.b_errcnt = 0; 657 um->um_tab.b_actf = dp->b_forw; 658 dp->b_active = 0; 659 dp->b_errcnt = 0; 660 dp->b_actf = bp->av_forw; 661 bp->b_resid = (-upaddr->upwc * sizeof(short)); 662 iodone(bp); 663 /* 664 * If this unit has more work to do, 665 * then start it up right away. 666 */ 667 if (dp->b_actf) 668 if (upustart(ui)) 669 needie = 0; 670 } 671 as &= ~(1<<ui->ui_slave); 672 /* 673 * Release unibus resources and flush data paths. 674 */ 675 ubadone(um); 676 doattn: 677 /* 678 * Process other units which need attention. 679 * For each unit which needs attention, call 680 * the unit start routine to place the slave 681 * on the controller device queue. 682 */ 683 while (unit = ffs(as)) { 684 unit--; /* was 1 origin */ 685 as &= ~(1<<unit); 686 upaddr->upas = 1<<unit; 687 if (unit < UPIPUNITS && upustart(upip[sc21][unit])) 688 needie = 0; 689 } 690 /* 691 * If the controller is not transferring, but 692 * there are devices ready to transfer, start 693 * the controller. 694 */ 695 if (um->um_tab.b_actf && um->um_tab.b_active == 0) 696 if (upstart(um)) 697 needie = 0; 698 if (needie) 699 upaddr->upcs1 = UP_IE; 700 } 701 702 upread(dev, uio) 703 dev_t dev; 704 struct uio *uio; 705 { 706 register int unit = minor(dev) >> 3; 707 708 if (unit >= NUP) 709 return (ENXIO); 710 return (physio(upstrategy, &rupbuf[unit], dev, B_READ, minphys, uio)); 711 } 712 713 upwrite(dev, uio) 714 dev_t dev; 715 struct uio *uio; 716 { 717 register int unit = minor(dev) >> 3; 718 719 if (unit >= NUP) 720 return (ENXIO); 721 return (physio(upstrategy, &rupbuf[unit], dev, B_WRITE, minphys, uio)); 722 } 723 724 /* 725 * Correct an ECC error, and restart the i/o to complete 726 * the transfer if necessary. This is quite complicated because 727 * the transfer may be going to an odd memory address base and/or 728 * across a page boundary. 729 */ 730 upecc(ui, flag) 731 register struct uba_device *ui; 732 int flag; 733 { 734 register struct updevice *up = (struct updevice *)ui->ui_addr; 735 register struct buf *bp = uputab[ui->ui_unit].b_actf; 736 register struct uba_ctlr *um = ui->ui_mi; 737 register struct upst *st; 738 struct uba_regs *ubp = ui->ui_hd->uh_uba; 739 register int i; 740 caddr_t addr; 741 int reg, bit, byte, npf, mask, o, cmd, ubaddr; 742 int bn, cn, tn, sn; 743 744 /* 745 * Npf is the number of sectors transferred before the sector 746 * containing the ECC error, and reg is the UBA register 747 * mapping (the first part of) the transfer. 748 * O is offset within a memory page of the first byte transferred. 749 */ 750 #ifndef NOBADSECT 751 if (flag == CONT) 752 npf = bp->b_error; 753 else 754 #endif 755 npf = btop((up->upwc * sizeof(short)) + bp->b_bcount); 756 reg = btop(um->um_ubinfo&0x3ffff) + npf; 757 o = (int)bp->b_un.b_addr & PGOFSET; 758 printf("up%d%c: soft ecc sn%d\n", dkunit(bp), 759 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 760 mask = up->upec2; 761 #ifdef UPECCDEBUG 762 printf("npf %d reg %x o %d mask %o pos %d\n", npf, reg, o, mask, 763 up->upec1); 764 #endif 765 bn = dkblock(bp); 766 st = &upst[ui->ui_type]; 767 cn = bp->b_cylin; 768 sn = bn%st->nspc + npf; 769 tn = sn/st->nsect; 770 sn %= st->nsect; 771 cn += tn/st->ntrak; 772 tn %= st->ntrak; 773 ubapurge(um); 774 um->um_tab.b_active=2; 775 /* 776 * action taken depends on the flag 777 */ 778 switch(flag){ 779 case ECC: 780 npf--; 781 reg--; 782 mask = up->upec2; 783 printf("up%d%c: soft ecc sn%d\n", dkunit(bp), 784 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 785 /* 786 * Flush the buffered data path, and compute the 787 * byte and bit position of the error. The variable i 788 * is the byte offset in the transfer, the variable byte 789 * is the offset from a page boundary in main memory. 790 */ 791 i = up->upec1 - 1; /* -1 makes 0 origin */ 792 bit = i&07; 793 i = (i&~07)>>3; 794 byte = i + o; 795 /* 796 * Correct while possible bits remain of mask. Since mask 797 * contains 11 bits, we continue while the bit offset is > -11. 798 * Also watch out for end of this block and the end of the whole 799 * transfer. 800 */ 801 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 802 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 803 (byte & PGOFSET); 804 #ifdef UPECCDEBUG 805 printf("addr %x map reg %x\n", 806 addr, *(int *)(&ubp->uba_map[reg+btop(byte)])); 807 printf("old: %x, ", getmemc(addr)); 808 #endif 809 putmemc(addr, getmemc(addr)^(mask<<bit)); 810 #ifdef UPECCDEBUG 811 printf("new: %x\n", getmemc(addr)); 812 #endif 813 byte++; 814 i++; 815 } 816 if (up->upwc == 0) 817 return (0); 818 npf++; 819 reg++; 820 break; 821 #ifndef NOBADSECT 822 case BSE: 823 /* 824 * if not in bad sector table, return 0 825 */ 826 if ((bn = isbad(&upbad[ui->ui_unit], cn, tn, sn)) < 0) 827 return(0); 828 /* 829 * flag this one as bad 830 */ 831 bp->b_flags |= B_BAD; 832 bp->b_error = npf + 1; 833 #ifdef UPECCDEBUG 834 printf("BSE: restart at %d\n",npf+1); 835 #endif 836 bn = st->ncyl * st->nspc -st->nsect - 1 - bn; 837 cn = bn / st->nspc; 838 sn = bn % st->nspc; 839 tn = sn / st->nsect; 840 sn %= st->nsect; 841 up->upwc = -(512 / sizeof (short)); 842 #ifdef UPECCDEBUG 843 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 844 #endif 845 break; 846 case CONT: 847 #ifdef UPECCDEBUG 848 printf("upecc, CONT: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 849 #endif 850 bp->b_flags &= ~B_BAD; 851 up->upwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof(short)); 852 if (up->upwc == 0) 853 return(0); 854 break; 855 #endif 856 } 857 if (up->upwc == 0) { 858 um->um_tab.b_active = 0; 859 return (0); 860 } 861 /* 862 * Have to continue the transfer... clear the drive, 863 * and compute the position where the transfer is to continue. 864 * We have completed npf+1 sectors of the transfer already; 865 * restart at offset o of next sector (i.e. in UBA register reg+1). 866 */ 867 #ifdef notdef 868 up->uper1 = 0; 869 up->upcs1 |= UP_GO; 870 #else 871 up->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO; 872 up->updc = cn; 873 up->upda = (tn << 8) | sn; 874 ubaddr = (int)ptob(reg) + o; 875 up->upba = ubaddr; 876 cmd = (ubaddr >> 8) & 0x300; 877 cmd |= ((bp->b_flags&B_READ)?UP_RCOM:UP_WCOM)|UP_IE|UP_GO; 878 um->um_tab.b_errcnt = 0; 879 up->upcs1 = cmd; 880 #endif 881 return (1); 882 } 883 884 /* 885 * Reset driver after UBA init. 886 * Cancel software state of all pending transfers 887 * and restart all units and the controller. 888 */ 889 upreset(uban) 890 int uban; 891 { 892 register struct uba_ctlr *um; 893 register struct uba_device *ui; 894 register sc21, unit; 895 896 for (sc21 = 0; sc21 < NSC; sc21++) { 897 if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban || 898 um->um_alive == 0) 899 continue; 900 printf(" sc%d", sc21); 901 um->um_tab.b_active = 0; 902 um->um_tab.b_actf = um->um_tab.b_actl = 0; 903 up_softc[sc21].sc_recal = 0; 904 up_softc[sc21].sc_wticks = 0; 905 if (um->um_ubinfo) { 906 printf("<%d>", (um->um_ubinfo>>28)&0xf); 907 um->um_ubinfo = 0; 908 } 909 ((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR; 910 for (unit = 0; unit < NUP; unit++) { 911 if ((ui = updinfo[unit]) == 0) 912 continue; 913 if (ui->ui_alive == 0 || ui->ui_mi != um) 914 continue; 915 uputab[unit].b_active = 0; 916 (void) upustart(ui); 917 } 918 (void) upstart(um); 919 } 920 } 921 922 /* 923 * Wake up every second and if an interrupt is pending 924 * but nothing has happened increment a counter. 925 * If nothing happens for 20 seconds, reset the UNIBUS 926 * and begin anew. 927 */ 928 upwatch() 929 { 930 register struct uba_ctlr *um; 931 register sc21, unit; 932 register struct up_softc *sc; 933 934 timeout(upwatch, (caddr_t)0, hz); 935 for (sc21 = 0; sc21 < NSC; sc21++) { 936 um = upminfo[sc21]; 937 if (um == 0 || um->um_alive == 0) 938 continue; 939 sc = &up_softc[sc21]; 940 if (um->um_tab.b_active == 0) { 941 for (unit = 0; unit < NUP; unit++) 942 if (uputab[unit].b_active && 943 updinfo[unit]->ui_mi == um) 944 goto active; 945 sc->sc_wticks = 0; 946 continue; 947 } 948 active: 949 sc->sc_wticks++; 950 if (sc->sc_wticks >= 20) { 951 sc->sc_wticks = 0; 952 printf("sc%d: lost interrupt\n", sc21); 953 ubareset(um->um_ubanum); 954 } 955 } 956 } 957 958 #define DBSIZE 20 959 960 updump(dev) 961 dev_t dev; 962 { 963 struct updevice *upaddr; 964 char *start; 965 int num, blk, unit; 966 struct size *sizes; 967 register struct uba_regs *uba; 968 register struct uba_device *ui; 969 register short *rp; 970 struct upst *st; 971 register int retry; 972 973 unit = minor(dev) >> 3; 974 if (unit >= NUP) 975 return (ENXIO); 976 #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 977 ui = phys(struct uba_device *, updinfo[unit]); 978 if (ui->ui_alive == 0) 979 return (ENXIO); 980 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 981 ubainit(uba); 982 upaddr = (struct updevice *)ui->ui_physaddr; 983 DELAY(5000000); 984 num = maxfree; 985 upaddr->upcs2 = unit; 986 DELAY(100); 987 upaddr->upcs1 = UP_DCLR|UP_GO; 988 upaddr->upcs1 = UP_PRESET|UP_GO; 989 upaddr->upof = UPOF_FMT22; 990 retry = 0; 991 do { 992 DELAY(25); 993 if (++retry > 527) 994 break; 995 } while ((upaddr->upds & UP_RDY) == 0); 996 if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) 997 return (EFAULT); 998 start = 0; 999 st = &upst[ui->ui_type]; 1000 sizes = phys(struct size *, st->sizes); 1001 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) 1002 return (EINVAL); 1003 while (num > 0) { 1004 register struct pte *io; 1005 register int i; 1006 int cn, sn, tn; 1007 daddr_t bn; 1008 1009 blk = num > DBSIZE ? DBSIZE : num; 1010 io = uba->uba_map; 1011 for (i = 0; i < blk; i++) 1012 *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 1013 *(int *)io = 0; 1014 bn = dumplo + btop(start); 1015 cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 1016 sn = bn%st->nspc; 1017 tn = sn/st->nsect; 1018 sn = sn%st->nsect; 1019 upaddr->updc = cn; 1020 rp = (short *) &upaddr->upda; 1021 *rp = (tn << 8) + sn; 1022 *--rp = 0; 1023 *--rp = -blk*NBPG / sizeof (short); 1024 *--rp = UP_GO|UP_WCOM; 1025 retry = 0; 1026 do { 1027 DELAY(25); 1028 if (++retry > 527) 1029 break; 1030 } while ((upaddr->upcs1 & UP_RDY) == 0); 1031 if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { 1032 printf("up%d: not ready", unit); 1033 if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { 1034 printf("\n"); 1035 return (EIO); 1036 } 1037 printf(" (flakey)\n"); 1038 } 1039 if (upaddr->upds&UPDS_ERR) 1040 return (EIO); 1041 start += blk*NBPG; 1042 num -= blk; 1043 } 1044 return (0); 1045 } 1046 #endif 1047