1 /* ts.c 4.27 82/08/13 */ 2 3 #include "ts.h" 4 #if NTS > 0 5 /* 6 * TS11 tape driver 7 * 8 * TODO: 9 * write dump code 10 */ 11 #include "../h/param.h" 12 #include "../h/systm.h" 13 #include "../h/buf.h" 14 #include "../h/dir.h" 15 #include "../h/conf.h" 16 #include "../h/user.h" 17 #include "../h/file.h" 18 #include "../h/map.h" 19 #include "../h/pte.h" 20 #include "../h/vm.h" 21 #include "../h/ubareg.h" 22 #include "../h/ubavar.h" 23 #include "../h/ioctl.h" 24 #include "../h/mtio.h" 25 #include "../h/cmap.h" 26 #include "../h/cpu.h" 27 #include "../h/uio.h" 28 29 #include "../h/tsreg.h" 30 31 /* 32 * There is a ctsbuf per tape controller. 33 * It is used as the token to pass to the internal routines 34 * to execute tape ioctls. 35 * In particular, when the tape is rewinding on close we release 36 * the user process but any further attempts to use the tape drive 37 * before the rewind completes will hang waiting for ctsbuf. 38 */ 39 struct buf ctsbuf[NTS]; 40 41 /* 42 * Raw tape operations use rtsbuf. The driver 43 * notices when rtsbuf is being used and allows the user 44 * program to continue after errors and read records 45 * not of the standard length (BSIZE). 46 */ 47 struct buf rtsbuf[NTS]; 48 49 /* 50 * Driver unibus interface routines and variables. 51 */ 52 int tsprobe(), tsslave(), tsattach(), tsdgo(), tsintr(); 53 struct uba_ctlr *tsminfo[NTS]; 54 struct uba_device *tsdinfo[NTS]; 55 struct buf tsutab[NTS]; 56 u_short tsstd[] = { 0772520, 0 }; 57 /*** PROBABLY DON'T NEED ALL THESE SINCE CONTROLLER == DRIVE ***/ 58 struct uba_driver zsdriver = 59 { tsprobe, tsslave, tsattach, tsdgo, tsstd, "ts", tsdinfo, "zs", tsminfo, 0 }; 60 61 /* bits in minor device */ 62 #define TSUNIT(dev) (minor(dev)&03) 63 #define T_NOREWIND 04 64 65 #define INF (daddr_t)1000000L 66 67 /* 68 * Software state per tape transport. 69 * Also contains hardware state in message packets. 70 * 71 * 1. A tape drive is a unique-open device; we refuse opens when it is already. 72 * 2. We keep track of the current position on a block tape and seek 73 * before operations by forward/back spacing if necessary. 74 * 3. We remember if the last operation was a write on a tape, so if a tape 75 * is open read write and the last thing done is a write we can 76 * write a standard end of tape mark (two eofs). 77 * 4. We remember the status registers after the last command, using 78 * then internally and returning them to the SENSE ioctl. 79 */ 80 struct ts_softc { 81 char sc_openf; /* lock against multiple opens */ 82 char sc_lastiow; /* last op was a write */ 83 short sc_resid; /* copy of last bc */ 84 daddr_t sc_blkno; /* block number, for block device tape */ 85 daddr_t sc_nxrec; /* position of end of tape, if known */ 86 struct ts_cmd sc_cmd; /* the command packet */ 87 struct ts_sts sc_sts; /* status packet, for returned status */ 88 struct ts_char sc_char; /* characteristics packet */ 89 struct ts_softc *sc_ubaddr; /* Unibus address of ts_softc structure */ 90 u_short sc_uba; /* Unibus addr of cmd pkt for tsdb */ 91 short sc_mapped; /* is ts_sfotc mapped in Unibus space? */ 92 } ts_softc[NTS]; 93 94 /* 95 * States for um->um_tab.b_active, the per controller state flag. 96 * This is used to sequence control in the driver. 97 */ 98 #define SSEEK 1 /* seeking */ 99 #define SIO 2 /* doing seq i/o */ 100 #define SCOM 3 /* sending control command */ 101 #define SREW 4 /* sending a drive rewind */ 102 103 /* 104 * Determine if there is a controller for 105 * a ts at address reg. Our goal is to make the 106 * device interrupt. 107 */ 108 /*ARGSUSED*/ 109 tsprobe(reg) 110 caddr_t reg; 111 { 112 register int br, cvec; /* must be r11,r10; value-result */ 113 114 #ifdef lint 115 br = 0; cvec = br; br = cvec; 116 tsintr(0); 117 #endif 118 ((struct tsdevice *)reg)->tssr = 0; 119 DELAY(100); 120 if ((((struct tsdevice *)reg)->tssr & TS_NBA) == 0) 121 return(0); 122 /* IT'S TOO HARD TO MAKE THIS THING INTERRUPT JUST TO FIND ITS VECTOR */ 123 cvec = ((unsigned)reg) & 07 ? 0260 : 0224; 124 br = 0x15; 125 return (sizeof (struct tsdevice)); 126 } 127 128 /* 129 * TS11 only supports one drive per controller; 130 * check for ui_slave == 0. 131 * 132 * DO WE REALLY NEED THIS ROUTINE??? 133 */ 134 /*ARGSUSED*/ 135 tsslave(ui, reg) 136 struct uba_device *ui; 137 caddr_t reg; 138 { 139 140 if (ui->ui_slave) /* non-zero slave not allowed */ 141 return(0); 142 return (1); 143 } 144 145 /* 146 * Record attachment of the unit to the controller. 147 * 148 * SHOULD THIS ROUTINE DO ANYTHING??? 149 */ 150 /*ARGSUSED*/ 151 tsattach(ui) 152 struct uba_device *ui; 153 { 154 155 } 156 157 /* 158 * Open the device. Tapes are unique open 159 * devices, so we refuse if it is already open. 160 * We also check that a tape is available, and 161 * don't block waiting here; if you want to wait 162 * for a tape you should timeout in user code. 163 */ 164 tsopen(dev, flag) 165 dev_t dev; 166 int flag; 167 { 168 register int tsunit; 169 register struct uba_device *ui; 170 register struct ts_softc *sc; 171 172 tsunit = TSUNIT(dev); 173 if (tsunit>=NTS || (sc = &ts_softc[tsunit])->sc_openf || 174 (ui = tsdinfo[tsunit]) == 0 || ui->ui_alive == 0) { 175 u.u_error = ENXIO; 176 return; 177 } 178 if (tsinit(tsunit)) { 179 u.u_error = ENXIO; 180 return; 181 } 182 tscommand(dev, TS_SENSE, 1); 183 if ((sc->sc_sts.s_xs0&TS_ONL) == 0) { 184 uprintf("ts%d: not online\n", tsunit); 185 u.u_error = EIO; 186 return; 187 } 188 if ((flag&(FREAD|FWRITE)) == FWRITE && (sc->sc_sts.s_xs0&TS_WLK)) { 189 uprintf("ts%d: no write ring\n", tsunit); 190 u.u_error = EIO; 191 return; 192 } 193 sc->sc_openf = 1; 194 sc->sc_blkno = (daddr_t)0; 195 sc->sc_nxrec = INF; 196 sc->sc_lastiow = 0; 197 } 198 199 /* 200 * Close tape device. 201 * 202 * If tape was open for writing or last operation was 203 * a write, then write two EOF's and backspace over the last one. 204 * Unless this is a non-rewinding special file, rewind the tape. 205 * Make the tape available to others. 206 */ 207 tsclose(dev, flag) 208 register dev_t dev; 209 register flag; 210 { 211 register struct ts_softc *sc = &ts_softc[TSUNIT(dev)]; 212 213 if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) { 214 tscommand(dev, TS_WEOF, 1); 215 tscommand(dev, TS_WEOF, 1); 216 tscommand(dev, TS_SREV, 1); 217 } 218 if ((minor(dev)&T_NOREWIND) == 0) 219 /* 220 * 0 count means don't hang waiting for rewind complete 221 * rather ctsbuf stays busy until the operation completes 222 * preventing further opens from completing by 223 * preventing a TS_SENSE from completing. 224 */ 225 tscommand(dev, TS_REW, 0); 226 sc->sc_openf = 0; 227 } 228 229 /* 230 * Initialize the TS11. Set up Unibus mapping for command 231 * packets and set device characteristics. 232 */ 233 tsinit(unit) 234 register int unit; 235 { 236 register struct ts_softc *sc = &ts_softc[unit]; 237 register struct uba_ctlr *um = tsminfo[unit]; 238 register struct tsdevice *addr = (struct tsdevice *)um->um_addr; 239 register int i; 240 241 /* 242 * Map the command and message packets into Unibus 243 * address space. We do all the command and message 244 * packets at once to minimize the amount of Unibus 245 * mapping necessary. 246 */ 247 if (sc->sc_mapped == 0) { 248 ctsbuf[unit].b_un.b_addr = (caddr_t)sc; 249 ctsbuf[unit].b_bcount = sizeof(*sc); 250 i = ubasetup(um->um_ubanum, &ctsbuf[unit], 0); 251 i &= 0777777; 252 sc->sc_ubaddr = (struct ts_softc *)i; 253 sc->sc_mapped++; 254 } 255 /* 256 * Now initialize the TS11 controller. 257 * Set the characteristics. 258 */ 259 if (addr->tssr & (TS_NBA|TS_OFL)) { 260 addr->tssr = 0; /* subsystem initialize */ 261 tswait(addr); 262 i = (int)&sc->sc_ubaddr->sc_cmd; /* Unibus addr of cmd */ 263 sc->sc_uba = (u_short)(i + ((i>>16)&3)); 264 sc->sc_char.char_addr = (int)&sc->sc_ubaddr->sc_sts; 265 sc->sc_char.char_size = sizeof(struct ts_sts); 266 sc->sc_char.char_mode = TS_ESS; 267 sc->sc_cmd.c_cmd = TS_ACK | TS_SETCHR; 268 i = (int)&sc->sc_ubaddr->sc_char; 269 sc->sc_cmd.c_loba = i; 270 sc->sc_cmd.c_hiba = (i>>16)&3; 271 sc->sc_cmd.c_size = sizeof(struct ts_char); 272 addr->tsdb = sc->sc_uba; 273 tswait(addr); 274 if (addr->tssr & TS_NBA) 275 return(1); 276 } 277 return(0); 278 } 279 280 /* 281 * Execute a command on the tape drive 282 * a specified number of times. 283 */ 284 tscommand(dev, com, count) 285 dev_t dev; 286 int com, count; 287 { 288 register struct buf *bp; 289 register int s; 290 291 bp = &ctsbuf[TSUNIT(dev)]; 292 s = spl5(); 293 while (bp->b_flags&B_BUSY) { 294 /* 295 * This special check is because B_BUSY never 296 * gets cleared in the non-waiting rewind case. 297 */ 298 if (bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 299 break; 300 bp->b_flags |= B_WANTED; 301 sleep((caddr_t)bp, PRIBIO); 302 } 303 bp->b_flags = B_BUSY|B_READ; 304 splx(s); 305 bp->b_dev = dev; 306 bp->b_repcnt = count; 307 bp->b_command = com; 308 bp->b_blkno = 0; 309 tsstrategy(bp); 310 /* 311 * In case of rewind from close, don't wait. 312 * This is the only case where count can be 0. 313 */ 314 if (count == 0) 315 return; 316 iowait(bp); 317 if (bp->b_flags&B_WANTED) 318 wakeup((caddr_t)bp); 319 bp->b_flags &= B_ERROR; 320 } 321 322 /* 323 * Queue a tape operation. 324 */ 325 tsstrategy(bp) 326 register struct buf *bp; 327 { 328 int tsunit = TSUNIT(bp->b_dev); 329 register struct uba_ctlr *um; 330 register struct buf *dp; 331 register int s; 332 333 /* 334 * Put transfer at end of controller queue 335 */ 336 bp->av_forw = NULL; 337 um = tsdinfo[tsunit]->ui_mi; 338 s = spl5(); 339 dp = &tsutab[tsunit]; 340 if (dp->b_actf == NULL) 341 dp->b_actf = bp; 342 else 343 dp->b_actl->av_forw = bp; 344 dp->b_actl = bp; 345 um->um_tab.b_actf = um->um_tab.b_actl = dp; 346 /* 347 * If the controller is not busy, get 348 * it going. 349 */ 350 if (um->um_tab.b_active == 0) 351 tsstart(um); 352 splx(s); 353 } 354 355 /* 356 * Start activity on a ts controller. 357 */ 358 tsstart(um) 359 register struct uba_ctlr *um; 360 { 361 register struct buf *bp; 362 register struct tsdevice *addr = (struct tsdevice *)um->um_addr; 363 register struct ts_softc *sc; 364 register struct ts_cmd *tc; 365 register struct uba_device *ui; 366 int tsunit, cmd; 367 daddr_t blkno; 368 369 /* 370 * Start the controller if there is something for it to do. 371 */ 372 loop: 373 if ((bp = um->um_tab.b_actf->b_actf) == NULL) 374 return; 375 tsunit = TSUNIT(bp->b_dev); 376 ui = tsdinfo[tsunit]; 377 sc = &ts_softc[tsunit]; 378 tc = &sc->sc_cmd; 379 /* 380 * Default is that last command was NOT a write command; 381 * if we do a write command we will notice this in tsintr(). 382 */ 383 sc->sc_lastiow = 0; 384 if (sc->sc_openf < 0 || (addr->tssr&TS_OFL)) { 385 /* 386 * Have had a hard error on a non-raw tape 387 * or the tape unit is now unavailable 388 * (e.g. taken off line). 389 */ 390 bp->b_flags |= B_ERROR; 391 goto next; 392 } 393 if (bp == &ctsbuf[TSUNIT(bp->b_dev)]) { 394 /* 395 * Execute control operation with the specified count. 396 */ 397 um->um_tab.b_active = 398 bp->b_command == TS_REW ? SREW : SCOM; 399 tc->c_repcnt = bp->b_repcnt; 400 goto dobpcmd; 401 } 402 /* 403 * The following checks handle boundary cases for operation 404 * on non-raw tapes. On raw tapes the initialization of 405 * sc->sc_nxrec by tsphys causes them to be skipped normally 406 * (except in the case of retries). 407 */ 408 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 409 /* 410 * Can't read past known end-of-file. 411 */ 412 bp->b_flags |= B_ERROR; 413 bp->b_error = ENXIO; 414 goto next; 415 } 416 if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 417 bp->b_flags&B_READ) { 418 /* 419 * Reading at end of file returns 0 bytes. 420 */ 421 bp->b_resid = bp->b_bcount; 422 clrbuf(bp); 423 goto next; 424 } 425 if ((bp->b_flags&B_READ) == 0) 426 /* 427 * Writing sets EOF 428 */ 429 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 430 /* 431 * If the data transfer command is in the correct place, 432 * set up all the registers except the csr, and give 433 * control over to the UNIBUS adapter routines, to 434 * wait for resources to start the i/o. 435 */ 436 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 437 tc->c_size = bp->b_bcount; 438 if ((bp->b_flags&B_READ) == 0) 439 cmd = TS_WCOM; 440 else 441 cmd = TS_RCOM; 442 if (um->um_tab.b_errcnt) 443 cmd |= TS_RETRY; 444 um->um_tab.b_active = SIO; 445 tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; 446 (void) ubago(ui); 447 return; 448 } 449 /* 450 * Tape positioned incorrectly; 451 * set to seek forwards or backwards to the correct spot. 452 * This happens for raw tapes only on error retries. 453 */ 454 um->um_tab.b_active = SSEEK; 455 if (blkno < bdbtofsb(bp->b_blkno)) { 456 bp->b_command = TS_SFORW; 457 tc->c_repcnt = bdbtofsb(bp->b_blkno) - blkno; 458 } else { 459 bp->b_command = TS_SREV; 460 tc->c_repcnt = blkno - bdbtofsb(bp->b_blkno); 461 } 462 dobpcmd: 463 /* 464 * Do the command in bp. 465 */ 466 tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; 467 addr->tsdb = sc->sc_uba; 468 return; 469 470 next: 471 /* 472 * Done with this operation due to error or 473 * the fact that it doesn't do anything. 474 * Release UBA resources (if any), dequeue 475 * the transfer and continue processing this slave. 476 */ 477 if (um->um_ubinfo) 478 ubadone(um); 479 um->um_tab.b_errcnt = 0; 480 um->um_tab.b_actf->b_actf = bp->av_forw; 481 iodone(bp); 482 goto loop; 483 } 484 485 /* 486 * The UNIBUS resources we needed have been 487 * allocated to us; start the device. 488 */ 489 tsdgo(um) 490 register struct uba_ctlr *um; 491 { 492 register struct tsdevice *addr = (struct tsdevice *)um->um_addr; 493 register struct ts_softc *sc = &ts_softc[um->um_ctlr]; 494 register int i; 495 496 i = um->um_ubinfo & 0777777; 497 sc->sc_cmd.c_loba = i; 498 sc->sc_cmd.c_hiba = (i>>16)&3; 499 addr->tsdb = sc->sc_uba; 500 } 501 502 /* 503 * Ts interrupt routine. 504 */ 505 /*ARGSUSED*/ 506 tsintr(ts11) 507 int ts11; 508 { 509 register struct buf *bp; 510 register struct uba_ctlr *um = tsminfo[ts11]; 511 register struct tsdevice *addr; 512 register struct ts_softc *sc; 513 int tsunit; 514 register state; 515 516 if ((bp = um->um_tab.b_actf->b_actf) == NULL) 517 return; 518 tsunit = TSUNIT(bp->b_dev); 519 addr = (struct tsdevice *)tsdinfo[tsunit]->ui_addr; 520 /* 521 * If last command was a rewind, and tape is still 522 * rewinding, wait for the rewind complete interrupt. 523 * 524 * SHOULD NEVER GET AN INTERRUPT IN THIS STATE. 525 */ 526 if (um->um_tab.b_active == SREW) { 527 um->um_tab.b_active = SCOM; 528 if ((addr->tssr&TS_SSR) == 0) 529 return; 530 } 531 /* 532 * An operation completed... record status 533 */ 534 sc = &ts_softc[tsunit]; 535 if ((bp->b_flags & B_READ) == 0) 536 sc->sc_lastiow = 1; 537 state = um->um_tab.b_active; 538 um->um_tab.b_active = 0; 539 /* 540 * Check for errors. 541 */ 542 if (addr->tssr&TS_SC) { 543 switch (addr->tssr & TS_TC) { 544 case TS_UNREC: /* unrecoverable */ 545 case TS_FATAL: /* fatal error */ 546 case TS_ATTN: /* attention (shouldn't happen) */ 547 case TS_RECNM: /* recoverable, no motion */ 548 break; 549 550 case TS_SUCC: /* success termination */ 551 printf("ts%d: success\n", TSUNIT(minor(bp->b_dev))); 552 goto ignoreerr; 553 554 case TS_ALERT: /* tape status alert */ 555 /* 556 * If we hit the end of the tape file, 557 * update our position. 558 */ 559 if (sc->sc_sts.s_xs0 & (TS_TMK|TS_EOT)) { 560 tsseteof(bp); /* set blkno and nxrec */ 561 state = SCOM; /* force completion */ 562 /* 563 * Stuff bc so it will be unstuffed correctly 564 * later to get resid. 565 */ 566 sc->sc_sts.s_rbpcr = bp->b_bcount; 567 goto opdone; 568 } 569 /* 570 * If we were reading raw tape and the record was too long 571 * or too short, then we don't consider this an error. 572 */ 573 if (bp == &rtsbuf[TSUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && 574 sc->sc_sts.s_xs0&(TS_RLS|TS_RLL)) 575 goto ignoreerr; 576 case TS_RECOV: /* recoverable, tape moved */ 577 /* 578 * If this was an i/o operation retry up to 8 times. 579 */ 580 if (state==SIO) { 581 if (++um->um_tab.b_errcnt < 7) { 582 ubadone(um); 583 goto opcont; 584 } else 585 sc->sc_blkno++; 586 } else { 587 /* 588 * Non-i/o errors on non-raw tape 589 * cause it to close. 590 */ 591 if (sc->sc_openf>0 && bp != &rtsbuf[TSUNIT(bp->b_dev)]) 592 sc->sc_openf = -1; 593 } 594 break; 595 596 case TS_REJECT: /* function reject */ 597 if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) 598 printf("ts%d: write locked\n", TSUNIT(bp->b_dev)); 599 if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) 600 printf("ts%d: offline\n", TSUNIT(bp->b_dev)); 601 break; 602 } 603 /* 604 * Couldn't recover error 605 */ 606 printf("ts%d: hard error bn%d xs0=%b", TSUNIT(bp->b_dev), 607 bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); 608 if (sc->sc_sts.s_xs1) 609 printf(" xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS); 610 if (sc->sc_sts.s_xs2) 611 printf(" xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS); 612 if (sc->sc_sts.s_xs3) 613 printf(" xs3=%b", sc->sc_sts.s_xs3, TSXS3_BITS); 614 printf("\n"); 615 bp->b_flags |= B_ERROR; 616 goto opdone; 617 } 618 /* 619 * Advance tape control FSM. 620 */ 621 ignoreerr: 622 switch (state) { 623 624 case SIO: 625 /* 626 * Read/write increments tape block number 627 */ 628 sc->sc_blkno++; 629 goto opdone; 630 631 case SCOM: 632 /* 633 * For forward/backward space record update current position. 634 */ 635 if (bp == &ctsbuf[TSUNIT(bp->b_dev)]) 636 switch (bp->b_command) { 637 638 case TS_SFORW: 639 sc->sc_blkno += bp->b_repcnt; 640 break; 641 642 case TS_SREV: 643 sc->sc_blkno -= bp->b_repcnt; 644 break; 645 } 646 goto opdone; 647 648 case SSEEK: 649 sc->sc_blkno = bdbtofsb(bp->b_blkno); 650 goto opcont; 651 652 default: 653 panic("tsintr"); 654 } 655 opdone: 656 /* 657 * Reset error count and remove 658 * from device queue. 659 */ 660 um->um_tab.b_errcnt = 0; 661 um->um_tab.b_actf->b_actf = bp->av_forw; 662 bp->b_resid = sc->sc_sts.s_rbpcr; 663 ubadone(um); 664 iodone(bp); 665 if (um->um_tab.b_actf->b_actf == 0) 666 return; 667 opcont: 668 tsstart(um); 669 } 670 671 tsseteof(bp) 672 register struct buf *bp; 673 { 674 register int tsunit = TSUNIT(bp->b_dev); 675 register struct ts_softc *sc = &ts_softc[tsunit]; 676 677 if (bp == &ctsbuf[TSUNIT(bp->b_dev)]) { 678 if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 679 /* reversing */ 680 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; 681 sc->sc_blkno = sc->sc_nxrec; 682 } else { 683 /* spacing forward */ 684 sc->sc_blkno = bdbtofsb(bp->b_blkno) + sc->sc_sts.s_rbpcr; 685 sc->sc_nxrec = sc->sc_blkno - 1; 686 } 687 return; 688 } 689 /* eof on read */ 690 sc->sc_nxrec = bdbtofsb(bp->b_blkno); 691 } 692 693 tsread(dev, uio) 694 dev_t dev; 695 struct uio *uio; 696 { 697 698 u.u_error = tsphys(dev, uio); 699 if (u.u_error) 700 return; 701 physio(tsstrategy, &rtsbuf[TSUNIT(dev)], dev, B_READ, minphys, uio); 702 } 703 704 tswrite(dev) 705 dev_t dev; 706 { 707 708 tsphys(dev, 0); 709 if (u.u_error) 710 return; 711 physio(tsstrategy, &rtsbuf[TSUNIT(dev)], dev, B_WRITE, minphys, 0); 712 } 713 714 /* 715 * Check that a raw device exists. 716 * If it does, set up sc_blkno and sc_nxrec 717 * so that the tape will appear positioned correctly. 718 */ 719 tsphys(dev, uio) 720 dev_t dev; 721 struct uio *uio; 722 { 723 register int tsunit = TSUNIT(dev); 724 register daddr_t a; 725 register struct ts_softc *sc; 726 register struct uba_device *ui; 727 728 if (tsunit >= NTS || (ui=tsdinfo[tsunit]) == 0 || ui->ui_alive == 0) { 729 u.u_error = ENXIO; 730 return (ENXIO); 731 } 732 sc = &ts_softc[tsunit]; 733 if (uio) 734 a = bdbtofsb(uio->uio_offset >> 9); 735 else 736 a = bdbtofsb(u.u_offset >> 9); 737 sc->sc_blkno = a; 738 sc->sc_nxrec = a + 1; 739 return (0); 740 } 741 742 tsreset(uban) 743 int uban; 744 { 745 register struct uba_ctlr *um; 746 register struct uba_device *ui; 747 register struct buf *dp; 748 register ts11; 749 750 for (ts11 = 0; ts11 < NTS; ts11++) { 751 if ((um = tsminfo[ts11]) == 0 || um->um_alive == 0 || 752 um->um_ubanum != uban) 753 continue; 754 printf(" ts%d", ts11); 755 um->um_tab.b_active = 0; 756 um->um_tab.b_actf = um->um_tab.b_actl = 0; 757 if (ts_softc[ts11].sc_openf > 0) 758 ts_softc[ts11].sc_openf = -1; 759 if (um->um_ubinfo) { 760 printf("<%d>", (um->um_ubinfo>>28)&0xf); 761 ubadone(um); 762 } 763 if ((ui = tsdinfo[ts11]) && ui->ui_mi == um && ui->ui_alive) { 764 dp = &tsutab[ts11]; 765 dp->b_active = 0; 766 dp->b_forw = 0; 767 if (um->um_tab.b_actf == NULL) 768 um->um_tab.b_actf = dp; 769 else 770 um->um_tab.b_actl->b_forw = dp; 771 um->um_tab.b_actl = dp; 772 } 773 (void) tsinit(ts11); 774 tsstart(um); 775 } 776 } 777 778 /*ARGSUSED*/ 779 tsioctl(dev, cmd, data, flag) 780 caddr_t data; 781 dev_t dev; 782 { 783 int tsunit = TSUNIT(dev); 784 register struct ts_softc *sc = &ts_softc[tsunit]; 785 register struct buf *bp = &ctsbuf[TSUNIT(dev)]; 786 register callcount; 787 int fcount; 788 struct mtop *mtop; 789 struct mtget *mtget; 790 /* we depend of the values and order of the MT codes here */ 791 static tsops[] = 792 {TS_WEOF,TS_SFORWF,TS_SREVF,TS_SFORW,TS_SREV,TS_REW,TS_OFFL,TS_SENSE}; 793 794 switch (cmd) { 795 796 case MTIOCTOP: /* tape operation */ 797 mtop = (struct mtop *)data; 798 switch(mtop->mt_op) { 799 800 case MTWEOF: 801 callcount = mtop->mt_count; 802 fcount = 1; 803 break; 804 805 case MTFSF: case MTBSF: 806 case MTFSR: case MTBSR: 807 callcount = 1; 808 fcount = mtop->mt_count; 809 break; 810 811 case MTREW: case MTOFFL: case MTNOP: 812 callcount = 1; 813 fcount = 1; 814 break; 815 816 default: 817 u.u_error = ENXIO; 818 return; 819 } 820 if (callcount <= 0 || fcount <= 0) { 821 u.u_error = ENXIO; 822 return; 823 } 824 while (--callcount >= 0) { 825 tscommand(dev, tsops[mtop->mt_op], fcount); 826 if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 827 bp->b_resid) { 828 u.u_error = EIO; 829 break; 830 } 831 if ((bp->b_flags&B_ERROR) || sc->sc_sts.s_xs0&TS_BOT) 832 break; 833 } 834 geterror(bp); 835 return; 836 837 case MTIOCGET: 838 mtget = (struct mtget *)data; 839 mtget->mt_dsreg = 0; 840 mtget->mt_erreg = sc->sc_sts.s_xs0; 841 mtget->mt_resid = sc->sc_resid; 842 mtget->mt_type = MT_ISTS; 843 return; 844 845 default: 846 u.u_error = ENXIO; 847 } 848 } 849 850 #define DBSIZE 20 851 852 tsdump() 853 { 854 register struct uba_device *ui; 855 register struct uba_regs *up; 856 register struct tsdevice *addr; 857 int blk, num; 858 int start; 859 860 start = 0; 861 num = maxfree; 862 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 863 if (tsdinfo[0] == 0) 864 return (ENXIO); 865 ui = phys(tsdinfo[0], struct uba_device *); 866 up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 867 ubainit(up); 868 DELAY(1000000); 869 addr = (struct tsdevice *)ui->ui_physaddr; 870 addr->tssr = 0; 871 tswait(addr); 872 while (num > 0) { 873 blk = num > DBSIZE ? DBSIZE : num; 874 tsdwrite(start, blk, addr, up); 875 start += blk; 876 num -= blk; 877 } 878 tseof(addr); 879 tseof(addr); 880 tswait(addr); 881 if (addr->tssr&TS_SC) 882 return (EIO); 883 addr->tssr = 0; 884 tswait(addr); 885 return (0); 886 } 887 888 tsdwrite(dbuf, num, addr, up) 889 register dbuf, num; 890 register struct tsdevice *addr; 891 struct uba_regs *up; 892 { 893 register struct pte *io; 894 register int npf; 895 896 tswait(addr); 897 io = up->uba_map; 898 npf = num+1; 899 while (--npf != 0) 900 *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV); 901 *(int *)io = 0; 902 #ifdef notyet 903 addr->tsbc = -(num*NBPG); 904 addr->tsba = 0; 905 addr->tscs = TS_WCOM | TM_GO; 906 #endif 907 } 908 909 tswait(addr) 910 register struct tsdevice *addr; 911 { 912 register s; 913 914 do 915 s = addr->tssr; 916 while ((s & TS_SSR) == 0); 917 } 918 919 tseof(addr) 920 struct tsdevice *addr; 921 { 922 923 tswait(addr); 924 #ifdef notyet 925 addr->tscs = TS_WEOF | TM_GO; 926 #endif 927 } 928 #endif 929