1*3244Swnj /* ts.c 4.7 81/03/13 */ 21900Swnj 31941Swnj #include "ts.h" 41900Swnj #if NTS > 0 51900Swnj /* 61900Swnj * TS11 tape driver 7*3244Swnj * 8*3244Swnj * TODO: 9*3244Swnj * test driver with more than one controller 10*3244Swnj * test reset code 11*3244Swnj * test dump code 12*3244Swnj * test rewinds without hanging in driver 13*3244Swnj * what happens if you offline tape during rewind? 14*3244Swnj * test using file system on tape 151900Swnj */ 161900Swnj #include "../h/param.h" 171900Swnj #include "../h/systm.h" 181900Swnj #include "../h/buf.h" 19*3244Swnj #include "../h/dir.h" 201900Swnj #include "../h/conf.h" 21*3244Swnj #include "../h/user.h" 221900Swnj #include "../h/file.h" 23*3244Swnj #include "../h/map.h" 241900Swnj #include "../h/pte.h" 251947Swnj #include "../h/vm.h" 26*3244Swnj #include "../h/ubareg.h" 27*3244Swnj #include "../h/ubavar.h" 28*3244Swnj #include "../h/mtio.h" 29*3244Swnj #include "../h/ioctl.h" 30*3244Swnj #include "../h/cmap.h" 31*3244Swnj #include "../h/cpu.h" 321900Swnj 33*3244Swnj #include "../h/tsreg.h" 341900Swnj 35*3244Swnj /* 36*3244Swnj * There is a ctsbuf per tape controller. 37*3244Swnj * It is used as the token to pass to the internal routines 38*3244Swnj * to execute tape ioctls. 39*3244Swnj * In particular, when the tape is rewinding on close we release 40*3244Swnj * the user process but any further attempts to use the tape drive 41*3244Swnj * before the rewind completes will hang waiting for ctsbuf. 42*3244Swnj */ 43*3244Swnj struct buf ctsbuf[NTS]; 441900Swnj 45*3244Swnj /* 46*3244Swnj * Raw tape operations use rtsbuf. The driver 47*3244Swnj * notices when rtsbuf is being used and allows the user 48*3244Swnj * program to continue after errors and read records 49*3244Swnj * not of the standard length (BSIZE). 50*3244Swnj */ 51*3244Swnj struct buf rtsbuf[NTS]; 521900Swnj 53*3244Swnj /* 54*3244Swnj * Driver unibus interface routines and variables. 55*3244Swnj */ 56*3244Swnj int tsprobe(), tsslave(), tsattach(), tsdgo(), tsintr(); 57*3244Swnj struct uba_ctlr *tsminfo[NTS]; 58*3244Swnj struct uba_device *tsdinfo[NTS]; 59*3244Swnj u_short tsstd[] = { 0772520, 0 }; 60*3244Swnj /*** PROBABLY DON'T NEED ALL THESE SINCE CONTROLLER == DRIVE ***/ 61*3244Swnj struct uba_driver zsdriver = 62*3244Swnj { tsprobe, tsslave, tsattach, tsdgo, tsstd, "ts", tsdinfo, "ts", tsminfo, 0 }; 631900Swnj 64*3244Swnj /* bits in minor device */ 65*3244Swnj #define TSUNIT(dev) (minor(dev)&03) 66*3244Swnj #define T_NOREWIND 04 671900Swnj 68*3244Swnj #define INF (daddr_t)1000000L 691900Swnj 70*3244Swnj /* 71*3244Swnj * Software state per tape transport. 72*3244Swnj * Also contains hardware state in message packets. 73*3244Swnj * 74*3244Swnj * 1. A tape drive is a unique-open device; we refuse opens when it is already. 75*3244Swnj * 2. We keep track of the current position on a block tape and seek 76*3244Swnj * before operations by forward/back spacing if necessary. 77*3244Swnj * 3. We remember if the last operation was a write on a tape, so if a tape 78*3244Swnj * is open read write and the last thing done is a write we can 79*3244Swnj * write a standard end of tape mark (two eofs). 80*3244Swnj * 4. We remember the status registers after the last command, using 81*3244Swnj * then internally and returning them to the SENSE ioctl. 82*3244Swnj */ 83*3244Swnj struct ts_softc { 84*3244Swnj char sc_openf; /* lock against multiple opens */ 85*3244Swnj char sc_lastiow; /* last op was a write */ 86*3244Swnj daddr_t sc_blkno; /* block number, for block device tape */ 87*3244Swnj daddr_t sc_nxrec; /* position of end of tape, if known */ 88*3244Swnj short sc_resid; /* copy of last bc */ 89*3244Swnj struct ts_cmd sc_cmd; /* the command packet - ADDR MUST BE 0 MOD 4 */ 90*3244Swnj struct ts_sts sc_sts; /* status packet, for returned status */ 91*3244Swnj struct ts_char sc_char; /* characteristics packet */ 92*3244Swnj u_short sc_uba; /* Unibus addr of cmd pkt for tsdb */ 93*3244Swnj } ts_softc[NTS]; 941900Swnj 95*3244Swnj struct ts_softc *ts_ubaddr; /* Unibus address of ts_softc */ 961900Swnj 97*3244Swnj /* 98*3244Swnj * States for um->um_tab.b_active, the per controller state flag. 99*3244Swnj * This is used to sequence control in the driver. 100*3244Swnj */ 101*3244Swnj #define SSEEK 1 /* seeking */ 102*3244Swnj #define SIO 2 /* doing seq i/o */ 103*3244Swnj #define SCOM 3 /* sending control command */ 104*3244Swnj #define SREW 4 /* sending a drive rewind */ 1051900Swnj 106*3244Swnj /* 107*3244Swnj * Determine if there is a controller for 108*3244Swnj * a ts at address reg. Our goal is to make the 109*3244Swnj * device interrupt. 110*3244Swnj */ 111*3244Swnj tsprobe(reg) 112*3244Swnj caddr_t reg; 113*3244Swnj { 114*3244Swnj register int br, cvec; /* must be r11,r10; value-result */ 1151900Swnj 116*3244Swnj #ifdef lint 117*3244Swnj br = 0; cvec = br; br = cvec; 118*3244Swnj #endif 119*3244Swnj /****************/ 120*3244Swnj /* */ 121*3244Swnj /* K L U D G E */ 122*3244Swnj /* */ 123*3244Swnj /****************/ 1241900Swnj 125*3244Swnj /* IT'S TOO HARD TO MAKE THIS THING INTERRUPT 126*3244Swnj JUST TO FIND ITS VECTOR */ 127*3244Swnj cvec = 0224; 128*3244Swnj br = 0x15; 129*3244Swnj } 1301900Swnj 131*3244Swnj /* 132*3244Swnj * TS11 only supports one drive per controller; 133*3244Swnj * check for ui_slave == 0. 134*3244Swnj * 135*3244Swnj * DO WE REALLY NEED THIS ROUTINE??? 136*3244Swnj */ 137*3244Swnj /*ARGSUSED*/ 138*3244Swnj tsslave(ui, reg) 139*3244Swnj struct uba_device *ui; 140*3244Swnj caddr_t reg; 141*3244Swnj { 1421900Swnj 143*3244Swnj if (ui->ui_slave) /* non-zero slave not allowed */ 144*3244Swnj return(0); 145*3244Swnj return (1); 146*3244Swnj } 1471900Swnj 148*3244Swnj /* 149*3244Swnj * Record attachment of the unit to the controller. 150*3244Swnj * 151*3244Swnj * SHOULD THIS ROUTINE DO ANYTHING??? 152*3244Swnj */ 153*3244Swnj /*ARGSUSED*/ 154*3244Swnj tsattach(ui) 155*3244Swnj struct uba_device *ui; 156*3244Swnj { 1571900Swnj 158*3244Swnj } 1591900Swnj 160*3244Swnj /* 161*3244Swnj * Open the device. Tapes are unique open 162*3244Swnj * devices, so we refuse if it is already open. 163*3244Swnj * We also check that a tape is available, and 164*3244Swnj * don't block waiting here; if you want to wait 165*3244Swnj * for a tape you should timeout in user code. 166*3244Swnj */ 1671900Swnj tsopen(dev, flag) 168*3244Swnj dev_t dev; 169*3244Swnj int flag; 1701900Swnj { 171*3244Swnj register int tsunit; 172*3244Swnj register struct uba_device *ui; 173*3244Swnj register struct ts_softc *sc; 1741900Swnj 175*3244Swnj tsunit = TSUNIT(dev); 176*3244Swnj if (tsunit>=NTS || (sc = &ts_softc[tsunit])->sc_openf || 177*3244Swnj (ui = tsdinfo[tsunit]) == 0 || ui->ui_alive == 0) { 1781900Swnj u.u_error = ENXIO; 1791900Swnj return; 1801900Swnj } 181*3244Swnj if (tsinit(tsunit)) { 1821900Swnj u.u_error = ENXIO; 1831900Swnj return; 1841900Swnj } 185*3244Swnj tscommand(dev, TS_SENSE, 1); 186*3244Swnj if ((sc->sc_sts.s_xs0&TS_ONL) == 0 || ((flag&(FREAD|FWRITE)) == 187*3244Swnj FWRITE && (sc->sc_sts.s_xs0&TS_WLK))) { 188*3244Swnj /* 189*3244Swnj * Not online or write locked. 190*3244Swnj */ 191*3244Swnj u.u_error = EIO; 192*3244Swnj return; 1931900Swnj } 194*3244Swnj sc->sc_openf = 1; 195*3244Swnj sc->sc_blkno = (daddr_t)0; 196*3244Swnj sc->sc_nxrec = INF; 197*3244Swnj sc->sc_lastiow = 0; 1981900Swnj } 1991900Swnj 200*3244Swnj /* 201*3244Swnj * Close tape device. 202*3244Swnj * 203*3244Swnj * If tape was open for writing or last operation was 204*3244Swnj * a write, then write two EOF's and backspace over the last one. 205*3244Swnj * Unless this is a non-rewinding special file, rewind the tape. 206*3244Swnj * Make the tape available to others. 207*3244Swnj */ 2081900Swnj tsclose(dev, flag) 209*3244Swnj register dev_t dev; 210*3244Swnj register flag; 2111900Swnj { 212*3244Swnj register struct ts_softc *sc = &ts_softc[TSUNIT(dev)]; 2131900Swnj 214*3244Swnj if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) { 215*3244Swnj tscommand(dev, TS_WEOF, 1); 216*3244Swnj tscommand(dev, TS_WEOF, 1); 217*3244Swnj tscommand(dev, TS_SREV, 1); 2181900Swnj } 219*3244Swnj if ((minor(dev)&T_NOREWIND) == 0) 220*3244Swnj /* 221*3244Swnj * 0 count means don't hang waiting for rewind complete 222*3244Swnj * rather ctsbuf stays busy until the operation completes 223*3244Swnj * preventing further opens from completing by 224*3244Swnj * preventing a TS_SENSE from completing. 225*3244Swnj */ 226*3244Swnj tscommand(dev, TS_REW, 0); 227*3244Swnj sc->sc_openf = 0; 2281900Swnj } 2291900Swnj 230*3244Swnj /* 231*3244Swnj * Initialize the TS11. Set up Unibus mapping for command 232*3244Swnj * packets and set device characteristics. 233*3244Swnj */ 234*3244Swnj tsinit(unit) 235*3244Swnj register int unit; 2361900Swnj { 237*3244Swnj register struct ts_softc *sc = &ts_softc[unit]; 238*3244Swnj register struct uba_ctlr *um = tsminfo[unit]; 239*3244Swnj register struct device *addr = (struct device *)um->um_addr; 240*3244Swnj register int i; 241*3244Swnj 242*3244Swnj /* 243*3244Swnj * Map the command and message packets into Unibus 244*3244Swnj * address space. We do all the command and message 245*3244Swnj * packets at once to minimize the amount of Unibus 246*3244Swnj * mapping necessary. 247*3244Swnj */ 248*3244Swnj if (ts_ubaddr == 0) { 249*3244Swnj ctsbuf[unit].b_un.b_addr = (caddr_t)ts_softc; 250*3244Swnj ctsbuf[unit].b_bcount = sizeof(ts_softc); 251*3244Swnj i = ubasetup(um->um_ubanum, &ctsbuf[unit], 0); 252*3244Swnj i &= 0777777; 253*3244Swnj ts_ubaddr = (struct ts_softc *)i; 254*3244Swnj /* MAKE SURE WE DON'T GET UNIBUS ADDRESS ZERO */ 255*3244Swnj if (ts_ubaddr == 0) 256*3244Swnj printf("ts%d: zero ubaddr\n", unit); 257*3244Swnj } 258*3244Swnj /* 259*3244Swnj * Now initialize the TS11 controller. 260*3244Swnj * Set the characteristics. 261*3244Swnj */ 262*3244Swnj if (addr->tssr & TS_NBA) { 263*3244Swnj addr->tssr = 0; /* subsystem initialize */ 264*3244Swnj tswait(addr); 265*3244Swnj i = (int)&ts_ubaddr[unit].sc_cmd; /* Unibus addr of cmd */ 266*3244Swnj sc->sc_uba = (u_short)(i + ((i>>16)&3)); 267*3244Swnj sc->sc_char.char_addr = (int)&ts_ubaddr[unit].sc_sts; 268*3244Swnj sc->sc_char.char_size = sizeof(struct ts_sts); 269*3244Swnj sc->sc_char.char_mode = TS_ESS; 270*3244Swnj sc->sc_cmd.c_cmd = TS_ACK | TS_SETCHR; 271*3244Swnj sc->sc_cmd.c_addr = (int)&ts_ubaddr[unit].sc_char; 272*3244Swnj sc->sc_cmd.c_size = sizeof(struct ts_char); 273*3244Swnj addr->tsdb = sc->sc_uba; 274*3244Swnj tswait(addr); 275*3244Swnj } 276*3244Swnj return(0); 277*3244Swnj } 278*3244Swnj 279*3244Swnj /* 280*3244Swnj * Execute a command on the tape drive 281*3244Swnj * a specified number of times. 282*3244Swnj */ 283*3244Swnj tscommand(dev, com, count) 284*3244Swnj dev_t dev; 285*3244Swnj int com, count; 286*3244Swnj { 2871900Swnj register struct buf *bp; 2881900Swnj 289*3244Swnj bp = &ctsbuf[TSUNIT(dev)]; 290*3244Swnj (void) spl5(); 291*3244Swnj while (bp->b_flags&B_BUSY) { 292*3244Swnj /* 293*3244Swnj * This special check is because B_BUSY never 294*3244Swnj * gets cleared in the non-waiting rewind case. 295*3244Swnj */ 296*3244Swnj if (bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 297*3244Swnj break; 2981900Swnj bp->b_flags |= B_WANTED; 2991900Swnj sleep((caddr_t)bp, PRIBIO); 3001900Swnj } 301*3244Swnj bp->b_flags = B_BUSY|B_READ; 302*3244Swnj (void) spl0(); 303*3244Swnj bp->b_dev = dev; 304*3244Swnj bp->b_repcnt = count; 305*3244Swnj bp->b_command = com; 3061900Swnj bp->b_blkno = 0; 3071900Swnj tsstrategy(bp); 308*3244Swnj /* 309*3244Swnj * In case of rewind from close, don't wait. 310*3244Swnj * This is the only case where count can be 0. 311*3244Swnj */ 312*3244Swnj if (count == 0) 313*3244Swnj return; 3141900Swnj iowait(bp); 315*3244Swnj if (bp->b_flags&B_WANTED) 3161900Swnj wakeup((caddr_t)bp); 317*3244Swnj bp->b_flags &= B_ERROR; 3181900Swnj } 3191900Swnj 320*3244Swnj /* 321*3244Swnj * Queue a tape operation. 322*3244Swnj */ 3231900Swnj tsstrategy(bp) 324*3244Swnj register struct buf *bp; 3251900Swnj { 326*3244Swnj int tsunit = TSUNIT(bp->b_dev); 327*3244Swnj register struct uba_ctlr *um; 3281900Swnj 329*3244Swnj /* 330*3244Swnj * Put transfer at end of controller queue 331*3244Swnj */ 3321900Swnj bp->av_forw = NULL; 333*3244Swnj um = tsdinfo[tsunit]->ui_mi; 334*3244Swnj (void) spl5(); 335*3244Swnj if (um->um_tab.b_actf == NULL) 336*3244Swnj um->um_tab.b_actf = bp; 3371900Swnj else 338*3244Swnj um->um_tab.b_actl->av_forw = bp; 339*3244Swnj um->um_tab.b_actl = bp; 340*3244Swnj /* 341*3244Swnj * If the controller is not busy, get 342*3244Swnj * it going. 343*3244Swnj */ 344*3244Swnj if (um->um_tab.b_active == 0) 345*3244Swnj tsstart(um); 346*3244Swnj (void) spl0(); 3471900Swnj } 3481900Swnj 349*3244Swnj /* 350*3244Swnj * Start activity on a ts controller. 351*3244Swnj */ 352*3244Swnj tsstart(um) 353*3244Swnj register struct uba_ctlr *um; 3541900Swnj { 3551900Swnj register struct buf *bp; 356*3244Swnj register struct device *addr = (struct device *)um->um_addr; 357*3244Swnj register struct ts_softc *sc; 358*3244Swnj register struct ts_cmd *tc; 359*3244Swnj register struct uba_device *ui; 360*3244Swnj int tsunit, cmd; 3611900Swnj daddr_t blkno; 3621900Swnj 363*3244Swnj /* 364*3244Swnj * Start the controller if there is something for it to do. 365*3244Swnj */ 366*3244Swnj loop: 367*3244Swnj if ((bp = um->um_tab.b_actf) == NULL) 3681900Swnj return; 369*3244Swnj tsunit = TSUNIT(bp->b_dev); 370*3244Swnj ui = tsdinfo[tsunit]; 371*3244Swnj sc = &ts_softc[tsunit]; 372*3244Swnj tc = &sc->sc_cmd; 373*3244Swnj /* 374*3244Swnj * Default is that last command was NOT a write command; 375*3244Swnj * if we do a write command we will notice this in tsintr(). 376*3244Swnj */ 377*3244Swnj sc->sc_lastiow = 1; 378*3244Swnj if (sc->sc_openf < 0 || (addr->tssr&TS_OFL)) { 379*3244Swnj /* 380*3244Swnj * Have had a hard error on a non-raw tape 381*3244Swnj * or the tape unit is now unavailable 382*3244Swnj * (e.g. taken off line). 383*3244Swnj */ 384*3244Swnj bp->b_flags |= B_ERROR; 385*3244Swnj goto next; 386*3244Swnj } 387*3244Swnj if (bp == &ctsbuf[TSUNIT(bp->b_dev)]) { 388*3244Swnj /* 389*3244Swnj * Execute control operation with the specified count. 390*3244Swnj */ 391*3244Swnj um->um_tab.b_active = 392*3244Swnj bp->b_command == TS_REW ? SREW : SCOM; 393*3244Swnj tc->c_repcnt = bp->b_repcnt; 394*3244Swnj goto dobpcmd; 395*3244Swnj } 396*3244Swnj /* 397*3244Swnj * The following checks handle boundary cases for operation 398*3244Swnj * on non-raw tapes. On raw tapes the initialization of 399*3244Swnj * sc->sc_nxrec by tsphys causes them to be skipped normally 400*3244Swnj * (except in the case of retries). 401*3244Swnj */ 402*3244Swnj if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 403*3244Swnj /* 404*3244Swnj * Can't read past known end-of-file. 405*3244Swnj */ 406*3244Swnj bp->b_flags |= B_ERROR; 407*3244Swnj bp->b_error = ENXIO; 408*3244Swnj goto next; 409*3244Swnj } 410*3244Swnj if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 411*3244Swnj bp->b_flags&B_READ) { 412*3244Swnj /* 413*3244Swnj * Reading at end of file returns 0 bytes. 414*3244Swnj */ 415*3244Swnj bp->b_resid = bp->b_bcount; 416*3244Swnj clrbuf(bp); 417*3244Swnj goto next; 418*3244Swnj } 419*3244Swnj if ((bp->b_flags&B_READ) == 0) 420*3244Swnj /* 421*3244Swnj * Writing sets EOF 422*3244Swnj */ 423*3244Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 424*3244Swnj /* 425*3244Swnj * If the data transfer command is in the correct place, 426*3244Swnj * set up all the registers except the csr, and give 427*3244Swnj * control over to the UNIBUS adapter routines, to 428*3244Swnj * wait for resources to start the i/o. 429*3244Swnj */ 430*3244Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 431*3244Swnj tc->c_size = bp->b_bcount; 432*3244Swnj if ((bp->b_flags&B_READ) == 0) 433*3244Swnj cmd = TS_WCOM; 4341900Swnj else 435*3244Swnj cmd = TS_RCOM; 436*3244Swnj if (um->um_tab.b_errcnt) 437*3244Swnj cmd |= TS_RETRY; 438*3244Swnj um->um_tab.b_active = SIO; 439*3244Swnj tc->c_cmd = TS_ACK | TS_CVC | cmd; 440*3244Swnj (void) ubago(ui); 441*3244Swnj return; 442*3244Swnj } 443*3244Swnj /* 444*3244Swnj * Tape positioned incorrectly; 445*3244Swnj * set to seek forwards or backwards to the correct spot. 446*3244Swnj * This happens for raw tapes only on error retries. 447*3244Swnj */ 448*3244Swnj um->um_tab.b_active = SSEEK; 449*3244Swnj if (blkno < dbtofsb(bp->b_blkno)) { 450*3244Swnj bp->b_command = TS_SFORW; 451*3244Swnj tc->c_repcnt = dbtofsb(bp->b_blkno) - blkno; 4521900Swnj } else { 453*3244Swnj bp->b_command = TS_SREV; 454*3244Swnj tc->c_repcnt = blkno - dbtofsb(bp->b_blkno); 4551900Swnj } 456*3244Swnj dobpcmd: 457*3244Swnj /* 458*3244Swnj * Do the command in bp. 459*3244Swnj */ 460*3244Swnj tc->c_cmd = TS_ACK | TS_CVC | bp->b_command; 461*3244Swnj addr->tsdb = sc->sc_uba; 4621900Swnj return; 4631900Swnj 464*3244Swnj next: 465*3244Swnj /* 466*3244Swnj * Done with this operation due to error or 467*3244Swnj * the fact that it doesn't do anything. 468*3244Swnj * Release UBA resources (if any), dequeue 469*3244Swnj * the transfer and continue processing this slave. 470*3244Swnj */ 471*3244Swnj if (um->um_ubinfo) 472*3244Swnj ubadone(um); 473*3244Swnj um->um_tab.b_errcnt = 0; 474*3244Swnj um->um_tab.b_actf = bp->av_forw; 4751900Swnj iodone(bp); 4761900Swnj goto loop; 4771900Swnj } 4781900Swnj 479*3244Swnj /* 480*3244Swnj * The UNIBUS resources we needed have been 481*3244Swnj * allocated to us; start the device. 482*3244Swnj */ 483*3244Swnj tsdgo(um) 484*3244Swnj register struct uba_ctlr *um; 4851900Swnj { 486*3244Swnj register struct device *addr = (struct device *)um->um_addr; 487*3244Swnj register struct ts_softc *sc = &ts_softc[um->um_ctlr]; 488*3244Swnj 489*3244Swnj sc->sc_cmd.c_addr = um->um_ubinfo & 0777777; 490*3244Swnj addr->tsdb = sc->sc_uba; 491*3244Swnj } 492*3244Swnj 493*3244Swnj /* 494*3244Swnj * Ts interrupt routine. 495*3244Swnj */ 496*3244Swnj /*ARGSUSED*/ 497*3244Swnj tsintr(ts11) 498*3244Swnj int ts11; 499*3244Swnj { 5001900Swnj register struct buf *bp; 501*3244Swnj register struct uba_ctlr *um = tsminfo[ts11]; 502*3244Swnj register struct device *addr; 503*3244Swnj register struct ts_softc *sc; 504*3244Swnj int tsunit; 505*3244Swnj register state; 5061900Swnj 507*3244Swnj if ((bp = um->um_tab.b_actf) == NULL) 5081900Swnj return; 509*3244Swnj tsunit = TSUNIT(bp->b_dev); 510*3244Swnj addr = (struct device *)tsdinfo[tsunit]->ui_addr; 511*3244Swnj /* 512*3244Swnj * If last command was a rewind, and tape is still 513*3244Swnj * rewinding, wait for the rewind complete interrupt. 514*3244Swnj * 515*3244Swnj * SHOULD NEVER GET AN INTERRUPT IN THIS STATE. 516*3244Swnj */ 517*3244Swnj if (um->um_tab.b_active == SREW) { 518*3244Swnj um->um_tab.b_active = SCOM; 519*3244Swnj if ((addr->tssr&TS_SSR) == 0) 520*3244Swnj return; 521*3244Swnj } 522*3244Swnj /* 523*3244Swnj * An operation completed... record status 524*3244Swnj */ 525*3244Swnj sc = &ts_softc[tsunit]; 526*3244Swnj if ((bp->b_flags & B_READ) == 0) 527*3244Swnj sc->sc_lastiow = 1; 528*3244Swnj state = um->um_tab.b_active; 529*3244Swnj um->um_tab.b_active = 0; 530*3244Swnj /* 531*3244Swnj * Check for errors. 532*3244Swnj */ 533*3244Swnj if (addr->tssr&TS_SC) { 534*3244Swnj switch (addr->tssr & TS_TC) { 535*3244Swnj case TS_UNREC: /* unrecoverable */ 536*3244Swnj case TS_FATAL: /* fatal error */ 537*3244Swnj case TS_ATTN: /* attention (shouldn't happen) */ 538*3244Swnj case TS_RECNM: /* recoverable, no motion */ 539*3244Swnj break; 5401900Swnj 541*3244Swnj case TS_SUCC: /* success termination */ 542*3244Swnj printf("ts%d: success\n", TSUNIT(minor(bp->b_dev))); 543*3244Swnj goto ignoreerr; 5441900Swnj 545*3244Swnj case TS_ALERT: /* tape status alert */ 546*3244Swnj /* 547*3244Swnj * If we hit the end of the tape file, 548*3244Swnj * update our position. 549*3244Swnj */ 550*3244Swnj if (sc->sc_sts.s_xs0 & (TS_TMK|TS_EOT)) { 551*3244Swnj tsseteof(bp); /* set blkno and nxrec */ 552*3244Swnj state = SCOM; /* force completion */ 553*3244Swnj /* 554*3244Swnj * Stuff bc so it will be unstuffed correctly 555*3244Swnj * later to get resid. 556*3244Swnj */ 557*3244Swnj sc->sc_sts.s_rbpcr = bp->b_bcount; 558*3244Swnj goto opdone; 559*3244Swnj } 560*3244Swnj /* 561*3244Swnj * If we were reading raw tape and the record was too long 562*3244Swnj * or too short, then we don't consider this an error. 563*3244Swnj */ 564*3244Swnj if (bp == &rtsbuf[TSUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && 565*3244Swnj sc->sc_sts.s_xs0&(TS_RLS|TS_RLL)) 566*3244Swnj goto ignoreerr; 567*3244Swnj case TS_RECOV: /* recoverable, tape moved */ 568*3244Swnj /* 569*3244Swnj * If this was an i/o operation retry up to 8 times. 570*3244Swnj */ 571*3244Swnj if (state==SIO) { 572*3244Swnj if (++um->um_tab.b_errcnt < 7) { 573*3244Swnj ubadone(um); 574*3244Swnj goto opcont; 575*3244Swnj } else 576*3244Swnj sc->sc_blkno++; 577*3244Swnj } else { 578*3244Swnj /* 579*3244Swnj * Non-i/o errors on non-raw tape 580*3244Swnj * cause it to close. 581*3244Swnj */ 582*3244Swnj if (sc->sc_openf>0 && bp != &rtsbuf[TSUNIT(bp->b_dev)]) 583*3244Swnj sc->sc_openf = -1; 584*3244Swnj } 5851900Swnj break; 586*3244Swnj 587*3244Swnj case TS_REJECT: /* function reject */ 588*3244Swnj if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) 589*3244Swnj printf("ts%d: write locked\n", TSUNIT(bp->b_dev)); 590*3244Swnj if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) 591*3244Swnj printf("ts%d: offline\n", TSUNIT(bp->b_dev)); 5921900Swnj break; 5931900Swnj } 594*3244Swnj /* 595*3244Swnj * Couldn't recover error 596*3244Swnj */ 597*3244Swnj printf("ts%d: hard error bn%d xs0=%b\n", TSUNIT(bp->b_dev), 598*3244Swnj bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); 599*3244Swnj bp->b_flags |= B_ERROR; 600*3244Swnj goto opdone; 601*3244Swnj } 602*3244Swnj /* 603*3244Swnj * Advance tape control FSM. 604*3244Swnj */ 605*3244Swnj ignoreerr: 606*3244Swnj switch (state) { 6071900Swnj 608*3244Swnj case SIO: 609*3244Swnj /* 610*3244Swnj * Read/write increments tape block number 611*3244Swnj */ 612*3244Swnj sc->sc_blkno++; 613*3244Swnj goto opdone; 6141900Swnj 6151900Swnj case SCOM: 616*3244Swnj /* 617*3244Swnj * For forward/backward space record update current position. 618*3244Swnj */ 619*3244Swnj if (bp == &ctsbuf[TSUNIT(bp->b_dev)]) 620*3244Swnj switch (bp->b_command) { 6211900Swnj 622*3244Swnj case TS_SFORW: 623*3244Swnj sc->sc_blkno += bp->b_repcnt; 624*3244Swnj break; 6251900Swnj 626*3244Swnj case TS_SREV: 627*3244Swnj sc->sc_blkno -= bp->b_repcnt; 628*3244Swnj break; 629*3244Swnj } 630*3244Swnj goto opdone; 631*3244Swnj 632*3244Swnj case SSEEK: 633*3244Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 634*3244Swnj goto opcont; 635*3244Swnj 6361900Swnj default: 637*3244Swnj panic("tsintr"); 6381900Swnj } 639*3244Swnj opdone: 640*3244Swnj /* 641*3244Swnj * Reset error count and remove 642*3244Swnj * from device queue. 643*3244Swnj */ 644*3244Swnj um->um_tab.b_errcnt = 0; 645*3244Swnj um->um_tab.b_actf = bp->av_forw; 646*3244Swnj bp->b_resid = sc->sc_sts.s_rbpcr; 647*3244Swnj ubadone(um); 648*3244Swnj iodone(bp); 649*3244Swnj if (um->um_tab.b_actf == 0) 650*3244Swnj return; 651*3244Swnj opcont: 652*3244Swnj tsstart(um); 653*3244Swnj } 654*3244Swnj 655*3244Swnj tsseteof(bp) 656*3244Swnj register struct buf *bp; 657*3244Swnj { 658*3244Swnj register int tsunit = TSUNIT(bp->b_dev); 659*3244Swnj register struct ts_softc *sc = &ts_softc[tsunit]; 660*3244Swnj 661*3244Swnj if (bp == &ctsbuf[TSUNIT(bp->b_dev)]) { 662*3244Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 663*3244Swnj /* reversing */ 664*3244Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; 665*3244Swnj sc->sc_blkno = sc->sc_nxrec; 666*3244Swnj } else { 667*3244Swnj /* spacing forward */ 668*3244Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + sc->sc_sts.s_rbpcr; 669*3244Swnj sc->sc_nxrec = sc->sc_blkno - 1; 6701900Swnj } 671*3244Swnj return; 672*3244Swnj } 673*3244Swnj /* eof on read */ 674*3244Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 6751900Swnj } 6761900Swnj 6771900Swnj tsread(dev) 678*3244Swnj dev_t dev; 6791900Swnj { 680*3244Swnj 6811900Swnj tsphys(dev); 682*3244Swnj if (u.u_error) 683*3244Swnj return; 684*3244Swnj physio(tsstrategy, &rtsbuf[TSUNIT(dev)], dev, B_READ, minphys); 6851900Swnj } 6861900Swnj 6871900Swnj tswrite(dev) 688*3244Swnj dev_t dev; 6891900Swnj { 690*3244Swnj 6911900Swnj tsphys(dev); 692*3244Swnj if (u.u_error) 693*3244Swnj return; 694*3244Swnj physio(tsstrategy, &rtsbuf[TSUNIT(dev)], dev, B_WRITE, minphys); 6951900Swnj } 6961900Swnj 697*3244Swnj /* 698*3244Swnj * Check that a raw device exists. 699*3244Swnj * If it does, set up sc_blkno and sc_nxrec 700*3244Swnj * so that the tape will appear positioned correctly. 701*3244Swnj */ 7021900Swnj tsphys(dev) 703*3244Swnj dev_t dev; 7041900Swnj { 705*3244Swnj register int tsunit = TSUNIT(dev); 706*3244Swnj register daddr_t a; 707*3244Swnj register struct ts_softc *sc; 708*3244Swnj register struct uba_device *ui; 7091900Swnj 710*3244Swnj if (tsunit >= NTS || (ui=tsdinfo[tsunit]) == 0 || ui->ui_alive == 0) { 711*3244Swnj u.u_error = ENXIO; 712*3244Swnj return; 713*3244Swnj } 714*3244Swnj sc = &ts_softc[tsunit]; 715*3244Swnj a = dbtofsb(u.u_offset >> 9); 716*3244Swnj sc->sc_blkno = a; 717*3244Swnj sc->sc_nxrec = a + 1; 7181900Swnj } 7191918Swnj 720*3244Swnj tsreset(uban) 721*3244Swnj int uban; 7221918Swnj { 723*3244Swnj register struct uba_ctlr *um; 724*3244Swnj register ts11; 725*3244Swnj register struct buf *dp; 7261918Swnj 727*3244Swnj for (ts11 = 0; ts11 < NTS; ts11++) { 728*3244Swnj if ((um = tsminfo[ts11]) == 0 || um->um_alive == 0 || 729*3244Swnj um->um_ubanum != uban) 730*3244Swnj continue; 731*3244Swnj printf(" ts%d", ts11); 732*3244Swnj um->um_tab.b_active = 0; 733*3244Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 734*3244Swnj ts_softc[ts11].sc_openf = -1; 735*3244Swnj if (um->um_ubinfo) { 736*3244Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 737*3244Swnj ubadone(um); 738*3244Swnj } 739*3244Swnj tsinit(ts11); 740*3244Swnj tsstart(um); 7411918Swnj } 7421918Swnj } 7431918Swnj 744*3244Swnj /*ARGSUSED*/ 745*3244Swnj tsioctl(dev, cmd, addr, flag) 746*3244Swnj caddr_t addr; 747*3244Swnj dev_t dev; 7481918Swnj { 749*3244Swnj int tsunit = TSUNIT(dev); 750*3244Swnj register struct ts_softc *sc = &ts_softc[tsunit]; 751*3244Swnj register struct buf *bp = &ctsbuf[TSUNIT(dev)]; 752*3244Swnj register callcount; 753*3244Swnj int fcount; 754*3244Swnj struct mtop mtop; 755*3244Swnj struct mtget mtget; 756*3244Swnj /* we depend of the values and order of the MT codes here */ 757*3244Swnj static tsops[] = 758*3244Swnj {TS_WEOF,TS_SFORW,TS_SREV,TS_SFORWF,TS_SREVF,TS_REW,TS_OFFL,TS_SENSE}; 7591918Swnj 760*3244Swnj switch (cmd) { 761*3244Swnj case MTIOCTOP: /* tape operation */ 762*3244Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 763*3244Swnj u.u_error = EFAULT; 764*3244Swnj return; 765*3244Swnj } 766*3244Swnj switch(mtop.mt_op) { 767*3244Swnj case MTWEOF: 768*3244Swnj callcount = mtop.mt_count; 769*3244Swnj fcount = 1; 770*3244Swnj break; 771*3244Swnj case MTFSF: case MTBSF: 772*3244Swnj case MTFSR: case MTBSR: 773*3244Swnj callcount = 1; 774*3244Swnj fcount = mtop.mt_count; 775*3244Swnj break; 776*3244Swnj case MTREW: case MTOFFL: case MTNOP: 777*3244Swnj callcount = 1; 778*3244Swnj fcount = 1; 779*3244Swnj break; 780*3244Swnj default: 781*3244Swnj u.u_error = ENXIO; 782*3244Swnj return; 783*3244Swnj } 784*3244Swnj if (callcount <= 0 || fcount <= 0) { 785*3244Swnj u.u_error = ENXIO; 786*3244Swnj return; 787*3244Swnj } 788*3244Swnj while (--callcount >= 0) { 789*3244Swnj tscommand(dev, tsops[mtop.mt_op], fcount); 790*3244Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 791*3244Swnj bp->b_resid) { 792*3244Swnj u.u_error = EIO; 793*3244Swnj break; 794*3244Swnj } 795*3244Swnj if ((bp->b_flags&B_ERROR) || sc->sc_sts.s_xs0&TS_BOT) 796*3244Swnj break; 797*3244Swnj } 798*3244Swnj geterror(bp); 799*3244Swnj return; 800*3244Swnj case MTIOCGET: 801*3244Swnj mtget.mt_dsreg = 0; 802*3244Swnj mtget.mt_erreg = sc->sc_sts.s_xs0; 803*3244Swnj mtget.mt_resid = sc->sc_resid; 804*3244Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 805*3244Swnj u.u_error = EFAULT; 806*3244Swnj return; 807*3244Swnj default: 808*3244Swnj u.u_error = ENXIO; 809*3244Swnj } 8101918Swnj } 8111918Swnj 812*3244Swnj #define DBSIZE 20 813*3244Swnj 814*3244Swnj tsdump() 8151918Swnj { 816*3244Swnj register struct uba_device *ui; 817*3244Swnj register struct uba_regs *up; 818*3244Swnj register struct device *addr; 819*3244Swnj int blk, num; 820*3244Swnj int start; 8211918Swnj 822*3244Swnj start = 0; 823*3244Swnj num = maxfree; 824*3244Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 825*3244Swnj if (tsdinfo[0] == 0) 826*3244Swnj return (ENXIO); 827*3244Swnj ui = phys(tsdinfo[0], struct uba_device *); 828*3244Swnj up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 829*3244Swnj #if VAX780 830*3244Swnj if (cpu == VAX_780) 831*3244Swnj ubainit(up); 832*3244Swnj #endif 833*3244Swnj DELAY(1000000); 834*3244Swnj addr = (struct device *)ui->ui_physaddr; 835*3244Swnj addr->tssr = 0; 836*3244Swnj tswait(addr); 837*3244Swnj while (num > 0) { 838*3244Swnj blk = num > DBSIZE ? DBSIZE : num; 839*3244Swnj tsdwrite(start, blk, addr, up); 840*3244Swnj start += blk; 841*3244Swnj num -= blk; 842*3244Swnj } 843*3244Swnj tseof(addr); 844*3244Swnj tseof(addr); 845*3244Swnj tswait(addr); 846*3244Swnj if (addr->tssr&TS_SC) 847*3244Swnj return (EIO); 848*3244Swnj addr->tssr = 0; 849*3244Swnj tswait(addr); 850*3244Swnj return (0); 8511918Swnj } 8521918Swnj 853*3244Swnj tsdwrite(dbuf, num, addr, up) 854*3244Swnj register dbuf, num; 855*3244Swnj register struct device *addr; 856*3244Swnj struct uba_regs *up; 8571918Swnj { 858*3244Swnj register struct pte *io; 859*3244Swnj register int npf; 8601918Swnj 861*3244Swnj tswait(addr); 862*3244Swnj io = up->uba_map; 863*3244Swnj npf = num+1; 864*3244Swnj while (--npf != 0) 865*3244Swnj *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV); 866*3244Swnj *(int *)io = 0; 867*3244Swnj #ifdef notyet 868*3244Swnj addr->tsbc = -(num*NBPG); 869*3244Swnj addr->tsba = 0; 870*3244Swnj addr->tscs = TS_WCOM | TM_GO; 871*3244Swnj #endif 8721918Swnj } 8731918Swnj 874*3244Swnj tswait(addr) 875*3244Swnj register struct device *addr; 8761918Swnj { 877*3244Swnj register s; 8781918Swnj 879*3244Swnj do 880*3244Swnj s = addr->tssr; 881*3244Swnj while ((s & TS_SSR) == 0); 8821918Swnj } 8831918Swnj 884*3244Swnj tseof(addr) 885*3244Swnj struct device *addr; 8861918Swnj { 8871918Swnj 888*3244Swnj tswait(addr); 889*3244Swnj #ifdef notyet 890*3244Swnj addr->tscs = TS_WEOF | TM_GO; 891*3244Swnj #endif 8921918Swnj } 8931900Swnj #endif 894