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