1*26127Skarels 2*26127Skarels #ifndef lint 3*26127Skarels static char *sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; 4*26127Skarels #endif lint 5*26127Skarels 6*26127Skarels 7*26127Skarels /************************************************************************ 8*26127Skarels * * 9*26127Skarels * Copyright (c) 1985 by * 10*26127Skarels * Digital Equipment Corporation, Maynard, MA * 11*26127Skarels * * 12*26127Skarels * Permission to use, copy, modify, and distribute this software * 13*26127Skarels * and its documentation is hereby granted to licensees of the * 14*26127Skarels * Regents of the University of California pursuant to their * 15*26127Skarels * license agreement for the "Fourth Berkeley Software * 16*26127Skarels * Distribution". * 17*26127Skarels * * 18*26127Skarels * The information in this software is subject to change without * 19*26127Skarels * notice and should not be construed as a commitment by Digital * 20*26127Skarels * Equipment Corporation. Digital makes no representations * 21*26127Skarels * about suitability of this software for any purpose. It is * 22*26127Skarels * supplied "as is" without express or implied warranty. * 23*26127Skarels * * 24*26127Skarels * This software is not subject to any license of the American * 25*26127Skarels * Telephone and Telegraph Company. * 26*26127Skarels * * 27*26127Skarels ************************************************************************ 28*26127Skarels * 29*26127Skarels * tmscp.c - TMSCP (TK50/TU81) tape device driver 30*26127Skarels * 31*26127Skarels * Modification History: 32*26127Skarels * 33*26127Skarels * 06-Jan-86 - afd 34*26127Skarels * Changed the probe routine to use DELAY (not TODR). This now 35*26127Skarels * works for MicroVAXen as well. This eliminates the busy-wait 36*26127Skarels * for MicroVAXen so a dead TK50 controller will not hang autoconf. 37*26127Skarels * 38*26127Skarels * 06-Dec-85 - afd 39*26127Skarels * Fixed a bug in density selection. The "set unit characteristics" 40*26127Skarels * command to select density, was clearing the "unit flags" field 41*26127Skarels * where the CACHE bit was for TU81-E. Now the unit's "format" and 42*26127Skarels * "unitflgs" are saved in tms_info struct. And are used on STUNT 43*26127Skarels * commands. 44*26127Skarels * 45*26127Skarels * 19-Oct-85 - afd 46*26127Skarels * Added support to the open routine to allow drives to be opened 47*26127Skarels * for low density (800 or 1600 bpi) use. When the slave routine 48*26127Skarels * initiates a "get-unit-char" cmd, the format menu for the unit 49*26127Skarels * is saved in the tms_info structure. The format menu is used in the 50*26127Skarels * start routine to select the proper low density. 51*26127Skarels * 52*26127Skarels * 02-Oct-85 - afd 53*26127Skarels * When a tmscp-type controller is initializing, it is possible for 54*26127Skarels * the sa reg to become 0 between states. Thus the init code in 55*26127Skarels * the interrupt routine had to be modified to reflect this. 56*26127Skarels * 57*26127Skarels * 21-Sep-85 - afd 58*26127Skarels * The TK50 declares a serious exception when a tape mark is encountered. 59*26127Skarels * This causes problems to dd (& other UN*X utilities). So a flag 60*26127Skarels * is set in the rsp() routine when a tape mark is encountered. If 61*26127Skarels * this flag is set, the start() routine appends the Clear Serious 62*26127Skarels * Exception modifier to the next command. 63*26127Skarels * 64*26127Skarels * 03-Sep-85 -- jaw 65*26127Skarels * messed up previous edit.. 66*26127Skarels * 67*26127Skarels * 29-Aug-85 - jaw 68*26127Skarels * fixed bugs in 8200 and 750 buffered datapath handling. 69*26127Skarels * 70*26127Skarels * 06-Aug-85 - afd 71*26127Skarels * 1. When repositioning records or files, the count of items skipped 72*26127Skarels * does NOT HAVE to be returned by controllers (& the TU81 doesn't). 73*26127Skarels * So tmscprsp() had to be modified to stop reporting 74*26127Skarels * residual count errors on reposition commands. 75*26127Skarels * 76*26127Skarels * 2. Fixed bug in the open routine which allowed multiple opens. 77*26127Skarels * 78*26127Skarels * 18-Jul-85 - afd 79*26127Skarels * 1. Need to return status when mt status (or corresponding ioctl) is done. 80*26127Skarels * Save resid, flags, endcode & status in tmscprsp() routine (except on 81*26127Skarels * clear serious exception no-op). Return these fields when status 82*26127Skarels * ioctl is done (in tmscpcommand()). How they are returned: 83*26127Skarels * mt_resid = resid 84*26127Skarels * mt_dsreg = flags|endcode 85*26127Skarels * mt_erreg = status 86*26127Skarels * 87*26127Skarels * 2. Added latent support for enabling/disabling caching. This is 88*26127Skarels * handled along with all other ioctl commands. 89*26127Skarels * 90*26127Skarels * 3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since 91*26127Skarels * we have already commited to issuing a command at that point. 92*26127Skarels * 93*26127Skarels * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); 94*26127Skarels * We need to: Unlink the buffer from the I/O wait queue, 95*26127Skarels * and signal iodone, so the higher level command can exit! 96*26127Skarels * Just as if it were a valid command. 97*26127Skarels * 98*26127Skarels * 11-jul-85 -- jaw 99*26127Skarels * fix bua/bda map registers. 100*26127Skarels * 101*26127Skarels * 19-Jun-85 -- jaw 102*26127Skarels * VAX8200 name change. 103*26127Skarels * 104*26127Skarels * 06-Jun-85 - jaw 105*26127Skarels * fixes for 8200. 106*26127Skarels * 107*26127Skarels * 9-Apr-85 - afd 108*26127Skarels * Added timeout code to the probe routine, so if the controller 109*26127Skarels * fails to init in 10 seconds we return failed status. 110*26127Skarels * 111*26127Skarels * 13-Mar-85 -jaw 112*26127Skarels * Changes for support of the VAX8200 were merged in. 113*26127Skarels * 114*26127Skarels * 27-Feb-85 -tresvik 115*26127Skarels * Changes for support of the VAX8600 were merged in. 116*26127Skarels * 117*26127Skarels */ 118*26127Skarels 119*26127Skarels #include "tms.h" 120*26127Skarels #define TMSCPDEVNUM (15) /* entry in bdevsw */ 121*26127Skarels #if NTMSCP > 0 || defined(BINARY) 122*26127Skarels 123*26127Skarels #include "../data/tmscp_data.c" 124*26127Skarels 125*26127Skarels /* Bits in minor device */ 126*26127Skarels #define TMSUNIT(dev) (minor(dev)&03) 127*26127Skarels #define T_NOREWIND 04 128*26127Skarels #define T_HIDENSITY 010 129*26127Skarels 130*26127Skarels /* Slave unit to controller mapping */ 131*26127Skarels #define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)]) 132*26127Skarels 133*26127Skarels /* 134*26127Skarels * Internal (ioctl) command codes (these must also be declared in the 135*26127Skarels * tmscpioctl routine). These correspond to ioctls in mtio.h 136*26127Skarels */ 137*26127Skarels #define TMS_WRITM 0 /* write tape mark */ 138*26127Skarels #define TMS_FSF 1 /* forward space file */ 139*26127Skarels #define TMS_BSF 2 /* backward space file */ 140*26127Skarels #define TMS_FSR 3 /* forward space record */ 141*26127Skarels #define TMS_BSR 4 /* backward space record */ 142*26127Skarels #define TMS_REW 5 /* rewind tape */ 143*26127Skarels #define TMS_OFFL 6 /* rewind tape & mark unit offline */ 144*26127Skarels #define TMS_SENSE 7 /* noop - do a get unit status */ 145*26127Skarels #define TMS_CACHE 8 /* enable cache */ 146*26127Skarels #define TMS_NOCACHE 9 /* disable cache */ 147*26127Skarels /* These go last: after all real mt cmds, just bump the numbers up */ 148*26127Skarels #define TMS_CSE 10 /* clear serious exception */ 149*26127Skarels #define TMS_LOWDENSITY 11 /* set unit to low density */ 150*26127Skarels #define TMS_HIDENSITY 12 /* set unit to high density */ 151*26127Skarels 152*26127Skarels /* 153*26127Skarels * Controller states 154*26127Skarels */ 155*26127Skarels #define S_IDLE 0 /* hasn't been initialized */ 156*26127Skarels #define S_STEP1 1 /* doing step 1 init */ 157*26127Skarels #define S_STEP2 2 /* doing step 2 init */ 158*26127Skarels #define S_STEP3 3 /* doing step 3 init */ 159*26127Skarels #define S_SCHAR 4 /* doing "set controller characteristics" */ 160*26127Skarels #define S_RUN 5 /* running */ 161*26127Skarels 162*26127Skarels int tmscperror = 0; /* causes hex dump of packets */ 163*26127Skarels int tmscp_cp_wait = 0; /* Something to wait on for command */ 164*26127Skarels /* packets and or credits. */ 165*26127Skarels int wakeup(); 166*26127Skarels extern int hz; /* Should find the right include */ 167*26127Skarels 168*26127Skarels #ifdef DEBUG 169*26127Skarels #define printd if (tmscpdebug) printf 170*26127Skarels int tmscpdebug = 1; 171*26127Skarels #define printd10 if(tmscpdebug >= 10) printf 172*26127Skarels #endif 173*26127Skarels 174*26127Skarels int tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr(); 175*26127Skarels struct mscp *tmscpgetcp(); 176*26127Skarels 177*26127Skarels #define DRVNAME "tms" 178*26127Skarels #define CTRLNAME "tmscp" 179*26127Skarels 180*26127Skarels u_short tmscpstd[] = { 0174500, 0 }; 181*26127Skarels struct uba_driver tmscpdriver = 182*26127Skarels { tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME 183*26127Skarels , tmscpminfo, 0}; 184*26127Skarels 185*26127Skarels #define b_qsize b_resid /* queue size per drive, in tmsutab */ 186*26127Skarels #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ 187*26127Skarels 188*26127Skarels 189*26127Skarels /*************************************************************************/ 190*26127Skarels 191*26127Skarels #define DELAYTEN 1000 192*26127Skarels 193*26127Skarels tmscpprobe(reg, ctlr) 194*26127Skarels caddr_t reg; /* address of the IP register */ 195*26127Skarels int ctlr; /* index of controller in the tmscp_softc array 196*26127Skarels */ 197*26127Skarels { 198*26127Skarels register int br, cvec; /* MUST be 1st (r11 & r10): IPL and intr vec */ 199*26127Skarels register struct tmscp_softc *sc = &tmscp_softc[ctlr]; 200*26127Skarels /* ptr to software controller structure */ 201*26127Skarels struct tmscpdevice *tmscpaddr; /* ptr to tmscpdevice struct (IP & SA) * 202*26127Skarels / 203*26127Skarels struct uba_ctlr *um; /* UNUSED ptr to uba_ctlr (controller) struct * 204*26127Skarels / 205*26127Skarels int count; /* for probe delay time out */ 206*26127Skarels 207*26127Skarels # ifdef lint 208*26127Skarels br = 0; cvec = br; br = cvec; reg = reg; 209*26127Skarels tmscpreset(0); tmscpintr(0); 210*26127Skarels # endif 211*26127Skarels 212*26127Skarels tmscpaddr = (struct tmscpdevice *) reg; 213*26127Skarels /* 214*26127Skarels * Set host-settable interrupt vector. 215*26127Skarels * Assign 0 to the ip register to start the tmscp-device initialization 216*26127Skarels . 217*26127Skarels * The device is not really initialized at this point, this is just to 218*26127Skarels * find out if the device exists. 219*26127Skarels */ 220*26127Skarels sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 221*26127Skarels tmscpaddr->tmscpip = 0; 222*26127Skarels 223*26127Skarels count=0; 224*26127Skarels while(count < DELAYTEN) 225*26127Skarels { /* wait for at most 10 secs */ 226*26127Skarels if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0) 227*26127Skarels break; 228*26127Skarels DELAY(10000); 229*26127Skarels count=count+1; 230*26127Skarels } 231*26127Skarels if (count == DELAYTEN) 232*26127Skarels return(0); 233*26127Skarels 234*26127Skarels tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->s 235*26127Skarels c_ivec/4); 236*26127Skarels 237*26127Skarels count=0; 238*26127Skarels while(count < DELAYTEN) 239*26127Skarels { 240*26127Skarels if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0) 241*26127Skarels break; 242*26127Skarels DELAY(10000); 243*26127Skarels count = count+1; 244*26127Skarels } 245*26127Skarels if (count == DELAYTEN) 246*26127Skarels return(0); 247*26127Skarels 248*26127Skarels return(sizeof (struct tmscpdevice)); 249*26127Skarels } 250*26127Skarels 251*26127Skarels /* 252*26127Skarels * Try to find a slave (a drive) on the controller. 253*26127Skarels * If the controller is not in the run state, call init to initialize it. 254*26127Skarels */ 255*26127Skarels tmscpslave (ui, reg) 256*26127Skarels struct uba_device *ui; /* ptr to the uba device structure */ 257*26127Skarels caddr_t reg; /* addr of the device controller */ 258*26127Skarels { 259*26127Skarels register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; 260*26127Skarels register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; 261*26127Skarels struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ 262*26127Skarels struct mscp *mp; 263*26127Skarels int i; /* Something to write into to start */ 264*26127Skarels /* the tmscp polling */ 265*26127Skarels 266*26127Skarels # ifdef lint 267*26127Skarels ui = ui; reg = reg; i = i; 268*26127Skarels # endif 269*26127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 270*26127Skarels /* 271*26127Skarels * If its not in the run state, start the initialization process 272*26127Skarels * (tmscpintr will complete it); if the initialization doesn't start; 273*26127Skarels * then return. 274*26127Skarels */ 275*26127Skarels if(sc->sc_state != S_RUN) 276*26127Skarels { 277*26127Skarels # ifdef DEBUG 278*26127Skarels printd("tmscpslave: ctlr not running: calling init \n"); 279*26127Skarels # endif 280*26127Skarels if(!tmscpinit(ui->ui_ctlr)) 281*26127Skarels return(0); 282*26127Skarels } 283*26127Skarels /* 284*26127Skarels * Wait for the controller to come into the run state or go idle. 285*26127Skarels * If it goes idle return. 286*26127Skarels */ 287*26127Skarels # ifdef DEBUG 288*26127Skarels i=1; 289*26127Skarels # endif 290*26127Skarels while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE) 291*26127Skarels # ifdef DEBUG 292*26127Skarels if (tmscpaddr->tmscpsa & TMSCP_ERR && i) 293*26127Skarels { 294*26127Skarels printd("tmscp-device: fatal error (%o)\n", tmscpaddr->t 295*26127Skarels mscpsa&0xffff); 296*26127Skarels i=0; 297*26127Skarels } 298*26127Skarels # endif 299*26127Skarels ; /* wait */ 300*26127Skarels if(sc->sc_state == S_IDLE) 301*26127Skarels { /* The tmscp device failed to initialize */ 302*26127Skarels printf("tmscp controller failed to init\n"); 303*26127Skarels return(0); 304*26127Skarels } 305*26127Skarels /* The controller is up so see if the drive is there */ 306*26127Skarels if(0 == (mp = tmscpgetcp(um))) 307*26127Skarels { 308*26127Skarels printf("tmscp can't get command packet\n"); 309*26127Skarels return(0); 310*26127Skarels } 311*26127Skarels /* Need to determine the drive type for generic driver */ 312*26127Skarels mp->mscp_opcode = M_OP_GTUNT; /* This should give us the device type 313*26127Skarels */ 314*26127Skarels mp->mscp_unit = ui->ui_slave; 315*26127Skarels mp->mscp_cmdref = (long) ui->ui_slave; 316*26127Skarels tms_info[ui->ui_unit].tms_status = 0; /* set to zero */ 317*26127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; 318*26127Skarels *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we shoul 319*26127Skarels d poll*/ 320*26127Skarels i = tmscpaddr->tmscpip; 321*26127Skarels while(!tms_info[ui->ui_unit].tms_status) 322*26127Skarels ; /* Wait for some status */ 323*26127Skarels # ifdef DEBUG 324*26127Skarels printd("tmscpslave: status = %o\n",tms_info[ui->ui_unit].tms_status & M 325*26127Skarels _ST_MASK); 326*26127Skarels # endif 327*26127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = 0; 328*26127Skarels if(!tms_info[ui->ui_unit].tms_type) /* packet from a GTUNT */ 329*26127Skarels return(0); /* Failed No such drive */ 330*26127Skarels else 331*26127Skarels return(1); /* Got it and it is there */ 332*26127Skarels } 333*26127Skarels 334*26127Skarels 335*26127Skarels /* 336*26127Skarels * Set ui flags to zero to show device is not online & set tmscpip. 337*26127Skarels * Unit to Controller mapping is set up here. 338*26127Skarels * Open routine will issue the online command, later. 339*26127Skarels */ 340*26127Skarels tmscpattach (ui) 341*26127Skarels register struct uba_device *ui; /* ptr to unibus dev struct */ 342*26127Skarels { 343*26127Skarels register struct uba_ctlr *um = ui->ui_mi; /* ptr to controller struct * 344*26127Skarels / 345*26127Skarels struct tmscpdevice *tmscpaddr = (struct tmscpdevice *) um->um_addr; /* 346*26127Skarels IP & SA */ 347*26127Skarels struct mscp *mp; 348*26127Skarels int i; /* Assign to here to start the tmscp-dev polling */ 349*26127Skarels 350*26127Skarels # ifdef lint 351*26127Skarels i = i; 352*26127Skarels # endif lint 353*26127Skarels ui->ui_flags = 0; 354*26127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; 355*26127Skarels # ifdef DEBUG 356*26127Skarels /* 357*26127Skarels * Check to see if the drive is available. 358*26127Skarels * If not then just print debug. 359*26127Skarels */ 360*26127Skarels if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL) 361*26127Skarels printd("tmscpattach: unavailable \n"); 362*26127Skarels # endif 363*26127Skarels utoctlr[ui->ui_unit] = ui->ui_ctlr; 364*26127Skarels } 365*26127Skarels 366*26127Skarels 367*26127Skarels /* 368*26127Skarels * TMSCP interrupt routine. 369*26127Skarels */ 370*26127Skarels tmscpintr (d) 371*26127Skarels int d; /* index to the controller */ 372*26127Skarels { 373*26127Skarels register struct uba_ctlr *um = tmscpminfo[d]; 374*26127Skarels register struct tmscpdevice *tmscpaddr = (struct tmscpdevice *)um->um_a 375*26127Skarels ddr; 376*26127Skarels struct buf *bp; 377*26127Skarels register int i; 378*26127Skarels register struct tmscp_softc *sc = &tmscp_softc[d]; 379*26127Skarels register struct tmscp *tm = &tmscp[d]; 380*26127Skarels struct tmscp *ttm; 381*26127Skarels struct mscp *mp; 382*26127Skarels 383*26127Skarels # ifdef DEBUG 384*26127Skarels printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr-> 385*26127Skarels tmscpsa); 386*26127Skarels # endif 387*26127Skarels 388*26127Skarels /* 389*26127Skarels * How the interrupt is handled depends on the state of the controller. 390*26127Skarels */ 391*26127Skarels switch (sc->sc_state) { 392*26127Skarels 393*26127Skarels case S_IDLE: 394*26127Skarels printf("tmscp%d: random interrupt ignored\n", d); 395*26127Skarels return; 396*26127Skarels 397*26127Skarels /* Controller was in step 1 last, see if its gone to step 2 */ 398*26127Skarels case S_STEP1: 399*26127Skarels # define STEP1MASK 0174377 400*26127Skarels # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) 401*26127Skarels for (i = 0; i < 150; i++) 402*26127Skarels { 403*26127Skarels if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) 404*26127Skarels { /* still in step 1 (wait 1/100 sec) */ 405*26127Skarels DELAY(10000); 406*26127Skarels # ifdef DEBUG 407*26127Skarels printd("still in step 1, delaying\n"); 408*26127Skarels # endif DEBUG 409*26127Skarels } 410*26127Skarels else 411*26127Skarels break; 412*26127Skarels } 413*26127Skarels if (i > 149) 414*26127Skarels { 415*26127Skarels sc->sc_state = S_IDLE; 416*26127Skarels printf("failed to initialize, in step1: sa 0x%x", tmscp 417*26127Skarels addr->tmscpsa); 418*26127Skarels wakeup((caddr_t)um); 419*26127Skarels return; 420*26127Skarels } 421*26127Skarels tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) 422*26127Skarels | ((cpu == VAX_780 || cpu == VAX_8600) ? TMSCP_PI : 0); 423*26127Skarels sc->sc_state = S_STEP2; 424*26127Skarels return; 425*26127Skarels 426*26127Skarels /* Controller was in step 2 last, see if its gone to step 3 */ 427*26127Skarels case S_STEP2: 428*26127Skarels # define STEP2MASK 0174377 429*26127Skarels # define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) 430*26127Skarels for (i = 0; i < 150; i++) 431*26127Skarels { 432*26127Skarels if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) 433*26127Skarels { /* still in step 2 (wait 1/100 sec) */ 434*26127Skarels DELAY(10000); 435*26127Skarels # ifdef DEBUG 436*26127Skarels printd("still in step 2, delaying\n"); 437*26127Skarels # endif DEBUG 438*26127Skarels } 439*26127Skarels else 440*26127Skarels break; 441*26127Skarels } 442*26127Skarels if (i > 149) 443*26127Skarels { 444*26127Skarels sc->sc_state = S_IDLE; 445*26127Skarels printf("failed to initialize, in step2: sa 0x%x", tmscp 446*26127Skarels addr->tmscpsa); 447*26127Skarels wakeup((caddr_t)um); 448*26127Skarels return; 449*26127Skarels } 450*26127Skarels tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) 451*26127Skarels >>16; 452*26127Skarels sc->sc_state = S_STEP3; 453*26127Skarels return; 454*26127Skarels 455*26127Skarels /* Controller was in step 3 last, see if its gone to step 4 */ 456*26127Skarels case S_STEP3: 457*26127Skarels # define STEP3MASK 0174000 458*26127Skarels # define STEP3GOOD TMSCP_STEP4 459*26127Skarels for (i = 0; i < 150; i++) 460*26127Skarels { 461*26127Skarels if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) 462*26127Skarels { /* still in step 3 (wait 1/100 sec) */ 463*26127Skarels DELAY(10000); 464*26127Skarels # ifdef DEBUG 465*26127Skarels printd("still in step 3, delaying\n"); 466*26127Skarels # endif DEBUG 467*26127Skarels } 468*26127Skarels else 469*26127Skarels break; 470*26127Skarels } 471*26127Skarels if (i > 149) 472*26127Skarels { 473*26127Skarels sc->sc_state = S_IDLE; 474*26127Skarels printf("failed to initialize, in step3: sa 0x%x", tmscp 475*26127Skarels addr->tmscpsa); 476*26127Skarels wakeup((caddr_t)um); 477*26127Skarels return; 478*26127Skarels } 479*26127Skarels /* 480*26127Skarels * Get microcode version and model number of controller; 481*26127Skarels * Signal initialization complete (_GO) (to the controller); 482*26127Skarels * ask for Last Fail response if tmscperror is set; 483*26127Skarels * Set state to "set controller characteristics". 484*26127Skarels */ 485*26127Skarels tmscpmicro[d] = tmscpaddr->tmscpsa; 486*26127Skarels tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); 487*26127Skarels sc->sc_state = S_SCHAR; 488*26127Skarels # ifdef DEBUG 489*26127Skarels printd("tmscpintr: completed state %d \n", sc->sc_state); 490*26127Skarels printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF, 491*26127Skarels (tmscpmicro[d]>>4) & 0xF); 492*26127Skarels # endif 493*26127Skarels 494*26127Skarels /* 495*26127Skarels * Initialize the data structures (response and command queues). 496*26127Skarels */ 497*26127Skarels ttm = sc->sc_tmscp; 498*26127Skarels for (i = 0; i < NRSP; i++) 499*26127Skarels { 500*26127Skarels tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | 501*26127Skarels (long)&ttm->tmscp_rsp[i].mscp_cmdref 502*26127Skarels ; 503*26127Skarels tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i]; 504*26127Skarels tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen; 505*26127Skarels } 506*26127Skarels for (i = 0; i < NCMD; i++) 507*26127Skarels { 508*26127Skarels tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | 509*26127Skarels (long)&ttm->tmscp_cmd[i].mscp_cmdref; 510*26127Skarels tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i]; 511*26127Skarels tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen; 512*26127Skarels tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1; 513*26127Skarels } 514*26127Skarels bp = &tmscpwtab[d]; 515*26127Skarels bp->av_forw = bp->av_back = bp; 516*26127Skarels sc->sc_lastcmd = 1; 517*26127Skarels sc->sc_lastrsp = 0; 518*26127Skarels mp = &tmscp[um->um_ctlr].tmscp_cmd[0]; 519*26127Skarels mp->mscp_unit = mp->mscp_modifier = 0; 520*26127Skarels mp->mscp_flags = 0; 521*26127Skarels mp->mscp_version = 0; 522*26127Skarels mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; 523*26127Skarels /* 524*26127Skarels * A host time out value of 0 means that the controller will not 525*26127Skarels * time out. This is ok for the TK50. 526*26127Skarels */ 527*26127Skarels mp->mscp_hsttmo = 0; 528*26127Skarels mp->mscp_time.val[0] = 0; 529*26127Skarels mp->mscp_time.val[1] = 0; 530*26127Skarels mp->mscp_cntdep = 0; 531*26127Skarels mp->mscp_opcode = M_OP_STCON; 532*26127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 533*26127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 534*26127Skarels return; 535*26127Skarels 536*26127Skarels case S_SCHAR: 537*26127Skarels case S_RUN: 538*26127Skarels break; 539*26127Skarels 540*26127Skarels default: 541*26127Skarels printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_ 542*26127Skarels state); 543*26127Skarels return; 544*26127Skarels } /* end switch */ 545*26127Skarels 546*26127Skarels /* 547*26127Skarels * The controller state is S_SCHAR or S_RUN 548*26127Skarels */ 549*26127Skarels 550*26127Skarels /* 551*26127Skarels * If the error bit is set in the SA register then print an error 552*26127Skarels * message and reinitialize the controller. 553*26127Skarels */ 554*26127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 555*26127Skarels { 556*26127Skarels printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xf 557*26127Skarels fff); 558*26127Skarels tmscpaddr->tmscpip = 0; 559*26127Skarels wakeup((caddr_t)um); 560*26127Skarels } 561*26127Skarels /* 562*26127Skarels * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) 563*26127Skarels */ 564*26127Skarels if (tm->tmscp_ca.ca_bdp) 565*26127Skarels { 566*26127Skarels /* 567*26127Skarels * THIS IS A KLUDGE. 568*26127Skarels * Maybe we should change the entire 569*26127Skarels * UBA interface structure. 570*26127Skarels */ 571*26127Skarels int s = spl6(); 572*26127Skarels i = um->um_ubinfo; 573*26127Skarels # ifdef DEBUG 574*26127Skarels printd("tmscp: purge bdp %d\n", tm->tmscp_ca.ca_bdp); 575*26127Skarels # endif 576*26127Skarels um->um_ubinfo = tm->tmscp_ca.ca_bdp<<28; 577*26127Skarels ubapurge(um); 578*26127Skarels um->um_ubinfo = i; 579*26127Skarels (void) splx(s); 580*26127Skarels tm->tmscp_ca.ca_bdp = 0; 581*26127Skarels tmscpaddr->tmscpsa = 0; /* signal purge complete */ 582*26127Skarels } 583*26127Skarels 584*26127Skarels /* 585*26127Skarels * Check for response ring transition. 586*26127Skarels */ 587*26127Skarels if (tm->tmscp_ca.ca_rspint) 588*26127Skarels { 589*26127Skarels tm->tmscp_ca.ca_rspint = 0; 590*26127Skarels for (i = sc->sc_lastrsp;; i++) 591*26127Skarels { 592*26127Skarels i %= NRSP; 593*26127Skarels if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) 594*26127Skarels break; 595*26127Skarels tmscprsp(um, tm, sc, i); 596*26127Skarels tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; 597*26127Skarels } 598*26127Skarels sc->sc_lastrsp = i; 599*26127Skarels } 600*26127Skarels 601*26127Skarels /* 602*26127Skarels * Check for command ring transition. 603*26127Skarels */ 604*26127Skarels if (tm->tmscp_ca.ca_cmdint) 605*26127Skarels { 606*26127Skarels # ifdef DEBUG 607*26127Skarels printd("tmscpintr: command ring transition\n"); 608*26127Skarels # endif 609*26127Skarels tm->tmscp_ca.ca_cmdint = 0; 610*26127Skarels } 611*26127Skarels if(tmscp_cp_wait) 612*26127Skarels wakeup(&tmscp_cp_wait); 613*26127Skarels (void) tmscpstart(um); 614*26127Skarels } 615*26127Skarels 616*26127Skarels 617*26127Skarels /* 618*26127Skarels * Open a tmscp device and set the unit online. If the controller is not 619*26127Skarels * in the run state, call init to initialize the tmscp controller first. 620*26127Skarels */ 621*26127Skarels 622*26127Skarels tmscpopen(dev, flag) 623*26127Skarels dev_t dev; 624*26127Skarels int flag; 625*26127Skarels { 626*26127Skarels register int unit; 627*26127Skarels register struct uba_device *ui; 628*26127Skarels register struct tmscp_softc *sc; 629*26127Skarels register struct mscp *mp; 630*26127Skarels register struct uba_ctlr *um; 631*26127Skarels struct tmscpdevice *tmscpaddr; 632*26127Skarels int s,i; 633*26127Skarels extern quota; 634*26127Skarels 635*26127Skarels # ifdef lint 636*26127Skarels flag = flag; i = i; 637*26127Skarels # endif 638*26127Skarels unit = TMSUNIT(dev); 639*26127Skarels # ifdef DEBUG 640*26127Skarels printd("tmscpopen unit %d\n",unit); 641*26127Skarels if(tmscpdebug)DELAY(10000); 642*26127Skarels # endif 643*26127Skarels if (unit >= nNTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0 644*26127Skarels || tms_info[ui->ui_unit].tms_openf) 645*26127Skarels return (ENXIO); 646*26127Skarels sc = &tmscp_softc[ui->ui_ctlr]; 647*26127Skarels s = spl5(); 648*26127Skarels if (sc->sc_state != S_RUN) 649*26127Skarels { 650*26127Skarels if (sc->sc_state == S_IDLE) 651*26127Skarels if(!tmscpinit(ui->ui_ctlr)) 652*26127Skarels { 653*26127Skarels printf("tmscp controller failed to init\n"); 654*26127Skarels (void) splx(s); 655*26127Skarels return(ENXIO); 656*26127Skarels } 657*26127Skarels /* 658*26127Skarels * Wait for initialization to complete 659*26127Skarels */ 660*26127Skarels timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ 661*26127Skarels sleep((caddr_t)ui->ui_mi, 0); 662*26127Skarels if (sc->sc_state != S_RUN) 663*26127Skarels { 664*26127Skarels (void) splx(s); 665*26127Skarels return (EIO); 666*26127Skarels } 667*26127Skarels } 668*26127Skarels /* 669*26127Skarels * Check to see if the device is really there. 670*26127Skarels * this code was taken from Fred Canters 11 driver 671*26127Skarels */ 672*26127Skarels um = ui->ui_mi; 673*26127Skarels tmscpaddr = (struct tmscpdevice *) um->um_addr; 674*26127Skarels (void) splx(s); 675*26127Skarels if(ui->ui_flags == 0) 676*26127Skarels { 677*26127Skarels s = spl5(); 678*26127Skarels while(0 ==(mp = tmscpgetcp(um))) 679*26127Skarels { 680*26127Skarels tmscp_cp_wait++; 681*26127Skarels sleep(&tmscp_cp_wait,PSWP+1); 682*26127Skarels tmscp_cp_wait--; 683*26127Skarels } 684*26127Skarels (void) splx(s); 685*26127Skarels mp->mscp_opcode = M_OP_ONLIN; 686*26127Skarels mp->mscp_unit = ui->ui_slave; 687*26127Skarels mp->mscp_cmdref = (long) & tms_info[ui->ui_unit].tms_type; 688*26127Skarels /* need to sleep on something */ 689*26127Skarels # ifdef DEBUG 690*26127Skarels printd("tmscpopen: bring unit %d online\n",ui->ui_unit); 691*26127Skarels # endif 692*26127Skarels *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT; 693*26127Skarels i = tmscpaddr->tmscpip; 694*26127Skarels /* 695*26127Skarels * To make sure we wake up, timeout in 240 seconds. 696*26127Skarels * Wakeup in tmscprsp routine. 697*26127Skarels * 240 seconds (4 minutes) is necessary since a rewind 698*26127Skarels * can take a few minutes. 699*26127Skarels */ 700*26127Skarels timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz); 701*26127Skarels sleep((caddr_t) mp->mscp_cmdref,PSWP+1); 702*26127Skarels } 703*26127Skarels if(ui->ui_flags == 0) 704*26127Skarels return(ENXIO); /* Didn't go online */ 705*26127Skarels tms_info[ui->ui_unit].tms_openf = 1; 706*26127Skarels tms_info[ui->ui_unit].tms_lastiow = 0; 707*26127Skarels /* 708*26127Skarels * If the high density device is not specified, set unit to low 709*26127Skarels * density. This is done as an "internal" ioctl command so 710*26127Skarels * that the command setup and response handling 711*26127Skarels * is done thru "regular" command routines. 712*26127Skarels */ 713*26127Skarels if ((minor(dev) & T_HIDENSITY) == 0) 714*26127Skarels tmscpcommand(dev, TMS_LOWDENSITY, 1); 715*26127Skarels else 716*26127Skarels tmscpcommand(dev, TMS_HIDENSITY, 1); 717*26127Skarels return (0); 718*26127Skarels } 719*26127Skarels 720*26127Skarels 721*26127Skarels /* 722*26127Skarels * Close tape device. 723*26127Skarels * 724*26127Skarels * If tape was open for writing or last operation was 725*26127Skarels * a write, then write two EOF's and backspace over the last one. 726*26127Skarels * Unless this is a non-rewinding special file, rewind the tape. 727*26127Skarels * 728*26127Skarels * NOTE: 729*26127Skarels * We want to be sure that any serious exception is cleared on the 730*26127Skarels * close. A Clear Serious Exception (CSE) modifier is always done on 731*26127Skarels * the rewind command. For the non-rewind case we check to see if the 732*26127Skarels * "serex" field is set in the softc struct; if it is then issue a noop 733*26127Skarels * command with the CSE modifier. 734*26127Skarels * Make the tape available to others, by clearing openf flag. 735*26127Skarels */ 736*26127Skarels tmscpclose(dev, flag) 737*26127Skarels register dev_t dev; 738*26127Skarels register flag; 739*26127Skarels { 740*26127Skarels register struct tmscp_softc *sc = &tmscp_softc[TMSCPCTLR(dev)]; 741*26127Skarels register struct uba_device *ui; 742*26127Skarels 743*26127Skarels ui = tmsdinfo[TMSUNIT(dev)]; 744*26127Skarels # ifdef DEBUG 745*26127Skarels printd("tmscpclose: ctlr = %d\n",TMSCPCTLR(dev)); 746*26127Skarels printd("tmscpclose: unit = %d\n",TMSUNIT(dev)); 747*26127Skarels if(tmscpdebug)DELAY(10000); 748*26127Skarels # endif 749*26127Skarels if (flag == FWRITE || (flag&FWRITE) && tms_info[ui->ui_unit].tms_lastio 750*26127Skarels w) 751*26127Skarels { 752*26127Skarels /* device, command, count */ 753*26127Skarels tmscpcommand (dev, TMS_WRITM, 1); 754*26127Skarels tmscpcommand (dev, TMS_WRITM, 1); 755*26127Skarels tmscpcommand (dev, TMS_BSR, 1); 756*26127Skarels } 757*26127Skarels if ((minor(dev)&T_NOREWIND) == 0) 758*26127Skarels /* 759*26127Skarels * Don't hang waiting for rewind complete. 760*26127Skarels */ 761*26127Skarels tmscpcommand(dev, TMS_REW, 0); 762*26127Skarels else 763*26127Skarels if (tms_info[ui->ui_unit].tms_serex) 764*26127Skarels { 765*26127Skarels # ifdef DEBUG 766*26127Skarels printd("tmscpclose: clearing serex\n"); 767*26127Skarels if(tmscpdebug)DELAY(10000); 768*26127Skarels # endif 769*26127Skarels tmscpcommand(dev, TMS_CSE, 1); 770*26127Skarels } 771*26127Skarels tms_info[ui->ui_unit].tms_openf = 0; 772*26127Skarels } 773*26127Skarels 774*26127Skarels 775*26127Skarels /* 776*26127Skarels * Execute a command on the tape drive a specified number of times. 777*26127Skarels * This routine sets up a buffer and calls the strategy routine which 778*26127Skarels * links the buffer onto the drive's buffer queue. 779*26127Skarels * The start routine will take care of creating a tmscp command packet 780*26127Skarels * with the command. The start routine is called by the strategy or the 781*26127Skarels * interrupt routine. 782*26127Skarels */ 783*26127Skarels 784*26127Skarels tmscpcommand (dev, com, count) 785*26127Skarels register dev_t dev; 786*26127Skarels int com, count; 787*26127Skarels { 788*26127Skarels register struct uba_device *ui; 789*26127Skarels register struct buf *bp; 790*26127Skarels register int s; 791*26127Skarels int unit = TMSUNIT(dev); 792*26127Skarels 793*26127Skarels if (unit >= nNTMS) 794*26127Skarels return (ENXIO); 795*26127Skarels ui = tmsdinfo[unit]; 796*26127Skarels bp = &ctmscpbuf[ui->ui_ctlr]; 797*26127Skarels 798*26127Skarels s = spl5(); 799*26127Skarels while (bp->b_flags&B_BUSY) 800*26127Skarels { 801*26127Skarels /* 802*26127Skarels * This special check is because B_BUSY never 803*26127Skarels * gets cleared in the non-waiting rewind case. 804*26127Skarels */ 805*26127Skarels if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) 806*26127Skarels break; 807*26127Skarels bp->b_flags |= B_WANTED; 808*26127Skarels sleep((caddr_t)bp, PRIBIO); 809*26127Skarels } 810*26127Skarels bp->b_flags = B_BUSY|B_READ; 811*26127Skarels splx(s); 812*26127Skarels /* 813*26127Skarels * Load the buffer. The b_count field gets used to hold the command 814*26127Skarels * count. the b_resid field gets used to hold the command mneumonic. 815*26127Skarels * These 2 fields are "known" to be "safe" to use for this purpose. 816*26127Skarels * (Most other drivers also use these fields in this way.) 817*26127Skarels */ 818*26127Skarels bp->b_dev = dev; 819*26127Skarels bp->b_bcount = count; 820*26127Skarels bp->b_resid = com; 821*26127Skarels bp->b_blkno = 0; 822*26127Skarels tmscpstrategy(bp); 823*26127Skarels /* 824*26127Skarels * In case of rewind from close, don't wait. 825*26127Skarels * This is the only case where count can be 0. 826*26127Skarels */ 827*26127Skarels if (count == 0) 828*26127Skarels return; 829*26127Skarels iowait(bp); 830*26127Skarels if (bp->b_flags&B_WANTED) 831*26127Skarels wakeup((caddr_t)bp); 832*26127Skarels bp->b_flags &= B_ERROR; 833*26127Skarels } 834*26127Skarels 835*26127Skarels /* 836*26127Skarels * Find an unused command packet 837*26127Skarels */ 838*26127Skarels struct mscp * 839*26127Skarels tmscpgetcp(um) 840*26127Skarels struct uba_ctlr *um; 841*26127Skarels { 842*26127Skarels register struct mscp *mp; 843*26127Skarels register struct tmscpca *cp; 844*26127Skarels register struct tmscp_softc *sc; 845*26127Skarels register int i; 846*26127Skarels int s; 847*26127Skarels 848*26127Skarels s = spl5(); 849*26127Skarels cp = &tmscp[um->um_ctlr].tmscp_ca; 850*26127Skarels sc = &tmscp_softc[um->um_ctlr]; 851*26127Skarels /* 852*26127Skarels * If no credits, can't issue any commands 853*26127Skarels * until some outstanding commands complete. 854*26127Skarels */ 855*26127Skarels i = sc->sc_lastcmd; 856*26127Skarels # ifdef DEBUG 857*26127Skarels printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); 858*26127Skarels # endif 859*26127Skarels if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && 860*26127Skarels (sc->sc_credits >= 2)) 861*26127Skarels { 862*26127Skarels sc->sc_credits--; /* This commits to issuing a command */ 863*26127Skarels cp->ca_cmddsc[i] &= ~TMSCP_INT; 864*26127Skarels mp = &tmscp[um->um_ctlr].tmscp_cmd[i]; 865*26127Skarels mp->mscp_unit = mp->mscp_modifier = 0; 866*26127Skarels mp->mscp_opcode = mp->mscp_flags = 0; 867*26127Skarels mp->mscp_bytecnt = mp->mscp_buffer = 0; 868*26127Skarels sc->sc_lastcmd = (i + 1) % NCMD; 869*26127Skarels (void) splx(s); 870*26127Skarels return(mp); 871*26127Skarels } 872*26127Skarels (void) splx(s); 873*26127Skarels return(NULL); 874*26127Skarels } 875*26127Skarels 876*26127Skarels 877*26127Skarels /* 878*26127Skarels * Initialize a TMSCP device. Set up UBA mapping registers, 879*26127Skarels * initialize data structures, and start hardware 880*26127Skarels * initialization sequence. 881*26127Skarels */ 882*26127Skarels tmscpinit (d) 883*26127Skarels int d; /* index to the controller */ 884*26127Skarels { 885*26127Skarels register struct tmscp_softc *sc; 886*26127Skarels register struct tmscp *t; /* communications area; cmd & resp packets * 887*26127Skarels / 888*26127Skarels struct tmscpdevice *tmscpaddr; 889*26127Skarels struct uba_ctlr *um; 890*26127Skarels 891*26127Skarels sc = &tmscp_softc[d]; 892*26127Skarels um = tmscpminfo[d]; 893*26127Skarels um->um_tab.b_active++; 894*26127Skarels t = &tmscp[d]; 895*26127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 896*26127Skarels if (sc->sc_mapped == 0) 897*26127Skarels { 898*26127Skarels /* 899*26127Skarels * Map the communications area and command 900*26127Skarels * and response packets into Unibus address 901*26127Skarels * space. 902*26127Skarels */ 903*26127Skarels sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (str 904*26127Skarels uct tmscp), 0); 905*26127Skarels # ifdef MVAX 906*26127Skarels if (cpu == MVAX_I) 907*26127Skarels sc->sc_tmscp = (struct tmscp *)(sc->sc_ubainfo & 0x3fff 908*26127Skarels ff); 909*26127Skarels else 910*26127Skarels # endif MVAX 911*26127Skarels sc->sc_tmscp = (struct tmscp *)(sc->sc_ubainfo & 0x3fff 912*26127Skarels f); 913*26127Skarels sc->sc_mapped = 1; 914*26127Skarels } 915*26127Skarels 916*26127Skarels /* 917*26127Skarels * Start the hardware initialization sequence. 918*26127Skarels */ 919*26127Skarels tmscpaddr->tmscpip = 0; /* start initialization */ 920*26127Skarels 921*26127Skarels while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 922*26127Skarels { 923*26127Skarels # ifdef DEBUG 924*26127Skarels printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); 925*26127Skarels DELAY(100000); 926*26127Skarels # endif 927*26127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) 928*26127Skarels return(0); /* CHECK */ 929*26127Skarels } 930*26127Skarels tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ 931*26127Skarels ivec/4); 932*26127Skarels /* 933*26127Skarels * Initialization continues in the interrupt routine. 934*26127Skarels */ 935*26127Skarels sc->sc_state = S_STEP1; 936*26127Skarels sc->sc_credits = 0; 937*26127Skarels return(1); 938*26127Skarels } 939*26127Skarels 940*26127Skarels 941*26127Skarels /* 942*26127Skarels * Start I/O operation 943*26127Skarels * This code is convoluted. The majority of it was copied from the uda driver. 944*26127Skarels */ 945*26127Skarels 946*26127Skarels tmscpstart(um) 947*26127Skarels register struct uba_ctlr *um; 948*26127Skarels { 949*26127Skarels register struct buf *bp, *dp; 950*26127Skarels register struct mscp *mp; 951*26127Skarels register struct tmscp_softc *sc; 952*26127Skarels register struct uba_device *ui; 953*26127Skarels struct tmscpdevice *tmscpaddr; 954*26127Skarels struct tmscp *tm = &tmscp[um->um_ctlr]; 955*26127Skarels int i,tempi; 956*26127Skarels char ioctl; /* flag: set true if its an IOCTL command */ 957*26127Skarels 958*26127Skarels sc = &tmscp_softc[um->um_ctlr]; 959*26127Skarels 960*26127Skarels for(;;) 961*26127Skarels { 962*26127Skarels if ((dp = um->um_tab.b_actf) == NULL) 963*26127Skarels { 964*26127Skarels /* 965*26127Skarels * Release unneeded UBA resources and return 966*26127Skarels * (drive was inactive) 967*26127Skarels */ 968*26127Skarels um->um_tab.b_active = 0; 969*26127Skarels break; 970*26127Skarels } 971*26127Skarels if ((bp = dp->b_actf) == NULL) 972*26127Skarels { 973*26127Skarels /* 974*26127Skarels * No more requests for this drive, remove 975*26127Skarels * from controller queue and look at next drive. 976*26127Skarels * We know we're at the head of the controller queue. 977*26127Skarels */ 978*26127Skarels dp->b_active = 0; 979*26127Skarels um->um_tab.b_actf = dp->b_forw; 980*26127Skarels continue; /* Need to check for loop */ 981*26127Skarels } 982*26127Skarels um->um_tab.b_active++; 983*26127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 984*26127Skarels if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) 985*26127Skarels { 986*26127Skarels harderr(bp, "tms"); 987*26127Skarels mprintf("tmscp%d: sa 0%o, state %d\n",um->um_ctlr, 988*26127Skarels tmscpaddr->tmscpsa&0xffff, sc->sc_state); 989*26127Skarels tmscpinit(um->um_ctlr); 990*26127Skarels /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ 991*26127Skarels break; 992*26127Skarels } 993*26127Skarels ui = tmsdinfo[(TMSUNIT(bp->b_dev))]; 994*26127Skarels /* 995*26127Skarels * Default is that last command was NOT a write command; 996*26127Skarels * if a write command is done it will be detected in tmscprsp. 997*26127Skarels */ 998*26127Skarels tms_info[ui->ui_unit].tms_lastiow = 0; 999*26127Skarels if (ui->ui_flags == 0) 1000*26127Skarels { /* not online */ 1001*26127Skarels if ((mp = tmscpgetcp(um)) == NULL) 1002*26127Skarels break; 1003*26127Skarels mp->mscp_opcode = M_OP_ONLIN; 1004*26127Skarels mp->mscp_unit = ui->ui_slave; 1005*26127Skarels dp->b_active = 2; 1006*26127Skarels um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ 1007*26127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 1008*26127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 1009*26127Skarels printf("tmscp%d fatal error (0%o)\n",um->um_ctlr, 1010*26127Skarels tmscpaddr->tmscpsa&0xffff); 1011*26127Skarels i = tmscpaddr->tmscpip; 1012*26127Skarels continue; 1013*26127Skarels } 1014*26127Skarels switch (cpu) { 1015*26127Skarels 1016*26127Skarels case VAX_8600: 1017*26127Skarels case VAX_780: 1018*26127Skarels i = UBA_NEEDBDP|UBA_CANTWAIT; 1019*26127Skarels break; 1020*26127Skarels case VAX_8200: 1021*26127Skarels case VAX_750: 1022*26127Skarels i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; 1023*26127Skarels break; 1024*26127Skarels case VAX_730: 1025*26127Skarels i = UBA_CANTWAIT; 1026*26127Skarels break; 1027*26127Skarels case MVAX_I: 1028*26127Skarels case MVAX_II: 1029*26127Skarels i = UBA_CANTWAIT|UBA_MAPANYWAY; 1030*26127Skarels break; 1031*26127Skarels } /* end switch (cpu) */ 1032*26127Skarels /* 1033*26127Skarels * If command is an ioctl command then set the ioctl flag for later use 1034*26127Skarels . 1035*26127Skarels * If not (i.e. it is a read or write) then attempt 1036*26127Skarels * to set up a buffer pointer. 1037*26127Skarels */ 1038*26127Skarels ioctl = 0; 1039*26127Skarels if (bp == &ctmscpbuf[um->um_ctlr]) 1040*26127Skarels ioctl = 1; 1041*26127Skarels else 1042*26127Skarels if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) 1043*26127Skarels { 1044*26127Skarels if(dp->b_qsize != 0) 1045*26127Skarels break; /* When a command completes and */ 1046*26127Skarels /* frees a bdp tmscpstart will be called * 1047*26127Skarels / 1048*26127Skarels if ((mp = tmscpgetcp(um)) == NULL) 1049*26127Skarels break; 1050*26127Skarels # ifdef DEBUG 1051*26127Skarels printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_un 1052*26127Skarels it, i); 1053*26127Skarels if(tmscpdebug)DELAY(10000); 1054*26127Skarels # endif 1055*26127Skarels mp->mscp_opcode = M_OP_GTUNT; 1056*26127Skarels mp->mscp_unit = ui->ui_slave; 1057*26127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 1058*26127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 1059*26127Skarels printf("tmscp%d: fatal error (0%o)\n",um->um_ct 1060*26127Skarels lr, 1061*26127Skarels tmscpaddr->tmscpsa&0xffff); 1062*26127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 1063*26127Skarels break; 1064*26127Skarels } 1065*26127Skarels # if defined(VAX750) || defined(VAX8200) 1066*26127Skarels if ((cpu == VAX_750) || (cpu == VAX_8200)) 1067*26127Skarels tempi = i & 0xfffffff; /* mask off bdp */ 1068*26127Skarels else 1069*26127Skarels # endif 1070*26127Skarels tempi = i; 1071*26127Skarels if ((mp = tmscpgetcp(um)) == NULL) 1072*26127Skarels { 1073*26127Skarels if (!ioctl) /* only need to release if NOT ioctl */ 1074*26127Skarels ubarelse(um->um_ubanum,&tempi); 1075*26127Skarels break; 1076*26127Skarels } 1077*26127Skarels mp->mscp_cmdref = (long)bp; /* pointer to get back */ 1078*26127Skarels mp->mscp_unit = ui->ui_slave; 1079*26127Skarels /* 1080*26127Skarels * If its an ioctl-type command then set up the appropriate 1081*26127Skarels * tmscp command; by doing a switch on the "b_resid" field where 1082*26127Skarels * the command mneumonic is stored. 1083*26127Skarels */ 1084*26127Skarels if (ioctl) 1085*26127Skarels { 1086*26127Skarels # ifdef DEBUG 1087*26127Skarels printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid); 1088*26127Skarels # endif 1089*26127Skarels /* 1090*26127Skarels * The reccnt and tmkcnt fields are set to zero by the getcp 1091*26127Skarels * routine (as bytecnt and buffer fields). Thus reccnt and 1092*26127Skarels * tmkcnt are only modified here if they need to be set to 1093*26127Skarels * a non-zero value. 1094*26127Skarels */ 1095*26127Skarels switch (bp->b_resid) { 1096*26127Skarels 1097*26127Skarels case TMS_WRITM: 1098*26127Skarels mp->mscp_opcode = M_OP_WRITM; 1099*26127Skarels break; 1100*26127Skarels case TMS_FSF: 1101*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1102*26127Skarels mp->mscp_tmkcnt = bp->b_bcount; 1103*26127Skarels break; 1104*26127Skarels case TMS_BSF: 1105*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1106*26127Skarels mp->mscp_modifier = M_MD_REVRS; 1107*26127Skarels mp->mscp_tmkcnt = bp->b_bcount; 1108*26127Skarels break; 1109*26127Skarels case TMS_FSR: 1110*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1111*26127Skarels mp->mscp_modifier = M_MD_OBJCT; 1112*26127Skarels mp->mscp_reccnt = bp->b_bcount; 1113*26127Skarels break; 1114*26127Skarels case TMS_BSR: 1115*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1116*26127Skarels mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; 1117*26127Skarels mp->mscp_reccnt = bp->b_bcount; 1118*26127Skarels break; 1119*26127Skarels /* 1120*26127Skarels * Clear serious exception is done for Rewind & Available cmds 1121*26127Skarels */ 1122*26127Skarels case TMS_REW: 1123*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1124*26127Skarels mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; 1125*26127Skarels if (bp->b_bcount == 0) 1126*26127Skarels mp->mscp_modifier |= M_MD_IMMED; 1127*26127Skarels tms_info[ui->ui_unit].tms_serex = 0; 1128*26127Skarels break; 1129*26127Skarels case TMS_OFFL: 1130*26127Skarels mp->mscp_opcode = M_OP_AVAIL; 1131*26127Skarels mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; 1132*26127Skarels tms_info[ui->ui_unit].tms_serex = 0; 1133*26127Skarels break; 1134*26127Skarels case TMS_SENSE: 1135*26127Skarels mp->mscp_opcode = M_OP_GTUNT; 1136*26127Skarels break; 1137*26127Skarels case TMS_CACHE: 1138*26127Skarels mp->mscp_opcode = M_OP_STUNT; 1139*26127Skarels tms_info[ui->ui_unit].tms_unitflgs |= M_UF_WBKNV; 1140*26127Skarels mp->mscp_unitflgs = tms_info[ui->ui_unit].tms_unitflgs; 1141*26127Skarels mp->mscp_format = tms_info[ui->ui_unit].tms_format; 1142*26127Skarels /* default device dependant parameters */ 1143*26127Skarels mp->mscp_mediaid = 0; 1144*26127Skarels break; 1145*26127Skarels case TMS_NOCACHE: 1146*26127Skarels mp->mscp_opcode = M_OP_STUNT; 1147*26127Skarels tms_info[ui->ui_unit].tms_unitflgs &= ~(M_UF_WBKNV); 1148*26127Skarels mp->mscp_unitflgs = tms_info[ui->ui_unit].tms_unitflgs; 1149*26127Skarels mp->mscp_format = tms_info[ui->ui_unit].tms_format; 1150*26127Skarels /* default device dependant parameters */ 1151*26127Skarels mp->mscp_mediaid = 0; 1152*26127Skarels break; 1153*26127Skarels case TMS_CSE: 1154*26127Skarels /* 1155*26127Skarels * This is a no-op command. It performs a 1156*26127Skarels * clear serious exception only. (Done on a 1157*26127Skarels * non-rewinding close after a serious exception.) 1158*26127Skarels */ 1159*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1160*26127Skarels mp->mscp_modifier = M_MD_CLSEX; 1161*26127Skarels tms_info[ui->ui_unit].tms_serex = 0; 1162*26127Skarels tms_info[ui->ui_unit].tms_clserex = 1; 1163*26127Skarels break; 1164*26127Skarels case TMS_LOWDENSITY: 1165*26127Skarels /* 1166*26127Skarels * Set the unit to low density 1167*26127Skarels */ 1168*26127Skarels mp->mscp_opcode = M_OP_STUNT; 1169*26127Skarels mp->mscp_unitflgs = tms_info[ui->ui_unit].tms_unitflgs; 1170*26127Skarels mp->mscp_mediaid = 0; /* default device dependant par 1171*26127Skarels ameters */ 1172*26127Skarels if ((tms_info[ui->ui_unit].tms_fmtmenu & M_TF_800) != 0 1173*26127Skarels ) 1174*26127Skarels mp->mscp_format = M_TF_800; 1175*26127Skarels else 1176*26127Skarels mp->mscp_format = M_TF_PE & tms_info[ui->ui_uni 1177*26127Skarels t].tms_fmtmenu; 1178*26127Skarels tms_info[ui->ui_unit].tms_format = mp->mscp_format; 1179*26127Skarels break; 1180*26127Skarels case TMS_HIDENSITY: 1181*26127Skarels /* 1182*26127Skarels * Set the unit to high density (format == 0) 1183*26127Skarels */ 1184*26127Skarels mp->mscp_opcode = M_OP_STUNT; 1185*26127Skarels mp->mscp_unitflgs = tms_info[ui->ui_unit].tms_unitflgs; 1186*26127Skarels mp->mscp_mediaid = 0; /* default device dependant par 1187*26127Skarels ameters */ 1188*26127Skarels mp->mscp_format = 0; 1189*26127Skarels tms_info[ui->ui_unit].tms_format = 0; 1190*26127Skarels break; 1191*26127Skarels default: 1192*26127Skarels printf("Bad ioctl on tms unit %d\n", ui->ui_unit); 1193*26127Skarels /* Need a no-op. Reposition no amount */ 1194*26127Skarels mp->mscp_opcode = M_OP_REPOS; 1195*26127Skarels break; 1196*26127Skarels } /* end switch (bp->b_resid) */ 1197*26127Skarels } 1198*26127Skarels else /* Its a read/write command (not an ioctl) */ 1199*26127Skarels { 1200*26127Skarels mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; 1201*26127Skarels mp->mscp_bytecnt = bp->b_bcount; 1202*26127Skarels # if MVAX 1203*26127Skarels if (cpu == MVAX_I) 1204*26127Skarels { 1205*26127Skarels mp->mscp_buffer = (i & 0x3ffff) | TMSCP_MAP; 1206*26127Skarels mp->mscp_mapbase = (long)&(uba_hd[um->um_ubanum].uh_phy 1207*26127Skarels suba->uba_map[0]); 1208*26127Skarels } 1209*26127Skarels else 1210*26127Skarels # endif MVAX 1211*26127Skarels mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); 1212*26127Skarels 1213*26127Skarels bp->b_ubinfo = tempi; /* save mapping info */ 1214*26127Skarels } 1215*26127Skarels if (tms_info[ui->ui_unit].tms_serex == 2) /* if tape mark read */ 1216*26127Skarels { 1217*26127Skarels mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc * 1218*26127Skarels / 1219*26127Skarels tms_info[ui->ui_unit].tms_serex = 0; 1220*26127Skarels } 1221*26127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 1222*26127Skarels # ifdef DEBUG 1223*26127Skarels printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode 1224*26127Skarels ,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); 1225*26127Skarels if(tmscpdebug)DELAY(100000); 1226*26127Skarels # endif 1227*26127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 1228*26127Skarels dp->b_qsize++; 1229*26127Skarels /* 1230*26127Skarels * Move drive to the end of the controller queue 1231*26127Skarels */ 1232*26127Skarels if (dp->b_forw != NULL) 1233*26127Skarels { 1234*26127Skarels um->um_tab.b_actf = dp->b_forw; 1235*26127Skarels um->um_tab.b_actl->b_forw = dp; 1236*26127Skarels um->um_tab.b_actl = dp; 1237*26127Skarels dp->b_forw = NULL; 1238*26127Skarels } 1239*26127Skarels /* 1240*26127Skarels * Move buffer to I/O wait queue 1241*26127Skarels */ 1242*26127Skarels dp->b_actf = bp->av_forw; 1243*26127Skarels dp = &tmscpwtab[um->um_ctlr]; 1244*26127Skarels bp->av_forw = dp; 1245*26127Skarels bp->av_back = dp->av_back; 1246*26127Skarels dp->av_back->av_forw = bp; 1247*26127Skarels dp->av_back = bp; 1248*26127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 1249*26127Skarels { 1250*26127Skarels printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr-> 1251*26127Skarels tmscpsa&0xffff); 1252*26127Skarels tmscpinit(um->um_ctlr); 1253*26127Skarels break; 1254*26127Skarels } 1255*26127Skarels } /* end for */ 1256*26127Skarels /* 1257*26127Skarels * Check for response ring transitions lost in the 1258*26127Skarels * Race condition 1259*26127Skarels */ 1260*26127Skarels for (i = sc->sc_lastrsp;; i++) 1261*26127Skarels { 1262*26127Skarels i %= NRSP; 1263*26127Skarels if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) 1264*26127Skarels break; 1265*26127Skarels tmscprsp(um, tm, sc, i); 1266*26127Skarels tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; 1267*26127Skarels } 1268*26127Skarels sc->sc_lastrsp = i; 1269*26127Skarels } 1270*26127Skarels 1271*26127Skarels 1272*26127Skarels /* 1273*26127Skarels * Process a response packet 1274*26127Skarels */ 1275*26127Skarels tmscprsp(um, tm, sc, i) 1276*26127Skarels register struct uba_ctlr *um; 1277*26127Skarels register struct tmscp *tm; 1278*26127Skarels register struct tmscp_softc *sc; 1279*26127Skarels int i; 1280*26127Skarels { 1281*26127Skarels register struct mscp *mp; 1282*26127Skarels struct uba_device *ui; 1283*26127Skarels struct buf *dp, *bp, nullbp; 1284*26127Skarels int st; 1285*26127Skarels 1286*26127Skarels mp = &tm->tmscp_rsp[i]; 1287*26127Skarels mp->mscp_header.tmscp_msglen = mscp_msglen; 1288*26127Skarels sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits * 1289*26127Skarels / 1290*26127Skarels if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ 1291*26127Skarels return; 1292*26127Skarels # ifdef DEBUG 1293*26127Skarels printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_sta 1294*26127Skarels tus&M_ST_MASK); 1295*26127Skarels # endif 1296*26127Skarels /* 1297*26127Skarels * If it's an error log message (datagram), 1298*26127Skarels * pass it on for more extensive processing. 1299*26127Skarels */ 1300*26127Skarels if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) 1301*26127Skarels { /* check */ 1302*26127Skarels tmserror(um, (struct mslg *)mp); 1303*26127Skarels return; 1304*26127Skarels } 1305*26127Skarels st = mp->mscp_status&M_ST_MASK; 1306*26127Skarels /* 1307*26127Skarels * The controller interrupts as drive 0. 1308*26127Skarels * This means that you must check for controller interrupts 1309*26127Skarels * before you check to see if there is a drive 0. 1310*26127Skarels */ 1311*26127Skarels if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) 1312*26127Skarels { 1313*26127Skarels if (st == M_ST_SUCC) 1314*26127Skarels { 1315*26127Skarels # ifdef DEBUG 1316*26127Skarels printd("ctlr has %d credits\n", mp->mscp_header.tmscp_c 1317*26127Skarels redits & 0xf); 1318*26127Skarels printd("ctlr timeout = %d\n", mp->mscp_cnttmo); 1319*26127Skarels # endif 1320*26127Skarels sc->sc_state = S_RUN; 1321*26127Skarels } 1322*26127Skarels else 1323*26127Skarels sc->sc_state = S_IDLE; 1324*26127Skarels um->um_tab.b_active = 0; 1325*26127Skarels wakeup((caddr_t)um); 1326*26127Skarels return; 1327*26127Skarels } 1328*26127Skarels if (mp->mscp_unit >= nNTMS) 1329*26127Skarels return; 1330*26127Skarels if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0) 1331*26127Skarels return; 1332*26127Skarels /* 1333*26127Skarels * Save endcode, endflags, and status for mtioctl get unit status. 1334*26127Skarels * NOTE: Don't do this on Clear serious exception (reposition no-op); 1335*26127Skarels * which is done on close since this would 1336*26127Skarels * overwrite the real status we want. 1337*26127Skarels */ 1338*26127Skarels if (tms_info[ui->ui_unit].tms_clserex != 1) 1339*26127Skarels { 1340*26127Skarels tms_info[ui->ui_unit].tms_endcode = mp->mscp_opcode; 1341*26127Skarels tms_info[ui->ui_unit].tms_flags = mp->mscp_flags; 1342*26127Skarels tms_info[ui->ui_unit].tms_status = st; 1343*26127Skarels } 1344*26127Skarels else tms_info[ui->ui_unit].tms_clserex = 0; 1345*26127Skarels 1346*26127Skarels switch (mp->mscp_opcode) { 1347*26127Skarels case M_OP_ONLIN|M_OP_END: 1348*26127Skarels tms_info[ui->ui_unit].tms_type = mp->mscp_mediaid; 1349*26127Skarels dp = &tmsutab[ui->ui_unit]; 1350*26127Skarels if (st == M_ST_SUCC) 1351*26127Skarels { 1352*26127Skarels /* 1353*26127Skarels * Link the drive onto the controller queue 1354*26127Skarels */ 1355*26127Skarels dp->b_forw = NULL; 1356*26127Skarels if (um->um_tab.b_actf == NULL) 1357*26127Skarels um->um_tab.b_actf = dp; 1358*26127Skarels else 1359*26127Skarels um->um_tab.b_actl->b_forw = dp; 1360*26127Skarels um->um_tab.b_actl = dp; 1361*26127Skarels ui->ui_flags = 1; /* mark it online */ 1362*26127Skarels tms_info[ui->ui_unit].tms_dsize=(daddr_t)mp->mscp_maxwr 1363*26127Skarels t; 1364*26127Skarels # ifdef DEBUG 1365*26127Skarels printd("tmscprsp: unit %d online\n", mp->mscp_unit); 1366*26127Skarels # endif 1367*26127Skarels /* 1368*26127Skarels * This define decodes the Media type identifier 1369*26127Skarels */ 1370*26127Skarels # define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) 1371*26127Skarels & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') 1372*26127Skarels # ifdef DEBUG 1373*26127Skarels printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n" 1374*26127Skarels ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4) 1375*26127Skarels ,F_to_C(mp,3), F_to_C(mp,2) 1376*26127Skarels ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 1377*26127Skarels 0x7f); 1378*26127Skarels # endif 1379*26127Skarels dp->b_active = 1; 1380*26127Skarels } /* end if st == M_ST_SUCC */ 1381*26127Skarels else 1382*26127Skarels { 1383*26127Skarels if(dp->b_actf) 1384*26127Skarels harderr(dp->b_actf,"tms"); 1385*26127Skarels else 1386*26127Skarels { 1387*26127Skarels nullbp.b_blkno = 0; 1388*26127Skarels nullbp.b_dev = makedev(TMSCPDEVNUM,ui->ui_unit) 1389*26127Skarels ; 1390*26127Skarels harderr(&nullbp, "tms" ); 1391*26127Skarels } 1392*26127Skarels printf("OFFLINE\n"); 1393*26127Skarels while (bp = dp->b_actf) 1394*26127Skarels { 1395*26127Skarels dp->b_actf = bp->av_forw; 1396*26127Skarels bp->b_flags |= B_ERROR; 1397*26127Skarels iodone(bp); 1398*26127Skarels } 1399*26127Skarels } 1400*26127Skarels if(mp->mscp_cmdref!=NULL) 1401*26127Skarels /* Seems to get lost sometimes in uda */ 1402*26127Skarels wakeup((caddr_t *) mp->mscp_cmdref); 1403*26127Skarels break; 1404*26127Skarels /* 1405*26127Skarels * The AVAILABLE ATTENTION message occurs when the 1406*26127Skarels * unit becomes available after loading, 1407*26127Skarels * marking the unit offline (ui_flags = 0) will force an 1408*26127Skarels * online command prior to using the unit. 1409*26127Skarels */ 1410*26127Skarels case M_OP_AVATN: 1411*26127Skarels ui->ui_flags = 0; 1412*26127Skarels tms_info[ui->ui_unit].tms_type = mp->mscp_mediaid; 1413*26127Skarels break; 1414*26127Skarels case M_OP_END: 1415*26127Skarels /* 1416*26127Skarels * An endcode without an opcode (0200) is an invalid command. 1417*26127Skarels * The mscp specification states that this would be a protocol 1418*26127Skarels * type error, such as illegal opcodes. The mscp spec. also 1419*26127Skarels * states that parameter error type of invalid commands should 1420*26127Skarels * return the normal end message for the command. This does not 1421*26127Skarels appear 1422*26127Skarels * to be the case. An invalid logical block number returned an 1423*26127Skarels endcode 1424*26127Skarels * of 0200 instead of the 0241 (read) that was expected. 1425*26127Skarels */ 1426*26127Skarels 1427*26127Skarels printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n", 1428*26127Skarels um->um_ctlr, mp->mscp_opcode, st); 1429*26127Skarels bp = (struct buf *)mp->mscp_cmdref; 1430*26127Skarels /* 1431*26127Skarels * Unlink buffer from I/O wait queue. 1432*26127Skarels * And signal iodone, so the higher level command can exit! 1433*26127Skarels * 1434*26127Skarels */ 1435*26127Skarels bp->av_back->av_forw = bp->av_forw; 1436*26127Skarels bp->av_forw->av_back = bp->av_back; 1437*26127Skarels dp = &tmsutab[ui->ui_unit]; 1438*26127Skarels dp->b_qsize--; 1439*26127Skarels iodone(bp); 1440*26127Skarels break; 1441*26127Skarels case M_OP_WRITE|M_OP_END: 1442*26127Skarels /* mark the last io op as a write */ 1443*26127Skarels tms_info[ui->ui_unit].tms_lastiow = 1; 1444*26127Skarels case M_OP_READ|M_OP_END: 1445*26127Skarels case M_OP_WRITM|M_OP_END: 1446*26127Skarels case M_OP_REPOS|M_OP_END: 1447*26127Skarels case M_OP_STUNT|M_OP_END: 1448*26127Skarels /* 1449*26127Skarels * The AVAILABLE message occurs when the mt ioctl "rewoffl" is 1450*26127Skarels * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is 1451*26127Skarels * done with the UNLOAD modifier. This performs a rewind, followed 1452*26127Skarels * by marking the unit offline. So mark the unit offline 1453*26127Skarels * software wise as well (ui_flags = 0 and 1454*26127Skarels * tms_info[ui->ui_unit].tms_openf = 0). 1455*26127Skarels */ 1456*26127Skarels case M_OP_AVAIL|M_OP_END: 1457*26127Skarels # ifdef DEBUG 1458*26127Skarels printd("tmscprsp: position = %d\n", mp->mscp_lbn); 1459*26127Skarels # endif 1460*26127Skarels bp = (struct buf *)mp->mscp_cmdref; 1461*26127Skarels /* 1462*26127Skarels * Only need to release buffer if the command was read or write 1463*26127Skarels . 1464*26127Skarels * No ubasetup was done in "tmscpstart" if it was an ioctl cmd. 1465*26127Skarels */ 1466*26127Skarels if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 1467*26127Skarels mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) 1468*26127Skarels ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); 1469*26127Skarels /* 1470*26127Skarels * Unlink buffer from I/O wait queue. 1471*26127Skarels */ 1472*26127Skarels bp->av_back->av_forw = bp->av_forw; 1473*26127Skarels bp->av_forw->av_back = bp->av_back; 1474*26127Skarels # if defined(VAX750) || defined(VAX8200) 1475*26127Skarels if ((cpu == VAX_750) || (cpu == VAX_8200)) { 1476*26127Skarels if ((tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ct 1477*26127Skarels lr]) && 1478*26127Skarels (um->um_ubinfo != 0)) { 1479*26127Skarels ubarelse(um->um_ubanum, &um->um_ubinfo); 1480*26127Skarels } 1481*26127Skarels else { 1482*26127Skarels if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 1483*26127Skarels mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) 1484*26127Skarels UBAPURGE(uba_hd[um->um_ubanum].uh_uba,(um->um_u 1485*26127Skarels binfo >>28) & 0x0f); 1486*26127Skarels } 1487*26127Skarels } 1488*26127Skarels # endif 1489*26127Skarels dp = &tmsutab[ui->ui_unit]; 1490*26127Skarels dp->b_qsize--; 1491*26127Skarels if (st == M_ST_OFFLN || st == M_ST_AVLBL) 1492*26127Skarels { 1493*26127Skarels ui->ui_flags = 0; /* mark unit offline */ 1494*26127Skarels tms_info[ui->ui_unit].tms_openf = 0; 1495*26127Skarels tms_info[ui->ui_unit].tms_type = mp->mscp_mediaid; 1496*26127Skarels /* 1497*26127Skarels * Link the buffer onto the front of the drive queue 1498*26127Skarels */ 1499*26127Skarels if ((bp->av_forw = dp->b_actf) == 0) 1500*26127Skarels dp->b_actl = bp; 1501*26127Skarels dp->b_actf = bp; 1502*26127Skarels /* 1503*26127Skarels * Link the drive onto the controller queue 1504*26127Skarels */ 1505*26127Skarels if (dp->b_active == 0) 1506*26127Skarels { 1507*26127Skarels dp->b_forw = NULL; 1508*26127Skarels if (um->um_tab.b_actf == NULL) 1509*26127Skarels um->um_tab.b_actf = dp; 1510*26127Skarels else 1511*26127Skarels um->um_tab.b_actl->b_forw = dp; 1512*26127Skarels um->um_tab.b_actl = dp; 1513*26127Skarels dp->b_active = 1; 1514*26127Skarels } 1515*26127Skarels # if defined(VAX750) || defined(VAX8200) 1516*26127Skarels if (((cpu == VAX_750) || (cpu == VAX_8200)) && um->um_u 1517*26127Skarels binfo == 0) 1518*26127Skarels um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t 1519*26127Skarels )0, 0, UBA_NEEDBDP); 1520*26127Skarels # endif 1521*26127Skarels return; 1522*26127Skarels } 1523*26127Skarels if (st != M_ST_SUCC) 1524*26127Skarels { 1525*26127Skarels if (mp->mscp_flags & M_EF_SEREX) 1526*26127Skarels tms_info[ui->ui_unit].tms_serex = 1; 1527*26127Skarels if (st != M_ST_TAPEM) 1528*26127Skarels { 1529*26127Skarels harderr(bp, "tms"); 1530*26127Skarels errinfo(st); /* produces more info * 1531*26127Skarels / 1532*26127Skarels # ifdef DEBUG 1533*26127Skarels printd("tmscprsp: error; status sub-code = 0%o, 1534*26127Skarels flags = 0%o\n", 1535*26127Skarels (mp->mscp_status & 177740)>>5, mp->mscp 1536*26127Skarels _flags); 1537*26127Skarels # endif 1538*26127Skarels bp->b_flags |= B_ERROR; 1539*26127Skarels } 1540*26127Skarels else 1541*26127Skarels /* Hit a tape mark - Set serex flag to 1542*26127Skarels * a special value so we can clear the 1543*26127Skarels * serious exception on the next command. 1544*26127Skarels */ 1545*26127Skarels tms_info[ui->ui_unit].tms_serex = 2; 1546*26127Skarels } 1547*26127Skarels /* 1548*26127Skarels * The tmscp spec states that controllers do not have to 1549*26127Skarels * report the number of records or files skipped. So on 1550*26127Skarels * reposition commands we go strictly by cmd status. 1551*26127Skarels */ 1552*26127Skarels if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) 1553*26127Skarels bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; 1554*26127Skarels else 1555*26127Skarels bp->b_resid = 0; 1556*26127Skarels tms_info[ui->ui_unit].tms_resid = bp->b_resid; 1557*26127Skarels iodone(bp); 1558*26127Skarels break; 1559*26127Skarels 1560*26127Skarels case M_OP_GTUNT|M_OP_END: 1561*26127Skarels # ifdef DEBUG 1562*26127Skarels printd("tmscprsp: GTUNT end packet status = 0%o\n",st); 1563*26127Skarels printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n 1564*26127Skarels " 1565*26127Skarels ,mp->mscp_unit, mp->mscp_mediaid 1566*26127Skarels ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) 1567*26127Skarels ,F_to_C(mp,1),F_to_C(mp,0) 1568*26127Skarels ,mp->mscp_mediaid & 0x7f 1569*26127Skarels ,mp->mscp_unitid.val[0] 1570*26127Skarels ,mp->mscp_unitid.val[1] 1571*26127Skarels ,mp->mscp_format); 1572*26127Skarels # endif 1573*26127Skarels tms_info[ui->ui_unit].tms_type = mp->mscp_mediaid; 1574*26127Skarels tms_info[ui->ui_unit].tms_fmtmenu = mp->mscp_fmtmenu; 1575*26127Skarels tms_info[ui->ui_unit].tms_unitflgs = mp->mscp_unitflgs; 1576*26127Skarels break; 1577*26127Skarels 1578*26127Skarels default: 1579*26127Skarels printf("tmscp unknown packet\n"); 1580*26127Skarels tmserror(um, (struct mslg *)mp); 1581*26127Skarels } /* end switch mp->mscp_opcode */ 1582*26127Skarels } 1583*26127Skarels 1584*26127Skarels 1585*26127Skarels /* 1586*26127Skarels * Give a meaningful error when the mscp_status field returns an error code. 1587*26127Skarels */ 1588*26127Skarels 1589*26127Skarels errinfo(st) 1590*26127Skarels int st; /* the status code */ 1591*26127Skarels { 1592*26127Skarels switch(st) { 1593*26127Skarels case M_ST_ICMD: 1594*26127Skarels printf("invalid command\n"); 1595*26127Skarels break; 1596*26127Skarels case M_ST_ABRTD: 1597*26127Skarels printf("command aborted\n"); 1598*26127Skarels break; 1599*26127Skarels case M_ST_OFFLN: 1600*26127Skarels printf("unit offline\n"); 1601*26127Skarels break; 1602*26127Skarels case M_ST_WRTPR: 1603*26127Skarels printf("unit write protected\n"); 1604*26127Skarels break; 1605*26127Skarels case M_ST_COMP: 1606*26127Skarels printf("compare error\n"); 1607*26127Skarels break; 1608*26127Skarels case M_ST_DATA: 1609*26127Skarels printf("data error\n"); 1610*26127Skarels break; 1611*26127Skarels case M_ST_HSTBF: 1612*26127Skarels printf("host buffer access error\n"); 1613*26127Skarels break; 1614*26127Skarels case M_ST_CNTLR: 1615*26127Skarels printf("controller error\n"); 1616*26127Skarels break; 1617*26127Skarels case M_ST_DRIVE: 1618*26127Skarels printf("drive error\n"); 1619*26127Skarels break; 1620*26127Skarels case M_ST_FMTER: 1621*26127Skarels printf("formatter error\n"); 1622*26127Skarels break; 1623*26127Skarels case M_ST_BOT: 1624*26127Skarels printf("BOT encountered\n"); 1625*26127Skarels break; 1626*26127Skarels case M_ST_TAPEM: 1627*26127Skarels printf("tape mark encountered\n"); 1628*26127Skarels break; 1629*26127Skarels case M_ST_RDTRN: 1630*26127Skarels printf("record data truncated\n"); 1631*26127Skarels break; 1632*26127Skarels case M_ST_PLOST: 1633*26127Skarels printf("position lost\n"); 1634*26127Skarels break; 1635*26127Skarels case M_ST_SEX: 1636*26127Skarels printf("serious exception\n"); 1637*26127Skarels break; 1638*26127Skarels case M_ST_LED: 1639*26127Skarels printf("LEOT detected\n"); 1640*26127Skarels break; 1641*26127Skarels } 1642*26127Skarels } 1643*26127Skarels 1644*26127Skarels 1645*26127Skarels /* 1646*26127Skarels * Manage buffers and perform block mode read and write operations. 1647*26127Skarels */ 1648*26127Skarels 1649*26127Skarels tmscpstrategy (bp) 1650*26127Skarels register struct buf *bp; 1651*26127Skarels { 1652*26127Skarels register struct uba_device *ui; 1653*26127Skarels register struct uba_ctlr *um; 1654*26127Skarels register struct buf *dp; 1655*26127Skarels register int unit = TMSUNIT(bp->b_dev); 1656*26127Skarels int s; 1657*26127Skarels 1658*26127Skarels if (unit >= nNTMS) 1659*26127Skarels { 1660*26127Skarels # ifdef DEBUG 1661*26127Skarels printd ("tmscpstrategy: bad unit # %d\n",unit); 1662*26127Skarels # endif 1663*26127Skarels bp->b_flags |= B_ERROR; 1664*26127Skarels iodone(bp); 1665*26127Skarels return; 1666*26127Skarels } 1667*26127Skarels ui = tmsdinfo[unit]; 1668*26127Skarels um = ui->ui_mi; 1669*26127Skarels if (ui == 0 || ui->ui_alive == 0) 1670*26127Skarels { 1671*26127Skarels bp->b_flags |= B_ERROR; 1672*26127Skarels iodone(bp); 1673*26127Skarels return; 1674*26127Skarels } 1675*26127Skarels s = spl5(); 1676*26127Skarels /* 1677*26127Skarels * Link the buffer onto the drive queue 1678*26127Skarels */ 1679*26127Skarels dp = &tmsutab[ui->ui_unit]; 1680*26127Skarels if (dp->b_actf == 0) 1681*26127Skarels dp->b_actf = bp; 1682*26127Skarels else 1683*26127Skarels dp->b_actl->av_forw = bp; 1684*26127Skarels dp->b_actl = bp; 1685*26127Skarels bp->av_forw = 0; 1686*26127Skarels /* 1687*26127Skarels * Link the drive onto the controller queue 1688*26127Skarels */ 1689*26127Skarels if (dp->b_active == 0) 1690*26127Skarels { 1691*26127Skarels dp->b_forw = NULL; 1692*26127Skarels if (um->um_tab.b_actf == NULL) 1693*26127Skarels um->um_tab.b_actf = dp; 1694*26127Skarels else 1695*26127Skarels um->um_tab.b_actl->b_forw = dp; 1696*26127Skarels um->um_tab.b_actl = dp; 1697*26127Skarels dp->b_active = 1; 1698*26127Skarels } 1699*26127Skarels /* 1700*26127Skarels * If the controller is not active, start it. 1701*26127Skarels */ 1702*26127Skarels if (um->um_tab.b_active == 0) 1703*26127Skarels { 1704*26127Skarels # if defined(VAX750) || defined(VAX8200) 1705*26127Skarels if (((cpu == VAX_750) || (cpu == VAX_8200)) 1706*26127Skarels && tmscpwtab[um->um_ctlr].av_forw == &tmscpwta 1707*26127Skarels b[um->um_ctlr]) 1708*26127Skarels { 1709*26127Skarels if (um->um_ubinfo != 0) 1710*26127Skarels mprintf("tmscpstrategy: ubinfo 0x%x\n",um->um_u 1711*26127Skarels binfo); 1712*26127Skarels else 1713*26127Skarels um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t 1714*26127Skarels )0, 0, UBA_NEEDBDP); 1715*26127Skarels } 1716*26127Skarels # endif 1717*26127Skarels # ifdef DEBUG 1718*26127Skarels printd10("tmscpstrategy: Controller not active, starting it\n") 1719*26127Skarels ; 1720*26127Skarels # endif 1721*26127Skarels (void) tmscpstart(um); 1722*26127Skarels } 1723*26127Skarels splx(s); 1724*26127Skarels return; 1725*26127Skarels } 1726*26127Skarels 1727*26127Skarels #define DBSIZE 32 1728*26127Skarels 1729*26127Skarels #define ca_Rspdsc ca_rspdsc[0] 1730*26127Skarels #define ca_Cmddsc ca_rspdsc[1] 1731*26127Skarels #define tmscp_Rsp tmscp_rsp[0] 1732*26127Skarels #define tmscp_Cmd tmscp_cmd[0] 1733*26127Skarels 1734*26127Skarels struct tmscp tmscpd[NTMSCP]; 1735*26127Skarels 1736*26127Skarels tmscpdump(dev) 1737*26127Skarels dev_t dev; 1738*26127Skarels { 1739*26127Skarels struct tmscpdevice *tmscpaddr; 1740*26127Skarels struct tmscp *tmscp_ubaddr; 1741*26127Skarels char *start; 1742*26127Skarels int num, blk, unit; 1743*26127Skarels register struct uba_regs *uba; 1744*26127Skarels register struct uba_device *ui; 1745*26127Skarels register struct tmscp *tmscpp; 1746*26127Skarels register struct pte *io; 1747*26127Skarels register int i; 1748*26127Skarels 1749*26127Skarels unit = minor(dev) & 03; 1750*26127Skarels if (unit >= nNTMS) 1751*26127Skarels return (ENXIO); 1752*26127Skarels # define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 1753*26127Skarels ui = phys(struct uba_device *, tmsdinfo[unit]); 1754*26127Skarels if (ui->ui_alive == 0) 1755*26127Skarels return (ENXIO); 1756*26127Skarels uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 1757*26127Skarels if (ui->ui_hd->uba_type) 1758*26127Skarels buainit(uba); 1759*26127Skarels else 1760*26127Skarels ubainit(uba); 1761*26127Skarels tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; 1762*26127Skarels DELAY(2000000); 1763*26127Skarels tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); 1764*26127Skarels 1765*26127Skarels num = btoc(sizeof(struct tmscp)) + 1; 1766*26127Skarels io = &uba->uba_map[NUBMREG-num]; 1767*26127Skarels for(i = 0; i<num; i++) 1768*26127Skarels *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); 1769*26127Skarels # ifdef MVAX 1770*26127Skarels if( cpu == MVAX_I ) 1771*26127Skarels tmscp_ubaddr = tmscpp; 1772*26127Skarels else 1773*26127Skarels # endif MVAX 1774*26127Skarels tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMR 1775*26127Skarels EG-num)<<9)); 1776*26127Skarels 1777*26127Skarels tmscpaddr->tmscpip = 0; 1778*26127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 1779*26127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 1780*26127Skarels tmscpaddr->tmscpsa = TMSCP_ERR; 1781*26127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) 1782*26127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 1783*26127Skarels tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; 1784*26127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) 1785*26127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 1786*26127Skarels tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) 1787*26127Skarels >> 16); 1788*26127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) 1789*26127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 1790*26127Skarels tmscpaddr->tmscpsa = TMSCP_GO; 1791*26127Skarels tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref 1792*26127Skarels ; 1793*26127Skarels tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref 1794*26127Skarels ; 1795*26127Skarels tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ 1796*26127Skarels tmscpp->tmscp_Cmd.mscp_cntflgs = 0; 1797*26127Skarels tmscpp->tmscp_Cmd.mscp_version = 0; 1798*26127Skarels if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { 1799*26127Skarels return(EFAULT); 1800*26127Skarels } 1801*26127Skarels tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; 1802*26127Skarels if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { 1803*26127Skarels return(EFAULT); 1804*26127Skarels } 1805*26127Skarels 1806*26127Skarels num = maxfree; 1807*26127Skarels start = 0; 1808*26127Skarels while (num > 0) 1809*26127Skarels { 1810*26127Skarels blk = num > DBSIZE ? DBSIZE : num; 1811*26127Skarels io = uba->uba_map; 1812*26127Skarels for (i = 0; i < blk; i++) 1813*26127Skarels *(int *)io++ = (btop(start)+i) | UBAMR_MRV; 1814*26127Skarels *(int *)io = 0; 1815*26127Skarels tmscpp->tmscp_Cmd.mscp_lbn = btop(start); 1816*26127Skarels tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; 1817*26127Skarels tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG; 1818*26127Skarels # ifdef MVAX 1819*26127Skarels if( cpu == MVAX_I ) 1820*26127Skarels tmscpp->tmscp_Cmd.mscp_buffer = (long) start; 1821*26127Skarels else 1822*26127Skarels # endif MVAX 1823*26127Skarels tmscpp->tmscp_Cmd.mscp_buffer = 0; 1824*26127Skarels if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) 1825*26127Skarels return(EIO); 1826*26127Skarels start += blk*NBPG; 1827*26127Skarels num -= blk; 1828*26127Skarels } 1829*26127Skarels return (0); 1830*26127Skarels } 1831*26127Skarels 1832*26127Skarels 1833*26127Skarels /* 1834*26127Skarels * Perform a standalone tmscp command. This routine is only used by tmscpdump. 1835*26127Skarels */ 1836*26127Skarels 1837*26127Skarels tmscpcmd(op, tmscpp, tmscpaddr) 1838*26127Skarels int op; 1839*26127Skarels register struct tmscp *tmscpp; 1840*26127Skarels struct tmscpdevice *tmscpaddr; 1841*26127Skarels { 1842*26127Skarels int i; 1843*26127Skarels 1844*26127Skarels # ifdef lint 1845*26127Skarels i = i; 1846*26127Skarels # endif 1847*26127Skarels 1848*26127Skarels tmscpp->tmscp_Cmd.mscp_opcode = op; 1849*26127Skarels tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; 1850*26127Skarels tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; 1851*26127Skarels tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; 1852*26127Skarels tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; 1853*26127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 1854*26127Skarels printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); 1855*26127Skarels i = tmscpaddr->tmscpip; 1856*26127Skarels for (;;) 1857*26127Skarels { 1858*26127Skarels if (tmscpp->tmscp_ca.ca_cmdint) 1859*26127Skarels tmscpp->tmscp_ca.ca_cmdint = 0; 1860*26127Skarels if (tmscpp->tmscp_ca.ca_rspint) 1861*26127Skarels break; 1862*26127Skarels } 1863*26127Skarels tmscpp->tmscp_ca.ca_rspint = 0; 1864*26127Skarels if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || 1865*26127Skarels (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) 1866*26127Skarels { 1867*26127Skarels printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, 1868*26127Skarels tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_s 1869*26127Skarels tatus); 1870*26127Skarels return(0); 1871*26127Skarels } 1872*26127Skarels return(1); 1873*26127Skarels } 1874*26127Skarels 1875*26127Skarels 1876*26127Skarels /* 1877*26127Skarels * Perform raw read 1878*26127Skarels */ 1879*26127Skarels 1880*26127Skarels tmscpread(dev, uio) 1881*26127Skarels dev_t dev; 1882*26127Skarels struct uio *uio; 1883*26127Skarels { 1884*26127Skarels register int unit = TMSUNIT(dev); 1885*26127Skarels 1886*26127Skarels if (unit >= nNTMS) 1887*26127Skarels return (ENXIO); 1888*26127Skarels return (physio(tmscpstrategy, &rtmsbuf[unit], dev, B_READ, minphys, uio 1889*26127Skarels )); 1890*26127Skarels } 1891*26127Skarels 1892*26127Skarels 1893*26127Skarels /* 1894*26127Skarels * Perform raw write 1895*26127Skarels */ 1896*26127Skarels 1897*26127Skarels tmscpwrite(dev, uio) 1898*26127Skarels dev_t dev; 1899*26127Skarels struct uio *uio; 1900*26127Skarels { 1901*26127Skarels register int unit = TMSUNIT(dev); 1902*26127Skarels 1903*26127Skarels if (unit >= nNTMS) 1904*26127Skarels return (ENXIO); 1905*26127Skarels return (physio(tmscpstrategy, &rtmsbuf[unit], dev, B_WRITE, minphys, ui 1906*26127Skarels o)); 1907*26127Skarels } 1908*26127Skarels 1909*26127Skarels 1910*26127Skarels /* 1911*26127Skarels * Catch ioctl commands, and call the "command" routine to do them. 1912*26127Skarels */ 1913*26127Skarels 1914*26127Skarels tmscpioctl(dev, cmd, data, flag) 1915*26127Skarels dev_t dev; 1916*26127Skarels int cmd; 1917*26127Skarels caddr_t data; 1918*26127Skarels int flag; 1919*26127Skarels { 1920*26127Skarels register struct tmscp_softc *sc = &tmscp_softc[TMSCPCTLR(dev)]; 1921*26127Skarels register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; 1922*26127Skarels register callcount; /* number of times to call cmd routine */ 1923*26127Skarels register struct uba_device *ui; 1924*26127Skarels int fcount; /* number of files (or records) to space */ 1925*26127Skarels struct mtop *mtop; /* mag tape cmd op to perform */ 1926*26127Skarels struct mtget *mtget; /* mag tape struct to get info in */ 1927*26127Skarels 1928*26127Skarels /* we depend of the values and order of the TMS ioctl codes here */ 1929*26127Skarels static tmsops[] = 1930*26127Skarels {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, 1931*26127Skarels TMS_CACHE,TMS_NOCACHE}; 1932*26127Skarels 1933*26127Skarels switch (cmd) { 1934*26127Skarels case MTIOCTOP: /* tape operation */ 1935*26127Skarels mtop = (struct mtop *)data; 1936*26127Skarels switch (mtop->mt_op) { 1937*26127Skarels 1938*26127Skarels case MTWEOF: 1939*26127Skarels callcount = mtop->mt_count; 1940*26127Skarels fcount = 1; 1941*26127Skarels break; 1942*26127Skarels case MTFSF: case MTBSF: 1943*26127Skarels case MTFSR: case MTBSR: 1944*26127Skarels callcount = 1; 1945*26127Skarels fcount = mtop->mt_count; 1946*26127Skarels break; 1947*26127Skarels case MTREW: case MTOFFL: case MTNOP: 1948*26127Skarels case MTCACHE: case MTNOCACHE: 1949*26127Skarels callcount = 1; 1950*26127Skarels fcount = 1; /* wait for this rewind */ 1951*26127Skarels break; 1952*26127Skarels default: 1953*26127Skarels return (ENXIO); 1954*26127Skarels } /* end switch mtop->mt_op */ 1955*26127Skarels 1956*26127Skarels if (callcount <= 0 || fcount <= 0) 1957*26127Skarels return (EINVAL); 1958*26127Skarels while (--callcount >= 0) 1959*26127Skarels { 1960*26127Skarels tmscpcommand(dev, tmsops[mtop->mt_op], fcount); 1961*26127Skarels if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 1962*26127Skarels bp->b_resid) 1963*26127Skarels return (EIO); 1964*26127Skarels if (bp->b_flags & B_ERROR) /* like hitting BOT */ 1965*26127Skarels break; 1966*26127Skarels } 1967*26127Skarels return (geterror(bp)); 1968*26127Skarels 1969*26127Skarels case MTIOCGET: 1970*26127Skarels /* 1971*26127Skarels * Return status info associated with the particular UNIT. 1972*26127Skarels */ 1973*26127Skarels ui = tmsdinfo[TMSUNIT(dev)]; 1974*26127Skarels mtget = (struct mtget *)data; 1975*26127Skarels mtget->mt_type = MT_ISTMSCP; 1976*26127Skarels mtget->mt_dsreg = tms_info[ui->ui_unit].tms_flags << 8; 1977*26127Skarels mtget->mt_dsreg |= tms_info[ui->ui_unit].tms_endcode; 1978*26127Skarels mtget->mt_erreg = tms_info[ui->ui_unit].tms_status; 1979*26127Skarels mtget->mt_resid = tms_info[ui->ui_unit].tms_resid; 1980*26127Skarels break; 1981*26127Skarels 1982*26127Skarels default: 1983*26127Skarels return (ENXIO); 1984*26127Skarels } 1985*26127Skarels return (0); 1986*26127Skarels } 1987*26127Skarels 1988*26127Skarels 1989*26127Skarels /* 1990*26127Skarels * Reset (for raw mode use only). 1991*26127Skarels */ 1992*26127Skarels 1993*26127Skarels tmscpreset (uban) 1994*26127Skarels int uban; 1995*26127Skarels { 1996*26127Skarels register struct uba_ctlr *um; 1997*26127Skarels register struct uba_device *ui; 1998*26127Skarels register struct buf *bp, *dp; 1999*26127Skarels register int unit; 2000*26127Skarels struct buf *nbp; 2001*26127Skarels int d; 2002*26127Skarels 2003*26127Skarels for (d = 0; d < NTMSCP; d++) 2004*26127Skarels { 2005*26127Skarels if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || 2006*26127Skarels um->um_alive == 0) 2007*26127Skarels continue; 2008*26127Skarels printf(" tmscp%d", d); 2009*26127Skarels um->um_tab.b_active = 0; 2010*26127Skarels um->um_tab.b_actf = um->um_tab.b_actl = 0; 2011*26127Skarels tmscp_softc[d].sc_state = S_IDLE; 2012*26127Skarels tmscp_softc[d].sc_mapped = 0; 2013*26127Skarels for (unit = 0; unit < nNTMS; unit++) 2014*26127Skarels { 2015*26127Skarels if ((ui = tmsdinfo[unit]) == 0) 2016*26127Skarels continue; 2017*26127Skarels if (ui->ui_alive == 0 || ui->ui_mi != um) 2018*26127Skarels continue; 2019*26127Skarels tmsutab[unit].b_active = 0; 2020*26127Skarels tmsutab[unit].b_qsize = 0; 2021*26127Skarels } 2022*26127Skarels for (bp = tmscpwtab[d].av_forw; bp != &tmscpwtab[d]; bp = nbp) 2023*26127Skarels { 2024*26127Skarels nbp = bp->av_forw; 2025*26127Skarels bp->b_ubinfo = 0; 2026*26127Skarels /* 2027*26127Skarels * Link the buffer onto the drive queue 2028*26127Skarels */ 2029*26127Skarels dp = &tmsutab[TMSUNIT(bp->b_dev)]; 2030*26127Skarels if (dp->b_actf == 0) 2031*26127Skarels dp->b_actf = bp; 2032*26127Skarels else 2033*26127Skarels dp->b_actl->av_forw = bp; 2034*26127Skarels dp->b_actl = bp; 2035*26127Skarels bp->av_forw = 0; 2036*26127Skarels /* 2037*26127Skarels * Link the drive onto the controller queue 2038*26127Skarels */ 2039*26127Skarels if (dp->b_active == 0) 2040*26127Skarels { 2041*26127Skarels dp->b_forw = NULL; 2042*26127Skarels if (um->um_tab.b_actf == NULL) 2043*26127Skarels um->um_tab.b_actf = dp; 2044*26127Skarels else 2045*26127Skarels um->um_tab.b_actl->b_forw = dp; 2046*26127Skarels um->um_tab.b_actl = dp; 2047*26127Skarels dp->b_active = 1; 2048*26127Skarels } 2049*26127Skarels } 2050*26127Skarels tmscpinit(d); 2051*26127Skarels } 2052*26127Skarels } 2053*26127Skarels 2054*26127Skarels 2055*26127Skarels /* 2056*26127Skarels * Process an error log message 2057*26127Skarels * 2058*26127Skarels * Only minimal decoding is done, only "useful" 2059*26127Skarels * information is printed. Eventually should 2060*26127Skarels * send message to an error logger. 2061*26127Skarels */ 2062*26127Skarels 2063*26127Skarels tmserror(um, mp) 2064*26127Skarels register struct uba_ctlr *um; 2065*26127Skarels register struct mslg *mp; 2066*26127Skarels { 2067*26127Skarels register i; 2068*26127Skarels 2069*26127Skarels # ifdef DEBUG 2070*26127Skarels printd("tmserror:\n"); 2071*26127Skarels # endif 2072*26127Skarels if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) 2073*26127Skarels mprintf("tmscp%d: %s error, ", um->um_ctlr, 2074*26127Skarels mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); 2075*26127Skarels 2076*26127Skarels switch (mp->mslg_format) { 2077*26127Skarels 2078*26127Skarels case M_FM_CNTERR: 2079*26127Skarels mprintf("controller error, event 0%o\n", mp->mslg_event); 2080*26127Skarels break; 2081*26127Skarels case M_FM_BUSADDR: 2082*26127Skarels mprintf("host memory access error, event 0%o, addr 0%o\n", 2083*26127Skarels mp->mslg_event, mp->mslg_busaddr); 2084*26127Skarels break; 2085*26127Skarels case M_FM_TAPETRN: 2086*26127Skarels mprintf("tape transfer error, unit %d, grp 0x%x, event 0%o\n", 2087*26127Skarels mp->mslg_unit, mp->mslg_group, mp->mslg_event); 2088*26127Skarels break; 2089*26127Skarels case M_FM_STIERR: 2090*26127Skarels mprintf("STI error, unit %d, event 0%o\n", 2091*26127Skarels mp->mslg_unit, mp->mslg_event); 2092*26127Skarels for(i = 0; i < 62;i++) 2093*26127Skarels mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); 2094*26127Skarels mprintf("\n"); 2095*26127Skarels break; 2096*26127Skarels case M_FM_STIDEL: 2097*26127Skarels mprintf("STI Drive Error Log, unit %d, event 0%o\n", 2098*26127Skarels mp->mslg_unit, mp->mslg_event); 2099*26127Skarels break; 2100*26127Skarels case M_FM_STIFEL: 2101*26127Skarels mprintf("STI Formatter Error Log, unit %d, event 0%o\n", 2102*26127Skarels mp->mslg_unit, mp->mslg_event); 2103*26127Skarels break; 2104*26127Skarels default: 2105*26127Skarels mprintf("unknown error, unit %d, format 0%o, event 0%o\n", 2106*26127Skarels mp->mslg_unit, mp->mslg_format, mp->mslg_event); 2107*26127Skarels } 2108*26127Skarels 2109*26127Skarels if (tmscperror) 2110*26127Skarels { 2111*26127Skarels register long *p = (long *)mp; 2112*26127Skarels 2113*26127Skarels for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) 2114*26127Skarels printf("%x ", *p++); 2115*26127Skarels printf("\n"); 2116*26127Skarels } 2117*26127Skarels } 2118*26127Skarels #endif 2119*26127Skarels 2120