1*26135Skarels /* @(#)tmscp.c 5.1 (Berkeley) 02/11/86 */ 2*26135Skarels 326127Skarels #ifndef lint 426127Skarels static char *sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; 526127Skarels #endif lint 626127Skarels 7*26135Skarels 826127Skarels /************************************************************************ 926127Skarels * * 1026127Skarels * Copyright (c) 1985 by * 1126127Skarels * Digital Equipment Corporation, Maynard, MA * 1226127Skarels * * 1326127Skarels * Permission to use, copy, modify, and distribute this software * 1426127Skarels * and its documentation is hereby granted to licensees of the * 1526127Skarels * Regents of the University of California pursuant to their * 1626127Skarels * license agreement for the "Fourth Berkeley Software * 1726127Skarels * Distribution". * 1826127Skarels * * 1926127Skarels * The information in this software is subject to change without * 2026127Skarels * notice and should not be construed as a commitment by Digital * 2126127Skarels * Equipment Corporation. Digital makes no representations * 2226127Skarels * about suitability of this software for any purpose. It is * 2326127Skarels * supplied "as is" without express or implied warranty. * 2426127Skarels * * 2526127Skarels * This software is not subject to any license of the American * 2626127Skarels * Telephone and Telegraph Company. * 2726127Skarels * * 2826127Skarels ************************************************************************ 2926127Skarels * 3026127Skarels * tmscp.c - TMSCP (TK50/TU81) tape device driver 3126127Skarels * 3226127Skarels * Modification History: 3326127Skarels * 3426127Skarels * 06-Jan-86 - afd 3526127Skarels * Changed the probe routine to use DELAY (not TODR). This now 3626127Skarels * works for MicroVAXen as well. This eliminates the busy-wait 3726127Skarels * for MicroVAXen so a dead TK50 controller will not hang autoconf. 3826127Skarels * 3926127Skarels * 06-Dec-85 - afd 4026127Skarels * Fixed a bug in density selection. The "set unit characteristics" 4126127Skarels * command to select density, was clearing the "unit flags" field 4226127Skarels * where the CACHE bit was for TU81-E. Now the unit's "format" and 4326127Skarels * "unitflgs" are saved in tms_info struct. And are used on STUNT 4426127Skarels * commands. 4526127Skarels * 4626127Skarels * 19-Oct-85 - afd 4726127Skarels * Added support to the open routine to allow drives to be opened 4826127Skarels * for low density (800 or 1600 bpi) use. When the slave routine 4926127Skarels * initiates a "get-unit-char" cmd, the format menu for the unit 5026127Skarels * is saved in the tms_info structure. The format menu is used in the 5126127Skarels * start routine to select the proper low density. 5226127Skarels * 5326127Skarels * 02-Oct-85 - afd 5426127Skarels * When a tmscp-type controller is initializing, it is possible for 5526127Skarels * the sa reg to become 0 between states. Thus the init code in 5626127Skarels * the interrupt routine had to be modified to reflect this. 5726127Skarels * 5826127Skarels * 21-Sep-85 - afd 5926127Skarels * The TK50 declares a serious exception when a tape mark is encountered. 6026127Skarels * This causes problems to dd (& other UN*X utilities). So a flag 6126127Skarels * is set in the rsp() routine when a tape mark is encountered. If 6226127Skarels * this flag is set, the start() routine appends the Clear Serious 6326127Skarels * Exception modifier to the next command. 6426127Skarels * 6526127Skarels * 03-Sep-85 -- jaw 6626127Skarels * messed up previous edit.. 6726127Skarels * 6826127Skarels * 29-Aug-85 - jaw 6926127Skarels * fixed bugs in 8200 and 750 buffered datapath handling. 7026127Skarels * 7126127Skarels * 06-Aug-85 - afd 7226127Skarels * 1. When repositioning records or files, the count of items skipped 7326127Skarels * does NOT HAVE to be returned by controllers (& the TU81 doesn't). 7426127Skarels * So tmscprsp() had to be modified to stop reporting 7526127Skarels * residual count errors on reposition commands. 7626127Skarels * 7726127Skarels * 2. Fixed bug in the open routine which allowed multiple opens. 7826127Skarels * 7926127Skarels * 18-Jul-85 - afd 8026127Skarels * 1. Need to return status when mt status (or corresponding ioctl) is done. 8126127Skarels * Save resid, flags, endcode & status in tmscprsp() routine (except on 8226127Skarels * clear serious exception no-op). Return these fields when status 8326127Skarels * ioctl is done (in tmscpcommand()). How they are returned: 8426127Skarels * mt_resid = resid 8526127Skarels * mt_dsreg = flags|endcode 8626127Skarels * mt_erreg = status 8726127Skarels * 8826127Skarels * 2. Added latent support for enabling/disabling caching. This is 8926127Skarels * handled along with all other ioctl commands. 9026127Skarels * 9126127Skarels * 3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since 9226127Skarels * we have already commited to issuing a command at that point. 9326127Skarels * 9426127Skarels * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); 9526127Skarels * We need to: Unlink the buffer from the I/O wait queue, 9626127Skarels * and signal iodone, so the higher level command can exit! 9726127Skarels * Just as if it were a valid command. 9826127Skarels * 9926127Skarels * 11-jul-85 -- jaw 10026127Skarels * fix bua/bda map registers. 10126127Skarels * 10226127Skarels * 19-Jun-85 -- jaw 10326127Skarels * VAX8200 name change. 10426127Skarels * 10526127Skarels * 06-Jun-85 - jaw 10626127Skarels * fixes for 8200. 10726127Skarels * 10826127Skarels * 9-Apr-85 - afd 10926127Skarels * Added timeout code to the probe routine, so if the controller 11026127Skarels * fails to init in 10 seconds we return failed status. 11126127Skarels * 11226127Skarels * 13-Mar-85 -jaw 11326127Skarels * Changes for support of the VAX8200 were merged in. 11426127Skarels * 11526127Skarels * 27-Feb-85 -tresvik 11626127Skarels * Changes for support of the VAX8600 were merged in. 11726127Skarels * 11826127Skarels */ 119*26135Skarels 12026127Skarels #include "tms.h" 121*26135Skarels #if NTMSCP > 0 122*26135Skarels 123*26135Skarels #include "../vax/pte.h" 124*26135Skarels 125*26135Skarels #include "param.h" 126*26135Skarels #include "systm.h" 127*26135Skarels #include "buf.h" 128*26135Skarels #include "conf.h" 129*26135Skarels #include "dir.h" 130*26135Skarels #include "user.h" 131*26135Skarels #include "file.h" 132*26135Skarels #include "map.h" 133*26135Skarels #include "vm.h" 134*26135Skarels #include "ioctl.h" 135*26135Skarels #include "syslog.h" 136*26135Skarels #include "mtio.h" 137*26135Skarels #include "cmap.h" 138*26135Skarels #include "uio.h" 139*26135Skarels 140*26135Skarels #include "../vax/cpu.h" 141*26135Skarels #include "../vax/mtpr.h" 142*26135Skarels #include "ubareg.h" 143*26135Skarels #include "ubavar.h" 144*26135Skarels 145*26135Skarels #define TENSEC (1000) 146*26135Skarels #define TMS_PRI LOG_INFO 147*26135Skarels 148*26135Skarels #define NRSPL2 3 /* log2 number of response packets */ 149*26135Skarels #define NCMDL2 3 /* log2 number of command packets */ 150*26135Skarels #define NRSP (1<<NRSPL2) 151*26135Skarels #define NCMD (1<<NCMDL2) 152*26135Skarels 153*26135Skarels #include "tmscpreg.h" 154*26135Skarels #include "../vax/tmscp.h" 155*26135Skarels 156*26135Skarels /* Software state per controller */ 157*26135Skarels 158*26135Skarels struct tmscp_softc { 159*26135Skarels short sc_state; /* state of controller */ 160*26135Skarels short sc_mapped; /* Unibus map allocated for tmscp struct? */ 161*26135Skarels int sc_ubainfo; /* Unibus mapping info */ 162*26135Skarels struct tmscp *sc_tmscp; /* Unibus address of tmscp struct */ 163*26135Skarels int sc_ivec; /* interrupt vector address */ 164*26135Skarels short sc_credits; /* transfer credits */ 165*26135Skarels short sc_lastcmd; /* pointer into command ring */ 166*26135Skarels short sc_lastrsp; /* pointer into response ring */ 167*26135Skarels } tmscp_softc[NTMSCP]; 168*26135Skarels 169*26135Skarels struct tmscp { 170*26135Skarels struct tmscpca tmscp_ca; /* communications area */ 171*26135Skarels struct mscp tmscp_rsp[NRSP]; /* response packets */ 172*26135Skarels struct mscp tmscp_cmd[NCMD]; /* command packets */ 173*26135Skarels } tmscp[NTMSCP]; 174*26135Skarels 175*26135Skarels /* 176*26135Skarels * Per drive-unit info 177*26135Skarels */ 178*26135Skarels struct tms_info { 179*26135Skarels daddr_t tms_dsize; /* Max user size from online pkt */ 180*26135Skarels unsigned tms_type; /* Drive type int field */ 181*26135Skarels int tms_resid; /* residual from last xfer */ 182*26135Skarels u_char tms_endcode; /* last command endcode */ 183*26135Skarels u_char tms_flags; /* last command end flags */ 184*26135Skarels unsigned tms_status; /* Command status from last command */ 185*26135Skarels char tms_openf; /* lock against multiple opens */ 186*26135Skarels char tms_lastiow; /* last op was a write */ 187*26135Skarels char tms_serex; /* set when serious exception occurs */ 188*26135Skarels char tms_clserex; /* set when serex being cleared by no-op */ 189*26135Skarels short tms_fmtmenu; /* the unit's format (density) menu */ 190*26135Skarels short tms_unitflgs; /* unit flag parameters */ 191*26135Skarels short tms_format; /* the unit's current format (density) */ 192*26135Skarels struct tty *tms_ttyp; /* record user's tty for errors */ 193*26135Skarels } tms_info[NTMS]; 194*26135Skarels struct uba_ctlr *tmscpminfo[NTMSCP]; 195*26135Skarels struct uba_device *tmsdinfo[NTMS]; 196*26135Skarels /* 197*26135Skarels * ifdef other tmscp devices here if they allow more than 1 unit/controller 198*26135Skarels */ 199*26135Skarels struct uba_device *tmscpip[NTMSCP][1]; 200*26135Skarels struct buf rtmsbuf[NTMS]; /* raw i/o buffer */ 201*26135Skarels struct buf ctmscpbuf[NTMSCP]; /* internal cmd buffer (for ioctls) */ 202*26135Skarels struct buf tmsutab[NTMS]; /* Drive queue */ 203*26135Skarels struct buf tmscpwtab[NTMSCP]; /* I/O wait queue, per controller */ 204*26135Skarels int tmscpmicro[NTMSCP]; /* to store microcode level */ 205*26135Skarels short utoctlr[NTMS]; /* Slave unit to controller mapping */ 206*26135Skarels /* filled in by the slave routine */ 207*26135Skarels 20826127Skarels /* Bits in minor device */ 20926127Skarels #define TMSUNIT(dev) (minor(dev)&03) 21026127Skarels #define T_NOREWIND 04 21126127Skarels #define T_HIDENSITY 010 212*26135Skarels 21326127Skarels /* Slave unit to controller mapping */ 21426127Skarels #define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)]) 215*26135Skarels 21626127Skarels /* 21726127Skarels * Internal (ioctl) command codes (these must also be declared in the 21826127Skarels * tmscpioctl routine). These correspond to ioctls in mtio.h 21926127Skarels */ 22026127Skarels #define TMS_WRITM 0 /* write tape mark */ 22126127Skarels #define TMS_FSF 1 /* forward space file */ 22226127Skarels #define TMS_BSF 2 /* backward space file */ 22326127Skarels #define TMS_FSR 3 /* forward space record */ 22426127Skarels #define TMS_BSR 4 /* backward space record */ 22526127Skarels #define TMS_REW 5 /* rewind tape */ 22626127Skarels #define TMS_OFFL 6 /* rewind tape & mark unit offline */ 22726127Skarels #define TMS_SENSE 7 /* noop - do a get unit status */ 22826127Skarels #define TMS_CACHE 8 /* enable cache */ 22926127Skarels #define TMS_NOCACHE 9 /* disable cache */ 23026127Skarels /* These go last: after all real mt cmds, just bump the numbers up */ 23126127Skarels #define TMS_CSE 10 /* clear serious exception */ 23226127Skarels #define TMS_LOWDENSITY 11 /* set unit to low density */ 23326127Skarels #define TMS_HIDENSITY 12 /* set unit to high density */ 234*26135Skarels 23526127Skarels /* 23626127Skarels * Controller states 23726127Skarels */ 23826127Skarels #define S_IDLE 0 /* hasn't been initialized */ 23926127Skarels #define S_STEP1 1 /* doing step 1 init */ 24026127Skarels #define S_STEP2 2 /* doing step 2 init */ 24126127Skarels #define S_STEP3 3 /* doing step 3 init */ 24226127Skarels #define S_SCHAR 4 /* doing "set controller characteristics" */ 24326127Skarels #define S_RUN 5 /* running */ 244*26135Skarels 24526127Skarels int tmscperror = 0; /* causes hex dump of packets */ 24626127Skarels int tmscp_cp_wait = 0; /* Something to wait on for command */ 24726127Skarels /* packets and or credits. */ 24826127Skarels int wakeup(); 24926127Skarels extern int hz; /* Should find the right include */ 250*26135Skarels 25126127Skarels #ifdef DEBUG 25226127Skarels #define printd if (tmscpdebug) printf 25326127Skarels int tmscpdebug = 1; 25426127Skarels #define printd10 if(tmscpdebug >= 10) printf 25526127Skarels #endif 256*26135Skarels 25726127Skarels int tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr(); 25826127Skarels struct mscp *tmscpgetcp(); 259*26135Skarels 26026127Skarels #define DRVNAME "tms" 26126127Skarels #define CTRLNAME "tmscp" 262*26135Skarels 26326127Skarels u_short tmscpstd[] = { 0174500, 0 }; 26426127Skarels struct uba_driver tmscpdriver = 26526127Skarels { tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME 26626127Skarels , tmscpminfo, 0}; 267*26135Skarels 26826127Skarels #define b_qsize b_resid /* queue size per drive, in tmsutab */ 26926127Skarels #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ 270*26135Skarels 271*26135Skarels 27226127Skarels /*************************************************************************/ 273*26135Skarels 27426127Skarels #define DELAYTEN 1000 275*26135Skarels 27626127Skarels tmscpprobe(reg, ctlr) 27726127Skarels caddr_t reg; /* address of the IP register */ 278*26135Skarels int ctlr; /* index of controller in the tmscp_softc array */ 27926127Skarels { 28026127Skarels register int br, cvec; /* MUST be 1st (r11 & r10): IPL and intr vec */ 28126127Skarels register struct tmscp_softc *sc = &tmscp_softc[ctlr]; 28226127Skarels /* ptr to software controller structure */ 283*26135Skarels struct tmscpdevice *tmscpaddr; /* ptr to tmscpdevice struct (IP & SA) */ 284*26135Skarels struct uba_ctlr *um; /* UNUSED ptr to uba_ctlr (controller) struct */ 28526127Skarels int count; /* for probe delay time out */ 286*26135Skarels 28726127Skarels # ifdef lint 28826127Skarels br = 0; cvec = br; br = cvec; reg = reg; 28926127Skarels tmscpreset(0); tmscpintr(0); 29026127Skarels # endif 291*26135Skarels 29226127Skarels tmscpaddr = (struct tmscpdevice *) reg; 29326127Skarels /* 29426127Skarels * Set host-settable interrupt vector. 295*26135Skarels * Assign 0 to the ip register to start the tmscp-device initialization. 29626127Skarels * The device is not really initialized at this point, this is just to 29726127Skarels * find out if the device exists. 29826127Skarels */ 29926127Skarels sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 30026127Skarels tmscpaddr->tmscpip = 0; 301*26135Skarels 30226127Skarels count=0; 30326127Skarels while(count < DELAYTEN) 30426127Skarels { /* wait for at most 10 secs */ 30526127Skarels if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0) 30626127Skarels break; 30726127Skarels DELAY(10000); 30826127Skarels count=count+1; 30926127Skarels } 31026127Skarels if (count == DELAYTEN) 31126127Skarels return(0); 312*26135Skarels 313*26135Skarels tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); 314*26135Skarels 31526127Skarels count=0; 31626127Skarels while(count < DELAYTEN) 31726127Skarels { 318*26135Skarels if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0) 31926127Skarels break; 32026127Skarels DELAY(10000); 32126127Skarels count = count+1; 32226127Skarels } 32326127Skarels if (count == DELAYTEN) 32426127Skarels return(0); 325*26135Skarels 32626127Skarels return(sizeof (struct tmscpdevice)); 32726127Skarels } 328*26135Skarels 32926127Skarels /* 33026127Skarels * Try to find a slave (a drive) on the controller. 33126127Skarels * If the controller is not in the run state, call init to initialize it. 33226127Skarels */ 33326127Skarels tmscpslave (ui, reg) 33426127Skarels struct uba_device *ui; /* ptr to the uba device structure */ 33526127Skarels caddr_t reg; /* addr of the device controller */ 33626127Skarels { 33726127Skarels register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; 33826127Skarels register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; 339*26135Skarels register struct tms_info *tms = &tms_info[ui->ui_unit]; 34026127Skarels struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ 34126127Skarels struct mscp *mp; 34226127Skarels int i; /* Something to write into to start */ 34326127Skarels /* the tmscp polling */ 344*26135Skarels 34526127Skarels # ifdef lint 34626127Skarels ui = ui; reg = reg; i = i; 34726127Skarels # endif 34826127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 34926127Skarels /* 35026127Skarels * If its not in the run state, start the initialization process 35126127Skarels * (tmscpintr will complete it); if the initialization doesn't start; 35226127Skarels * then return. 35326127Skarels */ 35426127Skarels if(sc->sc_state != S_RUN) 35526127Skarels { 35626127Skarels # ifdef DEBUG 35726127Skarels printd("tmscpslave: ctlr not running: calling init \n"); 35826127Skarels # endif 35926127Skarels if(!tmscpinit(ui->ui_ctlr)) 36026127Skarels return(0); 36126127Skarels } 36226127Skarels /* 36326127Skarels * Wait for the controller to come into the run state or go idle. 36426127Skarels * If it goes idle return. 36526127Skarels */ 36626127Skarels # ifdef DEBUG 36726127Skarels i=1; 36826127Skarels # endif 36926127Skarels while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE) 37026127Skarels # ifdef DEBUG 37126127Skarels if (tmscpaddr->tmscpsa & TMSCP_ERR && i) 37226127Skarels { 373*26135Skarels printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff); 37426127Skarels i=0; 37526127Skarels } 37626127Skarels # endif 37726127Skarels ; /* wait */ 37826127Skarels if(sc->sc_state == S_IDLE) 37926127Skarels { /* The tmscp device failed to initialize */ 38026127Skarels printf("tmscp controller failed to init\n"); 38126127Skarels return(0); 38226127Skarels } 38326127Skarels /* The controller is up so see if the drive is there */ 38426127Skarels if(0 == (mp = tmscpgetcp(um))) 38526127Skarels { 38626127Skarels printf("tmscp can't get command packet\n"); 38726127Skarels return(0); 38826127Skarels } 38926127Skarels /* Need to determine the drive type for generic driver */ 390*26135Skarels mp->mscp_opcode = M_OP_GTUNT; /* This should give us the device type */ 39126127Skarels mp->mscp_unit = ui->ui_slave; 39226127Skarels mp->mscp_cmdref = (long) ui->ui_slave; 393*26135Skarels tms->tms_status = 0; /* set to zero */ 39426127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; 395*26135Skarels *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/ 39626127Skarels i = tmscpaddr->tmscpip; 397*26135Skarels while(!tms->tms_status) 39826127Skarels ; /* Wait for some status */ 39926127Skarels # ifdef DEBUG 400*26135Skarels printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK); 401*26135Skarels # endif 40226127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = 0; 403*26135Skarels if(!tms->tms_type) /* packet from a GTUNT */ 40426127Skarels return(0); /* Failed No such drive */ 40526127Skarels else 40626127Skarels return(1); /* Got it and it is there */ 40726127Skarels } 408*26135Skarels 409*26135Skarels 41026127Skarels /* 41126127Skarels * Set ui flags to zero to show device is not online & set tmscpip. 41226127Skarels * Unit to Controller mapping is set up here. 41326127Skarels * Open routine will issue the online command, later. 41426127Skarels */ 41526127Skarels tmscpattach (ui) 41626127Skarels register struct uba_device *ui; /* ptr to unibus dev struct */ 41726127Skarels { 418*26135Skarels register struct uba_ctlr *um = ui->ui_mi; /* ptr to controller struct */ 419*26135Skarels struct tmscpdevice *tmscpaddr = (struct tmscpdevice *) um->um_addr; /* IP & SA */ 42026127Skarels struct mscp *mp; 42126127Skarels int i; /* Assign to here to start the tmscp-dev polling */ 422*26135Skarels 42326127Skarels # ifdef lint 42426127Skarels i = i; 42526127Skarels # endif lint 42626127Skarels ui->ui_flags = 0; 42726127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; 42826127Skarels # ifdef DEBUG 42926127Skarels /* 43026127Skarels * Check to see if the drive is available. 43126127Skarels * If not then just print debug. 43226127Skarels */ 43326127Skarels if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL) 43426127Skarels printd("tmscpattach: unavailable \n"); 43526127Skarels # endif 43626127Skarels utoctlr[ui->ui_unit] = ui->ui_ctlr; 43726127Skarels } 438*26135Skarels 439*26135Skarels 44026127Skarels /* 44126127Skarels * TMSCP interrupt routine. 44226127Skarels */ 44326127Skarels tmscpintr (d) 44426127Skarels int d; /* index to the controller */ 44526127Skarels { 44626127Skarels register struct uba_ctlr *um = tmscpminfo[d]; 447*26135Skarels register struct tmscpdevice *tmscpaddr = (struct tmscpdevice *)um->um_addr; 44826127Skarels struct buf *bp; 44926127Skarels register int i; 45026127Skarels register struct tmscp_softc *sc = &tmscp_softc[d]; 45126127Skarels register struct tmscp *tm = &tmscp[d]; 45226127Skarels struct tmscp *ttm; 45326127Skarels struct mscp *mp; 454*26135Skarels 45526127Skarels # ifdef DEBUG 456*26135Skarels printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa); 45726127Skarels # endif 458*26135Skarels 45926127Skarels /* 46026127Skarels * How the interrupt is handled depends on the state of the controller. 46126127Skarels */ 46226127Skarels switch (sc->sc_state) { 463*26135Skarels 46426127Skarels case S_IDLE: 46526127Skarels printf("tmscp%d: random interrupt ignored\n", d); 46626127Skarels return; 467*26135Skarels 46826127Skarels /* Controller was in step 1 last, see if its gone to step 2 */ 46926127Skarels case S_STEP1: 47026127Skarels # define STEP1MASK 0174377 47126127Skarels # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) 47226127Skarels for (i = 0; i < 150; i++) 47326127Skarels { 47426127Skarels if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) 47526127Skarels { /* still in step 1 (wait 1/100 sec) */ 47626127Skarels DELAY(10000); 47726127Skarels # ifdef DEBUG 47826127Skarels printd("still in step 1, delaying\n"); 47926127Skarels # endif DEBUG 48026127Skarels } 48126127Skarels else 48226127Skarels break; 48326127Skarels } 48426127Skarels if (i > 149) 48526127Skarels { 48626127Skarels sc->sc_state = S_IDLE; 487*26135Skarels printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa); 48826127Skarels wakeup((caddr_t)um); 48926127Skarels return; 49026127Skarels } 49126127Skarels tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) 49226127Skarels | ((cpu == VAX_780 || cpu == VAX_8600) ? TMSCP_PI : 0); 49326127Skarels sc->sc_state = S_STEP2; 49426127Skarels return; 495*26135Skarels 49626127Skarels /* Controller was in step 2 last, see if its gone to step 3 */ 49726127Skarels case S_STEP2: 49826127Skarels # define STEP2MASK 0174377 49926127Skarels # define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) 50026127Skarels for (i = 0; i < 150; i++) 50126127Skarels { 50226127Skarels if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) 50326127Skarels { /* still in step 2 (wait 1/100 sec) */ 50426127Skarels DELAY(10000); 50526127Skarels # ifdef DEBUG 50626127Skarels printd("still in step 2, delaying\n"); 50726127Skarels # endif DEBUG 50826127Skarels } 50926127Skarels else 51026127Skarels break; 51126127Skarels } 51226127Skarels if (i > 149) 51326127Skarels { 51426127Skarels sc->sc_state = S_IDLE; 515*26135Skarels printf("failed to initialize, in step2: sa 0x%x", tmscpaddr->tmscpsa); 51626127Skarels wakeup((caddr_t)um); 51726127Skarels return; 51826127Skarels } 519*26135Skarels tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)>>16; 52026127Skarels sc->sc_state = S_STEP3; 52126127Skarels return; 522*26135Skarels 52326127Skarels /* Controller was in step 3 last, see if its gone to step 4 */ 52426127Skarels case S_STEP3: 52526127Skarels # define STEP3MASK 0174000 52626127Skarels # define STEP3GOOD TMSCP_STEP4 52726127Skarels for (i = 0; i < 150; i++) 52826127Skarels { 52926127Skarels if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) 53026127Skarels { /* still in step 3 (wait 1/100 sec) */ 53126127Skarels DELAY(10000); 53226127Skarels # ifdef DEBUG 53326127Skarels printd("still in step 3, delaying\n"); 53426127Skarels # endif DEBUG 53526127Skarels } 53626127Skarels else 53726127Skarels break; 53826127Skarels } 53926127Skarels if (i > 149) 54026127Skarels { 54126127Skarels sc->sc_state = S_IDLE; 542*26135Skarels printf("failed to initialize, in step3: sa 0x%x", tmscpaddr->tmscpsa); 54326127Skarels wakeup((caddr_t)um); 54426127Skarels return; 54526127Skarels } 54626127Skarels /* 54726127Skarels * Get microcode version and model number of controller; 54826127Skarels * Signal initialization complete (_GO) (to the controller); 54926127Skarels * ask for Last Fail response if tmscperror is set; 55026127Skarels * Set state to "set controller characteristics". 55126127Skarels */ 55226127Skarels tmscpmicro[d] = tmscpaddr->tmscpsa; 55326127Skarels tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); 55426127Skarels sc->sc_state = S_SCHAR; 55526127Skarels # ifdef DEBUG 55626127Skarels printd("tmscpintr: completed state %d \n", sc->sc_state); 55726127Skarels printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF, 55826127Skarels (tmscpmicro[d]>>4) & 0xF); 55926127Skarels # endif 560*26135Skarels 56126127Skarels /* 56226127Skarels * Initialize the data structures (response and command queues). 56326127Skarels */ 56426127Skarels ttm = sc->sc_tmscp; 56526127Skarels for (i = 0; i < NRSP; i++) 56626127Skarels { 56726127Skarels tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | 568*26135Skarels (long)&ttm->tmscp_rsp[i].mscp_cmdref; 56926127Skarels tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i]; 57026127Skarels tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen; 57126127Skarels } 57226127Skarels for (i = 0; i < NCMD; i++) 57326127Skarels { 57426127Skarels tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | 57526127Skarels (long)&ttm->tmscp_cmd[i].mscp_cmdref; 57626127Skarels tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i]; 57726127Skarels tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen; 57826127Skarels tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1; 57926127Skarels } 58026127Skarels bp = &tmscpwtab[d]; 58126127Skarels bp->av_forw = bp->av_back = bp; 58226127Skarels sc->sc_lastcmd = 1; 58326127Skarels sc->sc_lastrsp = 0; 58426127Skarels mp = &tmscp[um->um_ctlr].tmscp_cmd[0]; 58526127Skarels mp->mscp_unit = mp->mscp_modifier = 0; 58626127Skarels mp->mscp_flags = 0; 58726127Skarels mp->mscp_version = 0; 58826127Skarels mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; 58926127Skarels /* 59026127Skarels * A host time out value of 0 means that the controller will not 59126127Skarels * time out. This is ok for the TK50. 59226127Skarels */ 59326127Skarels mp->mscp_hsttmo = 0; 59426127Skarels mp->mscp_time.val[0] = 0; 59526127Skarels mp->mscp_time.val[1] = 0; 59626127Skarels mp->mscp_cntdep = 0; 59726127Skarels mp->mscp_opcode = M_OP_STCON; 59826127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 59926127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 60026127Skarels return; 601*26135Skarels 60226127Skarels case S_SCHAR: 60326127Skarels case S_RUN: 60426127Skarels break; 605*26135Skarels 60626127Skarels default: 607*26135Skarels printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_state); 60826127Skarels return; 60926127Skarels } /* end switch */ 610*26135Skarels 61126127Skarels /* 61226127Skarels * The controller state is S_SCHAR or S_RUN 61326127Skarels */ 614*26135Skarels 61526127Skarels /* 61626127Skarels * If the error bit is set in the SA register then print an error 61726127Skarels * message and reinitialize the controller. 61826127Skarels */ 61926127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 62026127Skarels { 621*26135Skarels printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xffff); 62226127Skarels tmscpaddr->tmscpip = 0; 62326127Skarels wakeup((caddr_t)um); 62426127Skarels } 62526127Skarels /* 62626127Skarels * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) 62726127Skarels */ 62826127Skarels if (tm->tmscp_ca.ca_bdp) 62926127Skarels { 63026127Skarels /* 63126127Skarels * THIS IS A KLUDGE. 63226127Skarels * Maybe we should change the entire 63326127Skarels * UBA interface structure. 63426127Skarels */ 63526127Skarels int s = spl6(); 63626127Skarels i = um->um_ubinfo; 63726127Skarels # ifdef DEBUG 63826127Skarels printd("tmscp: purge bdp %d\n", tm->tmscp_ca.ca_bdp); 63926127Skarels # endif 64026127Skarels um->um_ubinfo = tm->tmscp_ca.ca_bdp<<28; 64126127Skarels ubapurge(um); 64226127Skarels um->um_ubinfo = i; 64326127Skarels (void) splx(s); 64426127Skarels tm->tmscp_ca.ca_bdp = 0; 64526127Skarels tmscpaddr->tmscpsa = 0; /* signal purge complete */ 64626127Skarels } 647*26135Skarels 64826127Skarels /* 64926127Skarels * Check for response ring transition. 65026127Skarels */ 65126127Skarels if (tm->tmscp_ca.ca_rspint) 65226127Skarels { 65326127Skarels tm->tmscp_ca.ca_rspint = 0; 65426127Skarels for (i = sc->sc_lastrsp;; i++) 65526127Skarels { 65626127Skarels i %= NRSP; 65726127Skarels if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) 65826127Skarels break; 65926127Skarels tmscprsp(um, tm, sc, i); 66026127Skarels tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; 66126127Skarels } 66226127Skarels sc->sc_lastrsp = i; 66326127Skarels } 664*26135Skarels 66526127Skarels /* 66626127Skarels * Check for command ring transition. 66726127Skarels */ 66826127Skarels if (tm->tmscp_ca.ca_cmdint) 66926127Skarels { 67026127Skarels # ifdef DEBUG 67126127Skarels printd("tmscpintr: command ring transition\n"); 67226127Skarels # endif 67326127Skarels tm->tmscp_ca.ca_cmdint = 0; 67426127Skarels } 67526127Skarels if(tmscp_cp_wait) 67626127Skarels wakeup(&tmscp_cp_wait); 67726127Skarels (void) tmscpstart(um); 67826127Skarels } 679*26135Skarels 680*26135Skarels 68126127Skarels /* 68226127Skarels * Open a tmscp device and set the unit online. If the controller is not 68326127Skarels * in the run state, call init to initialize the tmscp controller first. 68426127Skarels */ 685*26135Skarels 68626127Skarels tmscpopen(dev, flag) 68726127Skarels dev_t dev; 68826127Skarels int flag; 68926127Skarels { 69026127Skarels register int unit; 69126127Skarels register struct uba_device *ui; 69226127Skarels register struct tmscp_softc *sc; 693*26135Skarels register struct tms_info *tms; 69426127Skarels register struct mscp *mp; 69526127Skarels register struct uba_ctlr *um; 69626127Skarels struct tmscpdevice *tmscpaddr; 69726127Skarels int s,i; 69826127Skarels extern quota; 69926127Skarels 70026127Skarels # ifdef lint 70126127Skarels flag = flag; i = i; 70226127Skarels # endif 70326127Skarels unit = TMSUNIT(dev); 70426127Skarels # ifdef DEBUG 70526127Skarels printd("tmscpopen unit %d\n",unit); 70626127Skarels if(tmscpdebug)DELAY(10000); 70726127Skarels # endif 708*26135Skarels if (unit >= NTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0) 70926127Skarels return (ENXIO); 710*26135Skarels tms = &tms_info[ui->ui_unit]; 711*26135Skarels if (tms->tms_openf) 712*26135Skarels return (EBUSY); 71326127Skarels sc = &tmscp_softc[ui->ui_ctlr]; 714*26135Skarels tms->tms_openf = 1; 715*26135Skarels tms->tms_ttyp = u.u_ttyp; 71626127Skarels s = spl5(); 71726127Skarels if (sc->sc_state != S_RUN) 71826127Skarels { 71926127Skarels if (sc->sc_state == S_IDLE) 72026127Skarels if(!tmscpinit(ui->ui_ctlr)) 72126127Skarels { 72226127Skarels printf("tmscp controller failed to init\n"); 72326127Skarels (void) splx(s); 72426127Skarels return(ENXIO); 72526127Skarels } 72626127Skarels /* 72726127Skarels * Wait for initialization to complete 72826127Skarels */ 72926127Skarels timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ 73026127Skarels sleep((caddr_t)ui->ui_mi, 0); 73126127Skarels if (sc->sc_state != S_RUN) 73226127Skarels { 73326127Skarels (void) splx(s); 734*26135Skarels tms->tms_openf = 0; 73526127Skarels return (EIO); 73626127Skarels } 73726127Skarels } 73826127Skarels /* 73926127Skarels * Check to see if the device is really there. 74026127Skarels * this code was taken from Fred Canters 11 driver 74126127Skarels */ 74226127Skarels um = ui->ui_mi; 74326127Skarels tmscpaddr = (struct tmscpdevice *) um->um_addr; 74426127Skarels (void) splx(s); 74526127Skarels if(ui->ui_flags == 0) 74626127Skarels { 74726127Skarels s = spl5(); 74826127Skarels while(0 ==(mp = tmscpgetcp(um))) 74926127Skarels { 75026127Skarels tmscp_cp_wait++; 75126127Skarels sleep(&tmscp_cp_wait,PSWP+1); 75226127Skarels tmscp_cp_wait--; 75326127Skarels } 75426127Skarels (void) splx(s); 75526127Skarels mp->mscp_opcode = M_OP_ONLIN; 75626127Skarels mp->mscp_unit = ui->ui_slave; 757*26135Skarels mp->mscp_cmdref = (long) & tms->tms_type; 75826127Skarels /* need to sleep on something */ 75926127Skarels # ifdef DEBUG 76026127Skarels printd("tmscpopen: bring unit %d online\n",ui->ui_unit); 76126127Skarels # endif 76226127Skarels *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT; 76326127Skarels i = tmscpaddr->tmscpip; 76426127Skarels /* 76526127Skarels * To make sure we wake up, timeout in 240 seconds. 76626127Skarels * Wakeup in tmscprsp routine. 76726127Skarels * 240 seconds (4 minutes) is necessary since a rewind 76826127Skarels * can take a few minutes. 76926127Skarels */ 77026127Skarels timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz); 77126127Skarels sleep((caddr_t) mp->mscp_cmdref,PSWP+1); 77226127Skarels } 773*26135Skarels if(ui->ui_flags == 0) { 774*26135Skarels tms->tms_openf = 0; 77526127Skarels return(ENXIO); /* Didn't go online */ 776*26135Skarels } 777*26135Skarels tms->tms_lastiow = 0; 77826127Skarels /* 77926127Skarels * If the high density device is not specified, set unit to low 78026127Skarels * density. This is done as an "internal" ioctl command so 78126127Skarels * that the command setup and response handling 78226127Skarels * is done thru "regular" command routines. 78326127Skarels */ 78426127Skarels if ((minor(dev) & T_HIDENSITY) == 0) 78526127Skarels tmscpcommand(dev, TMS_LOWDENSITY, 1); 78626127Skarels else 78726127Skarels tmscpcommand(dev, TMS_HIDENSITY, 1); 78826127Skarels return (0); 78926127Skarels } 790*26135Skarels 791*26135Skarels 79226127Skarels /* 79326127Skarels * Close tape device. 79426127Skarels * 79526127Skarels * If tape was open for writing or last operation was 79626127Skarels * a write, then write two EOF's and backspace over the last one. 79726127Skarels * Unless this is a non-rewinding special file, rewind the tape. 79826127Skarels * 79926127Skarels * NOTE: 80026127Skarels * We want to be sure that any serious exception is cleared on the 80126127Skarels * close. A Clear Serious Exception (CSE) modifier is always done on 80226127Skarels * the rewind command. For the non-rewind case we check to see if the 80326127Skarels * "serex" field is set in the softc struct; if it is then issue a noop 80426127Skarels * command with the CSE modifier. 80526127Skarels * Make the tape available to others, by clearing openf flag. 80626127Skarels */ 80726127Skarels tmscpclose(dev, flag) 80826127Skarels register dev_t dev; 80926127Skarels register flag; 81026127Skarels { 81126127Skarels register struct tmscp_softc *sc = &tmscp_softc[TMSCPCTLR(dev)]; 812*26135Skarels register struct tms_info *tms; 81326127Skarels register struct uba_device *ui; 814*26135Skarels 81526127Skarels ui = tmsdinfo[TMSUNIT(dev)]; 81626127Skarels # ifdef DEBUG 81726127Skarels printd("tmscpclose: ctlr = %d\n",TMSCPCTLR(dev)); 81826127Skarels printd("tmscpclose: unit = %d\n",TMSUNIT(dev)); 81926127Skarels if(tmscpdebug)DELAY(10000); 82026127Skarels # endif 821*26135Skarels tms = &tms_info[ui->ui_unit]; 822*26135Skarels if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow) 82326127Skarels { 82426127Skarels /* device, command, count */ 82526127Skarels tmscpcommand (dev, TMS_WRITM, 1); 82626127Skarels tmscpcommand (dev, TMS_WRITM, 1); 82726127Skarels tmscpcommand (dev, TMS_BSR, 1); 82826127Skarels } 82926127Skarels if ((minor(dev)&T_NOREWIND) == 0) 83026127Skarels /* 83126127Skarels * Don't hang waiting for rewind complete. 83226127Skarels */ 83326127Skarels tmscpcommand(dev, TMS_REW, 0); 83426127Skarels else 835*26135Skarels if (tms->tms_serex) 83626127Skarels { 83726127Skarels # ifdef DEBUG 83826127Skarels printd("tmscpclose: clearing serex\n"); 83926127Skarels if(tmscpdebug)DELAY(10000); 84026127Skarels # endif 84126127Skarels tmscpcommand(dev, TMS_CSE, 1); 84226127Skarels } 843*26135Skarels tms->tms_openf = 0; 84426127Skarels } 845*26135Skarels 846*26135Skarels 84726127Skarels /* 84826127Skarels * Execute a command on the tape drive a specified number of times. 84926127Skarels * This routine sets up a buffer and calls the strategy routine which 85026127Skarels * links the buffer onto the drive's buffer queue. 85126127Skarels * The start routine will take care of creating a tmscp command packet 85226127Skarels * with the command. The start routine is called by the strategy or the 85326127Skarels * interrupt routine. 85426127Skarels */ 855*26135Skarels 85626127Skarels tmscpcommand (dev, com, count) 85726127Skarels register dev_t dev; 85826127Skarels int com, count; 85926127Skarels { 86026127Skarels register struct uba_device *ui; 86126127Skarels register struct buf *bp; 86226127Skarels register int s; 86326127Skarels int unit = TMSUNIT(dev); 864*26135Skarels 865*26135Skarels if (unit >= NTMS) 86626127Skarels return (ENXIO); 86726127Skarels ui = tmsdinfo[unit]; 86826127Skarels bp = &ctmscpbuf[ui->ui_ctlr]; 869*26135Skarels 87026127Skarels s = spl5(); 87126127Skarels while (bp->b_flags&B_BUSY) 87226127Skarels { 87326127Skarels /* 87426127Skarels * This special check is because B_BUSY never 87526127Skarels * gets cleared in the non-waiting rewind case. 87626127Skarels */ 87726127Skarels if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) 87826127Skarels break; 87926127Skarels bp->b_flags |= B_WANTED; 88026127Skarels sleep((caddr_t)bp, PRIBIO); 88126127Skarels } 88226127Skarels bp->b_flags = B_BUSY|B_READ; 88326127Skarels splx(s); 88426127Skarels /* 88526127Skarels * Load the buffer. The b_count field gets used to hold the command 88626127Skarels * count. the b_resid field gets used to hold the command mneumonic. 88726127Skarels * These 2 fields are "known" to be "safe" to use for this purpose. 88826127Skarels * (Most other drivers also use these fields in this way.) 88926127Skarels */ 89026127Skarels bp->b_dev = dev; 89126127Skarels bp->b_bcount = count; 89226127Skarels bp->b_resid = com; 89326127Skarels bp->b_blkno = 0; 89426127Skarels tmscpstrategy(bp); 89526127Skarels /* 89626127Skarels * In case of rewind from close, don't wait. 89726127Skarels * This is the only case where count can be 0. 89826127Skarels */ 89926127Skarels if (count == 0) 90026127Skarels return; 90126127Skarels iowait(bp); 90226127Skarels if (bp->b_flags&B_WANTED) 90326127Skarels wakeup((caddr_t)bp); 90426127Skarels bp->b_flags &= B_ERROR; 90526127Skarels } 906*26135Skarels 90726127Skarels /* 90826127Skarels * Find an unused command packet 90926127Skarels */ 91026127Skarels struct mscp * 91126127Skarels tmscpgetcp(um) 91226127Skarels struct uba_ctlr *um; 91326127Skarels { 91426127Skarels register struct mscp *mp; 91526127Skarels register struct tmscpca *cp; 91626127Skarels register struct tmscp_softc *sc; 91726127Skarels register int i; 91826127Skarels int s; 919*26135Skarels 92026127Skarels s = spl5(); 92126127Skarels cp = &tmscp[um->um_ctlr].tmscp_ca; 92226127Skarels sc = &tmscp_softc[um->um_ctlr]; 92326127Skarels /* 92426127Skarels * If no credits, can't issue any commands 92526127Skarels * until some outstanding commands complete. 92626127Skarels */ 92726127Skarels i = sc->sc_lastcmd; 92826127Skarels # ifdef DEBUG 92926127Skarels printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); 93026127Skarels # endif 93126127Skarels if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && 93226127Skarels (sc->sc_credits >= 2)) 93326127Skarels { 93426127Skarels sc->sc_credits--; /* This commits to issuing a command */ 93526127Skarels cp->ca_cmddsc[i] &= ~TMSCP_INT; 93626127Skarels mp = &tmscp[um->um_ctlr].tmscp_cmd[i]; 93726127Skarels mp->mscp_unit = mp->mscp_modifier = 0; 93826127Skarels mp->mscp_opcode = mp->mscp_flags = 0; 93926127Skarels mp->mscp_bytecnt = mp->mscp_buffer = 0; 94026127Skarels sc->sc_lastcmd = (i + 1) % NCMD; 94126127Skarels (void) splx(s); 94226127Skarels return(mp); 94326127Skarels } 94426127Skarels (void) splx(s); 94526127Skarels return(NULL); 94626127Skarels } 947*26135Skarels 948*26135Skarels 94926127Skarels /* 95026127Skarels * Initialize a TMSCP device. Set up UBA mapping registers, 95126127Skarels * initialize data structures, and start hardware 95226127Skarels * initialization sequence. 95326127Skarels */ 95426127Skarels tmscpinit (d) 95526127Skarels int d; /* index to the controller */ 95626127Skarels { 95726127Skarels register struct tmscp_softc *sc; 958*26135Skarels register struct tmscp *t; /* communications area; cmd & resp packets */ 95926127Skarels struct tmscpdevice *tmscpaddr; 96026127Skarels struct uba_ctlr *um; 961*26135Skarels 96226127Skarels sc = &tmscp_softc[d]; 96326127Skarels um = tmscpminfo[d]; 96426127Skarels um->um_tab.b_active++; 96526127Skarels t = &tmscp[d]; 96626127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 96726127Skarels if (sc->sc_mapped == 0) 96826127Skarels { 96926127Skarels /* 97026127Skarels * Map the communications area and command 97126127Skarels * and response packets into Unibus address 97226127Skarels * space. 97326127Skarels */ 974*26135Skarels sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (struct tmscp), 0); 97526127Skarels # ifdef MVAX 97626127Skarels if (cpu == MVAX_I) 977*26135Skarels sc->sc_tmscp = (struct tmscp *)(sc->sc_ubainfo & 0x3fffff); 97826127Skarels else 97926127Skarels # endif MVAX 980*26135Skarels sc->sc_tmscp = (struct tmscp *)(sc->sc_ubainfo & 0x3ffff); 98126127Skarels sc->sc_mapped = 1; 98226127Skarels } 983*26135Skarels 98426127Skarels /* 98526127Skarels * Start the hardware initialization sequence. 98626127Skarels */ 98726127Skarels tmscpaddr->tmscpip = 0; /* start initialization */ 988*26135Skarels 98926127Skarels while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 99026127Skarels { 99126127Skarels # ifdef DEBUG 99226127Skarels printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); 99326127Skarels DELAY(100000); 99426127Skarels # endif 99526127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) 99626127Skarels return(0); /* CHECK */ 99726127Skarels } 998*26135Skarels tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); 99926127Skarels /* 100026127Skarels * Initialization continues in the interrupt routine. 100126127Skarels */ 100226127Skarels sc->sc_state = S_STEP1; 100326127Skarels sc->sc_credits = 0; 100426127Skarels return(1); 100526127Skarels } 1006*26135Skarels 1007*26135Skarels 100826127Skarels /* 100926127Skarels * Start I/O operation 101026127Skarels * This code is convoluted. The majority of it was copied from the uda driver. 101126127Skarels */ 1012*26135Skarels 101326127Skarels tmscpstart(um) 101426127Skarels register struct uba_ctlr *um; 101526127Skarels { 101626127Skarels register struct buf *bp, *dp; 101726127Skarels register struct mscp *mp; 101826127Skarels register struct tmscp_softc *sc; 1019*26135Skarels register struct tms_info *tms; 102026127Skarels register struct uba_device *ui; 102126127Skarels struct tmscpdevice *tmscpaddr; 102226127Skarels struct tmscp *tm = &tmscp[um->um_ctlr]; 102326127Skarels int i,tempi; 102426127Skarels char ioctl; /* flag: set true if its an IOCTL command */ 1025*26135Skarels 102626127Skarels sc = &tmscp_softc[um->um_ctlr]; 102726127Skarels 102826127Skarels for(;;) 102926127Skarels { 103026127Skarels if ((dp = um->um_tab.b_actf) == NULL) 103126127Skarels { 103226127Skarels /* 103326127Skarels * Release unneeded UBA resources and return 103426127Skarels * (drive was inactive) 103526127Skarels */ 103626127Skarels um->um_tab.b_active = 0; 103726127Skarels break; 103826127Skarels } 103926127Skarels if ((bp = dp->b_actf) == NULL) 104026127Skarels { 104126127Skarels /* 104226127Skarels * No more requests for this drive, remove 104326127Skarels * from controller queue and look at next drive. 104426127Skarels * We know we're at the head of the controller queue. 104526127Skarels */ 104626127Skarels dp->b_active = 0; 104726127Skarels um->um_tab.b_actf = dp->b_forw; 104826127Skarels continue; /* Need to check for loop */ 104926127Skarels } 105026127Skarels um->um_tab.b_active++; 105126127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 1052*26135Skarels ui = tmsdinfo[(TMSUNIT(bp->b_dev))]; 1053*26135Skarels tms = &tms_info[ui->ui_unit]; 105426127Skarels if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) 105526127Skarels { 1056*26135Skarels tprintf(tms->tms_ttyp, 1057*26135Skarels "tms%d: hard error bn%d\n", 1058*26135Skarels minor(bp->b_dev)&03, bp->b_blkno); 1059*26135Skarels log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr, 106026127Skarels tmscpaddr->tmscpsa&0xffff, sc->sc_state); 106126127Skarels tmscpinit(um->um_ctlr); 106226127Skarels /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ 106326127Skarels break; 106426127Skarels } 106526127Skarels /* 106626127Skarels * Default is that last command was NOT a write command; 106726127Skarels * if a write command is done it will be detected in tmscprsp. 106826127Skarels */ 1069*26135Skarels tms->tms_lastiow = 0; 107026127Skarels if (ui->ui_flags == 0) 107126127Skarels { /* not online */ 107226127Skarels if ((mp = tmscpgetcp(um)) == NULL) 107326127Skarels break; 107426127Skarels mp->mscp_opcode = M_OP_ONLIN; 107526127Skarels mp->mscp_unit = ui->ui_slave; 107626127Skarels dp->b_active = 2; 107726127Skarels um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ 107826127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 107926127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 108026127Skarels printf("tmscp%d fatal error (0%o)\n",um->um_ctlr, 108126127Skarels tmscpaddr->tmscpsa&0xffff); 108226127Skarels i = tmscpaddr->tmscpip; 108326127Skarels continue; 108426127Skarels } 108526127Skarels switch (cpu) { 1086*26135Skarels 108726127Skarels case VAX_8600: 108826127Skarels case VAX_780: 108926127Skarels i = UBA_NEEDBDP|UBA_CANTWAIT; 109026127Skarels break; 109126127Skarels case VAX_750: 109226127Skarels i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; 109326127Skarels break; 109426127Skarels case VAX_730: 109526127Skarels i = UBA_CANTWAIT; 109626127Skarels break; 109726127Skarels } /* end switch (cpu) */ 109826127Skarels /* 1099*26135Skarels * If command is an ioctl command then set the ioctl flag for later use. 110026127Skarels * If not (i.e. it is a read or write) then attempt 110126127Skarels * to set up a buffer pointer. 110226127Skarels */ 110326127Skarels ioctl = 0; 110426127Skarels if (bp == &ctmscpbuf[um->um_ctlr]) 110526127Skarels ioctl = 1; 110626127Skarels else 110726127Skarels if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) 110826127Skarels { 110926127Skarels if(dp->b_qsize != 0) 111026127Skarels break; /* When a command completes and */ 1111*26135Skarels /* frees a bdp tmscpstart will be called */ 111226127Skarels if ((mp = tmscpgetcp(um)) == NULL) 111326127Skarels break; 111426127Skarels # ifdef DEBUG 1115*26135Skarels printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i); 111626127Skarels if(tmscpdebug)DELAY(10000); 111726127Skarels # endif 111826127Skarels mp->mscp_opcode = M_OP_GTUNT; 111926127Skarels mp->mscp_unit = ui->ui_slave; 112026127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 112126127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 1122*26135Skarels printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr, 112326127Skarels tmscpaddr->tmscpsa&0xffff); 112426127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 112526127Skarels break; 112626127Skarels } 1127*26135Skarels # if defined(VAX750) 1128*26135Skarels if (cpu == VAX_750) 112926127Skarels tempi = i & 0xfffffff; /* mask off bdp */ 113026127Skarels else 113126127Skarels # endif 113226127Skarels tempi = i; 113326127Skarels if ((mp = tmscpgetcp(um)) == NULL) 113426127Skarels { 113526127Skarels if (!ioctl) /* only need to release if NOT ioctl */ 113626127Skarels ubarelse(um->um_ubanum,&tempi); 113726127Skarels break; 113826127Skarels } 113926127Skarels mp->mscp_cmdref = (long)bp; /* pointer to get back */ 114026127Skarels mp->mscp_unit = ui->ui_slave; 114126127Skarels /* 114226127Skarels * If its an ioctl-type command then set up the appropriate 114326127Skarels * tmscp command; by doing a switch on the "b_resid" field where 114426127Skarels * the command mneumonic is stored. 114526127Skarels */ 114626127Skarels if (ioctl) 114726127Skarels { 114826127Skarels # ifdef DEBUG 114926127Skarels printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid); 115026127Skarels # endif 115126127Skarels /* 115226127Skarels * The reccnt and tmkcnt fields are set to zero by the getcp 115326127Skarels * routine (as bytecnt and buffer fields). Thus reccnt and 115426127Skarels * tmkcnt are only modified here if they need to be set to 115526127Skarels * a non-zero value. 115626127Skarels */ 115726127Skarels switch (bp->b_resid) { 1158*26135Skarels 115926127Skarels case TMS_WRITM: 116026127Skarels mp->mscp_opcode = M_OP_WRITM; 116126127Skarels break; 116226127Skarels case TMS_FSF: 116326127Skarels mp->mscp_opcode = M_OP_REPOS; 116426127Skarels mp->mscp_tmkcnt = bp->b_bcount; 116526127Skarels break; 116626127Skarels case TMS_BSF: 116726127Skarels mp->mscp_opcode = M_OP_REPOS; 116826127Skarels mp->mscp_modifier = M_MD_REVRS; 116926127Skarels mp->mscp_tmkcnt = bp->b_bcount; 117026127Skarels break; 117126127Skarels case TMS_FSR: 117226127Skarels mp->mscp_opcode = M_OP_REPOS; 117326127Skarels mp->mscp_modifier = M_MD_OBJCT; 117426127Skarels mp->mscp_reccnt = bp->b_bcount; 117526127Skarels break; 117626127Skarels case TMS_BSR: 117726127Skarels mp->mscp_opcode = M_OP_REPOS; 117826127Skarels mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; 117926127Skarels mp->mscp_reccnt = bp->b_bcount; 118026127Skarels break; 118126127Skarels /* 118226127Skarels * Clear serious exception is done for Rewind & Available cmds 118326127Skarels */ 118426127Skarels case TMS_REW: 118526127Skarels mp->mscp_opcode = M_OP_REPOS; 118626127Skarels mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; 118726127Skarels if (bp->b_bcount == 0) 118826127Skarels mp->mscp_modifier |= M_MD_IMMED; 1189*26135Skarels tms->tms_serex = 0; 119026127Skarels break; 119126127Skarels case TMS_OFFL: 119226127Skarels mp->mscp_opcode = M_OP_AVAIL; 119326127Skarels mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; 1194*26135Skarels tms->tms_serex = 0; 119526127Skarels break; 119626127Skarels case TMS_SENSE: 119726127Skarels mp->mscp_opcode = M_OP_GTUNT; 119826127Skarels break; 119926127Skarels case TMS_CACHE: 120026127Skarels mp->mscp_opcode = M_OP_STUNT; 1201*26135Skarels tms->tms_unitflgs |= M_UF_WBKNV; 1202*26135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 1203*26135Skarels mp->mscp_format = tms->tms_format; 120426127Skarels /* default device dependant parameters */ 120526127Skarels mp->mscp_mediaid = 0; 120626127Skarels break; 120726127Skarels case TMS_NOCACHE: 120826127Skarels mp->mscp_opcode = M_OP_STUNT; 1209*26135Skarels tms->tms_unitflgs &= ~(M_UF_WBKNV); 1210*26135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 1211*26135Skarels mp->mscp_format = tms->tms_format; 121226127Skarels /* default device dependant parameters */ 121326127Skarels mp->mscp_mediaid = 0; 121426127Skarels break; 121526127Skarels case TMS_CSE: 121626127Skarels /* 121726127Skarels * This is a no-op command. It performs a 121826127Skarels * clear serious exception only. (Done on a 121926127Skarels * non-rewinding close after a serious exception.) 122026127Skarels */ 122126127Skarels mp->mscp_opcode = M_OP_REPOS; 122226127Skarels mp->mscp_modifier = M_MD_CLSEX; 1223*26135Skarels tms->tms_serex = 0; 1224*26135Skarels tms->tms_clserex = 1; 122526127Skarels break; 122626127Skarels case TMS_LOWDENSITY: 122726127Skarels /* 122826127Skarels * Set the unit to low density 122926127Skarels */ 123026127Skarels mp->mscp_opcode = M_OP_STUNT; 1231*26135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 1232*26135Skarels mp->mscp_mediaid = 0; /* default device dependant parameters */ 1233*26135Skarels if ((tms->tms_fmtmenu & M_TF_800) != 0) 123426127Skarels mp->mscp_format = M_TF_800; 123526127Skarels else 1236*26135Skarels mp->mscp_format = M_TF_PE & tms->tms_fmtmenu; 1237*26135Skarels tms->tms_format = mp->mscp_format; 123826127Skarels break; 123926127Skarels case TMS_HIDENSITY: 124026127Skarels /* 124126127Skarels * Set the unit to high density (format == 0) 124226127Skarels */ 124326127Skarels mp->mscp_opcode = M_OP_STUNT; 1244*26135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 1245*26135Skarels mp->mscp_mediaid = 0; /* default device dependant parameters */ 124626127Skarels mp->mscp_format = 0; 1247*26135Skarels tms->tms_format = 0; 124826127Skarels break; 124926127Skarels default: 125026127Skarels printf("Bad ioctl on tms unit %d\n", ui->ui_unit); 125126127Skarels /* Need a no-op. Reposition no amount */ 125226127Skarels mp->mscp_opcode = M_OP_REPOS; 125326127Skarels break; 125426127Skarels } /* end switch (bp->b_resid) */ 125526127Skarels } 125626127Skarels else /* Its a read/write command (not an ioctl) */ 125726127Skarels { 125826127Skarels mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; 125926127Skarels mp->mscp_bytecnt = bp->b_bcount; 126026127Skarels # if MVAX 126126127Skarels if (cpu == MVAX_I) 126226127Skarels { 126326127Skarels mp->mscp_buffer = (i & 0x3ffff) | TMSCP_MAP; 1264*26135Skarels mp->mscp_mapbase = (long)&(uba_hd[um->um_ubanum].uh_physuba->uba_map[0]); 126526127Skarels } 126626127Skarels else 126726127Skarels # endif MVAX 126826127Skarels mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); 1269*26135Skarels 127026127Skarels bp->b_ubinfo = tempi; /* save mapping info */ 127126127Skarels } 1272*26135Skarels if (tms->tms_serex == 2) /* if tape mark read */ 127326127Skarels { 1274*26135Skarels mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc */ 1275*26135Skarels tms->tms_serex = 0; 127626127Skarels } 127726127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 127826127Skarels # ifdef DEBUG 1279*26135Skarels printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); 128026127Skarels if(tmscpdebug)DELAY(100000); 128126127Skarels # endif 128226127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 128326127Skarels dp->b_qsize++; 128426127Skarels /* 128526127Skarels * Move drive to the end of the controller queue 128626127Skarels */ 128726127Skarels if (dp->b_forw != NULL) 128826127Skarels { 128926127Skarels um->um_tab.b_actf = dp->b_forw; 129026127Skarels um->um_tab.b_actl->b_forw = dp; 129126127Skarels um->um_tab.b_actl = dp; 129226127Skarels dp->b_forw = NULL; 129326127Skarels } 129426127Skarels /* 129526127Skarels * Move buffer to I/O wait queue 129626127Skarels */ 129726127Skarels dp->b_actf = bp->av_forw; 129826127Skarels dp = &tmscpwtab[um->um_ctlr]; 129926127Skarels bp->av_forw = dp; 130026127Skarels bp->av_back = dp->av_back; 130126127Skarels dp->av_back->av_forw = bp; 130226127Skarels dp->av_back = bp; 130326127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 130426127Skarels { 1305*26135Skarels printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff); 130626127Skarels tmscpinit(um->um_ctlr); 130726127Skarels break; 130826127Skarels } 130926127Skarels } /* end for */ 131026127Skarels /* 131126127Skarels * Check for response ring transitions lost in the 131226127Skarels * Race condition 131326127Skarels */ 131426127Skarels for (i = sc->sc_lastrsp;; i++) 131526127Skarels { 131626127Skarels i %= NRSP; 131726127Skarels if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) 131826127Skarels break; 131926127Skarels tmscprsp(um, tm, sc, i); 132026127Skarels tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; 132126127Skarels } 132226127Skarels sc->sc_lastrsp = i; 132326127Skarels } 1324*26135Skarels 1325*26135Skarels 132626127Skarels /* 132726127Skarels * Process a response packet 132826127Skarels */ 132926127Skarels tmscprsp(um, tm, sc, i) 133026127Skarels register struct uba_ctlr *um; 133126127Skarels register struct tmscp *tm; 133226127Skarels register struct tmscp_softc *sc; 133326127Skarels int i; 133426127Skarels { 133526127Skarels register struct mscp *mp; 1336*26135Skarels register struct tms_info *tms; 133726127Skarels struct uba_device *ui; 133826127Skarels struct buf *dp, *bp, nullbp; 133926127Skarels int st; 1340*26135Skarels 134126127Skarels mp = &tm->tmscp_rsp[i]; 134226127Skarels mp->mscp_header.tmscp_msglen = mscp_msglen; 1343*26135Skarels sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits */ 134426127Skarels if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ 134526127Skarels return; 134626127Skarels # ifdef DEBUG 1347*26135Skarels printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK); 134826127Skarels # endif 134926127Skarels /* 135026127Skarels * If it's an error log message (datagram), 135126127Skarels * pass it on for more extensive processing. 135226127Skarels */ 135326127Skarels if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) 135426127Skarels { /* check */ 135526127Skarels tmserror(um, (struct mslg *)mp); 135626127Skarels return; 135726127Skarels } 135826127Skarels st = mp->mscp_status&M_ST_MASK; 135926127Skarels /* 136026127Skarels * The controller interrupts as drive 0. 136126127Skarels * This means that you must check for controller interrupts 136226127Skarels * before you check to see if there is a drive 0. 136326127Skarels */ 136426127Skarels if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) 136526127Skarels { 136626127Skarels if (st == M_ST_SUCC) 136726127Skarels { 136826127Skarels # ifdef DEBUG 1369*26135Skarels printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf); 137026127Skarels printd("ctlr timeout = %d\n", mp->mscp_cnttmo); 137126127Skarels # endif 137226127Skarels sc->sc_state = S_RUN; 137326127Skarels } 137426127Skarels else 137526127Skarels sc->sc_state = S_IDLE; 137626127Skarels um->um_tab.b_active = 0; 137726127Skarels wakeup((caddr_t)um); 137826127Skarels return; 137926127Skarels } 1380*26135Skarels if (mp->mscp_unit >= NTMS) 138126127Skarels return; 138226127Skarels if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0) 138326127Skarels return; 1384*26135Skarels tms = &tms_info[ui->ui_unit]; 138526127Skarels /* 138626127Skarels * Save endcode, endflags, and status for mtioctl get unit status. 138726127Skarels * NOTE: Don't do this on Clear serious exception (reposition no-op); 138826127Skarels * which is done on close since this would 138926127Skarels * overwrite the real status we want. 139026127Skarels */ 1391*26135Skarels if (tms->tms_clserex != 1) 139226127Skarels { 1393*26135Skarels tms->tms_endcode = mp->mscp_opcode; 1394*26135Skarels tms->tms_flags = mp->mscp_flags; 1395*26135Skarels tms->tms_status = st; 139626127Skarels } 1397*26135Skarels else tms->tms_clserex = 0; 1398*26135Skarels 139926127Skarels switch (mp->mscp_opcode) { 140026127Skarels case M_OP_ONLIN|M_OP_END: 1401*26135Skarels tms->tms_type = mp->mscp_mediaid; 140226127Skarels dp = &tmsutab[ui->ui_unit]; 140326127Skarels if (st == M_ST_SUCC) 140426127Skarels { 140526127Skarels /* 140626127Skarels * Link the drive onto the controller queue 140726127Skarels */ 140826127Skarels dp->b_forw = NULL; 140926127Skarels if (um->um_tab.b_actf == NULL) 141026127Skarels um->um_tab.b_actf = dp; 141126127Skarels else 141226127Skarels um->um_tab.b_actl->b_forw = dp; 141326127Skarels um->um_tab.b_actl = dp; 141426127Skarels ui->ui_flags = 1; /* mark it online */ 1415*26135Skarels tms->tms_dsize=(daddr_t)mp->mscp_maxwrt; 141626127Skarels # ifdef DEBUG 141726127Skarels printd("tmscprsp: unit %d online\n", mp->mscp_unit); 141826127Skarels # endif 141926127Skarels /* 142026127Skarels * This define decodes the Media type identifier 142126127Skarels */ 1422*26135Skarels # define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') 142326127Skarels # ifdef DEBUG 142426127Skarels printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n" 142526127Skarels ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4) 142626127Skarels ,F_to_C(mp,3), F_to_C(mp,2) 1427*26135Skarels ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f); 142826127Skarels # endif 142926127Skarels dp->b_active = 1; 143026127Skarels } /* end if st == M_ST_SUCC */ 143126127Skarels else 143226127Skarels { 143326127Skarels if(dp->b_actf) 1434*26135Skarels tprintf(tms->tms_ttyp, 1435*26135Skarels "tms%d: hard error bn%d: OFFLINE\n", 1436*26135Skarels minor(bp->b_dev)&03, bp->b_blkno); 143726127Skarels else 1438*26135Skarels tprintf(tms->tms_ttyp, 1439*26135Skarels "tms%d: hard error: OFFLINE\n", 1440*26135Skarels minor(bp->b_dev)&03); 144126127Skarels while (bp = dp->b_actf) 144226127Skarels { 144326127Skarels dp->b_actf = bp->av_forw; 144426127Skarels bp->b_flags |= B_ERROR; 144526127Skarels iodone(bp); 144626127Skarels } 144726127Skarels } 144826127Skarels if(mp->mscp_cmdref!=NULL) 144926127Skarels /* Seems to get lost sometimes in uda */ 145026127Skarels wakeup((caddr_t *) mp->mscp_cmdref); 145126127Skarels break; 145226127Skarels /* 145326127Skarels * The AVAILABLE ATTENTION message occurs when the 145426127Skarels * unit becomes available after loading, 145526127Skarels * marking the unit offline (ui_flags = 0) will force an 145626127Skarels * online command prior to using the unit. 145726127Skarels */ 145826127Skarels case M_OP_AVATN: 145926127Skarels ui->ui_flags = 0; 1460*26135Skarels tms->tms_type = mp->mscp_mediaid; 146126127Skarels break; 146226127Skarels case M_OP_END: 146326127Skarels /* 146426127Skarels * An endcode without an opcode (0200) is an invalid command. 146526127Skarels * The mscp specification states that this would be a protocol 146626127Skarels * type error, such as illegal opcodes. The mscp spec. also 146726127Skarels * states that parameter error type of invalid commands should 1468*26135Skarels * return the normal end message for the command. This does not appear 1469*26135Skarels * to be the case. An invalid logical block number returned an endcode 147026127Skarels * of 0200 instead of the 0241 (read) that was expected. 147126127Skarels */ 147226127Skarels 147326127Skarels printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n", 147426127Skarels um->um_ctlr, mp->mscp_opcode, st); 147526127Skarels bp = (struct buf *)mp->mscp_cmdref; 147626127Skarels /* 147726127Skarels * Unlink buffer from I/O wait queue. 147826127Skarels * And signal iodone, so the higher level command can exit! 147926127Skarels * 148026127Skarels */ 148126127Skarels bp->av_back->av_forw = bp->av_forw; 148226127Skarels bp->av_forw->av_back = bp->av_back; 148326127Skarels dp = &tmsutab[ui->ui_unit]; 148426127Skarels dp->b_qsize--; 148526127Skarels iodone(bp); 148626127Skarels break; 148726127Skarels case M_OP_WRITE|M_OP_END: 148826127Skarels /* mark the last io op as a write */ 1489*26135Skarels tms->tms_lastiow = 1; 149026127Skarels case M_OP_READ|M_OP_END: 149126127Skarels case M_OP_WRITM|M_OP_END: 149226127Skarels case M_OP_REPOS|M_OP_END: 149326127Skarels case M_OP_STUNT|M_OP_END: 149426127Skarels /* 149526127Skarels * The AVAILABLE message occurs when the mt ioctl "rewoffl" is 149626127Skarels * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is 149726127Skarels * done with the UNLOAD modifier. This performs a rewind, followed 149826127Skarels * by marking the unit offline. So mark the unit offline 149926127Skarels * software wise as well (ui_flags = 0 and 1500*26135Skarels * tms->tms_openf = 0). 150126127Skarels */ 150226127Skarels case M_OP_AVAIL|M_OP_END: 150326127Skarels # ifdef DEBUG 150426127Skarels printd("tmscprsp: position = %d\n", mp->mscp_lbn); 150526127Skarels # endif 150626127Skarels bp = (struct buf *)mp->mscp_cmdref; 150726127Skarels /* 1508*26135Skarels * Only need to release buffer if the command was read or write. 150926127Skarels * No ubasetup was done in "tmscpstart" if it was an ioctl cmd. 151026127Skarels */ 151126127Skarels if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 151226127Skarels mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) 151326127Skarels ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); 151426127Skarels /* 151526127Skarels * Unlink buffer from I/O wait queue. 151626127Skarels */ 151726127Skarels bp->av_back->av_forw = bp->av_forw; 151826127Skarels bp->av_forw->av_back = bp->av_back; 1519*26135Skarels # if defined(VAX750) 1520*26135Skarels if (cpu == VAX_750) { 1521*26135Skarels if ((tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) && 152226127Skarels (um->um_ubinfo != 0)) { 152326127Skarels ubarelse(um->um_ubanum, &um->um_ubinfo); 152426127Skarels } 152526127Skarels else { 152626127Skarels if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 152726127Skarels mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) 1528*26135Skarels UBAPURGE(uba_hd[um->um_ubanum].uh_uba,(um->um_ubinfo >>28) & 0x0f); 152926127Skarels } 153026127Skarels } 153126127Skarels # endif 153226127Skarels dp = &tmsutab[ui->ui_unit]; 153326127Skarels dp->b_qsize--; 153426127Skarels if (st == M_ST_OFFLN || st == M_ST_AVLBL) 153526127Skarels { 153626127Skarels ui->ui_flags = 0; /* mark unit offline */ 1537*26135Skarels tms->tms_openf = 0; 1538*26135Skarels tms->tms_type = mp->mscp_mediaid; 153926127Skarels /* 154026127Skarels * Link the buffer onto the front of the drive queue 154126127Skarels */ 154226127Skarels if ((bp->av_forw = dp->b_actf) == 0) 154326127Skarels dp->b_actl = bp; 154426127Skarels dp->b_actf = bp; 154526127Skarels /* 154626127Skarels * Link the drive onto the controller queue 154726127Skarels */ 154826127Skarels if (dp->b_active == 0) 154926127Skarels { 155026127Skarels dp->b_forw = NULL; 155126127Skarels if (um->um_tab.b_actf == NULL) 155226127Skarels um->um_tab.b_actf = dp; 155326127Skarels else 155426127Skarels um->um_tab.b_actl->b_forw = dp; 155526127Skarels um->um_tab.b_actl = dp; 155626127Skarels dp->b_active = 1; 155726127Skarels } 1558*26135Skarels # if defined(VAX750) 1559*26135Skarels if (cpu == VAX_750 && um->um_ubinfo == 0) 1560*26135Skarels um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); 156126127Skarels # endif 156226127Skarels return; 156326127Skarels } 156426127Skarels if (st != M_ST_SUCC) 156526127Skarels { 156626127Skarels if (mp->mscp_flags & M_EF_SEREX) 1567*26135Skarels tms->tms_serex = 1; 156826127Skarels if (st != M_ST_TAPEM) 156926127Skarels { 1570*26135Skarels tprintf(tms->tms_ttyp, 1571*26135Skarels "tms%d: hard error bn%d\n", 1572*26135Skarels minor(bp->b_dev)&03, bp->b_blkno); 1573*26135Skarels errinfo(st); /* produces more info */ 157426127Skarels # ifdef DEBUG 1575*26135Skarels printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n", 1576*26135Skarels (mp->mscp_status & 177740)>>5, mp->mscp_flags); 157726127Skarels # endif 157826127Skarels bp->b_flags |= B_ERROR; 157926127Skarels } 158026127Skarels else 158126127Skarels /* Hit a tape mark - Set serex flag to 158226127Skarels * a special value so we can clear the 158326127Skarels * serious exception on the next command. 158426127Skarels */ 1585*26135Skarels tms->tms_serex = 2; 158626127Skarels } 158726127Skarels /* 158826127Skarels * The tmscp spec states that controllers do not have to 158926127Skarels * report the number of records or files skipped. So on 159026127Skarels * reposition commands we go strictly by cmd status. 159126127Skarels */ 159226127Skarels if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) 159326127Skarels bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; 159426127Skarels else 159526127Skarels bp->b_resid = 0; 1596*26135Skarels tms->tms_resid = bp->b_resid; 159726127Skarels iodone(bp); 159826127Skarels break; 1599*26135Skarels 160026127Skarels case M_OP_GTUNT|M_OP_END: 160126127Skarels # ifdef DEBUG 160226127Skarels printd("tmscprsp: GTUNT end packet status = 0%o\n",st); 1603*26135Skarels printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n" 160426127Skarels ,mp->mscp_unit, mp->mscp_mediaid 160526127Skarels ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) 160626127Skarels ,F_to_C(mp,1),F_to_C(mp,0) 160726127Skarels ,mp->mscp_mediaid & 0x7f 160826127Skarels ,mp->mscp_unitid.val[0] 160926127Skarels ,mp->mscp_unitid.val[1] 161026127Skarels ,mp->mscp_format); 161126127Skarels # endif 1612*26135Skarels tms->tms_type = mp->mscp_mediaid; 1613*26135Skarels tms->tms_fmtmenu = mp->mscp_fmtmenu; 1614*26135Skarels tms->tms_unitflgs = mp->mscp_unitflgs; 161526127Skarels break; 1616*26135Skarels 161726127Skarels default: 161826127Skarels printf("tmscp unknown packet\n"); 161926127Skarels tmserror(um, (struct mslg *)mp); 162026127Skarels } /* end switch mp->mscp_opcode */ 162126127Skarels } 1622*26135Skarels 1623*26135Skarels 162426127Skarels /* 162526127Skarels * Give a meaningful error when the mscp_status field returns an error code. 162626127Skarels */ 1627*26135Skarels 162826127Skarels errinfo(st) 162926127Skarels int st; /* the status code */ 163026127Skarels { 163126127Skarels switch(st) { 163226127Skarels case M_ST_ICMD: 163326127Skarels printf("invalid command\n"); 163426127Skarels break; 163526127Skarels case M_ST_ABRTD: 163626127Skarels printf("command aborted\n"); 163726127Skarels break; 163826127Skarels case M_ST_OFFLN: 163926127Skarels printf("unit offline\n"); 164026127Skarels break; 164126127Skarels case M_ST_WRTPR: 164226127Skarels printf("unit write protected\n"); 164326127Skarels break; 164426127Skarels case M_ST_COMP: 164526127Skarels printf("compare error\n"); 164626127Skarels break; 164726127Skarels case M_ST_DATA: 164826127Skarels printf("data error\n"); 164926127Skarels break; 165026127Skarels case M_ST_HSTBF: 165126127Skarels printf("host buffer access error\n"); 165226127Skarels break; 165326127Skarels case M_ST_CNTLR: 165426127Skarels printf("controller error\n"); 165526127Skarels break; 165626127Skarels case M_ST_DRIVE: 165726127Skarels printf("drive error\n"); 165826127Skarels break; 165926127Skarels case M_ST_FMTER: 166026127Skarels printf("formatter error\n"); 166126127Skarels break; 166226127Skarels case M_ST_BOT: 166326127Skarels printf("BOT encountered\n"); 166426127Skarels break; 166526127Skarels case M_ST_TAPEM: 166626127Skarels printf("tape mark encountered\n"); 166726127Skarels break; 166826127Skarels case M_ST_RDTRN: 166926127Skarels printf("record data truncated\n"); 167026127Skarels break; 167126127Skarels case M_ST_PLOST: 167226127Skarels printf("position lost\n"); 167326127Skarels break; 167426127Skarels case M_ST_SEX: 167526127Skarels printf("serious exception\n"); 167626127Skarels break; 167726127Skarels case M_ST_LED: 167826127Skarels printf("LEOT detected\n"); 167926127Skarels break; 168026127Skarels } 168126127Skarels } 1682*26135Skarels 1683*26135Skarels 168426127Skarels /* 168526127Skarels * Manage buffers and perform block mode read and write operations. 168626127Skarels */ 1687*26135Skarels 168826127Skarels tmscpstrategy (bp) 168926127Skarels register struct buf *bp; 169026127Skarels { 169126127Skarels register struct uba_device *ui; 169226127Skarels register struct uba_ctlr *um; 169326127Skarels register struct buf *dp; 169426127Skarels register int unit = TMSUNIT(bp->b_dev); 169526127Skarels int s; 1696*26135Skarels 1697*26135Skarels if (unit >= NTMS) 169826127Skarels { 169926127Skarels # ifdef DEBUG 170026127Skarels printd ("tmscpstrategy: bad unit # %d\n",unit); 170126127Skarels # endif 170226127Skarels bp->b_flags |= B_ERROR; 170326127Skarels iodone(bp); 170426127Skarels return; 170526127Skarels } 170626127Skarels ui = tmsdinfo[unit]; 170726127Skarels um = ui->ui_mi; 170826127Skarels if (ui == 0 || ui->ui_alive == 0) 170926127Skarels { 171026127Skarels bp->b_flags |= B_ERROR; 171126127Skarels iodone(bp); 171226127Skarels return; 171326127Skarels } 171426127Skarels s = spl5(); 171526127Skarels /* 171626127Skarels * Link the buffer onto the drive queue 171726127Skarels */ 171826127Skarels dp = &tmsutab[ui->ui_unit]; 171926127Skarels if (dp->b_actf == 0) 172026127Skarels dp->b_actf = bp; 172126127Skarels else 172226127Skarels dp->b_actl->av_forw = bp; 172326127Skarels dp->b_actl = bp; 172426127Skarels bp->av_forw = 0; 172526127Skarels /* 172626127Skarels * Link the drive onto the controller queue 172726127Skarels */ 172826127Skarels if (dp->b_active == 0) 172926127Skarels { 173026127Skarels dp->b_forw = NULL; 173126127Skarels if (um->um_tab.b_actf == NULL) 173226127Skarels um->um_tab.b_actf = dp; 173326127Skarels else 173426127Skarels um->um_tab.b_actl->b_forw = dp; 173526127Skarels um->um_tab.b_actl = dp; 173626127Skarels dp->b_active = 1; 173726127Skarels } 173826127Skarels /* 173926127Skarels * If the controller is not active, start it. 174026127Skarels */ 174126127Skarels if (um->um_tab.b_active == 0) 174226127Skarels { 1743*26135Skarels # if defined(VAX750) 1744*26135Skarels if (cpu == VAX_750 1745*26135Skarels && tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) 174626127Skarels { 174726127Skarels if (um->um_ubinfo != 0) 1748*26135Skarels log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n", 1749*26135Skarels um->um_ubinfo); 175026127Skarels else 1751*26135Skarels um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); 175226127Skarels } 175326127Skarels # endif 175426127Skarels # ifdef DEBUG 1755*26135Skarels printd10("tmscpstrategy: Controller not active, starting it\n"); 175626127Skarels # endif 175726127Skarels (void) tmscpstart(um); 175826127Skarels } 175926127Skarels splx(s); 176026127Skarels return; 176126127Skarels } 1762*26135Skarels 176326127Skarels #define DBSIZE 32 1764*26135Skarels 176526127Skarels #define ca_Rspdsc ca_rspdsc[0] 176626127Skarels #define ca_Cmddsc ca_rspdsc[1] 176726127Skarels #define tmscp_Rsp tmscp_rsp[0] 176826127Skarels #define tmscp_Cmd tmscp_cmd[0] 1769*26135Skarels 177026127Skarels struct tmscp tmscpd[NTMSCP]; 1771*26135Skarels 177226127Skarels tmscpdump(dev) 177326127Skarels dev_t dev; 177426127Skarels { 177526127Skarels struct tmscpdevice *tmscpaddr; 177626127Skarels struct tmscp *tmscp_ubaddr; 177726127Skarels char *start; 177826127Skarels int num, blk, unit; 177926127Skarels register struct uba_regs *uba; 178026127Skarels register struct uba_device *ui; 178126127Skarels register struct tmscp *tmscpp; 178226127Skarels register struct pte *io; 178326127Skarels register int i; 1784*26135Skarels 178526127Skarels unit = minor(dev) & 03; 1786*26135Skarels if (unit >= NTMS) 178726127Skarels return (ENXIO); 178826127Skarels # define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 178926127Skarels ui = phys(struct uba_device *, tmsdinfo[unit]); 179026127Skarels if (ui->ui_alive == 0) 179126127Skarels return (ENXIO); 179226127Skarels uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 1793*26135Skarels ubainit(uba); 179426127Skarels tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; 179526127Skarels DELAY(2000000); 179626127Skarels tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); 1797*26135Skarels 179826127Skarels num = btoc(sizeof(struct tmscp)) + 1; 179926127Skarels io = &uba->uba_map[NUBMREG-num]; 180026127Skarels for(i = 0; i<num; i++) 180126127Skarels *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); 1802*26135Skarels tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9)); 1803*26135Skarels 180426127Skarels tmscpaddr->tmscpip = 0; 180526127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 180626127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 180726127Skarels tmscpaddr->tmscpsa = TMSCP_ERR; 180826127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) 180926127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 181026127Skarels tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; 181126127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) 181226127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 1813*26135Skarels tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); 181426127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) 181526127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 181626127Skarels tmscpaddr->tmscpsa = TMSCP_GO; 1817*26135Skarels tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref; 1818*26135Skarels tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref; 181926127Skarels tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ 182026127Skarels tmscpp->tmscp_Cmd.mscp_cntflgs = 0; 182126127Skarels tmscpp->tmscp_Cmd.mscp_version = 0; 182226127Skarels if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { 182326127Skarels return(EFAULT); 182426127Skarels } 182526127Skarels tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; 182626127Skarels if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { 182726127Skarels return(EFAULT); 182826127Skarels } 1829*26135Skarels 183026127Skarels num = maxfree; 183126127Skarels start = 0; 183226127Skarels while (num > 0) 183326127Skarels { 183426127Skarels blk = num > DBSIZE ? DBSIZE : num; 183526127Skarels io = uba->uba_map; 183626127Skarels for (i = 0; i < blk; i++) 183726127Skarels *(int *)io++ = (btop(start)+i) | UBAMR_MRV; 183826127Skarels *(int *)io = 0; 183926127Skarels tmscpp->tmscp_Cmd.mscp_lbn = btop(start); 184026127Skarels tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; 184126127Skarels tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG; 184226127Skarels # ifdef MVAX 184326127Skarels if( cpu == MVAX_I ) 184426127Skarels tmscpp->tmscp_Cmd.mscp_buffer = (long) start; 184526127Skarels else 184626127Skarels # endif MVAX 184726127Skarels tmscpp->tmscp_Cmd.mscp_buffer = 0; 184826127Skarels if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) 184926127Skarels return(EIO); 185026127Skarels start += blk*NBPG; 185126127Skarels num -= blk; 185226127Skarels } 185326127Skarels return (0); 185426127Skarels } 1855*26135Skarels 1856*26135Skarels 185726127Skarels /* 185826127Skarels * Perform a standalone tmscp command. This routine is only used by tmscpdump. 185926127Skarels */ 1860*26135Skarels 186126127Skarels tmscpcmd(op, tmscpp, tmscpaddr) 186226127Skarels int op; 186326127Skarels register struct tmscp *tmscpp; 186426127Skarels struct tmscpdevice *tmscpaddr; 186526127Skarels { 186626127Skarels int i; 1867*26135Skarels 186826127Skarels # ifdef lint 186926127Skarels i = i; 187026127Skarels # endif 1871*26135Skarels 187226127Skarels tmscpp->tmscp_Cmd.mscp_opcode = op; 187326127Skarels tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; 187426127Skarels tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; 187526127Skarels tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; 187626127Skarels tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; 187726127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 187826127Skarels printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); 187926127Skarels i = tmscpaddr->tmscpip; 188026127Skarels for (;;) 188126127Skarels { 188226127Skarels if (tmscpp->tmscp_ca.ca_cmdint) 188326127Skarels tmscpp->tmscp_ca.ca_cmdint = 0; 188426127Skarels if (tmscpp->tmscp_ca.ca_rspint) 188526127Skarels break; 188626127Skarels } 188726127Skarels tmscpp->tmscp_ca.ca_rspint = 0; 188826127Skarels if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || 188926127Skarels (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) 189026127Skarels { 189126127Skarels printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, 1892*26135Skarels tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status); 189326127Skarels return(0); 189426127Skarels } 189526127Skarels return(1); 189626127Skarels } 1897*26135Skarels 1898*26135Skarels 189926127Skarels /* 190026127Skarels * Perform raw read 190126127Skarels */ 1902*26135Skarels 190326127Skarels tmscpread(dev, uio) 190426127Skarels dev_t dev; 190526127Skarels struct uio *uio; 190626127Skarels { 190726127Skarels register int unit = TMSUNIT(dev); 1908*26135Skarels 1909*26135Skarels if (unit >= NTMS) 191026127Skarels return (ENXIO); 1911*26135Skarels return (physio(tmscpstrategy, &rtmsbuf[unit], dev, B_READ, minphys, uio)); 191226127Skarels } 1913*26135Skarels 1914*26135Skarels 191526127Skarels /* 191626127Skarels * Perform raw write 191726127Skarels */ 1918*26135Skarels 191926127Skarels tmscpwrite(dev, uio) 192026127Skarels dev_t dev; 192126127Skarels struct uio *uio; 192226127Skarels { 192326127Skarels register int unit = TMSUNIT(dev); 1924*26135Skarels 1925*26135Skarels if (unit >= NTMS) 192626127Skarels return (ENXIO); 1927*26135Skarels return (physio(tmscpstrategy, &rtmsbuf[unit], dev, B_WRITE, minphys, uio)); 192826127Skarels } 1929*26135Skarels 1930*26135Skarels 193126127Skarels /* 193226127Skarels * Catch ioctl commands, and call the "command" routine to do them. 193326127Skarels */ 1934*26135Skarels 193526127Skarels tmscpioctl(dev, cmd, data, flag) 193626127Skarels dev_t dev; 193726127Skarels int cmd; 193826127Skarels caddr_t data; 193926127Skarels int flag; 194026127Skarels { 194126127Skarels register struct tmscp_softc *sc = &tmscp_softc[TMSCPCTLR(dev)]; 194226127Skarels register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; 194326127Skarels register callcount; /* number of times to call cmd routine */ 194426127Skarels register struct uba_device *ui; 1945*26135Skarels register struct tms_info *tms; 194626127Skarels int fcount; /* number of files (or records) to space */ 194726127Skarels struct mtop *mtop; /* mag tape cmd op to perform */ 194826127Skarels struct mtget *mtget; /* mag tape struct to get info in */ 1949*26135Skarels 195026127Skarels /* we depend of the values and order of the TMS ioctl codes here */ 195126127Skarels static tmsops[] = 195226127Skarels {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, 195326127Skarels TMS_CACHE,TMS_NOCACHE}; 1954*26135Skarels 195526127Skarels switch (cmd) { 195626127Skarels case MTIOCTOP: /* tape operation */ 195726127Skarels mtop = (struct mtop *)data; 195826127Skarels switch (mtop->mt_op) { 1959*26135Skarels 196026127Skarels case MTWEOF: 196126127Skarels callcount = mtop->mt_count; 196226127Skarels fcount = 1; 196326127Skarels break; 196426127Skarels case MTFSF: case MTBSF: 196526127Skarels case MTFSR: case MTBSR: 196626127Skarels callcount = 1; 196726127Skarels fcount = mtop->mt_count; 196826127Skarels break; 196926127Skarels case MTREW: case MTOFFL: case MTNOP: 197026127Skarels case MTCACHE: case MTNOCACHE: 197126127Skarels callcount = 1; 197226127Skarels fcount = 1; /* wait for this rewind */ 197326127Skarels break; 197426127Skarels default: 197526127Skarels return (ENXIO); 197626127Skarels } /* end switch mtop->mt_op */ 1977*26135Skarels 197826127Skarels if (callcount <= 0 || fcount <= 0) 197926127Skarels return (EINVAL); 198026127Skarels while (--callcount >= 0) 198126127Skarels { 198226127Skarels tmscpcommand(dev, tmsops[mtop->mt_op], fcount); 198326127Skarels if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 198426127Skarels bp->b_resid) 198526127Skarels return (EIO); 198626127Skarels if (bp->b_flags & B_ERROR) /* like hitting BOT */ 198726127Skarels break; 198826127Skarels } 198926127Skarels return (geterror(bp)); 1990*26135Skarels 199126127Skarels case MTIOCGET: 199226127Skarels /* 199326127Skarels * Return status info associated with the particular UNIT. 199426127Skarels */ 199526127Skarels ui = tmsdinfo[TMSUNIT(dev)]; 1996*26135Skarels tms = &tms_info[ui->ui_unit]; 199726127Skarels mtget = (struct mtget *)data; 199826127Skarels mtget->mt_type = MT_ISTMSCP; 1999*26135Skarels mtget->mt_dsreg = tms->tms_flags << 8; 2000*26135Skarels mtget->mt_dsreg |= tms->tms_endcode; 2001*26135Skarels mtget->mt_erreg = tms->tms_status; 2002*26135Skarels mtget->mt_resid = tms->tms_resid; 200326127Skarels break; 2004*26135Skarels 200526127Skarels default: 200626127Skarels return (ENXIO); 200726127Skarels } 200826127Skarels return (0); 200926127Skarels } 2010*26135Skarels 2011*26135Skarels 201226127Skarels /* 201326127Skarels * Reset (for raw mode use only). 201426127Skarels */ 2015*26135Skarels 201626127Skarels tmscpreset (uban) 201726127Skarels int uban; 201826127Skarels { 201926127Skarels register struct uba_ctlr *um; 202026127Skarels register struct uba_device *ui; 202126127Skarels register struct buf *bp, *dp; 202226127Skarels register int unit; 202326127Skarels struct buf *nbp; 202426127Skarels int d; 2025*26135Skarels 202626127Skarels for (d = 0; d < NTMSCP; d++) 202726127Skarels { 202826127Skarels if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || 202926127Skarels um->um_alive == 0) 203026127Skarels continue; 203126127Skarels printf(" tmscp%d", d); 203226127Skarels um->um_tab.b_active = 0; 203326127Skarels um->um_tab.b_actf = um->um_tab.b_actl = 0; 203426127Skarels tmscp_softc[d].sc_state = S_IDLE; 203526127Skarels tmscp_softc[d].sc_mapped = 0; 2036*26135Skarels for (unit = 0; unit < NTMS; unit++) 203726127Skarels { 203826127Skarels if ((ui = tmsdinfo[unit]) == 0) 203926127Skarels continue; 204026127Skarels if (ui->ui_alive == 0 || ui->ui_mi != um) 204126127Skarels continue; 204226127Skarels tmsutab[unit].b_active = 0; 204326127Skarels tmsutab[unit].b_qsize = 0; 204426127Skarels } 204526127Skarels for (bp = tmscpwtab[d].av_forw; bp != &tmscpwtab[d]; bp = nbp) 204626127Skarels { 204726127Skarels nbp = bp->av_forw; 204826127Skarels bp->b_ubinfo = 0; 204926127Skarels /* 205026127Skarels * Link the buffer onto the drive queue 205126127Skarels */ 205226127Skarels dp = &tmsutab[TMSUNIT(bp->b_dev)]; 205326127Skarels if (dp->b_actf == 0) 205426127Skarels dp->b_actf = bp; 205526127Skarels else 205626127Skarels dp->b_actl->av_forw = bp; 205726127Skarels dp->b_actl = bp; 205826127Skarels bp->av_forw = 0; 205926127Skarels /* 206026127Skarels * Link the drive onto the controller queue 206126127Skarels */ 206226127Skarels if (dp->b_active == 0) 206326127Skarels { 206426127Skarels dp->b_forw = NULL; 206526127Skarels if (um->um_tab.b_actf == NULL) 206626127Skarels um->um_tab.b_actf = dp; 206726127Skarels else 206826127Skarels um->um_tab.b_actl->b_forw = dp; 206926127Skarels um->um_tab.b_actl = dp; 207026127Skarels dp->b_active = 1; 207126127Skarels } 207226127Skarels } 207326127Skarels tmscpinit(d); 207426127Skarels } 207526127Skarels } 2076*26135Skarels 2077*26135Skarels 207826127Skarels /* 207926127Skarels * Process an error log message 208026127Skarels * 208126127Skarels * Only minimal decoding is done, only "useful" 208226127Skarels * information is printed. Eventually should 208326127Skarels * send message to an error logger. 208426127Skarels */ 2085*26135Skarels 208626127Skarels tmserror(um, mp) 208726127Skarels register struct uba_ctlr *um; 208826127Skarels register struct mslg *mp; 208926127Skarels { 209026127Skarels register i; 2091*26135Skarels 209226127Skarels # ifdef DEBUG 209326127Skarels printd("tmserror:\n"); 209426127Skarels # endif 209526127Skarels if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) 2096*26135Skarels log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr, 209726127Skarels mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); 2098*26135Skarels 209926127Skarels switch (mp->mslg_format) { 2100*26135Skarels 210126127Skarels case M_FM_CNTERR: 2102*26135Skarels log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event); 210326127Skarels break; 210426127Skarels case M_FM_BUSADDR: 2105*26135Skarels log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", 210626127Skarels mp->mslg_event, mp->mslg_busaddr); 210726127Skarels break; 210826127Skarels case M_FM_TAPETRN: 2109*26135Skarels log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", 211026127Skarels mp->mslg_unit, mp->mslg_group, mp->mslg_event); 211126127Skarels break; 211226127Skarels case M_FM_STIERR: 2113*26135Skarels log(TMS_PRI, "STI error, unit %d, event 0%o\n", 211426127Skarels mp->mslg_unit, mp->mslg_event); 2115*26135Skarels #ifdef notdef 2116*26135Skarels /* too painful to do with log() */ 211726127Skarels for(i = 0; i < 62;i++) 211826127Skarels mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); 211926127Skarels mprintf("\n"); 2120*26135Skarels #endif 212126127Skarels break; 212226127Skarels case M_FM_STIDEL: 2123*26135Skarels log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n", 212426127Skarels mp->mslg_unit, mp->mslg_event); 212526127Skarels break; 212626127Skarels case M_FM_STIFEL: 2127*26135Skarels log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n", 212826127Skarels mp->mslg_unit, mp->mslg_event); 212926127Skarels break; 213026127Skarels default: 2131*26135Skarels log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n", 213226127Skarels mp->mslg_unit, mp->mslg_format, mp->mslg_event); 213326127Skarels } 2134*26135Skarels 213526127Skarels if (tmscperror) 213626127Skarels { 213726127Skarels register long *p = (long *)mp; 2138*26135Skarels 213926127Skarels for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) 214026127Skarels printf("%x ", *p++); 214126127Skarels printf("\n"); 214226127Skarels } 214326127Skarels } 214426127Skarels #endif 2145