1 /* up.c 4.13 81/02/10 */ 2 3 #include "up.h" 4 #if NSC21 > 0 5 /* 6 * UNIBUS disk driver with overlapped seeks and ECC recovery. 7 */ 8 #define DELAY(N) { register int d; d = N; while (--d > 0); } 9 10 #include "../h/param.h" 11 #include "../h/systm.h" 12 #include "../h/cpu.h" 13 #include "../h/nexus.h" 14 #include "../h/dk.h" 15 #include "../h/buf.h" 16 #include "../h/conf.h" 17 #include "../h/dir.h" 18 #include "../h/user.h" 19 #include "../h/map.h" 20 #include "../h/pte.h" 21 #include "../h/mba.h" 22 #include "../h/mtpr.h" 23 #include "../h/uba.h" 24 #include "../h/vm.h" 25 #include "../h/cmap.h" 26 27 #include "../h/upreg.h" 28 29 struct up_softc { 30 int sc_softas; 31 int sc_seek; 32 int sc_info; 33 int sc_wticks; 34 } up_softc[NSC21]; 35 36 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 37 struct size 38 { 39 daddr_t nblocks; 40 int cyloff; 41 } up_sizes[8] = { 42 15884, 0, /* A=cyl 0 thru 26 */ 43 33440, 27, /* B=cyl 27 thru 81 */ 44 495520, 0, /* C=cyl 0 thru 814 */ 45 15884, 562, /* D=cyl 562 thru 588 */ 46 55936, 589, /* E=cyl 589 thru 680 */ 47 81472, 681, /* F=cyl 681 thru 814 */ 48 153824, 562, /* G=cyl 562 thru 814 */ 49 291346, 82, /* H=cyl 82 thru 561 */ 50 }, fj_sizes[8] = { 51 15884, 0, /* A=cyl 0 thru 49 */ 52 33440, 50, /* B=cyl 50 thru 154 */ 53 263360, 0, /* C=cyl 0 thru 822 */ 54 0, 0, 55 0, 0, 56 0, 0, 57 0, 0, 58 213760, 155, /* H=cyl 155 thru 822 */ 59 }; 60 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 61 62 #define _upSDIST 2 /* 1.0 msec */ 63 #define _upRDIST 4 /* 2.0 msec */ 64 65 int upSDIST = _upSDIST; 66 int upRDIST = _upRDIST; 67 68 int upcntrlr(), upslave(), updgo(), upintr(); 69 struct uba_minfo *upminfo[NSC21]; 70 struct uba_dinfo *updinfo[NUP]; 71 struct uba_minfo up_minfo[NSC21]; 72 /* there is no reason for this to be a global structure, it 73 is only known/used locally, it would be better combined 74 with up_softc - but that would mean I would have to alter 75 more than I want to just now. Similarly, there is no longer 76 any real need for upminfo, but the code still uses it so ... 77 */ 78 79 u_short upstd[] = { 0 }; 80 int (*upivec[])() = { upintr, 0 }; 81 struct uba_driver updriver = 82 { upcntrlr, upslave, updgo, 4, 0, upstd, updinfo, upivec }; 83 struct buf uputab[NUP]; 84 85 struct upst { 86 short nsect; 87 short ntrak; 88 short nspc; 89 short ncyl; 90 struct size *sizes; 91 } upst[] = { 92 32, 19, 32*19, 815, up_sizes, /* 9300 */ 93 32, 19, 32*19, 823, up_sizes, /* so cdc will boot */ 94 32, 10, 32*10, 823, fj_sizes, /* fujitsu 160m */ 95 }; 96 97 int up_offset[16] = 98 { 99 P400, M400, P400, M400, 100 P800, M800, P800, M800, 101 P1200, M1200, P1200, M1200, 102 0, 0, 0, 0, 103 }; 104 105 struct buf rupbuf; /* GROT */ 106 107 #define b_cylin b_resid 108 109 #ifdef INTRLVE 110 daddr_t dkblock(); 111 #endif 112 113 int upwstart, upwatch(); /* Have started guardian */ 114 115 /*ARGSUSED*/ 116 upcntrlr(um, reg) 117 struct uba_minfo *um; 118 caddr_t reg; 119 { 120 ((struct device *)reg)->upcs1 |= (IE|RDY); 121 return(1); /* just assume it is us (for now) */ 122 } 123 124 upslave(ui, reg, slaveno, uban) 125 struct uba_dinfo *ui; 126 caddr_t reg; 127 { 128 register struct device *upaddr = (struct device *)reg; 129 register struct uba_minfo *um; 130 register int sc21; 131 132 upaddr->upcs1 = 0; /* conservative */ 133 upaddr->upcs2 = slaveno; 134 if (upaddr->upcs2&NED) { 135 upaddr->upcs1 = DCLR|GO; 136 return (0); 137 } 138 /*** we should check device type (return 0 if we don't like it) ***/ 139 /*** and set type index in ui->ui_type, but we KNOW all we are ***/ 140 /*** going to see at the minute is a 9300, and the index for a ***/ 141 /*** 9300 is 0, which is the value already in ui->ui_type, so ..***/ 142 143 um = &up_minfo[0]; 144 for (sc21 = 0; sc21 < NSC21; sc21++) { 145 if (um->um_alive == 0) { /* this is a new ctrlr */ 146 um->um_addr = reg; 147 um->um_ubanum = uban; 148 um->um_num = sc21; /* not needed after up_softc 149 combined with um ??? */ 150 um->um_alive = 1; 151 upminfo[sc21] = um; /* just till upminfo vanishes */ 152 goto found; 153 } 154 if (um->um_addr == reg && um->um_ubanum == uban) 155 goto found; 156 um++; 157 } 158 return(0); /* too many sc21's */ 159 160 found: 161 ui->ui_mi = um; 162 163 if (upwstart == 0) { 164 timeout(upwatch, (caddr_t)0, HZ); 165 upwstart++; 166 } 167 return (1); 168 } 169 170 /* 171 dk_mspw[UPDK_N+unit] = .0000020345; 172 */ 173 174 upstrategy(bp) 175 register struct buf *bp; 176 { 177 register struct uba_dinfo *ui; 178 register struct uba_minfo *um; 179 register struct upst *st; 180 register int unit; 181 int xunit = minor(bp->b_dev) & 07; 182 long sz, bn; 183 184 sz = bp->b_bcount; 185 sz = (sz+511) >> 9; /* transfer size in 512 byte sectors */ 186 unit = dkunit(bp); 187 if (unit >= NUP) 188 goto bad; 189 ui = updinfo[unit]; 190 if (ui == 0 || ui->ui_alive == 0) 191 goto bad; 192 st = &upst[ui->ui_type]; 193 if (bp->b_blkno < 0 || 194 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 195 goto bad; 196 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 197 (void) spl5(); 198 disksort(&uputab[ui->ui_unit], bp); 199 if (uputab[ui->ui_unit].b_active == 0) { 200 (void) upustart(ui); 201 bp = &ui->ui_mi->um_tab; 202 if (bp->b_actf && bp->b_active == 0) 203 (void) upstart(ui->ui_mi); 204 } 205 (void) spl0(); 206 return; 207 208 bad: 209 bp->b_flags |= B_ERROR; 210 iodone(bp); 211 return; 212 } 213 214 upustart(ui) 215 register struct uba_dinfo *ui; 216 { 217 register struct buf *bp, *dp; 218 register struct uba_minfo *um; 219 register struct device *upaddr; 220 register struct upst *st; 221 daddr_t bn; 222 int sn, cn, csn; 223 int didie = 0; 224 225 /* SC21 cancels commands if you say cs1 = IE, so dont */ 226 /* being ultra-cautious, we clear as bits only in upintr() */ 227 dk_busy &= ~(1<<ui->ui_dk); 228 dp = &uputab[ui->ui_unit]; 229 if ((bp = dp->b_actf) == NULL) 230 goto out; 231 /* dont confuse controller by giving SEARCH while dt in progress */ 232 um = ui->ui_mi; 233 if (um->um_tab.b_active) { 234 up_softc[um->um_num].sc_softas |= 1<<ui->ui_slave; 235 return (0); 236 } 237 if (dp->b_active) 238 goto done; 239 dp->b_active = 1; 240 upaddr = (struct device *)um->um_addr; 241 upaddr->upcs2 = ui->ui_slave; 242 if ((upaddr->upds & VV) == 0) { 243 upaddr->upcs1 = IE|DCLR|GO; 244 upaddr->upcs1 = IE|PRESET|GO; 245 upaddr->upof = FMT22; 246 didie = 1; 247 } 248 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) 249 goto done; 250 st = &upst[ui->ui_type]; 251 bn = dkblock(bp); 252 cn = bp->b_cylin; 253 sn = bn%st->nspc; 254 sn = (sn + st->nsect - upSDIST) % st->nsect; 255 if (cn - upaddr->updc) 256 goto search; /* Not on-cylinder */ 257 /**** WHAT SHOULD THIS BE NOW ??? 258 else if (upseek) 259 goto done; /* Ok just to be on-cylinder */ 260 csn = (upaddr->upla>>6) - sn - 1; 261 if (csn < 0) 262 csn += st->nsect; 263 if (csn > st->nsect - upRDIST) 264 goto done; 265 search: 266 upaddr->updc = cn; 267 /*** ANOTHER OCCURRENCE 268 if (upseek) 269 upaddr->upcs1 = IE|SEEK|GO; 270 else ****/ { 271 upaddr->upda = sn; 272 upaddr->upcs1 = IE|SEARCH|GO; 273 } 274 didie = 1; 275 if (ui->ui_dk >= 0) { 276 dk_busy |= 1<<ui->ui_dk; 277 dk_seek[ui->ui_dk]++; 278 } 279 goto out; 280 done: 281 dp->b_forw = NULL; 282 if (um->um_tab.b_actf == NULL) 283 um->um_tab.b_actf = dp; 284 else 285 um->um_tab.b_actl->b_forw = dp; 286 um->um_tab.b_actl = dp; 287 out: 288 return (didie); 289 } 290 291 upstart(um) 292 register struct uba_minfo *um; 293 { 294 register struct buf *bp, *dp; 295 register struct uba_dinfo *ui; 296 register unit; 297 register struct device *upaddr; 298 register struct upst *st; 299 daddr_t bn; 300 int dn, sn, tn, cn, cmd; 301 302 loop: 303 if ((dp = um->um_tab.b_actf) == NULL) 304 return (0); 305 if ((bp = dp->b_actf) == NULL) { 306 um->um_tab.b_actf = dp->b_forw; 307 goto loop; 308 } 309 /* 310 * Mark the controller busy, and multi-part disk address. 311 * Select the unit on which the i/o is to take place. 312 */ 313 um->um_tab.b_active++; 314 ui = updinfo[dkunit(bp)]; 315 bn = dkblock(bp); 316 dn = ui->ui_slave; 317 st = &upst[ui->ui_type]; 318 sn = bn%st->nspc; 319 tn = sn/st->nsect; 320 sn %= st->nsect; 321 upaddr = (struct device *)ui->ui_addr; 322 if ((upaddr->upcs2 & 07) != dn) 323 upaddr->upcs2 = dn; 324 up_softc[um->um_num].sc_info = 325 ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP|UBA_CANTWAIT); 326 /* 327 * If drive is not present and on-line, then 328 * get rid of this with an error and loop to get 329 * rid of the rest of its queued requests. 330 * (Then on to any other ready drives.) 331 */ 332 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) { 333 printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds); 334 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) { 335 printf("-- hard\n"); 336 um->um_tab.b_active = 0; 337 um->um_tab.b_errcnt = 0; 338 dp->b_actf = bp->av_forw; 339 dp->b_active = 0; 340 bp->b_flags |= B_ERROR; 341 iodone(bp); 342 /* A funny place to do this ... */ 343 ubarelse(&up_softc[um->um_num].sc_info); 344 goto loop; 345 } 346 printf("-- came back\n"); 347 } 348 /* 349 * If this is a retry, then with the 16'th retry we 350 * begin to try offsetting the heads to recover the data. 351 */ 352 if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) { 353 upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | FMT22; 354 upaddr->upcs1 = IE|OFFSET|GO; 355 while (upaddr->upds & PIP) 356 DELAY(25); 357 } 358 /* 359 * Now set up the transfer, retrieving the high 360 * 2 bits of the UNIBUS address from the information 361 * returned by ubasetup() for the cs1 register bits 8 and 9. 362 */ 363 upaddr->updc = cn; 364 upaddr->upda = (tn << 8) + sn; 365 upaddr->upba = up_softc[um->um_num].sc_info; 366 upaddr->upwc = -bp->b_bcount / sizeof (short); 367 cmd = (up_softc[um->um_num].sc_info >> 8) & 0x300; 368 if (bp->b_flags & B_READ) 369 cmd |= IE|RCOM|GO; 370 else 371 cmd |= IE|WCOM|GO; 372 upaddr->upcs1 = cmd; 373 /* 374 * This is a controller busy situation. 375 * Record in dk slot NUP+UPDK_N (after last drive) 376 * unless there aren't that many slots reserved for 377 * us in which case we record this as a drive busy 378 * (if there is room for that). 379 */ 380 unit = ui->ui_dk; 381 dk_busy |= 1<<unit; 382 dk_xfer[unit]++; 383 dk_wds[unit] += bp->b_bcount>>6; 384 return (1); 385 } 386 387 updgo() 388 { 389 } 390 391 /* 392 * Handle a device interrupt. 393 * 394 * If the transferring drive needs attention, service it 395 * retrying on error or beginning next transfer. 396 * Service all other ready drives, calling ustart to transfer 397 * their blocks to the ready queue in um->um_tab, and then restart 398 * the controller if there is anything to do. 399 */ 400 upintr(sc21) 401 register sc21; 402 { 403 register struct buf *bp, *dp; 404 register struct uba_minfo *um = upminfo[sc21]; 405 register struct uba_dinfo *ui; 406 register struct device *upaddr = (struct device *)um->um_addr; 407 register unit; 408 int as = upaddr->upas & 0377; 409 int needie = 1; 410 411 (void) spl6(); 412 up_softc[um->um_num].sc_wticks = 0; 413 if (um->um_tab.b_active) { 414 if ((upaddr->upcs1 & RDY) == 0) { 415 printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1, 416 upaddr->upds, upaddr->upwc); 417 printf("as=%d act %d %d %d\n", as, um->um_tab.b_active, 418 uputab[0].b_active, uputab[1].b_active); 419 } 420 dp = um->um_tab.b_actf; 421 bp = dp->b_actf; 422 ui = updinfo[dkunit(bp)]; 423 dk_busy &= ~(1 << ui->ui_dk); 424 upaddr->upcs2 = ui->ui_slave; 425 if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) { 426 int cs2; 427 while ((upaddr->upds & DRY) == 0) 428 DELAY(25); 429 if (++um->um_tab.b_errcnt > 28 || upaddr->uper1&WLE) 430 bp->b_flags |= B_ERROR; 431 else 432 um->um_tab.b_active = 0; /* force retry */ 433 if (um->um_tab.b_errcnt > 27) { 434 cs2 = (int)upaddr->upcs2; 435 deverror(bp, cs2, (int)upaddr->uper1); 436 } 437 if ((upaddr->uper1&(DCK|ECH))==DCK && upecc(ui)) 438 return; 439 upaddr->upcs1 = TRE|IE|DCLR|GO; 440 needie = 0; 441 if ((um->um_tab.b_errcnt&07) == 4) { 442 upaddr->upcs1 = RECAL|GO|IE; 443 while(upaddr->upds & PIP) 444 DELAY(25); 445 } 446 if (um->um_tab.b_errcnt == 28 && cs2&(NEM|MXF)) { 447 printf("FLAKEY UP "); 448 ubareset(um->um_ubanum); 449 return; 450 } 451 } 452 if (um->um_tab.b_active) { 453 if (um->um_tab.b_errcnt >= 16) { 454 upaddr->upcs1 = RTC|GO|IE; 455 while (upaddr->upds & PIP) 456 DELAY(25); 457 needie = 0; 458 } 459 um->um_tab.b_active = 0; 460 um->um_tab.b_errcnt = 0; 461 um->um_tab.b_actf = dp->b_forw; 462 dp->b_active = 0; 463 dp->b_errcnt = 0; 464 dp->b_actf = bp->av_forw; 465 bp->b_resid = (-upaddr->upwc * sizeof(short)); 466 if (bp->b_resid) 467 printf("resid %d ds %o er? %o %o %o\n", 468 bp->b_resid, upaddr->upds, 469 upaddr->uper1, upaddr->uper2, upaddr->uper3); 470 iodone(bp); 471 if (dp->b_actf) 472 if (upustart(ui)) 473 needie = 0; 474 } 475 up_softc[um->um_num].sc_softas &= ~(1<<ui->ui_slave); 476 ubarelse(&up_softc[um->um_num].sc_info); 477 } else { 478 if (upaddr->upcs1 & TRE) 479 upaddr->upcs1 = TRE; 480 } 481 as |= up_softc[um->um_num].sc_softas; 482 for (unit = 0; unit < NUP; unit++) { 483 if ((ui = updinfo[unit]) == 0 || ui->ui_mi != um) 484 continue; 485 if (as & (1<<unit)) { 486 if (as & (1<<unit)) 487 upaddr->upas = 1<<unit; 488 if (upustart(ui)) 489 needie = 0; 490 } 491 } 492 if (um->um_tab.b_actf && um->um_tab.b_active == 0) 493 if (upstart(um)) 494 needie = 0; 495 if (needie) 496 upaddr->upcs1 = IE; 497 } 498 499 upread(dev) 500 { 501 physio(upstrategy, &rupbuf, dev, B_READ, minphys); 502 } 503 504 upwrite(dev) 505 { 506 physio(upstrategy, &rupbuf, dev, B_WRITE, minphys); 507 } 508 509 /* 510 * Correct an ECC error, and restart the i/o to complete 511 * the transfer if necessary. This is quite complicated because 512 * the transfer may be going to an odd memory address base and/or 513 * across a page boundary. 514 */ 515 upecc(ui) 516 register struct uba_dinfo *ui; 517 { 518 register struct device *up = (struct device *)ui->ui_addr; 519 register struct buf *bp = uputab[ui->ui_unit].b_actf; 520 register struct uba_minfo *um = ui->ui_mi; 521 register struct upst *st; 522 struct uba_regs *ubp = ui->ui_hd->uh_uba; 523 register int i; 524 caddr_t addr; 525 int reg, bit, byte, npf, mask, o, cmd, ubaddr; 526 int bn, cn, tn, sn; 527 528 /* 529 * Npf is the number of sectors transferred before the sector 530 * containing the ECC error, and reg is the UBA register 531 * mapping (the first part of) the transfer. 532 * O is offset within a memory page of the first byte transferred. 533 */ 534 npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1; 535 reg = btop(up_softc[um->um_num].sc_info&0x3ffff) + npf; 536 o = (int)bp->b_un.b_addr & PGOFSET; 537 printf("%D ", bp->b_blkno+npf); 538 prdev("ECC", bp->b_dev); 539 mask = up->upec2; 540 if (mask == 0) { 541 up->upof = FMT22; /* == RTC ???? */ 542 return (0); 543 } 544 /* 545 * Flush the buffered data path, and compute the 546 * byte and bit position of the error. The variable i 547 * is the byte offset in the transfer, the variable byte 548 * is the offset from a page boundary in main memory. 549 */ 550 ubp->uba_dpr[(up_softc[um->um_num].sc_info>>28)&0x0f] |= UBA_BNE; 551 i = up->upec1 - 1; /* -1 makes 0 origin */ 552 bit = i&07; 553 i = (i&~07)>>3; 554 byte = i + o; 555 /* 556 * Correct while possible bits remain of mask. Since mask 557 * contains 11 bits, we continue while the bit offset is > -11. 558 * Also watch out for end of this block and the end of the whole 559 * transfer. 560 */ 561 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 562 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 563 (byte & PGOFSET); 564 putmemc(addr, getmemc(addr)^(mask<<bit)); 565 byte++; 566 i++; 567 bit -= 8; 568 } 569 um->um_tab.b_active++; /* Either complete or continuing... */ 570 if (up->upwc == 0) 571 return (0); 572 /* 573 * Have to continue the transfer... clear the drive, 574 * and compute the position where the transfer is to continue. 575 * We have completed npf+1 sectors of the transfer already; 576 * restart at offset o of next sector (i.e. in UBA register reg+1). 577 */ 578 up->upcs1 = TRE|IE|DCLR|GO; 579 bn = dkblock(bp); 580 st = &upst[ui->ui_type]; 581 cn = bp->b_cylin; 582 sn = bn%st->nspc + npf + 1; 583 tn = sn/st->nsect; 584 sn %= st->nsect; 585 cn += tn/st->ntrak; 586 tn %= st->ntrak; 587 up->updc = cn; 588 up->upda = (tn << 8) | sn; 589 ubaddr = (int)ptob(reg+1) + o; 590 up->upba = ubaddr; 591 cmd = (ubaddr >> 8) & 0x300; 592 cmd |= IE|GO|RCOM; 593 up->upcs1 = cmd; 594 return (1); 595 } 596 597 /* 598 * Reset driver after UBA init. 599 * Cancel software state of all pending transfers 600 * and restart all units and the controller. 601 */ 602 upreset(uban) 603 { 604 register struct uba_minfo *um; 605 register struct uba_dinfo *ui; 606 register sc21, unit; 607 608 /* we should really delay the printf & DELAY till we know 609 * that there is at least one sc21 on this UBA, but then 610 * we would have to remember we had done it before, or the 611 * msg would come twice(or whatever) - but perhaps that 612 * wouldn't be such a bad thing - too many delays would 613 * be annoying however 614 */ 615 printf(" up"); 616 DELAY(15000000); /* give it time to self-test */ 617 for (sc21 = 0; sc21 < NSC21; sc21++) { 618 if ((um = upminfo[sc21]) == 0) 619 continue; 620 if (um->um_ubanum != uban) 621 continue; 622 if (!um->um_alive) 623 continue; 624 um->um_tab.b_active = 0; 625 um->um_tab.b_actf = um->um_tab.b_actl = 0; 626 if (up_softc[um->um_num].sc_info) { 627 printf("<%d>", (up_softc[um->um_num].sc_info>>28)&0xf); 628 ubarelse(&up_softc[um->um_num].sc_info); 629 } 630 ((struct device *)(um->um_addr))->upcs2 = CLR; 631 for (unit = 0; unit < NUP; unit++) { 632 if ((ui = updinfo[unit]) == 0) 633 continue; 634 if (ui->ui_alive == 0) 635 continue; 636 uputab[unit].b_active = 0; 637 (void) upustart(ui); 638 } 639 (void) upstart(um); 640 } 641 } 642 643 /* 644 * Wake up every second and if an interrupt is pending 645 * but nothing has happened increment a counter. 646 * If nothing happens for 20 seconds, reset the controller 647 * and begin anew. 648 */ 649 upwatch() 650 { 651 register struct uba_minfo *um; 652 register sc21, unit; 653 654 timeout(upwatch, (caddr_t)0, HZ); 655 for (sc21 = 0; sc21 < NSC21; sc21++) { 656 um = upminfo[sc21]; 657 if (um->um_tab.b_active == 0) { 658 for (unit = 0; unit < NUP; unit++) 659 if (updinfo[unit]->ui_mi == um && 660 uputab[unit].b_active) 661 goto active; 662 up_softc[sc21].sc_wticks = 0; 663 continue; 664 } 665 active: 666 up_softc[sc21].sc_wticks++; 667 if (up_softc[sc21].sc_wticks >= 20) { 668 up_softc[sc21].sc_wticks = 0; 669 printf("LOST INTERRUPT RESET"); 670 upreset(um->um_ubanum); 671 printf("\n"); 672 } 673 } 674 } 675 676 #define DBSIZE 20 677 678 updump(dev) 679 dev_t dev; 680 { 681 struct device *upaddr; 682 char *start; 683 int num, blk, unit, nsect, ntrak, nspc; 684 struct size *sizes; 685 register struct uba_regs *uba; 686 register struct uba_dinfo *ui; 687 register short *rp; 688 struct upst *st; 689 int bdp; 690 691 unit = minor(dev) >> 3; 692 if (unit >= NUP) { 693 printf("bad unit\n"); 694 return (-1); 695 } 696 #define phys1(cast, addr) ((cast)((int)addr & 0x7fffffff)) 697 #define phys(cast, addr) phys1(cast, phys1(cast *, &addr)) 698 ui = phys(struct uba_dinfo *, updinfo[unit]); 699 if (ui->ui_alive == 0) { 700 printf("dna\n"); 701 return(-1); 702 } 703 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 704 #if VAX780 705 if (cpu == VAX_780) { 706 uba->uba_cr = UBA_ADINIT; 707 uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE; 708 while ((uba->uba_cnfgr & UBA_UBIC) == 0) 709 ; 710 } 711 #endif 712 DELAY(1000000); 713 upaddr = (struct device *)ui->ui_physaddr; 714 while ((upaddr->upcs1&DVA) == 0) 715 ; 716 num = maxfree; 717 start = 0; 718 upaddr->upcs2 = unit; 719 if ((upaddr->upds & VV) == 0) { 720 upaddr->upcs1 = DCLR|GO; 721 upaddr->upcs1 = PRESET|GO; 722 upaddr->upof = FMT22; 723 } 724 if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) { 725 printf("up !DPR || !MOL\n"); 726 return (-1); 727 } 728 st = phys1(struct upst *, &upst[ui->ui_type]); 729 nsect = st->nsect; 730 ntrak = st->ntrak; 731 sizes = phys(struct size *, st->sizes); 732 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) { 733 printf("oor\n"); 734 return (-1); 735 } 736 nspc = st->nspc; 737 while (num > 0) { 738 register struct pte *io; 739 register int i; 740 int cn, sn, tn; 741 daddr_t bn; 742 743 blk = num > DBSIZE ? DBSIZE : num; 744 bdp = 1; /* trick pcc */ 745 uba->uba_dpr[bdp] |= UBA_BNE; 746 io = uba->uba_map; 747 for (i = 0; i < blk; i++) 748 *(int *)io++ = (btop(start)+i) | (1<<21) | UBA_MRV; 749 *(int *)io = 0; 750 bn = dumplo + btop(start); 751 cn = bn/nspc + sizes[minor(dev)&07].cyloff; 752 sn = bn%nspc; 753 tn = sn/nsect; 754 sn = sn%nsect; 755 upaddr->updc = cn; 756 rp = (short *) &upaddr->upda; 757 *rp = (tn << 8) + sn; 758 *--rp = 0; 759 *--rp = -blk*NBPG / sizeof (short); 760 *--rp = GO|WCOM; 761 do { 762 DELAY(25); 763 } while ((upaddr->upcs1 & RDY) == 0); 764 if (upaddr->upcs1&ERR) { 765 printf("up dump dsk err: (%d,%d,%d) cs1=%x, er1=%x\n", 766 cn, tn, sn, upaddr->upcs1, upaddr->uper1); 767 return (-1); 768 } 769 start += blk*NBPG; 770 num -= blk; 771 } 772 bdp = 1; /* crud to fool c compiler */ 773 uba->uba_dpr[bdp] |= UBA_BNE; 774 return (0); 775 } 776 #endif 777