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