1 /* tm.c 4.22 03/06/81 */ 2 3 #include "te.h" 4 #if NTM > 0 5 int tmgapsdcnt; /* DEBUG */ 6 /* 7 * TM11/TE10 tape driver 8 * 9 * Todo: 10 * Test driver with more than one slave 11 * Test reset code 12 * Do rewinds without hanging in driver 13 */ 14 #define DELAY(N) { register int d = N; while (--d > 0); } 15 #include "../h/param.h" 16 #include "../h/buf.h" 17 #include "../h/dir.h" 18 #include "../h/conf.h" 19 #include "../h/user.h" 20 #include "../h/file.h" 21 #include "../h/map.h" 22 #include "../h/pte.h" 23 #include "../h/vm.h" 24 #include "../h/uba.h" 25 #include "../h/mtio.h" 26 #include "../h/ioctl.h" 27 #include "../h/cmap.h" 28 #include "../h/cpu.h" 29 30 #include "../h/tmreg.h" 31 32 struct buf ctmbuf[NTE]; 33 struct buf rtmbuf[NTE]; 34 35 int tmprobe(), tmslave(), tmattach(), tmdgo(), tmintr(); 36 struct uba_minfo *tmminfo[NTM]; 37 struct uba_dinfo *tmdinfo[NTE]; 38 struct buf tmutab[NTE]; 39 #ifdef notyet 40 struct uba_dinfo *tmip[NTM][4]; 41 #endif 42 u_short tmstd[] = { 0772520, 0 }; 43 struct uba_driver tmdriver = 44 { tmprobe, tmslave, tmattach, tmdgo, tmstd, "te", tmdinfo, "tm", tmminfo, 0 }; 45 46 /* bits in minor device */ 47 #define TMUNIT(dev) (minor(dev)&03) 48 #define T_NOREWIND 04 49 #define T_1600BPI 08 50 51 #define INF (daddr_t)1000000L 52 53 /* 54 * Software state per tape transport. 55 */ 56 struct tm_softc { 57 char sc_openf; /* lock against multiple opens */ 58 char sc_lastiow; /* last op was a write */ 59 daddr_t sc_blkno; /* block number, for block device tape */ 60 daddr_t sc_nxrec; /* desired block position */ 61 u_short sc_erreg; /* copy of last erreg */ 62 u_short sc_dsreg; /* copy of last dsreg */ 63 short sc_resid; /* copy of last bc */ 64 #ifdef notdef 65 short sc_lastcmd; /* last command to handle direction changes */ 66 #endif 67 } tm_softc[NTM]; 68 69 /* 70 * States for um->um_tab.b_active, the 71 * per controller state flag. 72 */ 73 #define SSEEK 1 /* seeking */ 74 #define SIO 2 /* doing seq i/o */ 75 #define SCOM 3 /* sending control command */ 76 #define SREW 4 /* sending a drive rewind */ 77 78 /* WE CURRENTLY HANDLE REWINDS PRIMITIVELY, BUSYING OUT THE CONTROLLER */ 79 /* DURING THE REWIND... IF WE EVER GET TWO TRANSPORTS, WE CAN DEBUG MORE */ 80 /* SOPHISTICATED LOGIC... THIS SIMPLE CODE AT LEAST MAY WORK. */ 81 82 /* 83 * Determine if there is a controller for 84 * a tm at address reg. Our goal is to make the 85 * device interrupt. 86 */ 87 tmprobe(reg) 88 caddr_t reg; 89 { 90 register int br, cvec; 91 92 #ifdef lint 93 br = 0; br = cvec; cvec = br; 94 #endif 95 ((struct device *)reg)->tmcs = TM_IE; 96 /* 97 * If this is a tm11, it ought to have interrupted 98 * by now, if it isn't (ie: it is a ts04) then we just 99 * hope that it didn't interrupt, so autoconf will ignore it. 100 * Just in case, we will reference one 101 * of the more distant registers, and hope for a machine 102 * check, or similar disaster if this is a ts. 103 * 104 * Note: on an 11/780, badaddr will just generate 105 * a uba error for a ts; but our caller will notice that 106 * so we won't check for it. 107 */ 108 if (badaddr(&((struct device *)reg)->tmrd, 2)) 109 return (0); 110 return (1); 111 } 112 113 /* 114 * Due to a design flaw, we cannot ascertain if the tape 115 * exists or not unless it is on line - ie: unless a tape is 116 * mounted. This is too servere a restriction to bear, 117 * so all units are assumed to exist. 118 */ 119 /*ARGSUSED*/ 120 tmslave(ui, reg) 121 struct uba_dinfo *ui; 122 caddr_t reg; 123 { 124 125 return (1); 126 } 127 128 /* 129 * Record attachment of the unit to the controller port. 130 */ 131 /*ARGSUSED*/ 132 tmattach(ui) 133 struct uba_dinfo *ui; 134 { 135 136 #ifdef notyet 137 tmip[ui->ui_ctlr][ui->ui_slave] = ui; 138 #endif 139 } 140 141 /* 142 * Open the device. Tapes are unique open 143 * devices, so we refuse if it is already open. 144 * We also check that a tape is available, and 145 * don't block waiting here. 146 */ 147 tmopen(dev, flag) 148 dev_t dev; 149 int flag; 150 { 151 register int unit; 152 register struct uba_dinfo *ui; 153 register struct tm_softc *sc; 154 155 unit = TMUNIT(dev); 156 if (unit>=NTE || (sc = &tm_softc[unit])->sc_openf || 157 (ui = tmdinfo[unit]) == 0 || ui->ui_alive == 0) { 158 u.u_error = ENXIO; 159 return; 160 } 161 tmcommand(dev, TM_SENSE, 1); 162 if ((sc->sc_erreg&(TM_SELR|TM_TUR)) != (TM_SELR|TM_TUR) || 163 (flag&(FREAD|FWRITE)) == FWRITE && sc->sc_erreg&TM_WRL) { 164 u.u_error = EIO; 165 return; 166 } 167 sc->sc_openf = 1; 168 sc->sc_blkno = (daddr_t)0; 169 sc->sc_nxrec = INF; 170 sc->sc_lastiow = 0; 171 } 172 173 /* 174 * Close tape device. 175 * 176 * If tape was open for writing or last operation was 177 * a write, then write two EOF's and backspace over the last one. 178 * Unless this is a non-rewinding special file, rewind the tape. 179 * Make the tape available to others. 180 */ 181 tmclose(dev, flag) 182 register dev_t dev; 183 register flag; 184 { 185 register struct tm_softc *sc = &tm_softc[TMUNIT(dev)]; 186 187 if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) { 188 tmcommand(dev, TM_WEOF, 1); 189 tmcommand(dev, TM_WEOF, 1); 190 tmcommand(dev, TM_SREV, 1); 191 } 192 if ((minor(dev)&T_NOREWIND) == 0) 193 tmcommand(dev, TM_REW, 1); 194 sc->sc_openf = 0; 195 } 196 197 /* 198 * Execute a command on the tape drive 199 * a specified number of times. 200 */ 201 tmcommand(dev, com, count) 202 dev_t dev; 203 int com, count; 204 { 205 register struct buf *bp; 206 207 bp = &ctmbuf[TMUNIT(dev)]; 208 (void) spl5(); 209 while (bp->b_flags&B_BUSY) { 210 bp->b_flags |= B_WANTED; 211 sleep((caddr_t)bp, PRIBIO); 212 } 213 bp->b_flags = B_BUSY|B_READ; 214 (void) spl0(); 215 bp->b_dev = dev; 216 bp->b_repcnt = -count; 217 bp->b_command = com; 218 bp->b_blkno = 0; 219 tmstrategy(bp); 220 iowait(bp); 221 if (bp->b_flags&B_WANTED) 222 wakeup((caddr_t)bp); 223 bp->b_flags &= B_ERROR; 224 } 225 226 /* 227 * Decipher a tape operation and do what is needed 228 * to see that it happens. 229 */ 230 tmstrategy(bp) 231 register struct buf *bp; 232 { 233 int unit = TMUNIT(bp->b_dev); 234 register struct uba_minfo *um; 235 register struct buf *dp; 236 register struct tm_softc *sc = &tm_softc[unit]; 237 238 /* 239 * Put transfer at end of unit queue 240 */ 241 dp = &tmutab[unit]; 242 bp->av_forw = NULL; 243 (void) spl5(); 244 if (dp->b_actf == NULL) { 245 dp->b_actf = bp; 246 /* 247 * Transport not already active... 248 * put at end of controller queue. 249 */ 250 dp->b_forw = NULL; 251 um = tmdinfo[unit]->ui_mi; 252 if (um->um_tab.b_actf == NULL) 253 um->um_tab.b_actf = dp; 254 else 255 um->um_tab.b_actl->b_forw = dp; 256 um->um_tab.b_actl = dp; 257 } else 258 dp->b_actl->av_forw = bp; 259 dp->b_actl = bp; 260 /* 261 * If the controller is not busy, get 262 * it going. 263 */ 264 if (um->um_tab.b_active == 0) 265 tmstart(um); 266 (void) spl0(); 267 } 268 269 /* 270 * Start activity on a tm controller. 271 */ 272 tmstart(um) 273 register struct uba_minfo *um; 274 { 275 register struct buf *bp, *dp; 276 register struct device *addr = (struct device *)um->um_addr; 277 register struct tm_softc *sc; 278 register struct uba_dinfo *ui; 279 int unit, cmd; 280 daddr_t blkno; 281 282 /* 283 * Look for an idle transport on the controller. 284 */ 285 loop: 286 if ((dp = um->um_tab.b_actf) == NULL) 287 return; 288 if ((bp = dp->b_actf) == NULL) { 289 um->um_tab.b_actf = dp->b_forw; 290 goto loop; 291 } 292 unit = TMUNIT(bp->b_dev); 293 ui = tmdinfo[unit]; 294 /* 295 * Record pre-transfer status (e.g. for TM_SENSE) 296 */ 297 sc = &tm_softc[unit]; 298 addr = (struct device *)um->um_addr; 299 addr->tmcs = (ui->ui_slave << 8); 300 sc->sc_dsreg = addr->tmcs; 301 sc->sc_erreg = addr->tmer; 302 sc->sc_resid = addr->tmbc; 303 /* 304 * Default is that last command was NOT a write command; 305 * if we do a write command we will notice this in tmintr(). 306 */ 307 sc->sc_lastiow = 1; 308 if (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) { 309 /* 310 * Have had a hard error on this (non-raw) tape, 311 * or the tape unit is now unavailable (e.g. taken off 312 * line). 313 */ 314 bp->b_flags |= B_ERROR; 315 goto next; 316 } 317 /* 318 * If operation is not a control operation, 319 * check for boundary conditions. 320 */ 321 if (bp != &ctmbuf[unit]) { 322 if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 323 bp->b_flags |= B_ERROR; 324 bp->b_error = ENXIO; /* past EOF */ 325 goto next; 326 } 327 if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 328 bp->b_flags&B_READ) { 329 bp->b_resid = bp->b_bcount; 330 clrbuf(bp); /* at EOF */ 331 goto next; 332 } 333 if ((bp->b_flags&B_READ) == 0) 334 /* write sets EOF */ 335 sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 336 } 337 /* 338 * Set up the command, and then if this is a mt ioctl, 339 * do the operation using, for TM_SFORW and TM_SREV, the specified 340 * operation count. 341 */ 342 cmd = TM_IE | TM_GO | (ui->ui_slave << 8); 343 if ((minor(bp->b_dev) & T_1600BPI) == 0) 344 cmd |= TM_D800; 345 if (bp == &ctmbuf[unit]) { 346 if (bp->b_command == TM_SENSE) 347 goto next; 348 um->um_tab.b_active = 349 bp->b_command == TM_REW ? SREW : SCOM; 350 if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV) 351 addr->tmbc = bp->b_repcnt; 352 goto dobpcmd; 353 } 354 /* 355 * If the data transfer command is in the correct place, 356 * set up all the registers except the csr, and give 357 * control over to the UNIBUS adapter routines, to 358 * wait for resources to start the i/o. 359 */ 360 if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 361 addr->tmbc = -bp->b_bcount; 362 if ((bp->b_flags&B_READ) == 0) { 363 if (um->um_tab.b_errcnt) 364 cmd |= TM_WIRG; 365 else 366 cmd |= TM_WCOM; 367 } else 368 cmd |= TM_RCOM; 369 um->um_tab.b_active = SIO; 370 um->um_cmd = cmd; 371 #ifdef notdef 372 if (tmreverseop(sc->sc_lastcmd)) 373 while (addr->tmer & TM_SDWN) 374 tmgapsdcnt++; 375 sc->sc_lastcmd = TM_RCOM; /* will serve */ 376 #endif 377 ubago(ui); 378 return; 379 } 380 /* 381 * Block tape positioned incorrectly; 382 * seek forwards or backwards to the correct spot. 383 */ 384 um->um_tab.b_active = SSEEK; 385 if (blkno < dbtofsb(bp->b_blkno)) { 386 bp->b_command = TM_SFORW; 387 addr->tmbc = blkno - dbtofsb(bp->b_blkno); 388 } else { 389 bp->b_command = TM_SREV; 390 addr->tmbc = dbtofsb(bp->b_blkno) - blkno; 391 } 392 dobpcmd: 393 #ifdef notdef 394 if (tmreverseop(sc->sc_lastcmd) != tmreverseop(bp->b_command)) 395 while (addr->tmer & TM_SDWN) 396 tmgapsdcnt++; 397 sc->sc_lastcmd = bp->b_command; 398 #endif 399 addr->tmcs = (cmd | bp->b_command); 400 return; 401 402 next: 403 /* 404 * Done with this operation due to error or 405 * the fact that it doesn't do anything. 406 * Release UBA resources (if any), dequeue 407 * the transfer and continue processing this slave. 408 */ 409 if (um->um_ubinfo) 410 ubadone(um); 411 um->um_tab.b_errcnt = 0; 412 dp->b_actf = bp->av_forw; 413 iodone(bp); 414 goto loop; 415 } 416 417 /* 418 * The UNIBUS resources we needed have been 419 * allocated to us; start the device. 420 */ 421 tmdgo(um) 422 register struct uba_minfo *um; 423 { 424 register struct device *addr = (struct device *)um->um_addr; 425 426 addr->tmba = um->um_ubinfo; 427 addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30); 428 } 429 430 /* 431 * Tm interrupt routine. 432 */ 433 /*ARGSUSED*/ 434 tmintr(tm11) 435 int tm11; 436 { 437 struct buf *dp; 438 register struct buf *bp; 439 register struct uba_minfo *um = tmminfo[tm11]; 440 register struct device *addr = (struct device *)tmdinfo[tm11]->ui_addr; 441 register struct tm_softc *sc; 442 int unit; 443 register state; 444 445 /* 446 * If last command was a rewind, and tape is still 447 * rewinding, wait for the rewind complete interrupt. 448 */ 449 if (um->um_tab.b_active == SREW) { 450 um->um_tab.b_active = SCOM; 451 if (addr->tmer&TM_RWS) 452 return; 453 } 454 /* 455 * An operation completed... record status 456 */ 457 if ((dp = um->um_tab.b_actf) == NULL) 458 return; 459 bp = dp->b_actf; 460 unit = TMUNIT(bp->b_dev); 461 sc = &tm_softc[unit]; 462 sc->sc_dsreg = addr->tmcs; 463 sc->sc_erreg = addr->tmer; 464 sc->sc_resid = addr->tmbc; 465 if ((bp->b_flags & B_READ) == 0) 466 sc->sc_lastiow = 1; 467 state = um->um_tab.b_active; 468 um->um_tab.b_active = 0; 469 /* 470 * Check for errors. 471 */ 472 if (addr->tmcs&TM_ERR) { 473 while (addr->tmer & TM_SDWN) 474 ; /* await settle down */ 475 /* 476 * If we hit the end of the tape update our position. 477 */ 478 if (addr->tmer&TM_EOF) { 479 tmseteof(bp); /* set blkno and nxrec */ 480 state = SCOM; /* force completion */ 481 /* 482 * Stuff bc so it will be unstuffed correctly 483 * later to get resid. 484 */ 485 addr->tmbc = -bp->b_bcount; 486 goto opdone; 487 } 488 /* 489 * If we were reading and the only error was that the 490 * record was to long, then we don't consider this an error. 491 */ 492 if ((bp->b_flags&B_READ) && 493 (addr->tmer&(TM_HARD|TM_SOFT)) == TM_RLE) 494 goto ignoreerr; 495 /* 496 * If error is not hard, and this was an i/o operation 497 * retry up to 8 times. 498 */ 499 if ((addr->tmer&TM_HARD)==0 && state==SIO) { 500 if (++um->um_tab.b_errcnt < 7) { 501 sc->sc_blkno++; 502 ubadone(um); 503 goto opcont; 504 } 505 } else 506 /* 507 * Hard or non-i/o errors on non-raw tape 508 * cause it to close. 509 */ 510 if (sc->sc_openf>0 && bp != &rtmbuf[unit]) 511 sc->sc_openf = -1; 512 /* 513 * Couldn't recover error 514 */ 515 printf("te%d: hard error bn%d er=%b\n", minor(bp->b_dev)&03, 516 bp->b_blkno, sc->sc_erreg, TMEREG_BITS); 517 bp->b_flags |= B_ERROR; 518 goto opdone; 519 } 520 /* 521 * Advance tape control FSM. 522 */ 523 ignoreerr: 524 switch (state) { 525 526 case SIO: 527 /* 528 * Read/write increments tape block number 529 */ 530 sc->sc_blkno++; 531 goto opdone; 532 533 case SCOM: 534 /* 535 * Unless special operation, op completed. 536 */ 537 if (bp != &ctmbuf[unit]) 538 goto opdone; 539 /* 540 * Operation on block device... 541 * iterate operations which don't repeat 542 * for themselves in the hardware; for forward/ 543 * backward space record update the current position. 544 */ 545 switch (bp->b_command) { 546 547 case TM_SFORW: 548 sc->sc_blkno -= bp->b_repcnt; 549 goto opdone; 550 551 case TM_SREV: 552 sc->sc_blkno += bp->b_repcnt; 553 goto opdone; 554 555 default: 556 if (++bp->b_repcnt < 0) 557 goto opcont; 558 goto opdone; 559 } 560 561 case SSEEK: 562 sc->sc_blkno = dbtofsb(bp->b_blkno); 563 goto opcont; 564 565 default: 566 panic("tmintr"); 567 } 568 opdone: 569 /* 570 * Reset error count and remove 571 * from device queue. 572 */ 573 um->um_tab.b_errcnt = 0; 574 dp->b_actf = bp->av_forw; 575 bp->b_resid = -addr->tmbc; 576 ubadone(um); 577 iodone(bp); 578 /* 579 * Circulate slave to end of controller 580 * queue to give other slaves a chance. 581 */ 582 um->um_tab.b_actf = dp->b_forw; 583 if (dp->b_actf) { 584 dp->b_forw = NULL; 585 if (um->um_tab.b_actf == NULL) 586 um->um_tab.b_actf = dp; 587 else 588 um->um_tab.b_actl->b_forw = dp; 589 um->um_tab.b_actl = dp; 590 } 591 if (um->um_tab.b_actf == 0) 592 return; 593 opcont: 594 tmstart(um); 595 } 596 597 tmseteof(bp) 598 register struct buf *bp; 599 { 600 register int unit = TMUNIT(bp->b_dev); 601 register struct device *addr = 602 (struct device *)tmdinfo[unit]->ui_addr; 603 register struct tm_softc *sc = &tm_softc[unit]; 604 605 if (bp == &ctmbuf[unit]) { 606 if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 607 /* reversing */ 608 sc->sc_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc; 609 sc->sc_blkno = sc->sc_nxrec; 610 } else { 611 /* spacing forward */ 612 sc->sc_blkno = dbtofsb(bp->b_blkno) + addr->tmbc; 613 sc->sc_nxrec = sc->sc_blkno - 1; 614 } 615 return; 616 } 617 /* eof on read */ 618 sc->sc_nxrec = dbtofsb(bp->b_blkno); 619 } 620 621 tmread(dev) 622 dev_t dev; 623 { 624 625 tmphys(dev); 626 physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_READ, minphys); 627 } 628 629 tmwrite(dev) 630 dev_t dev; 631 { 632 633 tmphys(dev); 634 physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_WRITE, minphys); 635 } 636 637 tmphys(dev) 638 dev_t dev; 639 { 640 register daddr_t a; 641 register struct tm_softc *sc = &tm_softc[TMUNIT(dev)]; 642 643 a = dbtofsb(u.u_offset >> 9); 644 sc->sc_blkno = a; 645 sc->sc_nxrec = a + 1; 646 } 647 648 tmreset(uban) 649 int uban; 650 { 651 register struct uba_minfo *um; 652 register tm11, unit; 653 register struct uba_dinfo *ui; 654 register struct buf *dp; 655 656 for (tm11 = 0; tm11 < NTM; tm11++) { 657 if ((um = tmminfo[tm11]) == 0 || um->um_alive == 0 || 658 um->um_ubanum != uban) 659 continue; 660 printf(" tm%d", tm11); 661 um->um_tab.b_active = 0; 662 um->um_tab.b_actf = um->um_tab.b_actl = 0; 663 if (um->um_ubinfo) { 664 printf("<%d>", (um->um_ubinfo>>28)&0xf); 665 ubadone(um); 666 } 667 ((struct device *)(um->um_addr))->tmcs = TM_DCLR; 668 for (unit = 0; unit < NTE; unit++) { 669 if ((ui = tmdinfo[unit]) == 0) 670 continue; 671 if (ui->ui_alive == 0) 672 continue; 673 dp = &tmutab[unit]; 674 dp->b_active = 0; 675 dp->b_forw = 0; 676 if (um->um_tab.b_actf == NULL) 677 um->um_tab.b_actf = dp; 678 else 679 um->um_tab.b_actl->b_forw = dp; 680 um->um_tab.b_actl = dp; 681 tm_softc[unit].sc_openf = -1; 682 } 683 tmstart(um); 684 } 685 } 686 687 /*ARGSUSED*/ 688 tmioctl(dev, cmd, addr, flag) 689 caddr_t addr; 690 dev_t dev; 691 { 692 int unit = TMUNIT(dev); 693 register struct tm_softc *sc = &tm_softc[unit]; 694 register struct buf *bp = &ctmbuf[unit]; 695 register callcount; 696 int fcount; 697 struct mtop mtop; 698 struct mtget mtget; 699 /* we depend of the values and order of the MT codes here */ 700 static tmops[] = 701 {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE}; 702 703 switch (cmd) { 704 case MTIOCTOP: /* tape operation */ 705 if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 706 u.u_error = EFAULT; 707 return; 708 } 709 switch(mtop.mt_op) { 710 case MTWEOF: 711 callcount = mtop.mt_count; 712 fcount = 1; 713 break; 714 case MTFSF: case MTBSF: 715 callcount = mtop.mt_count; 716 fcount = INF; 717 break; 718 case MTFSR: case MTBSR: 719 callcount = 1; 720 fcount = mtop.mt_count; 721 break; 722 case MTREW: case MTOFFL: case MTNOP: 723 callcount = 1; 724 fcount = 1; 725 break; 726 default: 727 u.u_error = ENXIO; 728 return; 729 } 730 if (callcount <= 0 || fcount <= 0) { 731 u.u_error = ENXIO; 732 return; 733 } 734 while (--callcount >= 0) { 735 tmcommand(dev, tmops[mtop.mt_op], fcount); 736 if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 737 bp->b_resid) { 738 u.u_error = EIO; 739 break; 740 } 741 if ((bp->b_flags&B_ERROR) || sc->sc_erreg&TM_BOT) 742 break; 743 } 744 geterror(bp); 745 return; 746 case MTIOCGET: 747 mtget.mt_dsreg = sc->sc_dsreg; 748 mtget.mt_erreg = sc->sc_erreg; 749 mtget.mt_resid = sc->sc_resid; 750 if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 751 u.u_error = EFAULT; 752 return; 753 default: 754 u.u_error = ENXIO; 755 } 756 } 757 758 #define DBSIZE 20 759 760 tmdump() 761 { 762 register struct uba_dinfo *ui; 763 register struct uba_regs *up; 764 register struct device *addr; 765 int blk, num; 766 int start; 767 768 start = 0; 769 num = maxfree; 770 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 771 if (tmdinfo[0] == 0) 772 return (ENXIO); 773 ui = phys(tmdinfo[0], struct uba_dinfo *); 774 up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 775 #if VAX780 776 if (cpu == VAX_780) 777 ubainit(up); 778 #endif 779 DELAY(1000000); 780 addr = (struct device *)ui->ui_physaddr; 781 tmwait(addr); 782 addr->tmcs = TM_DCLR | TM_GO; 783 while (num > 0) { 784 blk = num > DBSIZE ? DBSIZE : num; 785 tmdwrite(start, blk, addr, up); 786 start += blk; 787 num -= blk; 788 } 789 tmeof(addr); 790 tmeof(addr); 791 tmwait(addr); 792 if (addr->tmcs&TM_ERR) 793 return (EIO); 794 addr->tmcs = TM_REW | TM_GO; 795 tmwait(addr); 796 return (0); 797 } 798 799 tmdwrite(dbuf, num, addr, up) 800 register dbuf, num; 801 register struct device *addr; 802 struct uba_regs *up; 803 { 804 register struct pte *io; 805 register int npf; 806 807 tmwait(addr); 808 io = up->uba_map; 809 npf = num+1; 810 while (--npf != 0) 811 *(int *)io++ = (dbuf++ | (1<<UBA_DPSHIFT) | UBA_MRV); 812 *(int *)io = 0; 813 addr->tmbc = -(num*NBPG); 814 addr->tmba = 0; 815 addr->tmcs = TM_WCOM | TM_GO; 816 } 817 818 tmwait(addr) 819 register struct device *addr; 820 { 821 register s; 822 823 do 824 s = addr->tmcs; 825 while ((s & TM_CUR) == 0); 826 } 827 828 tmeof(addr) 829 struct device *addr; 830 { 831 832 tmwait(addr); 833 addr->tmcs = TM_WEOF | TM_GO; 834 } 835 #endif 836