1 /* up.c 3.24 09/27/80 */ 2 3 /* 4 * UNIBUS disk driver with overlapped seeks and ECC recovery. 5 * 6 * This driver works marginally on an Emulex SC-11B controller with rev 7 * level J microcode, defining: 8 * int olducode = 1; 9 * to force CPU stalling delays. 10 * 11 * It has worked with no delays and no problems on a prototype 12 * SC-21 controller. Emulex intends to upgrade all SC-11s on VAXes to SC-21s. 13 * You should get a SC-21 to replace any SC-11 on a VAX. 14 * 15 * SC-11B Controller switch settings: 16 * SW1-1 5/19 surfaces (off, 19 surfaces on Ampex 9300) 17 * SW1-2 chksum enable (off, checksum disabled) 18 * SW1-3 volume select (off, 815 cylinders) 19 * SW1-4 sector select (on, 32 sectors) 20 * SW1-5 unused (off) 21 * SW1-6 port select (on, single port) 22 * SW1-7 npr delay (off, disable) 23 * SW1-8 ecc test mode (off, disable) 24 * and top mounted switches: 25 * SW2-1 extend opcodes (off=open, disable) 26 * SW2-2 extend diag (off=open, disable) 27 * SW2-3 4 wd dma burst (on=closed, enable) 28 * SW2-4 unused (off=open) 29 */ 30 31 #include "../h/param.h" 32 #include "../h/systm.h" 33 #include "../h/dk.h" 34 #include "../h/buf.h" 35 #include "../h/conf.h" 36 #include "../h/dir.h" 37 #include "../h/user.h" 38 #include "../h/map.h" 39 #include "../h/pte.h" 40 #include "../h/mba.h" 41 #include "../h/mtpr.h" 42 #include "../h/uba.h" 43 #include "../h/vm.h" 44 45 /* 46 * Define number of drives, and range of sampling information to be used. 47 * 48 * Normally, DK_N .. DK_N+NUP-1 gather individual drive stats, 49 * and DK_N+NUP gathers controller transferring stats. 50 * 51 * If DK_N+NUP > DK_NMAX, then transfer stats are divided per drive. 52 * If DK_NMAX is yet smaller, some drives are not monitored. 53 */ 54 #define DK_N 2 55 #define DK_NMAX 3 56 57 #define ushort unsigned short 58 59 struct device 60 { 61 ushort upcs1; /* control and status register 1 */ 62 short upwc; /* word count register */ 63 ushort upba; /* UNIBUS address register */ 64 ushort upda; /* desired address register */ 65 ushort upcs2; /* control and status register 2 */ 66 ushort upds; /* drive Status */ 67 ushort uper1; /* error register 1 */ 68 ushort upas; /* attention summary */ 69 ushort upla; /* look ahead */ 70 ushort updb; /* data buffer */ 71 ushort upmr; /* maintenance */ 72 ushort updt; /* drive type */ 73 ushort upsn; /* serial number */ 74 ushort upof; /* offset register */ 75 ushort updc; /* desired cylinder address register */ 76 ushort upcc; /* current cylinder */ 77 ushort uper2; /* error register 2 */ 78 ushort uper3; /* error register 3 */ 79 ushort upec1; /* burst error bit position */ 80 ushort upec2; /* burst error bit pattern */ 81 }; 82 83 /* 84 * Software extension to the upas register, so we can 85 * postpone starting SEARCH commands until the controller 86 * is not transferring. 87 */ 88 int upsoftas; 89 90 /* 91 * If upseek then we don't issue SEARCH commands but rather just 92 * settle for a SEEK to the correct cylinder. 93 */ 94 int upseek; 95 96 #define UPADDR ((struct device *)(UBA0_DEV + 0176700)) 97 98 #define NUP 2 /* Number of drives this installation */ 99 100 #define NSECT 32 101 #define NTRAC 19 102 103 /* 104 * Constants controlling on-cylinder SEARCH usage. 105 * 106 * upSDIST/2 msec time needed to start transfer 107 * upRDIST/2 msec tolerable rotational latency when on-cylinder 108 * 109 * If we are no closer than upSDIST sectors and no further than upSDIST+upRDIST 110 * and in the driver then we take it as it is. Otherwise we do a SEARCH 111 * requesting an interrupt upSDIST sectors in advance. 112 */ 113 #define _upSDIST 6 /* 3.0 msec */ 114 #define _upRDIST 6 /* 3.0 msec */ 115 116 int upSDIST = _upSDIST; 117 int upRDIST = _upRDIST; 118 119 /* 120 * To fill a 300M drive: 121 * A is designed to be used as a root. 122 * B is suitable for a swap area. 123 * H is the primary storage area. 124 * On systems with RP06'es, we normally use only 291346 blocks of the H 125 * area, and use DEF or G to cover the rest of the drive. The C system 126 * covers the whole drive and can be used for pack-pack copying. 127 */ 128 struct size 129 { 130 daddr_t nblocks; 131 int cyloff; 132 } up_sizes[8] = { 133 15884, 0, /* A=cyl 0 thru 26 */ 134 33440, 27, /* B=cyl 27 thru 81 */ 135 495520, 0, /* C=cyl 0 thru 814 */ 136 15884, 562, /* D=cyl 562 thru 588 */ 137 55936, 589, /* E=cyl 589 thru 680 */ 138 81472, 681, /* F=cyl 681 thru 814 */ 139 153824, 562, /* G=cyl 562 thru 814 */ 140 445664, 82, /* H=cyl 82 thru 814 */ 141 /* Later, and more safely for H area... 142 291346, 82, /* H=cyl 82 thru 561 */ 143 }; 144 145 /* 146 * The following defines are used in offset positioning 147 * when trying to recover disk errors, with the constants being 148 * +/- microinches. Note that header compare inhibit (HCI) is not 149 * tried (this makes sense only during read, in any case.) 150 * 151 * NOT ALL OF THESE ARE IMPLEMENTED ON 9300!?! 152 */ 153 #define P400 020 154 #define M400 0220 155 #define P800 040 156 #define M800 0240 157 #define P1200 060 158 #define M1200 0260 159 #define HCI 020000 160 161 int up_offset[16] = 162 { 163 P400, M400, P400, M400, 164 P800, M800, P800, M800, 165 P1200, M1200, P1200, M1200, 166 0, 0, 0, 0, 167 }; 168 169 /* 170 * Each drive has a table uputab[i]. On this table are sorted the 171 * pending requests implementing an elevator algorithm (see dsort.c.) 172 * In the upustart() routine, each drive is independently advanced 173 * until it is on the desired cylinder for the next transfer and near 174 * the desired sector. The drive is then chained onto the uptab 175 * table, and the transfer is initiated by the upstart() routine. 176 * When the transfer is completed the driver reinvokes the upustart() 177 * routine to set up the next transfer. 178 */ 179 struct buf uptab; 180 struct buf uputab[NUP]; 181 182 struct buf rupbuf; /* Buffer for raw i/o */ 183 184 /* Drive commands, placed in upcs1 */ 185 #define GO 01 /* Go bit, set in all commands */ 186 #define PRESET 020 /* Preset drive at init or after errors */ 187 #define OFFSET 014 /* Offset heads to try to recover error */ 188 #define RTC 016 /* Return to center-line after OFFSET */ 189 #define SEARCH 030 /* Search for cylinder+sector */ 190 #define SEEK 04 /* Seek to cylinder */ 191 #define RECAL 06 /* Recalibrate, needed after seek error */ 192 #define DCLR 010 /* Drive clear, after error */ 193 #define WCOM 060 /* Write */ 194 #define RCOM 070 /* Read */ 195 196 /* Other bits of upcs1 */ 197 #define IE 0100 /* Controller wide interrupt enable */ 198 #define TRE 040000 /* Transfer error */ 199 #define RDY 0200 /* Transfer terminated */ 200 201 /* Drive status bits of upds */ 202 #define PIP 020000 /* Positioning in progress */ 203 #define ERR 040000 /* Error has occurred, DCLR necessary */ 204 #define VV 0100 /* Volume is valid, set by PRESET */ 205 #define DPR 0400 /* Drive has been preset */ 206 #define MOL 010000 /* Drive is online, heads loaded, etc */ 207 #define DRY 0200 /* Drive ready */ 208 209 /* Bits of upcs2 */ 210 #define CLR 040 /* Controller clear */ 211 /* Bits of uper1 */ 212 #define DCK 0100000 /* Ecc error occurred */ 213 #define ECH 0100 /* Ecc error was unrecoverable */ 214 #define WLE 04000 /* Attempt to write read-only drive */ 215 216 /* Bits of upof; the offset bits above are also in this register */ 217 #define FMT22 010000 /* 16 bits/word, must be always set */ 218 219 #define b_cylin b_resid 220 221 int up_ubinfo; /* Information about UBA usage saved here */ 222 /* 223 * The EMULEX controller balks if accessed quickly after 224 * certain operations. With rev J delays seem to be needed only 225 * when selecting a new unit, and in drive initialization type 226 * like PRESET and DCLR. The following variables control the delay 227 * DELAY(n) is approximately n usec. 228 */ 229 int olducode = 1; 230 int idelay = 500; /* Delay after PRESET or DCLR */ 231 int osdelay = 150; /* Old delay after selecting drive in upcs2 */ 232 int ordelay = 100; /* Old delay after SEARCH */ 233 int oasdel = 100; /* Old delay after clearing bit in upas */ 234 int nsdelay = 25; 235 236 #define DELAY(N) { register int d; d = N; while (--d > 0); } 237 238 int nwaitcs2; /* How many sdelay loops ? */ 239 int neasycs2; /* How many sdelay loops not needed ? */ 240 241 int up_wticks; /* Ticks waiting for interrupt */ 242 int upwstart; /* Have started guardian */ 243 int upwatch(); 244 245 #ifdef INTRLVE 246 daddr_t dkblock(); 247 #endif 248 249 /* 250 * Queue an i/o request for a drive, checking first that it is in range. 251 * 252 * A unit start is issued if the drive is inactive, causing 253 * a SEARCH for the correct cylinder/sector. If the drive is 254 * already nearly on the money and the controller is not transferring 255 * we kick it to start the transfer. 256 */ 257 upstrategy(bp) 258 register struct buf *bp; 259 { 260 register struct buf *dp; 261 register unit, xunit; 262 long sz, bn; 263 264 if (upwstart == 0) { 265 timeout((caddr_t)upwatch, 0, HZ); 266 upwstart++; 267 } 268 xunit = minor(bp->b_dev) & 077; 269 sz = bp->b_bcount; 270 sz = (sz+511) >> 9; /* transfer size in 512 byte sectors */ 271 unit = dkunit(bp); 272 if (unit >= NUP || 273 bp->b_blkno < 0 || 274 (bn = dkblock(bp))+sz > up_sizes[xunit&07].nblocks) { 275 bp->b_flags |= B_ERROR; 276 iodone(bp); 277 return; 278 } 279 bp->b_cylin = bn/(NSECT*NTRAC) + up_sizes[xunit&07].cyloff; 280 dp = &uputab[unit]; 281 (void) spl5(); 282 disksort(dp, bp); 283 if (dp->b_active == 0) { 284 (void) upustart(unit); 285 if (uptab.b_actf && uptab.b_active == 0) 286 (void) upstart(); 287 } 288 (void) spl0(); 289 } 290 291 /* 292 * Start activity on specified drive; called when drive is inactive 293 * and new transfer request arrives and also when upas indicates that 294 * a SEARCH command is complete. 295 */ 296 upustart(unit) 297 register unit; 298 { 299 register struct buf *bp, *dp; 300 register struct device *upaddr = UPADDR; 301 daddr_t bn; 302 int sn, cn, csn; 303 int didie = 0; 304 305 /* 306 * Other drivers tend to say something like 307 * upaddr->upcs1 = IE; 308 * upaddr->upas = 1<<unit; 309 * here, but the SC-11B will cancel a command which 310 * happens to be sitting in the cs1 if you clear the go 311 * bit by storing there (so the first is not safe), 312 * and it also does not like being bothered with operations 313 * such as clearing upas when a transfer is active (as 314 * it may well be.) 315 * 316 * Thus we keep careful track of when we re-enable IE 317 * after an interrupt and do it only if we didn't issue 318 * a command which re-enabled it as a matter of course. 319 * We clear bits in upas in the interrupt routine, when 320 * no transfers are active. 321 */ 322 if (unit >= NUP) 323 goto out; 324 if (unit+DK_N <= DK_NMAX) 325 dk_busy &= ~(1<<(unit+DK_N)); 326 dp = &uputab[unit]; 327 if ((bp = dp->b_actf) == NULL) 328 goto out; 329 /* 330 * The SC-11B doesn't start SEARCH commands when transfers are 331 * in progress. In fact, it tends to get confused when given 332 * SEARCH'es during transfers, generating interrupts with neither 333 * RDY nor a bit in the upas register. Thus we defer 334 * until an interrupt when a transfer is pending. 335 */ 336 if (uptab.b_active) { 337 upsoftas |= 1<<unit; 338 return (0); 339 } 340 if (dp->b_active) 341 goto done; 342 dp->b_active = 1; 343 if ((upaddr->upcs2 & 07) != unit) { 344 upaddr->upcs2 = unit; 345 DELAY(olducode ? osdelay : nsdelay); 346 nwaitcs2++; 347 } else 348 neasycs2++; 349 /* 350 * If we have changed packs or just initialized, 351 * then the volume will not be valid; if so, clear 352 * the drive, preset it and put in 16bit/word mode. 353 */ 354 if ((upaddr->upds & VV) == 0) { 355 upaddr->upcs1 = IE|DCLR|GO; 356 DELAY(idelay); 357 upaddr->upcs1 = IE|PRESET|GO; 358 DELAY(idelay); 359 upaddr->upof = FMT22; 360 didie = 1; 361 } 362 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) 363 goto done; 364 /* 365 * Do enough of the disk address decoding to determine 366 * which cylinder and sector the request is on. 367 * If we are on the correct cylinder and the desired sector 368 * lies between upSDIST and upSDIST+upRDIST sectors ahead of us, then 369 * we don't bother to SEARCH but just begin the transfer asap. 370 * Otherwise ask for a interrupt upSDIST sectors ahead. 371 */ 372 bn = dkblock(bp); 373 cn = bp->b_cylin; 374 sn = bn%(NSECT*NTRAC); 375 sn = (sn+NSECT-upSDIST)%NSECT; 376 377 if (cn - upaddr->updc) 378 goto search; /* Not on-cylinder */ 379 else if (upseek) 380 goto done; /* Ok just to be on-cylinder */ 381 csn = (upaddr->upla>>6) - sn - 1; 382 if (csn < 0) 383 csn += NSECT; 384 if (csn > NSECT-upRDIST) 385 goto done; 386 387 search: 388 upaddr->updc = cn; 389 if (upseek) 390 upaddr->upcs1 = IE|SEEK|GO; 391 else { 392 upaddr->upda = sn; 393 upaddr->upcs1 = IE|SEARCH|GO; 394 } 395 didie = 1; 396 /* 397 * Mark this unit busy. 398 */ 399 unit += DK_N; 400 if (unit <= DK_NMAX && DK_N+NUP <= DK_NMAX) { 401 dk_busy |= 1<<unit; 402 dk_numb[unit]++; 403 } 404 if (olducode) 405 DELAY(ordelay); 406 goto out; 407 408 done: 409 /* 410 * This unit is ready to go so 411 * link it onto the chain of ready disks. 412 */ 413 dp->b_forw = NULL; 414 if (uptab.b_actf == NULL) 415 uptab.b_actf = dp; 416 else 417 uptab.b_actl->b_forw = dp; 418 uptab.b_actl = dp; 419 420 out: 421 return (didie); 422 } 423 424 /* 425 * Start a transfer; call from top level at spl5() or on interrupt. 426 */ 427 upstart() 428 { 429 register struct buf *bp, *dp; 430 register unit; 431 register struct device *upaddr; 432 daddr_t bn; 433 int dn, sn, tn, cn, cmd; 434 435 loop: 436 /* 437 * Pick a drive off the queue of ready drives, and 438 * perform the first transfer on its queue. 439 * 440 * Looping here is completely for the sake of drives which 441 * are not present and on-line, for which we completely clear the 442 * request queue. 443 */ 444 if ((dp = uptab.b_actf) == NULL) 445 return (0); 446 if ((bp = dp->b_actf) == NULL) { 447 uptab.b_actf = dp->b_forw; 448 goto loop; 449 } 450 /* 451 * Mark the controller busy, and multi-part disk address. 452 * Select the unit on which the i/o is to take place. 453 */ 454 uptab.b_active++; 455 unit = minor(bp->b_dev) & 077; 456 dn = dkunit(bp); 457 bn = dkblock(bp); 458 cn = up_sizes[unit&07].cyloff; 459 cn += bn/(NSECT*NTRAC); 460 sn = bn%(NSECT*NTRAC); 461 tn = sn/NSECT; 462 sn %= NSECT; 463 upaddr = UPADDR; 464 if ((upaddr->upcs2 & 07) != dn) { 465 upaddr->upcs2 = dn; 466 /* DELAY(sdelay); Provided by ubasetup() */ 467 nwaitcs2++; 468 } else 469 neasycs2++; 470 up_ubinfo = ubasetup(bp, 1); /* Providing delay */ 471 /* 472 * If drive is not present and on-line, then 473 * get rid of this with an error and loop to get 474 * rid of the rest of its queued requests. 475 * (Then on to any other ready drives.) 476 */ 477 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) { 478 printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds); 479 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) { 480 printf("-- hard\n"); 481 uptab.b_active = 0; 482 uptab.b_errcnt = 0; 483 dp->b_actf = bp->av_forw; 484 dp->b_active = 0; 485 bp->b_flags |= B_ERROR; 486 iodone(bp); 487 /* A funny place to do this ... */ 488 ubafree(up_ubinfo), up_ubinfo = 0; 489 goto loop; 490 } 491 printf("-- came back\n"); 492 } 493 /* 494 * If this is a retry, then with the 16'th retry we 495 * begin to try offsetting the heads to recover the data. 496 */ 497 if (uptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) { 498 upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22; 499 upaddr->upcs1 = IE|OFFSET|GO; 500 DELAY(idelay); 501 while (upaddr->upds & PIP) 502 DELAY(25); 503 } 504 /* 505 * Now set up the transfer, retrieving the high 506 * 2 bits of the UNIBUS address from the information 507 * returned by ubasetup() for the cs1 register bits 8 and 9. 508 */ 509 upaddr->updc = cn; 510 upaddr->upda = (tn << 8) + sn; 511 upaddr->upba = up_ubinfo; 512 upaddr->upwc = -bp->b_bcount / sizeof (short); 513 cmd = (up_ubinfo >> 8) & 0x300; 514 if (bp->b_flags & B_READ) 515 cmd |= IE|RCOM|GO; 516 else 517 cmd |= IE|WCOM|GO; 518 upaddr->upcs1 = cmd; 519 /* 520 * This is a controller busy situation. 521 * Record in dk slot NUP+DK_N (after last drive) 522 * unless there aren't that many slots reserved for 523 * us in which case we record this as a drive busy 524 * (if there is room for that). 525 */ 526 unit = dn+DK_N; 527 if (NUP+DK_N == DK_NMAX) 528 unit = NUP+DK_N; 529 if (unit <= DK_NMAX) { 530 dk_busy |= 1<<unit; 531 dk_numb[unit]++; 532 dk_wds[unit] += bp->b_bcount>>6; 533 } 534 return (1); 535 } 536 537 /* 538 * Handle a device interrupt. 539 * 540 * If the transferring drive needs attention, service it 541 * retrying on error or beginning next transfer. 542 * Service all other ready drives, calling ustart to transfer 543 * their blocks to the ready queue in uptab, and then restart 544 * the controller if there is anything to do. 545 */ 546 upintr() 547 { 548 register struct buf *bp, *dp; 549 register unit; 550 register struct device *upaddr = UPADDR; 551 int as = upaddr->upas & 0377; 552 int oupsoftas; 553 int needie = 1; 554 555 (void) spl6(); 556 up_wticks = 0; 557 if (uptab.b_active) { 558 /* 559 * The drive is transferring, thus the hardware 560 * (say the designers) will only interrupt when the transfer 561 * completes; check for it anyways. 562 */ 563 if ((upaddr->upcs1 & RDY) == 0) { 564 printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1, 565 upaddr->upds, upaddr->upwc); 566 printf("as=%d act %d %d %d\n", as, uptab.b_active, 567 uputab[0].b_active, uputab[1].b_active); 568 } 569 /* 570 * Mark controller or drive not busy, and check for an 571 * error condition which may have resulted from the transfer. 572 */ 573 dp = uptab.b_actf; 574 bp = dp->b_actf; 575 unit = dkunit(bp); 576 if (DK_N+NUP == DK_NMAX) 577 dk_busy &= ~(1<<(DK_N+NUP)); 578 else if (DK_N+unit <= DK_NMAX) 579 dk_busy &= ~(1<<(DK_N+unit)); 580 if ((upaddr->upcs2 & 07) != unit) { 581 upaddr->upcs2 = unit; 582 DELAY(olducode ? osdelay : nsdelay); 583 nwaitcs2++; 584 } else 585 neasycs2++; 586 if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) { 587 /* 588 * An error occurred, indeed. Select this unit 589 * to get at the drive status (a SEARCH may have 590 * intervened to change the selected unit), and 591 * wait for the command which caused the interrupt 592 * to complete (DRY). 593 */ 594 while ((upaddr->upds & DRY) == 0) 595 DELAY(25); 596 /* 597 * After 28 retries (16 w/o servo offsets, and then 598 * 12 with servo offsets), or if we encountered 599 * an error because the drive is write-protected, 600 * give up. Print an error message on the last 2 601 * retries before a hard failure. 602 */ 603 if (++uptab.b_errcnt > 28 || upaddr->uper1&WLE) 604 bp->b_flags |= B_ERROR; 605 else 606 uptab.b_active = 0; /* To force retry */ 607 if (uptab.b_errcnt > 27) 608 deverror(bp, upaddr->upcs2, upaddr->uper1); 609 /* 610 * If this was a correctible ECC error, let upecc 611 * do the dirty work to correct it. If upecc 612 * starts another READ for the rest of the data 613 * then it returns 1 (having set uptab.b_active). 614 * Otherwise we are done and fall through to 615 * finish up. 616 */ 617 if ((upaddr->uper1&(DCK|ECH))==DCK && upecc(upaddr, bp)) 618 return; 619 /* 620 * Clear the drive and, every 4 retries, recalibrate 621 * to hopefully help clear up seek positioning problems. 622 */ 623 upaddr->upcs1 = TRE|IE|DCLR|GO; 624 DELAY(idelay); 625 needie = 0; 626 if ((uptab.b_errcnt&07) == 4) { 627 upaddr->upcs1 = RECAL|GO|IE; 628 DELAY(idelay); 629 while(upaddr->upds & PIP) 630 DELAY(25); 631 } 632 } 633 /* 634 * If we are still noted as active, then no 635 * (further) retries are necessary. 636 * 637 * Make sure the correct unit is selected, 638 * return it to centerline if necessary, and mark 639 * this i/o complete, starting the next transfer 640 * on this drive with the upustart routine (if any). 641 */ 642 if (uptab.b_active) { 643 if (uptab.b_errcnt >= 16) { 644 upaddr->upcs1 = RTC|GO|IE; 645 DELAY(idelay); 646 while (upaddr->upds & PIP) 647 DELAY(25); 648 needie = 0; 649 } 650 uptab.b_active = 0; 651 uptab.b_errcnt = 0; 652 uptab.b_actf = dp->b_forw; 653 dp->b_active = 0; 654 dp->b_errcnt = 0; 655 dp->b_actf = bp->av_forw; 656 bp->b_resid = (-upaddr->upwc * sizeof(short)); 657 if (bp->b_resid) 658 printf("resid %d ds %o er? %o %o %o\n", 659 bp->b_resid, upaddr->upds, 660 upaddr->uper1, upaddr->uper2, upaddr->uper3); 661 iodone(bp); 662 if(dp->b_actf) 663 if (upustart(unit)) 664 needie = 0; 665 } 666 as &= ~(1<<unit); 667 upsoftas &= ~(1<<unit); 668 ubafree(up_ubinfo), up_ubinfo = 0; 669 } else { 670 if (upaddr->upcs1 & TRE) { 671 upaddr->upcs1 = TRE; 672 DELAY(idelay); 673 } 674 } 675 /* 676 * If we have a unit with an outstanding SEARCH, 677 * and the hardware indicates the unit requires attention, 678 * the bring the drive to the ready queue. 679 * Finally, if the controller is not transferring 680 * start it if any drives are now ready to transfer. 681 */ 682 as |= upsoftas; 683 oupsoftas = upsoftas; 684 upsoftas = 0; 685 for (unit = 0; unit < NUP; unit++) 686 if ((as|oupsoftas) & (1<<unit)) { 687 if (as & (1<<unit)) { 688 upaddr->upas = 1<<unit; 689 if (olducode) 690 DELAY(oasdel); 691 } 692 if (upustart(unit)) 693 needie = 0; 694 } 695 if (uptab.b_actf && uptab.b_active == 0) 696 if (upstart()) 697 needie = 0; 698 out: 699 if (needie) 700 upaddr->upcs1 = IE; 701 } 702 703 upread(dev) 704 { 705 706 physio(upstrategy, &rupbuf, dev, B_READ, minphys); 707 } 708 709 upwrite(dev) 710 { 711 712 physio(upstrategy, &rupbuf, dev, B_WRITE, minphys); 713 } 714 715 /* 716 * Correct an ECC error, and restart the i/o to complete 717 * the transfer if necessary. This is quite complicated because 718 * the transfer may be going to an odd memory address base and/or 719 * across a page boundary. 720 */ 721 upecc(up, bp) 722 register struct device *up; 723 register struct buf *bp; 724 { 725 struct uba_regs *ubp = (struct uba_regs *)UBA0; 726 register int i; 727 caddr_t addr; 728 int reg, bit, byte, npf, mask, o, cmd, ubaddr; 729 int bn, cn, tn, sn; 730 731 /* 732 * Npf is the number of sectors transferred before the sector 733 * containing the ECC error, and reg is the UBA register 734 * mapping (the first part of) the transfer. 735 * O is offset within a memory page of the first byte transferred. 736 */ 737 npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1; 738 reg = btop(up_ubinfo&0x3ffff) + npf; 739 o = (int)bp->b_un.b_addr & PGOFSET; 740 printf("%D ", bp->b_blkno+npf); 741 prdev("ECC", bp->b_dev); 742 mask = up->upec2; 743 if (mask == 0) { 744 up->upof = FMT22; /* == RTC ???? */ 745 DELAY(idelay); 746 return (0); 747 } 748 /* 749 * Flush the buffered data path, and compute the 750 * byte and bit position of the error. The variable i 751 * is the byte offset in the transfer, the variable byte 752 * is the offset from a page boundary in main memory. 753 */ 754 ubp->uba_dpr[(up_ubinfo>>28)&0x0f] |= BNE; 755 i = up->upec1 - 1; /* -1 makes 0 origin */ 756 bit = i&07; 757 i = (i&~07)>>3; 758 byte = i + o; 759 /* 760 * Correct while possible bits remain of mask. Since mask 761 * contains 11 bits, we continue while the bit offset is > -11. 762 * Also watch out for end of this block and the end of the whole 763 * transfer. 764 */ 765 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 766 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 767 (byte & PGOFSET); 768 putmemc(addr, getmemc(addr)^(mask<<bit)); 769 byte++; 770 i++; 771 bit -= 8; 772 } 773 uptab.b_active++; /* Either complete or continuing... */ 774 if (up->upwc == 0) 775 return (0); 776 /* 777 * Have to continue the transfer... clear the drive, 778 * and compute the position where the transfer is to continue. 779 * We have completed npf+1 sectors of the transfer already; 780 * restart at offset o of next sector (i.e. in UBA register reg+1). 781 */ 782 up->upcs1 = TRE|IE|DCLR|GO; 783 DELAY(idelay); 784 bn = dkblock(bp); 785 cn = bp->b_cylin; 786 sn = bn%(NSECT*NTRAC) + npf + 1; 787 tn = sn/NSECT; 788 sn %= NSECT; 789 cn += tn/NTRAC; 790 tn %= NTRAC; 791 up->updc = cn; 792 up->upda = (tn << 8) | sn; 793 ubaddr = (int)ptob(reg+1) + o; 794 up->upba = ubaddr; 795 cmd = (ubaddr >> 8) & 0x300; 796 cmd |= IE|GO|RCOM; 797 up->upcs1 = cmd; 798 return (1); 799 } 800 801 /* 802 * Reset driver after UBA init. 803 * Cancel software state of all pending transfers 804 * and restart all units and the controller. 805 */ 806 upreset() 807 { 808 int unit; 809 810 printf(" up"); 811 uptab.b_active = 0; 812 uptab.b_actf = uptab.b_actl = 0; 813 if (DK_N+NUP == DK_NMAX) 814 dk_busy &= ~(1<<(DK_N+NUP)); 815 if (up_ubinfo) { 816 printf("<%d>", (up_ubinfo>>28)&0xf); 817 ubafree(up_ubinfo), up_ubinfo = 0; 818 } 819 UPADDR->upcs2 = CLR; /* clear controller */ 820 DELAY(idelay); 821 for (unit = 0; unit < NUP; unit++) { 822 uputab[unit].b_active = 0; 823 (void) upustart(unit); 824 } 825 (void) upstart(); 826 } 827 828 /* 829 * Wake up every second and if an interrupt is pending 830 * but nothing has happened increment a counter. 831 * If nothing happens for 20 seconds, reset the controller 832 * and begin anew. 833 */ 834 upwatch() 835 { 836 int i; 837 838 timeout((caddr_t)upwatch, 0, HZ); 839 if (uptab.b_active == 0) { 840 for (i = 0; i < NUP; i++) 841 if (uputab[i].b_active) 842 goto active; 843 up_wticks = 0; /* idling */ 844 return; 845 } 846 active: 847 up_wticks++; 848 if (up_wticks >= 20) { 849 up_wticks = 0; 850 printf("LOST INTERRUPT RESET"); 851 upreset(); 852 printf("\n"); 853 } 854 } 855