1*30917Skarels /* @(#)tmscp.c 7.2 (Berkeley) 04/17/87 */ 226135Skarels 326127Skarels #ifndef lint 426127Skarels static char *sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; 526127Skarels #endif lint 626127Skarels 726135Skarels 826127Skarels /************************************************************************ 926127Skarels * * 1027468Skjd * Licensed from Digital Equipment Corporation * 1127468Skjd * Copyright (c) * 1227468Skjd * Digital Equipment Corporation * 1327468Skjd * Maynard, Massachusetts * 1427468Skjd * 1985, 1986 * 1527468Skjd * All rights reserved. * 1626127Skarels * * 1727468Skjd * The Information in this software is subject to change * 1827468Skjd * without notice and should not be construed as a commitment * 1927468Skjd * by Digital Equipment Corporation. Digital makes no * 2027468Skjd * representations about the suitability of this software for * 2127468Skjd * any purpose. It is supplied "As Is" without expressed or * 2227468Skjd * implied warranty. * 2326127Skarels * * 2427468Skjd * If the Regents of the University of California or its * 2527468Skjd * licensees modify the software in a manner creating * 2627468Skjd * diriviative copyright rights, appropriate copyright * 2727468Skjd * legends may be placed on the drivative work in addition * 2827468Skjd * to that set forth above. * 2926127Skarels * * 3026127Skarels ************************************************************************ 3126127Skarels * 3226127Skarels * tmscp.c - TMSCP (TK50/TU81) tape device driver 3326127Skarels * 3426127Skarels * Modification History: 3526127Skarels * 3626127Skarels * 06-Jan-86 - afd 3726127Skarels * Changed the probe routine to use DELAY (not TODR). This now 3826127Skarels * works for MicroVAXen as well. This eliminates the busy-wait 3926127Skarels * for MicroVAXen so a dead TK50 controller will not hang autoconf. 4026127Skarels * 4126127Skarels * 06-Dec-85 - afd 4226127Skarels * Fixed a bug in density selection. The "set unit characteristics" 4326127Skarels * command to select density, was clearing the "unit flags" field 4426127Skarels * where the CACHE bit was for TU81-E. Now the unit's "format" and 4526127Skarels * "unitflgs" are saved in tms_info struct. And are used on STUNT 4626127Skarels * commands. 4726127Skarels * 4826127Skarels * 19-Oct-85 - afd 4926127Skarels * Added support to the open routine to allow drives to be opened 5026127Skarels * for low density (800 or 1600 bpi) use. When the slave routine 5126127Skarels * initiates a "get-unit-char" cmd, the format menu for the unit 5226127Skarels * is saved in the tms_info structure. The format menu is used in the 5326127Skarels * start routine to select the proper low density. 5426127Skarels * 5526127Skarels * 02-Oct-85 - afd 5626127Skarels * When a tmscp-type controller is initializing, it is possible for 5726127Skarels * the sa reg to become 0 between states. Thus the init code in 5826127Skarels * the interrupt routine had to be modified to reflect this. 5926127Skarels * 6026127Skarels * 21-Sep-85 - afd 6126127Skarels * The TK50 declares a serious exception when a tape mark is encountered. 6226127Skarels * This causes problems to dd (& other UN*X utilities). So a flag 6326127Skarels * is set in the rsp() routine when a tape mark is encountered. If 6426127Skarels * this flag is set, the start() routine appends the Clear Serious 6526127Skarels * Exception modifier to the next command. 6626127Skarels * 6726127Skarels * 03-Sep-85 -- jaw 6826127Skarels * messed up previous edit.. 6926127Skarels * 7026127Skarels * 29-Aug-85 - jaw 7126127Skarels * fixed bugs in 8200 and 750 buffered datapath handling. 7226127Skarels * 7326127Skarels * 06-Aug-85 - afd 7426127Skarels * 1. When repositioning records or files, the count of items skipped 7526127Skarels * does NOT HAVE to be returned by controllers (& the TU81 doesn't). 7626127Skarels * So tmscprsp() had to be modified to stop reporting 7726127Skarels * residual count errors on reposition commands. 7826127Skarels * 7926127Skarels * 2. Fixed bug in the open routine which allowed multiple opens. 8026127Skarels * 8126127Skarels * 18-Jul-85 - afd 8226127Skarels * 1. Need to return status when mt status (or corresponding ioctl) is done. 8326127Skarels * Save resid, flags, endcode & status in tmscprsp() routine (except on 8426127Skarels * clear serious exception no-op). Return these fields when status 8526127Skarels * ioctl is done (in tmscpcommand()). How they are returned: 8626127Skarels * mt_resid = resid 8726127Skarels * mt_dsreg = flags|endcode 8826127Skarels * mt_erreg = status 8926127Skarels * 9026127Skarels * 2. Added latent support for enabling/disabling caching. This is 9126127Skarels * handled along with all other ioctl commands. 9226127Skarels * 9326127Skarels * 3. Need to issue a no-op on unrecognized ioctl in tmscpstart(), since 9426127Skarels * we have already commited to issuing a command at that point. 9526127Skarels * 9626127Skarels * 4. In tmscprsp() routine if encode is 0200 (invalid command issued); 9726127Skarels * We need to: Unlink the buffer from the I/O wait queue, 9826127Skarels * and signal iodone, so the higher level command can exit! 9926127Skarels * Just as if it were a valid command. 10026127Skarels * 10126127Skarels * 11-jul-85 -- jaw 10226127Skarels * fix bua/bda map registers. 10326127Skarels * 10426127Skarels * 19-Jun-85 -- jaw 10526127Skarels * VAX8200 name change. 10626127Skarels * 10726127Skarels * 06-Jun-85 - jaw 10826127Skarels * fixes for 8200. 10926127Skarels * 11026127Skarels * 9-Apr-85 - afd 11126127Skarels * Added timeout code to the probe routine, so if the controller 11226127Skarels * fails to init in 10 seconds we return failed status. 11326127Skarels * 11426127Skarels * 13-Mar-85 -jaw 11526127Skarels * Changes for support of the VAX8200 were merged in. 11626127Skarels * 11726127Skarels * 27-Feb-85 -tresvik 11826127Skarels * Changes for support of the VAX8600 were merged in. 11926127Skarels * 12026127Skarels */ 12126135Skarels 12226127Skarels #include "tms.h" 12326135Skarels #if NTMSCP > 0 12426135Skarels 12526135Skarels #include "param.h" 12626135Skarels #include "systm.h" 12726135Skarels #include "buf.h" 12826135Skarels #include "conf.h" 12926135Skarels #include "dir.h" 13026135Skarels #include "user.h" 13126135Skarels #include "file.h" 13226135Skarels #include "map.h" 13326135Skarels #include "vm.h" 13426135Skarels #include "ioctl.h" 13526135Skarels #include "syslog.h" 13626135Skarels #include "mtio.h" 13726135Skarels #include "cmap.h" 13826135Skarels #include "uio.h" 13926838Skarels #include "tty.h" 14026135Skarels 141*30917Skarels #include "../vax/pte.h" 14226135Skarels #include "../vax/cpu.h" 14326135Skarels #include "../vax/mtpr.h" 14426135Skarels #include "ubareg.h" 14526135Skarels #include "ubavar.h" 14626135Skarels 14726135Skarels #define TENSEC (1000) 14826135Skarels #define TMS_PRI LOG_INFO 14926135Skarels 15026135Skarels #define NRSPL2 3 /* log2 number of response packets */ 15126135Skarels #define NCMDL2 3 /* log2 number of command packets */ 15226135Skarels #define NRSP (1<<NRSPL2) 15326135Skarels #define NCMD (1<<NCMDL2) 15426135Skarels 15526135Skarels #include "tmscpreg.h" 15626135Skarels #include "../vax/tmscp.h" 15726135Skarels 15826135Skarels /* Software state per controller */ 15926135Skarels 16026135Skarels struct tmscp_softc { 16126135Skarels short sc_state; /* state of controller */ 16226135Skarels short sc_mapped; /* Unibus map allocated for tmscp struct? */ 16326135Skarels int sc_ubainfo; /* Unibus mapping info */ 16426135Skarels struct tmscp *sc_tmscp; /* Unibus address of tmscp struct */ 16526135Skarels int sc_ivec; /* interrupt vector address */ 16626135Skarels short sc_credits; /* transfer credits */ 16726135Skarels short sc_lastcmd; /* pointer into command ring */ 16826135Skarels short sc_lastrsp; /* pointer into response ring */ 16926135Skarels } tmscp_softc[NTMSCP]; 17026135Skarels 17126135Skarels struct tmscp { 17226135Skarels struct tmscpca tmscp_ca; /* communications area */ 17326135Skarels struct mscp tmscp_rsp[NRSP]; /* response packets */ 17426135Skarels struct mscp tmscp_cmd[NCMD]; /* command packets */ 17526135Skarels } tmscp[NTMSCP]; 17626135Skarels 17726135Skarels /* 17826135Skarels * Per drive-unit info 17926135Skarels */ 18026135Skarels struct tms_info { 18126135Skarels daddr_t tms_dsize; /* Max user size from online pkt */ 18226135Skarels unsigned tms_type; /* Drive type int field */ 18326135Skarels int tms_resid; /* residual from last xfer */ 18426135Skarels u_char tms_endcode; /* last command endcode */ 18526135Skarels u_char tms_flags; /* last command end flags */ 18626135Skarels unsigned tms_status; /* Command status from last command */ 18726135Skarels char tms_openf; /* lock against multiple opens */ 18826135Skarels char tms_lastiow; /* last op was a write */ 18926135Skarels char tms_serex; /* set when serious exception occurs */ 19026135Skarels char tms_clserex; /* set when serex being cleared by no-op */ 19126135Skarels short tms_fmtmenu; /* the unit's format (density) menu */ 19226135Skarels short tms_unitflgs; /* unit flag parameters */ 19326135Skarels short tms_format; /* the unit's current format (density) */ 19426135Skarels struct tty *tms_ttyp; /* record user's tty for errors */ 19526135Skarels } tms_info[NTMS]; 19626135Skarels struct uba_ctlr *tmscpminfo[NTMSCP]; 19726135Skarels struct uba_device *tmsdinfo[NTMS]; 19826135Skarels /* 19926135Skarels * ifdef other tmscp devices here if they allow more than 1 unit/controller 20026135Skarels */ 20126135Skarels struct uba_device *tmscpip[NTMSCP][1]; 20226135Skarels struct buf rtmsbuf[NTMS]; /* raw i/o buffer */ 20326135Skarels struct buf ctmscpbuf[NTMSCP]; /* internal cmd buffer (for ioctls) */ 20426135Skarels struct buf tmsutab[NTMS]; /* Drive queue */ 20526135Skarels struct buf tmscpwtab[NTMSCP]; /* I/O wait queue, per controller */ 20626135Skarels int tmscpmicro[NTMSCP]; /* to store microcode level */ 20726135Skarels short utoctlr[NTMS]; /* Slave unit to controller mapping */ 20826135Skarels /* filled in by the slave routine */ 20926135Skarels 21026127Skarels /* Bits in minor device */ 21126127Skarels #define TMSUNIT(dev) (minor(dev)&03) 21226127Skarels #define T_NOREWIND 04 21326127Skarels #define T_HIDENSITY 010 21426135Skarels 21526127Skarels /* Slave unit to controller mapping */ 21626127Skarels #define TMSCPCTLR(dev) (utoctlr[TMSUNIT(dev)]) 21726135Skarels 21826127Skarels /* 21926127Skarels * Internal (ioctl) command codes (these must also be declared in the 22026127Skarels * tmscpioctl routine). These correspond to ioctls in mtio.h 22126127Skarels */ 22226127Skarels #define TMS_WRITM 0 /* write tape mark */ 22326127Skarels #define TMS_FSF 1 /* forward space file */ 22426127Skarels #define TMS_BSF 2 /* backward space file */ 22526127Skarels #define TMS_FSR 3 /* forward space record */ 22626127Skarels #define TMS_BSR 4 /* backward space record */ 22726127Skarels #define TMS_REW 5 /* rewind tape */ 22826127Skarels #define TMS_OFFL 6 /* rewind tape & mark unit offline */ 22926127Skarels #define TMS_SENSE 7 /* noop - do a get unit status */ 23026127Skarels #define TMS_CACHE 8 /* enable cache */ 23126127Skarels #define TMS_NOCACHE 9 /* disable cache */ 23226127Skarels /* These go last: after all real mt cmds, just bump the numbers up */ 23326127Skarels #define TMS_CSE 10 /* clear serious exception */ 23426127Skarels #define TMS_LOWDENSITY 11 /* set unit to low density */ 23526127Skarels #define TMS_HIDENSITY 12 /* set unit to high density */ 23626135Skarels 23726127Skarels /* 23826127Skarels * Controller states 23926127Skarels */ 24026127Skarels #define S_IDLE 0 /* hasn't been initialized */ 24126127Skarels #define S_STEP1 1 /* doing step 1 init */ 24226127Skarels #define S_STEP2 2 /* doing step 2 init */ 24326127Skarels #define S_STEP3 3 /* doing step 3 init */ 24426127Skarels #define S_SCHAR 4 /* doing "set controller characteristics" */ 24526127Skarels #define S_RUN 5 /* running */ 24626135Skarels 24726127Skarels int tmscperror = 0; /* causes hex dump of packets */ 24826127Skarels int tmscp_cp_wait = 0; /* Something to wait on for command */ 24926127Skarels /* packets and or credits. */ 25026127Skarels int wakeup(); 25126127Skarels extern int hz; /* Should find the right include */ 25226135Skarels 25326127Skarels #ifdef DEBUG 25426127Skarels #define printd if (tmscpdebug) printf 25526127Skarels int tmscpdebug = 1; 25626127Skarels #define printd10 if(tmscpdebug >= 10) printf 25726127Skarels #endif 25826135Skarels 25926127Skarels int tmscpprobe(), tmscpslave(), tmscpattach(), tmscpintr(); 26026127Skarels struct mscp *tmscpgetcp(); 26126135Skarels 26226127Skarels #define DRVNAME "tms" 26326127Skarels #define CTRLNAME "tmscp" 26426135Skarels 26526127Skarels u_short tmscpstd[] = { 0174500, 0 }; 26626127Skarels struct uba_driver tmscpdriver = 26726127Skarels { tmscpprobe, tmscpslave, tmscpattach, 0, tmscpstd, DRVNAME, tmsdinfo, CTRLNAME 26826127Skarels , tmscpminfo, 0}; 26926135Skarels 27026127Skarels #define b_qsize b_resid /* queue size per drive, in tmsutab */ 27126127Skarels #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ 27226135Skarels 27326135Skarels 27426127Skarels /*************************************************************************/ 27526135Skarels 27626127Skarels #define DELAYTEN 1000 27726135Skarels 27826127Skarels tmscpprobe(reg, ctlr) 27926127Skarels caddr_t reg; /* address of the IP register */ 28026135Skarels int ctlr; /* index of controller in the tmscp_softc array */ 28126127Skarels { 28226127Skarels register int br, cvec; /* MUST be 1st (r11 & r10): IPL and intr vec */ 28326127Skarels register struct tmscp_softc *sc = &tmscp_softc[ctlr]; 28426127Skarels /* ptr to software controller structure */ 28526135Skarels struct tmscpdevice *tmscpaddr; /* ptr to tmscpdevice struct (IP & SA) */ 28626127Skarels int count; /* for probe delay time out */ 28726135Skarels 28826127Skarels # ifdef lint 28926127Skarels br = 0; cvec = br; br = cvec; reg = reg; 29026127Skarels tmscpreset(0); tmscpintr(0); 29126127Skarels # endif 29226135Skarels 29326127Skarels tmscpaddr = (struct tmscpdevice *) reg; 29426127Skarels /* 29526127Skarels * Set host-settable interrupt vector. 29626135Skarels * Assign 0 to the ip register to start the tmscp-device initialization. 29726127Skarels * The device is not really initialized at this point, this is just to 29826127Skarels * find out if the device exists. 29926127Skarels */ 30026127Skarels sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 30126127Skarels tmscpaddr->tmscpip = 0; 30226135Skarels 30326127Skarels count=0; 30426127Skarels while(count < DELAYTEN) 30526127Skarels { /* wait for at most 10 secs */ 30626127Skarels if((tmscpaddr->tmscpsa & TMSCP_STEP1) != 0) 30726127Skarels break; 30826127Skarels DELAY(10000); 30926127Skarels count=count+1; 31026127Skarels } 31126127Skarels if (count == DELAYTEN) 31226127Skarels return(0); 31326135Skarels 31426135Skarels tmscpaddr->tmscpsa = TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); 31526135Skarels 31626127Skarels count=0; 31726127Skarels while(count < DELAYTEN) 31826127Skarels { 31926135Skarels if((tmscpaddr->tmscpsa & TMSCP_STEP2) != 0) 32026127Skarels break; 32126127Skarels DELAY(10000); 32226127Skarels count = count+1; 32326127Skarels } 32426127Skarels if (count == DELAYTEN) 32526127Skarels return(0); 32626135Skarels 32726127Skarels return(sizeof (struct tmscpdevice)); 32826127Skarels } 32926135Skarels 33026127Skarels /* 33126127Skarels * Try to find a slave (a drive) on the controller. 33226127Skarels * If the controller is not in the run state, call init to initialize it. 33326127Skarels */ 33426127Skarels tmscpslave (ui, reg) 33526127Skarels struct uba_device *ui; /* ptr to the uba device structure */ 33626127Skarels caddr_t reg; /* addr of the device controller */ 33726127Skarels { 33826127Skarels register struct uba_ctlr *um = tmscpminfo[ui->ui_ctlr]; 33926127Skarels register struct tmscp_softc *sc = &tmscp_softc[ui->ui_ctlr]; 34026135Skarels register struct tms_info *tms = &tms_info[ui->ui_unit]; 34126127Skarels struct tmscpdevice *tmscpaddr; /* ptr to IP & SA */ 34226127Skarels struct mscp *mp; 34326127Skarels int i; /* Something to write into to start */ 34426127Skarels /* the tmscp polling */ 34526135Skarels 34626127Skarels # ifdef lint 34726293Skarels reg = reg; 34826127Skarels # endif 34926127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 35026127Skarels /* 35126127Skarels * If its not in the run state, start the initialization process 35226127Skarels * (tmscpintr will complete it); if the initialization doesn't start; 35326127Skarels * then return. 35426127Skarels */ 35526127Skarels if(sc->sc_state != S_RUN) 35626127Skarels { 35726127Skarels # ifdef DEBUG 35826127Skarels printd("tmscpslave: ctlr not running: calling init \n"); 35926127Skarels # endif 36026127Skarels if(!tmscpinit(ui->ui_ctlr)) 36126127Skarels return(0); 36226127Skarels } 36326127Skarels /* 36426127Skarels * Wait for the controller to come into the run state or go idle. 36526127Skarels * If it goes idle return. 36626127Skarels */ 36726127Skarels # ifdef DEBUG 36826127Skarels i=1; 36926127Skarels # endif 37026127Skarels while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE) 37126127Skarels # ifdef DEBUG 37226127Skarels if (tmscpaddr->tmscpsa & TMSCP_ERR && i) 37326127Skarels { 37426135Skarels printd("tmscp-device: fatal error (%o)\n", tmscpaddr->tmscpsa&0xffff); 37526127Skarels i=0; 37626127Skarels } 37726127Skarels # endif 37826127Skarels ; /* wait */ 37926127Skarels if(sc->sc_state == S_IDLE) 38026127Skarels { /* The tmscp device failed to initialize */ 38126127Skarels printf("tmscp controller failed to init\n"); 38226127Skarels return(0); 38326127Skarels } 38426127Skarels /* The controller is up so see if the drive is there */ 38526127Skarels if(0 == (mp = tmscpgetcp(um))) 38626127Skarels { 38726127Skarels printf("tmscp can't get command packet\n"); 38826127Skarels return(0); 38926127Skarels } 39026127Skarels /* Need to determine the drive type for generic driver */ 39126135Skarels mp->mscp_opcode = M_OP_GTUNT; /* This should give us the device type */ 39226127Skarels mp->mscp_unit = ui->ui_slave; 39326127Skarels mp->mscp_cmdref = (long) ui->ui_slave; 39426135Skarels tms->tms_status = 0; /* set to zero */ 39526127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; 39626135Skarels *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT;/* maybe we should poll*/ 39726127Skarels i = tmscpaddr->tmscpip; 39826293Skarels #ifdef lint 39926293Skarels i = i; 40026293Skarels #endif 40126135Skarels while(!tms->tms_status) 40226127Skarels ; /* Wait for some status */ 40326127Skarels # ifdef DEBUG 40426135Skarels printd("tmscpslave: status = %o\n",tms->tms_status & M_ST_MASK); 40526135Skarels # endif 40626127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = 0; 40726135Skarels if(!tms->tms_type) /* packet from a GTUNT */ 40826127Skarels return(0); /* Failed No such drive */ 40926127Skarels else 41026127Skarels return(1); /* Got it and it is there */ 41126127Skarels } 41226135Skarels 41326135Skarels 41426127Skarels /* 41526127Skarels * Set ui flags to zero to show device is not online & set tmscpip. 41626127Skarels * Unit to Controller mapping is set up here. 41726127Skarels * Open routine will issue the online command, later. 41826127Skarels */ 41926127Skarels tmscpattach (ui) 42026127Skarels register struct uba_device *ui; /* ptr to unibus dev struct */ 42126127Skarels { 42226135Skarels 42326127Skarels ui->ui_flags = 0; 42426127Skarels tmscpip[ui->ui_ctlr][ui->ui_slave] = ui; 42526127Skarels # ifdef DEBUG 42626127Skarels /* 42726127Skarels * Check to see if the drive is available. 42826127Skarels * If not then just print debug. 42926127Skarels */ 43026127Skarels if(tms_info[ui->ui_unit].tms_status != M_ST_AVLBL) 43126127Skarels printd("tmscpattach: unavailable \n"); 43226127Skarels # endif 43326127Skarels utoctlr[ui->ui_unit] = ui->ui_ctlr; 43426127Skarels } 43526135Skarels 43626135Skarels 43726127Skarels /* 43826127Skarels * TMSCP interrupt routine. 43926127Skarels */ 44026127Skarels tmscpintr (d) 44126127Skarels int d; /* index to the controller */ 44226127Skarels { 44326127Skarels register struct uba_ctlr *um = tmscpminfo[d]; 44426135Skarels register struct tmscpdevice *tmscpaddr = (struct tmscpdevice *)um->um_addr; 44526127Skarels struct buf *bp; 44626127Skarels register int i; 44726127Skarels register struct tmscp_softc *sc = &tmscp_softc[d]; 44826127Skarels register struct tmscp *tm = &tmscp[d]; 44926127Skarels struct tmscp *ttm; 45026127Skarels struct mscp *mp; 45126135Skarels 45226127Skarels # ifdef DEBUG 45326135Skarels printd10("tmscpintr: state %d, tmscpsa %o\n", sc->sc_state, tmscpaddr->tmscpsa); 45426127Skarels # endif 45526135Skarels 45626127Skarels /* 45726127Skarels * How the interrupt is handled depends on the state of the controller. 45826127Skarels */ 45926127Skarels switch (sc->sc_state) { 46026135Skarels 46126127Skarels case S_IDLE: 46226127Skarels printf("tmscp%d: random interrupt ignored\n", d); 46326127Skarels return; 46426135Skarels 46526127Skarels /* Controller was in step 1 last, see if its gone to step 2 */ 46626127Skarels case S_STEP1: 46726127Skarels # define STEP1MASK 0174377 46826127Skarels # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) 46926127Skarels for (i = 0; i < 150; i++) 47026127Skarels { 47126127Skarels if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) 47226127Skarels { /* still in step 1 (wait 1/100 sec) */ 47326127Skarels DELAY(10000); 47426127Skarels # ifdef DEBUG 47526127Skarels printd("still in step 1, delaying\n"); 47626127Skarels # endif DEBUG 47726127Skarels } 47826127Skarels else 47926127Skarels break; 48026127Skarels } 48126127Skarels if (i > 149) 48226127Skarels { 48326127Skarels sc->sc_state = S_IDLE; 48426135Skarels printf("failed to initialize, in step1: sa 0x%x", tmscpaddr->tmscpsa); 48526127Skarels wakeup((caddr_t)um); 48626127Skarels return; 48726127Skarels } 48826127Skarels tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase) 48926127Skarels | ((cpu == VAX_780 || cpu == VAX_8600) ? TMSCP_PI : 0); 49026127Skarels sc->sc_state = S_STEP2; 49126127Skarels return; 49226135Skarels 49326127Skarels /* Controller was in step 2 last, see if its gone to step 3 */ 49426127Skarels case S_STEP2: 49526127Skarels # define STEP2MASK 0174377 49626127Skarels # define STEP2GOOD (TMSCP_STEP3|TMSCP_IE|(sc->sc_ivec/4)) 49726127Skarels for (i = 0; i < 150; i++) 49826127Skarels { 49926127Skarels if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) 50026127Skarels { /* still in step 2 (wait 1/100 sec) */ 50126127Skarels DELAY(10000); 50226127Skarels # ifdef DEBUG 50326127Skarels printd("still in step 2, delaying\n"); 50426127Skarels # endif DEBUG 50526127Skarels } 50626127Skarels else 50726127Skarels break; 50826127Skarels } 50926127Skarels if (i > 149) 51026127Skarels { 51126127Skarels sc->sc_state = S_IDLE; 51226135Skarels printf("failed to initialize, in step2: sa 0x%x", tmscpaddr->tmscpsa); 51326127Skarels wakeup((caddr_t)um); 51426127Skarels return; 51526127Skarels } 51626135Skarels tmscpaddr->tmscpsa = ((int)&sc->sc_tmscp->tmscp_ca.ca_ringbase)>>16; 51726127Skarels sc->sc_state = S_STEP3; 51826127Skarels return; 51926135Skarels 52026127Skarels /* Controller was in step 3 last, see if its gone to step 4 */ 52126127Skarels case S_STEP3: 52226127Skarels # define STEP3MASK 0174000 52326127Skarels # define STEP3GOOD TMSCP_STEP4 52426127Skarels for (i = 0; i < 150; i++) 52526127Skarels { 52626127Skarels if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) 52726127Skarels { /* still in step 3 (wait 1/100 sec) */ 52826127Skarels DELAY(10000); 52926127Skarels # ifdef DEBUG 53026127Skarels printd("still in step 3, delaying\n"); 53126127Skarels # endif DEBUG 53226127Skarels } 53326127Skarels else 53426127Skarels break; 53526127Skarels } 53626127Skarels if (i > 149) 53726127Skarels { 53826127Skarels sc->sc_state = S_IDLE; 53926135Skarels printf("failed to initialize, in step3: sa 0x%x", tmscpaddr->tmscpsa); 54026127Skarels wakeup((caddr_t)um); 54126127Skarels return; 54226127Skarels } 54326127Skarels /* 54426127Skarels * Get microcode version and model number of controller; 54526127Skarels * Signal initialization complete (_GO) (to the controller); 54626127Skarels * ask for Last Fail response if tmscperror is set; 54726127Skarels * Set state to "set controller characteristics". 54826127Skarels */ 54926127Skarels tmscpmicro[d] = tmscpaddr->tmscpsa; 55026127Skarels tmscpaddr->tmscpsa = TMSCP_GO | (tmscperror? TMSCP_LF : 0); 55126127Skarels sc->sc_state = S_SCHAR; 55226127Skarels # ifdef DEBUG 55326127Skarels printd("tmscpintr: completed state %d \n", sc->sc_state); 55426127Skarels printd("tmscp%d Version %d model %d\n",d,tmscpmicro[d]&0xF, 55526127Skarels (tmscpmicro[d]>>4) & 0xF); 55626127Skarels # endif 55726135Skarels 55826127Skarels /* 55926127Skarels * Initialize the data structures (response and command queues). 56026127Skarels */ 56126127Skarels ttm = sc->sc_tmscp; 56226127Skarels for (i = 0; i < NRSP; i++) 56326127Skarels { 56426127Skarels tm->tmscp_ca.ca_rspdsc[i] = TMSCP_OWN | TMSCP_INT | 56526135Skarels (long)&ttm->tmscp_rsp[i].mscp_cmdref; 56626127Skarels tm->tmscp_rsp[i].mscp_dscptr = &tm->tmscp_ca.ca_rspdsc[i]; 56726127Skarels tm->tmscp_rsp[i].mscp_header.tmscp_msglen = mscp_msglen; 56826127Skarels } 56926127Skarels for (i = 0; i < NCMD; i++) 57026127Skarels { 57126127Skarels tm->tmscp_ca.ca_cmddsc[i] = TMSCP_INT | 57226127Skarels (long)&ttm->tmscp_cmd[i].mscp_cmdref; 57326127Skarels tm->tmscp_cmd[i].mscp_dscptr = &tm->tmscp_ca.ca_cmddsc[i]; 57426127Skarels tm->tmscp_cmd[i].mscp_header.tmscp_msglen = mscp_msglen; 57526127Skarels tm->tmscp_cmd[i].mscp_header.tmscp_vcid = 1; 57626127Skarels } 57726127Skarels bp = &tmscpwtab[d]; 57826127Skarels bp->av_forw = bp->av_back = bp; 57926127Skarels sc->sc_lastcmd = 1; 58026127Skarels sc->sc_lastrsp = 0; 58126127Skarels mp = &tmscp[um->um_ctlr].tmscp_cmd[0]; 58226127Skarels mp->mscp_unit = mp->mscp_modifier = 0; 58326127Skarels mp->mscp_flags = 0; 58426127Skarels mp->mscp_version = 0; 58526127Skarels mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; 58626127Skarels /* 58726127Skarels * A host time out value of 0 means that the controller will not 58826127Skarels * time out. This is ok for the TK50. 58926127Skarels */ 59026127Skarels mp->mscp_hsttmo = 0; 59126127Skarels mp->mscp_time.val[0] = 0; 59226127Skarels mp->mscp_time.val[1] = 0; 59326127Skarels mp->mscp_cntdep = 0; 59426127Skarels mp->mscp_opcode = M_OP_STCON; 59526127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 59626127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 59726127Skarels return; 59826135Skarels 59926127Skarels case S_SCHAR: 60026127Skarels case S_RUN: 60126127Skarels break; 60226135Skarels 60326127Skarels default: 60426135Skarels printf("tmscp%d: interrupt in unknown state %d ignored\n",d,sc->sc_state); 60526127Skarels return; 60626127Skarels } /* end switch */ 60726135Skarels 60826127Skarels /* 60926127Skarels * The controller state is S_SCHAR or S_RUN 61026127Skarels */ 61126135Skarels 61226127Skarels /* 61326127Skarels * If the error bit is set in the SA register then print an error 61426127Skarels * message and reinitialize the controller. 61526127Skarels */ 61626127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 61726127Skarels { 61826135Skarels printf("tmscp%d: fatal error (%o)\n", d, tmscpaddr->tmscpsa&0xffff); 61926127Skarels tmscpaddr->tmscpip = 0; 62026127Skarels wakeup((caddr_t)um); 62126127Skarels } 62226127Skarels /* 62326127Skarels * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus) 62426127Skarels */ 62526127Skarels if (tm->tmscp_ca.ca_bdp) 62626127Skarels { 62726370Skarels UBAPURGE(um->um_hd->uh_uba, tm->tmscp_ca.ca_bdp); 62826127Skarels tm->tmscp_ca.ca_bdp = 0; 62926127Skarels tmscpaddr->tmscpsa = 0; /* signal purge complete */ 63026127Skarels } 63126135Skarels 63226127Skarels /* 63326127Skarels * Check for response ring transition. 63426127Skarels */ 63526127Skarels if (tm->tmscp_ca.ca_rspint) 63626127Skarels { 63726127Skarels tm->tmscp_ca.ca_rspint = 0; 63826127Skarels for (i = sc->sc_lastrsp;; i++) 63926127Skarels { 64026127Skarels i %= NRSP; 64126127Skarels if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) 64226127Skarels break; 64326127Skarels tmscprsp(um, tm, sc, i); 64426127Skarels tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; 64526127Skarels } 64626127Skarels sc->sc_lastrsp = i; 64726127Skarels } 64826135Skarels 64926127Skarels /* 65026127Skarels * Check for command ring transition. 65126127Skarels */ 65226127Skarels if (tm->tmscp_ca.ca_cmdint) 65326127Skarels { 65426127Skarels # ifdef DEBUG 65526127Skarels printd("tmscpintr: command ring transition\n"); 65626127Skarels # endif 65726127Skarels tm->tmscp_ca.ca_cmdint = 0; 65826127Skarels } 65926127Skarels if(tmscp_cp_wait) 66026370Skarels wakeup((caddr_t)&tmscp_cp_wait); 66126127Skarels (void) tmscpstart(um); 66226127Skarels } 66326135Skarels 66426135Skarels 66526127Skarels /* 66626127Skarels * Open a tmscp device and set the unit online. If the controller is not 66726127Skarels * in the run state, call init to initialize the tmscp controller first. 66826127Skarels */ 66926135Skarels 67026293Skarels /* ARGSUSED */ 67126127Skarels tmscpopen(dev, flag) 67226127Skarels dev_t dev; 67326127Skarels int flag; 67426127Skarels { 67526127Skarels register int unit; 67626127Skarels register struct uba_device *ui; 67726127Skarels register struct tmscp_softc *sc; 67826135Skarels register struct tms_info *tms; 67926127Skarels register struct mscp *mp; 68026127Skarels register struct uba_ctlr *um; 68126127Skarels struct tmscpdevice *tmscpaddr; 68226127Skarels int s,i; 68326127Skarels 68426127Skarels unit = TMSUNIT(dev); 68526127Skarels # ifdef DEBUG 68626127Skarels printd("tmscpopen unit %d\n",unit); 68726127Skarels if(tmscpdebug)DELAY(10000); 68826127Skarels # endif 68926135Skarels if (unit >= NTMS || (ui = tmsdinfo[unit]) == 0 || ui->ui_alive == 0) 69026127Skarels return (ENXIO); 69126135Skarels tms = &tms_info[ui->ui_unit]; 69226135Skarels if (tms->tms_openf) 69326135Skarels return (EBUSY); 69426127Skarels sc = &tmscp_softc[ui->ui_ctlr]; 69526135Skarels tms->tms_openf = 1; 69626135Skarels tms->tms_ttyp = u.u_ttyp; 69726127Skarels s = spl5(); 69826127Skarels if (sc->sc_state != S_RUN) 69926127Skarels { 70026127Skarels if (sc->sc_state == S_IDLE) 70126127Skarels if(!tmscpinit(ui->ui_ctlr)) 70226127Skarels { 70326127Skarels printf("tmscp controller failed to init\n"); 70426127Skarels (void) splx(s); 705*30917Skarels tms->tms_openf = 0; 70626127Skarels return(ENXIO); 70726127Skarels } 70826127Skarels /* 70926127Skarels * Wait for initialization to complete 71026127Skarels */ 71126127Skarels timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ 71226127Skarels sleep((caddr_t)ui->ui_mi, 0); 71326127Skarels if (sc->sc_state != S_RUN) 71426127Skarels { 71526127Skarels (void) splx(s); 71626135Skarels tms->tms_openf = 0; 71726127Skarels return (EIO); 71826127Skarels } 71926127Skarels } 72026127Skarels /* 72126127Skarels * Check to see if the device is really there. 72226127Skarels * this code was taken from Fred Canters 11 driver 72326127Skarels */ 72426127Skarels um = ui->ui_mi; 72526127Skarels tmscpaddr = (struct tmscpdevice *) um->um_addr; 72626127Skarels (void) splx(s); 72726127Skarels if(ui->ui_flags == 0) 72826127Skarels { 72926127Skarels s = spl5(); 73026127Skarels while(0 ==(mp = tmscpgetcp(um))) 73126127Skarels { 73226127Skarels tmscp_cp_wait++; 73326370Skarels sleep((caddr_t)&tmscp_cp_wait,PSWP+1); 73426127Skarels tmscp_cp_wait--; 73526127Skarels } 73626127Skarels (void) splx(s); 73726127Skarels mp->mscp_opcode = M_OP_ONLIN; 73826127Skarels mp->mscp_unit = ui->ui_slave; 73926135Skarels mp->mscp_cmdref = (long) & tms->tms_type; 74026127Skarels /* need to sleep on something */ 74126127Skarels # ifdef DEBUG 74226127Skarels printd("tmscpopen: bring unit %d online\n",ui->ui_unit); 74326127Skarels # endif 74426127Skarels *((long *) mp->mscp_dscptr ) |= TMSCP_OWN | TMSCP_INT; 74526127Skarels i = tmscpaddr->tmscpip; 74626293Skarels #ifdef lint 74726293Skarels i = i; 74826293Skarels #endif 74926127Skarels /* 75026127Skarels * To make sure we wake up, timeout in 240 seconds. 75126127Skarels * Wakeup in tmscprsp routine. 75226127Skarels * 240 seconds (4 minutes) is necessary since a rewind 75326127Skarels * can take a few minutes. 75426127Skarels */ 75526127Skarels timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz); 75626127Skarels sleep((caddr_t) mp->mscp_cmdref,PSWP+1); 75726127Skarels } 75826135Skarels if(ui->ui_flags == 0) { 75926135Skarels tms->tms_openf = 0; 76026127Skarels return(ENXIO); /* Didn't go online */ 76126135Skarels } 76226135Skarels tms->tms_lastiow = 0; 76326127Skarels /* 76426127Skarels * If the high density device is not specified, set unit to low 76526127Skarels * density. This is done as an "internal" ioctl command so 76626127Skarels * that the command setup and response handling 76726127Skarels * is done thru "regular" command routines. 76826127Skarels */ 76926127Skarels if ((minor(dev) & T_HIDENSITY) == 0) 77026127Skarels tmscpcommand(dev, TMS_LOWDENSITY, 1); 77126127Skarels else 77226127Skarels tmscpcommand(dev, TMS_HIDENSITY, 1); 77326127Skarels return (0); 77426127Skarels } 77526135Skarels 77626135Skarels 77726127Skarels /* 77826127Skarels * Close tape device. 77926127Skarels * 78026127Skarels * If tape was open for writing or last operation was 78126127Skarels * a write, then write two EOF's and backspace over the last one. 78226127Skarels * Unless this is a non-rewinding special file, rewind the tape. 78326127Skarels * 78426127Skarels * NOTE: 78526127Skarels * We want to be sure that any serious exception is cleared on the 78626127Skarels * close. A Clear Serious Exception (CSE) modifier is always done on 78726127Skarels * the rewind command. For the non-rewind case we check to see if the 78826127Skarels * "serex" field is set in the softc struct; if it is then issue a noop 78926127Skarels * command with the CSE modifier. 79026127Skarels * Make the tape available to others, by clearing openf flag. 79126127Skarels */ 79226127Skarels tmscpclose(dev, flag) 79326127Skarels register dev_t dev; 79426127Skarels register flag; 79526127Skarels { 79626135Skarels register struct tms_info *tms; 79726127Skarels register struct uba_device *ui; 79826135Skarels 79926127Skarels ui = tmsdinfo[TMSUNIT(dev)]; 80026127Skarels # ifdef DEBUG 80126127Skarels printd("tmscpclose: ctlr = %d\n",TMSCPCTLR(dev)); 80226127Skarels printd("tmscpclose: unit = %d\n",TMSUNIT(dev)); 80326127Skarels if(tmscpdebug)DELAY(10000); 80426127Skarels # endif 80526135Skarels tms = &tms_info[ui->ui_unit]; 80626135Skarels if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow) 80726127Skarels { 80826127Skarels /* device, command, count */ 80926127Skarels tmscpcommand (dev, TMS_WRITM, 1); 81026127Skarels tmscpcommand (dev, TMS_WRITM, 1); 81126127Skarels tmscpcommand (dev, TMS_BSR, 1); 81226127Skarels } 81326127Skarels if ((minor(dev)&T_NOREWIND) == 0) 81426127Skarels /* 81526127Skarels * Don't hang waiting for rewind complete. 81626127Skarels */ 81726127Skarels tmscpcommand(dev, TMS_REW, 0); 81826127Skarels else 81926135Skarels if (tms->tms_serex) 82026127Skarels { 82126127Skarels # ifdef DEBUG 82226127Skarels printd("tmscpclose: clearing serex\n"); 82326127Skarels if(tmscpdebug)DELAY(10000); 82426127Skarels # endif 82526127Skarels tmscpcommand(dev, TMS_CSE, 1); 82626127Skarels } 82726135Skarels tms->tms_openf = 0; 82826127Skarels } 82926135Skarels 83026135Skarels 83126127Skarels /* 83226127Skarels * Execute a command on the tape drive a specified number of times. 83326127Skarels * This routine sets up a buffer and calls the strategy routine which 83426127Skarels * links the buffer onto the drive's buffer queue. 83526127Skarels * The start routine will take care of creating a tmscp command packet 83626127Skarels * with the command. The start routine is called by the strategy or the 83726127Skarels * interrupt routine. 83826127Skarels */ 83926135Skarels 84026127Skarels tmscpcommand (dev, com, count) 84126127Skarels register dev_t dev; 84226127Skarels int com, count; 84326127Skarels { 84426127Skarels register struct uba_device *ui; 84526127Skarels register struct buf *bp; 84626127Skarels register int s; 84726127Skarels int unit = TMSUNIT(dev); 84826135Skarels 84926127Skarels ui = tmsdinfo[unit]; 85026127Skarels bp = &ctmscpbuf[ui->ui_ctlr]; 85126135Skarels 85226127Skarels s = spl5(); 85326127Skarels while (bp->b_flags&B_BUSY) 85426127Skarels { 85526127Skarels /* 85626127Skarels * This special check is because B_BUSY never 85726127Skarels * gets cleared in the non-waiting rewind case. 85826127Skarels */ 85926127Skarels if (bp->b_bcount == 0 && (bp->b_flags&B_DONE)) 86026127Skarels break; 86126127Skarels bp->b_flags |= B_WANTED; 86226127Skarels sleep((caddr_t)bp, PRIBIO); 86326127Skarels } 86426127Skarels bp->b_flags = B_BUSY|B_READ; 86526127Skarels splx(s); 86626127Skarels /* 86726127Skarels * Load the buffer. The b_count field gets used to hold the command 86826127Skarels * count. the b_resid field gets used to hold the command mneumonic. 86926127Skarels * These 2 fields are "known" to be "safe" to use for this purpose. 87026127Skarels * (Most other drivers also use these fields in this way.) 87126127Skarels */ 87226127Skarels bp->b_dev = dev; 87326127Skarels bp->b_bcount = count; 87426127Skarels bp->b_resid = com; 87526127Skarels bp->b_blkno = 0; 87626127Skarels tmscpstrategy(bp); 87726127Skarels /* 87826127Skarels * In case of rewind from close, don't wait. 87926127Skarels * This is the only case where count can be 0. 88026127Skarels */ 88126127Skarels if (count == 0) 88226127Skarels return; 88326127Skarels iowait(bp); 88426127Skarels if (bp->b_flags&B_WANTED) 88526127Skarels wakeup((caddr_t)bp); 88626127Skarels bp->b_flags &= B_ERROR; 88726127Skarels } 88826135Skarels 88926127Skarels /* 89026127Skarels * Find an unused command packet 89126127Skarels */ 89226127Skarels struct mscp * 89326127Skarels tmscpgetcp(um) 89426127Skarels struct uba_ctlr *um; 89526127Skarels { 89626127Skarels register struct mscp *mp; 89726127Skarels register struct tmscpca *cp; 89826127Skarels register struct tmscp_softc *sc; 89926127Skarels register int i; 90026127Skarels int s; 90126135Skarels 90226127Skarels s = spl5(); 90326127Skarels cp = &tmscp[um->um_ctlr].tmscp_ca; 90426127Skarels sc = &tmscp_softc[um->um_ctlr]; 90526127Skarels /* 90626127Skarels * If no credits, can't issue any commands 90726127Skarels * until some outstanding commands complete. 90826127Skarels */ 90926127Skarels i = sc->sc_lastcmd; 91026127Skarels # ifdef DEBUG 91126127Skarels printd10("tmscpgetcp: %d credits remain\n", sc->sc_credits); 91226127Skarels # endif 91326127Skarels if(((cp->ca_cmddsc[i]&(TMSCP_OWN|TMSCP_INT))==TMSCP_INT) && 91426127Skarels (sc->sc_credits >= 2)) 91526127Skarels { 91626127Skarels sc->sc_credits--; /* This commits to issuing a command */ 91726127Skarels cp->ca_cmddsc[i] &= ~TMSCP_INT; 91826127Skarels mp = &tmscp[um->um_ctlr].tmscp_cmd[i]; 91926127Skarels mp->mscp_unit = mp->mscp_modifier = 0; 92026127Skarels mp->mscp_opcode = mp->mscp_flags = 0; 92126127Skarels mp->mscp_bytecnt = mp->mscp_buffer = 0; 92226127Skarels sc->sc_lastcmd = (i + 1) % NCMD; 92326127Skarels (void) splx(s); 92426127Skarels return(mp); 92526127Skarels } 92626127Skarels (void) splx(s); 92726127Skarels return(NULL); 92826127Skarels } 92926135Skarels 93026135Skarels 93126127Skarels /* 93226127Skarels * Initialize a TMSCP device. Set up UBA mapping registers, 93326127Skarels * initialize data structures, and start hardware 93426127Skarels * initialization sequence. 93526127Skarels */ 93626127Skarels tmscpinit (d) 93726127Skarels int d; /* index to the controller */ 93826127Skarels { 93926127Skarels register struct tmscp_softc *sc; 94026135Skarels register struct tmscp *t; /* communications area; cmd & resp packets */ 94126127Skarels struct tmscpdevice *tmscpaddr; 94226127Skarels struct uba_ctlr *um; 94326135Skarels 94426127Skarels sc = &tmscp_softc[d]; 94526127Skarels um = tmscpminfo[d]; 94626127Skarels um->um_tab.b_active++; 94726127Skarels t = &tmscp[d]; 94826127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 94926127Skarels if (sc->sc_mapped == 0) 95026127Skarels { 95126127Skarels /* 95226127Skarels * Map the communications area and command 95326127Skarels * and response packets into Unibus address 95426127Skarels * space. 95526127Skarels */ 95626135Skarels sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)t, sizeof (struct tmscp), 0); 95726127Skarels # ifdef MVAX 95826127Skarels if (cpu == MVAX_I) 95926135Skarels sc->sc_tmscp = (struct tmscp *)(sc->sc_ubainfo & 0x3fffff); 96026127Skarels else 96126127Skarels # endif MVAX 96226135Skarels sc->sc_tmscp = (struct tmscp *)(sc->sc_ubainfo & 0x3ffff); 96326127Skarels sc->sc_mapped = 1; 96426127Skarels } 96526135Skarels 96626127Skarels /* 96726127Skarels * Start the hardware initialization sequence. 96826127Skarels */ 96926127Skarels tmscpaddr->tmscpip = 0; /* start initialization */ 97026135Skarels 97126127Skarels while((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 97226127Skarels { 97326127Skarels # ifdef DEBUG 97426127Skarels printd("tmscpinit: tmscpsa = 0%o\n",tmscpaddr->tmscpsa); 97526127Skarels DELAY(100000); 97626127Skarels # endif 97726127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) 97826127Skarels return(0); /* CHECK */ 97926127Skarels } 98026135Skarels tmscpaddr->tmscpsa=TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8)|TMSCP_IE|(sc->sc_ivec/4); 98126127Skarels /* 98226127Skarels * Initialization continues in the interrupt routine. 98326127Skarels */ 98426127Skarels sc->sc_state = S_STEP1; 98526127Skarels sc->sc_credits = 0; 98626127Skarels return(1); 98726127Skarels } 98826135Skarels 98926135Skarels 99026127Skarels /* 99126127Skarels * Start I/O operation 99226127Skarels * This code is convoluted. The majority of it was copied from the uda driver. 99326127Skarels */ 99426135Skarels 99526127Skarels tmscpstart(um) 99626127Skarels register struct uba_ctlr *um; 99726127Skarels { 99826127Skarels register struct buf *bp, *dp; 99926127Skarels register struct mscp *mp; 100026127Skarels register struct tmscp_softc *sc; 100126135Skarels register struct tms_info *tms; 100226127Skarels register struct uba_device *ui; 100326127Skarels struct tmscpdevice *tmscpaddr; 100426127Skarels struct tmscp *tm = &tmscp[um->um_ctlr]; 100526127Skarels int i,tempi; 100626127Skarels char ioctl; /* flag: set true if its an IOCTL command */ 100726135Skarels 100826127Skarels sc = &tmscp_softc[um->um_ctlr]; 100926127Skarels 101026127Skarels for(;;) 101126127Skarels { 101226127Skarels if ((dp = um->um_tab.b_actf) == NULL) 101326127Skarels { 101426127Skarels /* 101526127Skarels * Release unneeded UBA resources and return 101626127Skarels * (drive was inactive) 101726127Skarels */ 101826127Skarels um->um_tab.b_active = 0; 101926127Skarels break; 102026127Skarels } 102126127Skarels if ((bp = dp->b_actf) == NULL) 102226127Skarels { 102326127Skarels /* 102426127Skarels * No more requests for this drive, remove 102526127Skarels * from controller queue and look at next drive. 102626127Skarels * We know we're at the head of the controller queue. 102726127Skarels */ 102826127Skarels dp->b_active = 0; 102926127Skarels um->um_tab.b_actf = dp->b_forw; 103026127Skarels continue; /* Need to check for loop */ 103126127Skarels } 103226127Skarels um->um_tab.b_active++; 103326127Skarels tmscpaddr = (struct tmscpdevice *)um->um_addr; 103426135Skarels ui = tmsdinfo[(TMSUNIT(bp->b_dev))]; 103526135Skarels tms = &tms_info[ui->ui_unit]; 103626127Skarels if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN) 103726127Skarels { 103826135Skarels tprintf(tms->tms_ttyp, 103926135Skarels "tms%d: hard error bn%d\n", 104026135Skarels minor(bp->b_dev)&03, bp->b_blkno); 104126135Skarels log(TMS_PRI, "tmscp%d: sa 0%o, state %d\n",um->um_ctlr, 104226127Skarels tmscpaddr->tmscpsa&0xffff, sc->sc_state); 104326370Skarels (void)tmscpinit(um->um_ctlr); 104426127Skarels /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */ 104526127Skarels break; 104626127Skarels } 104726127Skarels /* 104826127Skarels * Default is that last command was NOT a write command; 104926127Skarels * if a write command is done it will be detected in tmscprsp. 105026127Skarels */ 105126135Skarels tms->tms_lastiow = 0; 105226127Skarels if (ui->ui_flags == 0) 105326127Skarels { /* not online */ 105426127Skarels if ((mp = tmscpgetcp(um)) == NULL) 105526127Skarels break; 105626127Skarels mp->mscp_opcode = M_OP_ONLIN; 105726127Skarels mp->mscp_unit = ui->ui_slave; 105826127Skarels dp->b_active = 2; 105926127Skarels um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ 106026127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 106126127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 106226127Skarels printf("tmscp%d fatal error (0%o)\n",um->um_ctlr, 106326127Skarels tmscpaddr->tmscpsa&0xffff); 106426127Skarels i = tmscpaddr->tmscpip; 106526127Skarels continue; 106626127Skarels } 106726127Skarels switch (cpu) { 106826135Skarels 106926127Skarels case VAX_8600: 107026127Skarels case VAX_780: 107126127Skarels i = UBA_NEEDBDP|UBA_CANTWAIT; 107226127Skarels break; 107326127Skarels case VAX_750: 107426127Skarels i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; 107526127Skarels break; 107626127Skarels case VAX_730: 107726127Skarels i = UBA_CANTWAIT; 107826127Skarels break; 107926127Skarels } /* end switch (cpu) */ 108026127Skarels /* 108126135Skarels * If command is an ioctl command then set the ioctl flag for later use. 108226127Skarels * If not (i.e. it is a read or write) then attempt 108326127Skarels * to set up a buffer pointer. 108426127Skarels */ 108526127Skarels ioctl = 0; 108626127Skarels if (bp == &ctmscpbuf[um->um_ctlr]) 108726127Skarels ioctl = 1; 108826127Skarels else 108926127Skarels if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) 109026127Skarels { 109126127Skarels if(dp->b_qsize != 0) 109226127Skarels break; /* When a command completes and */ 109326135Skarels /* frees a bdp tmscpstart will be called */ 109426127Skarels if ((mp = tmscpgetcp(um)) == NULL) 109526127Skarels break; 109626127Skarels # ifdef DEBUG 109726135Skarels printd("tmscpstart: GTUNT %d ubasetup = %d\n",ui->ui_unit, i); 109826127Skarels if(tmscpdebug)DELAY(10000); 109926127Skarels # endif 110026127Skarels mp->mscp_opcode = M_OP_GTUNT; 110126127Skarels mp->mscp_unit = ui->ui_slave; 110226127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 110326127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 110426135Skarels printf("tmscp%d: fatal error (0%o)\n",um->um_ctlr, 110526127Skarels tmscpaddr->tmscpsa&0xffff); 110626127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 110726127Skarels break; 110826127Skarels } 110926135Skarels # if defined(VAX750) 111026135Skarels if (cpu == VAX_750) 111126127Skarels tempi = i & 0xfffffff; /* mask off bdp */ 111226127Skarels else 111326127Skarels # endif 111426127Skarels tempi = i; 111526127Skarels if ((mp = tmscpgetcp(um)) == NULL) 111626127Skarels { 111726127Skarels if (!ioctl) /* only need to release if NOT ioctl */ 111826127Skarels ubarelse(um->um_ubanum,&tempi); 111926127Skarels break; 112026127Skarels } 112126127Skarels mp->mscp_cmdref = (long)bp; /* pointer to get back */ 112226127Skarels mp->mscp_unit = ui->ui_slave; 112326127Skarels /* 112426127Skarels * If its an ioctl-type command then set up the appropriate 112526127Skarels * tmscp command; by doing a switch on the "b_resid" field where 112626127Skarels * the command mneumonic is stored. 112726127Skarels */ 112826127Skarels if (ioctl) 112926127Skarels { 113026127Skarels # ifdef DEBUG 113126127Skarels printd("tmscpstart: doing ioctl cmd %d\n", bp->b_resid); 113226127Skarels # endif 113326127Skarels /* 113426127Skarels * The reccnt and tmkcnt fields are set to zero by the getcp 113526127Skarels * routine (as bytecnt and buffer fields). Thus reccnt and 113626127Skarels * tmkcnt are only modified here if they need to be set to 113726127Skarels * a non-zero value. 113826127Skarels */ 113926293Skarels switch ((int)bp->b_resid) { 114026135Skarels 114126127Skarels case TMS_WRITM: 114226127Skarels mp->mscp_opcode = M_OP_WRITM; 114326127Skarels break; 114426127Skarels case TMS_FSF: 114526127Skarels mp->mscp_opcode = M_OP_REPOS; 114626127Skarels mp->mscp_tmkcnt = bp->b_bcount; 114726127Skarels break; 114826127Skarels case TMS_BSF: 114926127Skarels mp->mscp_opcode = M_OP_REPOS; 115026127Skarels mp->mscp_modifier = M_MD_REVRS; 115126127Skarels mp->mscp_tmkcnt = bp->b_bcount; 115226127Skarels break; 115326127Skarels case TMS_FSR: 115426127Skarels mp->mscp_opcode = M_OP_REPOS; 115526127Skarels mp->mscp_modifier = M_MD_OBJCT; 115626127Skarels mp->mscp_reccnt = bp->b_bcount; 115726127Skarels break; 115826127Skarels case TMS_BSR: 115926127Skarels mp->mscp_opcode = M_OP_REPOS; 116026127Skarels mp->mscp_modifier = M_MD_REVRS | M_MD_OBJCT; 116126127Skarels mp->mscp_reccnt = bp->b_bcount; 116226127Skarels break; 116326127Skarels /* 116426127Skarels * Clear serious exception is done for Rewind & Available cmds 116526127Skarels */ 116626127Skarels case TMS_REW: 116726127Skarels mp->mscp_opcode = M_OP_REPOS; 116826127Skarels mp->mscp_modifier = M_MD_REWND | M_MD_CLSEX; 116926127Skarels if (bp->b_bcount == 0) 117026127Skarels mp->mscp_modifier |= M_MD_IMMED; 117126135Skarels tms->tms_serex = 0; 117226127Skarels break; 117326127Skarels case TMS_OFFL: 117426127Skarels mp->mscp_opcode = M_OP_AVAIL; 117526127Skarels mp->mscp_modifier = M_MD_UNLOD | M_MD_CLSEX; 117626135Skarels tms->tms_serex = 0; 117726127Skarels break; 117826127Skarels case TMS_SENSE: 117926127Skarels mp->mscp_opcode = M_OP_GTUNT; 118026127Skarels break; 118126127Skarels case TMS_CACHE: 118226127Skarels mp->mscp_opcode = M_OP_STUNT; 118326135Skarels tms->tms_unitflgs |= M_UF_WBKNV; 118426135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 118526135Skarels mp->mscp_format = tms->tms_format; 118626127Skarels /* default device dependant parameters */ 118726127Skarels mp->mscp_mediaid = 0; 118826127Skarels break; 118926127Skarels case TMS_NOCACHE: 119026127Skarels mp->mscp_opcode = M_OP_STUNT; 119126135Skarels tms->tms_unitflgs &= ~(M_UF_WBKNV); 119226135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 119326135Skarels mp->mscp_format = tms->tms_format; 119426127Skarels /* default device dependant parameters */ 119526127Skarels mp->mscp_mediaid = 0; 119626127Skarels break; 119726127Skarels case TMS_CSE: 119826127Skarels /* 119926127Skarels * This is a no-op command. It performs a 120026127Skarels * clear serious exception only. (Done on a 120126127Skarels * non-rewinding close after a serious exception.) 120226127Skarels */ 120326127Skarels mp->mscp_opcode = M_OP_REPOS; 120426127Skarels mp->mscp_modifier = M_MD_CLSEX; 120526135Skarels tms->tms_serex = 0; 120626135Skarels tms->tms_clserex = 1; 120726127Skarels break; 120826127Skarels case TMS_LOWDENSITY: 120926127Skarels /* 121026127Skarels * Set the unit to low density 121126127Skarels */ 121226127Skarels mp->mscp_opcode = M_OP_STUNT; 121326135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 121426135Skarels mp->mscp_mediaid = 0; /* default device dependant parameters */ 121526135Skarels if ((tms->tms_fmtmenu & M_TF_800) != 0) 121626127Skarels mp->mscp_format = M_TF_800; 121726127Skarels else 121826135Skarels mp->mscp_format = M_TF_PE & tms->tms_fmtmenu; 121926135Skarels tms->tms_format = mp->mscp_format; 122026127Skarels break; 122126127Skarels case TMS_HIDENSITY: 122226127Skarels /* 122326127Skarels * Set the unit to high density (format == 0) 122426127Skarels */ 122526127Skarels mp->mscp_opcode = M_OP_STUNT; 122626135Skarels mp->mscp_unitflgs = tms->tms_unitflgs; 122726135Skarels mp->mscp_mediaid = 0; /* default device dependant parameters */ 122826127Skarels mp->mscp_format = 0; 122926135Skarels tms->tms_format = 0; 123026127Skarels break; 123126127Skarels default: 123226127Skarels printf("Bad ioctl on tms unit %d\n", ui->ui_unit); 123326127Skarels /* Need a no-op. Reposition no amount */ 123426127Skarels mp->mscp_opcode = M_OP_REPOS; 123526127Skarels break; 123626127Skarels } /* end switch (bp->b_resid) */ 123726127Skarels } 123826127Skarels else /* Its a read/write command (not an ioctl) */ 123926127Skarels { 124026127Skarels mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; 124126127Skarels mp->mscp_bytecnt = bp->b_bcount; 124226127Skarels # if MVAX 124326127Skarels if (cpu == MVAX_I) 124426127Skarels { 124526127Skarels mp->mscp_buffer = (i & 0x3ffff) | TMSCP_MAP; 124626135Skarels mp->mscp_mapbase = (long)&(uba_hd[um->um_ubanum].uh_physuba->uba_map[0]); 124726127Skarels } 124826127Skarels else 124926127Skarels # endif MVAX 125026127Skarels mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); 125126135Skarels 125226127Skarels bp->b_ubinfo = tempi; /* save mapping info */ 125326127Skarels } 125426135Skarels if (tms->tms_serex == 2) /* if tape mark read */ 125526127Skarels { 125626135Skarels mp->mscp_modifier |= M_MD_CLSEX; /* clear serious exc */ 125726135Skarels tms->tms_serex = 0; 125826127Skarels } 125926127Skarels *((long *)mp->mscp_dscptr) |= TMSCP_OWN|TMSCP_INT; 126026127Skarels # ifdef DEBUG 126126135Skarels printd("tmscpstart: opcode 0%o mod %o unit %d cnt %d\n",mp->mscp_opcode,mp->mscp_modifier,mp->mscp_unit,mp->mscp_bytecnt); 126226127Skarels if(tmscpdebug)DELAY(100000); 126326127Skarels # endif 126426127Skarels i = tmscpaddr->tmscpip; /* initiate polling */ 126526127Skarels dp->b_qsize++; 126626127Skarels /* 126726127Skarels * Move drive to the end of the controller queue 126826127Skarels */ 126926127Skarels if (dp->b_forw != NULL) 127026127Skarels { 127126127Skarels um->um_tab.b_actf = dp->b_forw; 127226127Skarels um->um_tab.b_actl->b_forw = dp; 127326127Skarels um->um_tab.b_actl = dp; 127426127Skarels dp->b_forw = NULL; 127526127Skarels } 127626127Skarels /* 127726127Skarels * Move buffer to I/O wait queue 127826127Skarels */ 127926127Skarels dp->b_actf = bp->av_forw; 128026127Skarels dp = &tmscpwtab[um->um_ctlr]; 128126127Skarels bp->av_forw = dp; 128226127Skarels bp->av_back = dp->av_back; 128326127Skarels dp->av_back->av_forw = bp; 128426127Skarels dp->av_back = bp; 128526127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 128626127Skarels { 128726135Skarels printf("tmscp%d: fatal error (0%o)\n", um->um_ctlr, tmscpaddr->tmscpsa&0xffff); 128826370Skarels (void)tmscpinit(um->um_ctlr); 128926127Skarels break; 129026127Skarels } 129126127Skarels } /* end for */ 129226127Skarels /* 129326127Skarels * Check for response ring transitions lost in the 129426127Skarels * Race condition 129526127Skarels */ 129626127Skarels for (i = sc->sc_lastrsp;; i++) 129726127Skarels { 129826127Skarels i %= NRSP; 129926127Skarels if (tm->tmscp_ca.ca_rspdsc[i]&TMSCP_OWN) 130026127Skarels break; 130126127Skarels tmscprsp(um, tm, sc, i); 130226127Skarels tm->tmscp_ca.ca_rspdsc[i] |= TMSCP_OWN; 130326127Skarels } 130426127Skarels sc->sc_lastrsp = i; 130526127Skarels } 130626135Skarels 130726135Skarels 130826127Skarels /* 130926127Skarels * Process a response packet 131026127Skarels */ 131126127Skarels tmscprsp(um, tm, sc, i) 131226127Skarels register struct uba_ctlr *um; 131326127Skarels register struct tmscp *tm; 131426127Skarels register struct tmscp_softc *sc; 131526127Skarels int i; 131626127Skarels { 131726127Skarels register struct mscp *mp; 131826135Skarels register struct tms_info *tms; 131926127Skarels struct uba_device *ui; 132026293Skarels struct buf *dp, *bp; 132126127Skarels int st; 132226135Skarels 132326127Skarels mp = &tm->tmscp_rsp[i]; 132426127Skarels mp->mscp_header.tmscp_msglen = mscp_msglen; 132526135Skarels sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf; /* low 4 bits */ 132626127Skarels if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10) /* Check */ 132726127Skarels return; 132826127Skarels # ifdef DEBUG 132926135Skarels printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK); 133026127Skarels # endif 133126127Skarels /* 133226127Skarels * If it's an error log message (datagram), 133326127Skarels * pass it on for more extensive processing. 133426127Skarels */ 133526127Skarels if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10) 133626127Skarels { /* check */ 133726127Skarels tmserror(um, (struct mslg *)mp); 133826127Skarels return; 133926127Skarels } 134026127Skarels st = mp->mscp_status&M_ST_MASK; 134126127Skarels /* 134226127Skarels * The controller interrupts as drive 0. 134326127Skarels * This means that you must check for controller interrupts 134426127Skarels * before you check to see if there is a drive 0. 134526127Skarels */ 134626127Skarels if((M_OP_STCON|M_OP_END) == mp->mscp_opcode) 134726127Skarels { 134826127Skarels if (st == M_ST_SUCC) 134926127Skarels { 135026127Skarels # ifdef DEBUG 135126135Skarels printd("ctlr has %d credits\n", mp->mscp_header.tmscp_credits & 0xf); 135226127Skarels printd("ctlr timeout = %d\n", mp->mscp_cnttmo); 135326127Skarels # endif 135426127Skarels sc->sc_state = S_RUN; 135526127Skarels } 135626127Skarels else 135726127Skarels sc->sc_state = S_IDLE; 135826127Skarels um->um_tab.b_active = 0; 135926127Skarels wakeup((caddr_t)um); 136026127Skarels return; 136126127Skarels } 136226135Skarels if (mp->mscp_unit >= NTMS) 136326127Skarels return; 136426127Skarels if ((ui = tmscpip[um->um_ctlr][mp->mscp_unit]) == 0) 136526127Skarels return; 136626135Skarels tms = &tms_info[ui->ui_unit]; 136726127Skarels /* 136826127Skarels * Save endcode, endflags, and status for mtioctl get unit status. 136926127Skarels * NOTE: Don't do this on Clear serious exception (reposition no-op); 137026127Skarels * which is done on close since this would 137126127Skarels * overwrite the real status we want. 137226127Skarels */ 137326135Skarels if (tms->tms_clserex != 1) 137426127Skarels { 137526135Skarels tms->tms_endcode = mp->mscp_opcode; 137626135Skarels tms->tms_flags = mp->mscp_flags; 137726135Skarels tms->tms_status = st; 137826127Skarels } 137926135Skarels else tms->tms_clserex = 0; 138026135Skarels 138126127Skarels switch (mp->mscp_opcode) { 138226127Skarels case M_OP_ONLIN|M_OP_END: 138326135Skarels tms->tms_type = mp->mscp_mediaid; 138426127Skarels dp = &tmsutab[ui->ui_unit]; 138526127Skarels if (st == M_ST_SUCC) 138626127Skarels { 138726127Skarels /* 138826127Skarels * Link the drive onto the controller queue 138926127Skarels */ 139026127Skarels dp->b_forw = NULL; 139126127Skarels if (um->um_tab.b_actf == NULL) 139226127Skarels um->um_tab.b_actf = dp; 139326127Skarels else 139426127Skarels um->um_tab.b_actl->b_forw = dp; 139526127Skarels um->um_tab.b_actl = dp; 139626127Skarels ui->ui_flags = 1; /* mark it online */ 139726135Skarels tms->tms_dsize=(daddr_t)mp->mscp_maxwrt; 139826127Skarels # ifdef DEBUG 139926127Skarels printd("tmscprsp: unit %d online\n", mp->mscp_unit); 140026127Skarels # endif 140126127Skarels /* 140226127Skarels * This define decodes the Media type identifier 140326127Skarels */ 140426135Skarels # define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') 140526127Skarels # ifdef DEBUG 140626127Skarels printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n" 140726127Skarels ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4) 140826127Skarels ,F_to_C(mp,3), F_to_C(mp,2) 140926135Skarels ,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f); 141026127Skarels # endif 141126127Skarels dp->b_active = 1; 141226127Skarels } /* end if st == M_ST_SUCC */ 141326127Skarels else 141426127Skarels { 141526293Skarels if (bp = dp->b_actf) 141626135Skarels tprintf(tms->tms_ttyp, 141726135Skarels "tms%d: hard error bn%d: OFFLINE\n", 141826135Skarels minor(bp->b_dev)&03, bp->b_blkno); 141926127Skarels else 142026135Skarels tprintf(tms->tms_ttyp, 142126135Skarels "tms%d: hard error: OFFLINE\n", 142226293Skarels ui->ui_unit); 142326127Skarels while (bp = dp->b_actf) 142426127Skarels { 142526127Skarels dp->b_actf = bp->av_forw; 142626127Skarels bp->b_flags |= B_ERROR; 142726127Skarels iodone(bp); 142826127Skarels } 142926127Skarels } 143026127Skarels if(mp->mscp_cmdref!=NULL) 143126127Skarels /* Seems to get lost sometimes in uda */ 143226370Skarels wakeup((caddr_t)mp->mscp_cmdref); 143326127Skarels break; 143426127Skarels /* 143526127Skarels * The AVAILABLE ATTENTION message occurs when the 143626127Skarels * unit becomes available after loading, 143726127Skarels * marking the unit offline (ui_flags = 0) will force an 143826127Skarels * online command prior to using the unit. 143926127Skarels */ 144026127Skarels case M_OP_AVATN: 144126127Skarels ui->ui_flags = 0; 144226135Skarels tms->tms_type = mp->mscp_mediaid; 144326127Skarels break; 144426127Skarels case M_OP_END: 144526127Skarels /* 144626127Skarels * An endcode without an opcode (0200) is an invalid command. 144726127Skarels * The mscp specification states that this would be a protocol 144826127Skarels * type error, such as illegal opcodes. The mscp spec. also 144926127Skarels * states that parameter error type of invalid commands should 145026135Skarels * return the normal end message for the command. This does not appear 145126135Skarels * to be the case. An invalid logical block number returned an endcode 145226127Skarels * of 0200 instead of the 0241 (read) that was expected. 145326127Skarels */ 145426127Skarels 145526127Skarels printf("tmscp%d: invalid cmd, endcode = %o, status=%o\n", 145626127Skarels um->um_ctlr, mp->mscp_opcode, st); 145726127Skarels bp = (struct buf *)mp->mscp_cmdref; 145826127Skarels /* 145926127Skarels * Unlink buffer from I/O wait queue. 146026127Skarels * And signal iodone, so the higher level command can exit! 146126127Skarels * 146226127Skarels */ 146326127Skarels bp->av_back->av_forw = bp->av_forw; 146426127Skarels bp->av_forw->av_back = bp->av_back; 146526127Skarels dp = &tmsutab[ui->ui_unit]; 146626127Skarels dp->b_qsize--; 146726127Skarels iodone(bp); 146826127Skarels break; 146926127Skarels case M_OP_WRITE|M_OP_END: 147026127Skarels /* mark the last io op as a write */ 147126135Skarels tms->tms_lastiow = 1; 147226127Skarels case M_OP_READ|M_OP_END: 147326127Skarels case M_OP_WRITM|M_OP_END: 147426127Skarels case M_OP_REPOS|M_OP_END: 147526127Skarels case M_OP_STUNT|M_OP_END: 147626127Skarels /* 147726127Skarels * The AVAILABLE message occurs when the mt ioctl "rewoffl" is 147826127Skarels * issued. For the ioctl, "rewoffl", a tmscp AVAILABLE command is 147926127Skarels * done with the UNLOAD modifier. This performs a rewind, followed 148026127Skarels * by marking the unit offline. So mark the unit offline 148126127Skarels * software wise as well (ui_flags = 0 and 148226135Skarels * tms->tms_openf = 0). 148326127Skarels */ 148426127Skarels case M_OP_AVAIL|M_OP_END: 148526127Skarels # ifdef DEBUG 148626127Skarels printd("tmscprsp: position = %d\n", mp->mscp_lbn); 148726127Skarels # endif 148826127Skarels bp = (struct buf *)mp->mscp_cmdref; 148926127Skarels /* 149026135Skarels * Only need to release buffer if the command was read or write. 149126127Skarels * No ubasetup was done in "tmscpstart" if it was an ioctl cmd. 149226127Skarels */ 149326127Skarels if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 149426127Skarels mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) 149526127Skarels ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); 149626127Skarels /* 149726127Skarels * Unlink buffer from I/O wait queue. 149826127Skarels */ 149926127Skarels bp->av_back->av_forw = bp->av_forw; 150026127Skarels bp->av_forw->av_back = bp->av_back; 150126135Skarels # if defined(VAX750) 150226135Skarels if (cpu == VAX_750) { 150326135Skarels if ((tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) && 150426127Skarels (um->um_ubinfo != 0)) { 150526127Skarels ubarelse(um->um_ubanum, &um->um_ubinfo); 150626127Skarels } 150726127Skarels else { 150826127Skarels if (mp->mscp_opcode == (M_OP_READ|M_OP_END) || 150926127Skarels mp->mscp_opcode == (M_OP_WRITE|M_OP_END)) 151026135Skarels UBAPURGE(uba_hd[um->um_ubanum].uh_uba,(um->um_ubinfo >>28) & 0x0f); 151126127Skarels } 151226127Skarels } 151326127Skarels # endif 151426127Skarels dp = &tmsutab[ui->ui_unit]; 151526127Skarels dp->b_qsize--; 151626127Skarels if (st == M_ST_OFFLN || st == M_ST_AVLBL) 151726127Skarels { 151826127Skarels ui->ui_flags = 0; /* mark unit offline */ 151926135Skarels tms->tms_openf = 0; 152026135Skarels tms->tms_type = mp->mscp_mediaid; 152126127Skarels /* 152226127Skarels * Link the buffer onto the front of the drive queue 152326127Skarels */ 152426127Skarels if ((bp->av_forw = dp->b_actf) == 0) 152526127Skarels dp->b_actl = bp; 152626127Skarels dp->b_actf = bp; 152726127Skarels /* 152826127Skarels * Link the drive onto the controller queue 152926127Skarels */ 153026127Skarels if (dp->b_active == 0) 153126127Skarels { 153226127Skarels dp->b_forw = NULL; 153326127Skarels if (um->um_tab.b_actf == NULL) 153426127Skarels um->um_tab.b_actf = dp; 153526127Skarels else 153626127Skarels um->um_tab.b_actl->b_forw = dp; 153726127Skarels um->um_tab.b_actl = dp; 153826127Skarels dp->b_active = 1; 153926127Skarels } 154026135Skarels # if defined(VAX750) 154126135Skarels if (cpu == VAX_750 && um->um_ubinfo == 0) 154226135Skarels um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); 154326127Skarels # endif 154426127Skarels return; 154526127Skarels } 154626127Skarels if (st != M_ST_SUCC) 154726127Skarels { 154826127Skarels if (mp->mscp_flags & M_EF_SEREX) 154926135Skarels tms->tms_serex = 1; 155026127Skarels if (st != M_ST_TAPEM) 155126127Skarels { 155226135Skarels tprintf(tms->tms_ttyp, 155326135Skarels "tms%d: hard error bn%d\n", 155426135Skarels minor(bp->b_dev)&03, bp->b_blkno); 155526135Skarels errinfo(st); /* produces more info */ 155626127Skarels # ifdef DEBUG 155726135Skarels printd("tmscprsp: error; status sub-code = 0%o, flags = 0%o\n", 155826135Skarels (mp->mscp_status & 177740)>>5, mp->mscp_flags); 155926127Skarels # endif 156026127Skarels bp->b_flags |= B_ERROR; 156126127Skarels } 156226127Skarels else 156326127Skarels /* Hit a tape mark - Set serex flag to 156426127Skarels * a special value so we can clear the 156526127Skarels * serious exception on the next command. 156626127Skarels */ 156726135Skarels tms->tms_serex = 2; 156826127Skarels } 156926127Skarels /* 157026127Skarels * The tmscp spec states that controllers do not have to 157126127Skarels * report the number of records or files skipped. So on 157226127Skarels * reposition commands we go strictly by cmd status. 157326127Skarels */ 157426127Skarels if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) 157526127Skarels bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; 157626127Skarels else 157726127Skarels bp->b_resid = 0; 157826135Skarels tms->tms_resid = bp->b_resid; 157926127Skarels iodone(bp); 158026127Skarels break; 158126135Skarels 158226127Skarels case M_OP_GTUNT|M_OP_END: 158326127Skarels # ifdef DEBUG 158426127Skarels printd("tmscprsp: GTUNT end packet status = 0%o\n",st); 158526135Skarels printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n" 158626127Skarels ,mp->mscp_unit, mp->mscp_mediaid 158726127Skarels ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) 158826127Skarels ,F_to_C(mp,1),F_to_C(mp,0) 158926127Skarels ,mp->mscp_mediaid & 0x7f 159026127Skarels ,mp->mscp_unitid.val[0] 159126127Skarels ,mp->mscp_unitid.val[1] 159226127Skarels ,mp->mscp_format); 159326127Skarels # endif 159426135Skarels tms->tms_type = mp->mscp_mediaid; 159526135Skarels tms->tms_fmtmenu = mp->mscp_fmtmenu; 159626135Skarels tms->tms_unitflgs = mp->mscp_unitflgs; 159726127Skarels break; 159826135Skarels 159926127Skarels default: 160026127Skarels printf("tmscp unknown packet\n"); 160126127Skarels tmserror(um, (struct mslg *)mp); 160226127Skarels } /* end switch mp->mscp_opcode */ 160326127Skarels } 160426135Skarels 160526135Skarels 160626127Skarels /* 160726127Skarels * Give a meaningful error when the mscp_status field returns an error code. 160826127Skarels */ 160926135Skarels 161026127Skarels errinfo(st) 161126127Skarels int st; /* the status code */ 161226127Skarels { 161326127Skarels switch(st) { 161426127Skarels case M_ST_ICMD: 161526127Skarels printf("invalid command\n"); 161626127Skarels break; 161726127Skarels case M_ST_ABRTD: 161826127Skarels printf("command aborted\n"); 161926127Skarels break; 162026127Skarels case M_ST_OFFLN: 162126127Skarels printf("unit offline\n"); 162226127Skarels break; 162326127Skarels case M_ST_WRTPR: 162426127Skarels printf("unit write protected\n"); 162526127Skarels break; 162626127Skarels case M_ST_COMP: 162726127Skarels printf("compare error\n"); 162826127Skarels break; 162926127Skarels case M_ST_DATA: 163026127Skarels printf("data error\n"); 163126127Skarels break; 163226127Skarels case M_ST_HSTBF: 163326127Skarels printf("host buffer access error\n"); 163426127Skarels break; 163526127Skarels case M_ST_CNTLR: 163626127Skarels printf("controller error\n"); 163726127Skarels break; 163826127Skarels case M_ST_DRIVE: 163926127Skarels printf("drive error\n"); 164026127Skarels break; 164126127Skarels case M_ST_FMTER: 164226127Skarels printf("formatter error\n"); 164326127Skarels break; 164426127Skarels case M_ST_BOT: 164526127Skarels printf("BOT encountered\n"); 164626127Skarels break; 164726127Skarels case M_ST_TAPEM: 164826127Skarels printf("tape mark encountered\n"); 164926127Skarels break; 165026127Skarels case M_ST_RDTRN: 165126127Skarels printf("record data truncated\n"); 165226127Skarels break; 165326127Skarels case M_ST_PLOST: 165426127Skarels printf("position lost\n"); 165526127Skarels break; 165626127Skarels case M_ST_SEX: 165726127Skarels printf("serious exception\n"); 165826127Skarels break; 165926127Skarels case M_ST_LED: 166026127Skarels printf("LEOT detected\n"); 166126127Skarels break; 166226127Skarels } 166326127Skarels } 166426135Skarels 166526135Skarels 166626127Skarels /* 166726127Skarels * Manage buffers and perform block mode read and write operations. 166826127Skarels */ 166926135Skarels 167026127Skarels tmscpstrategy (bp) 167126127Skarels register struct buf *bp; 167226127Skarels { 167326127Skarels register struct uba_device *ui; 167426127Skarels register struct uba_ctlr *um; 167526127Skarels register struct buf *dp; 167626127Skarels register int unit = TMSUNIT(bp->b_dev); 167726127Skarels int s; 167826135Skarels 167926135Skarels if (unit >= NTMS) 168026127Skarels { 168126127Skarels # ifdef DEBUG 168226127Skarels printd ("tmscpstrategy: bad unit # %d\n",unit); 168326127Skarels # endif 168426127Skarels bp->b_flags |= B_ERROR; 168526127Skarels iodone(bp); 168626127Skarels return; 168726127Skarels } 168826127Skarels ui = tmsdinfo[unit]; 168926127Skarels um = ui->ui_mi; 169026127Skarels if (ui == 0 || ui->ui_alive == 0) 169126127Skarels { 169226127Skarels bp->b_flags |= B_ERROR; 169326127Skarels iodone(bp); 169426127Skarels return; 169526127Skarels } 169626127Skarels s = spl5(); 169726127Skarels /* 169826127Skarels * Link the buffer onto the drive queue 169926127Skarels */ 170026127Skarels dp = &tmsutab[ui->ui_unit]; 170126127Skarels if (dp->b_actf == 0) 170226127Skarels dp->b_actf = bp; 170326127Skarels else 170426127Skarels dp->b_actl->av_forw = bp; 170526127Skarels dp->b_actl = bp; 170626127Skarels bp->av_forw = 0; 170726127Skarels /* 170826127Skarels * Link the drive onto the controller queue 170926127Skarels */ 171026127Skarels if (dp->b_active == 0) 171126127Skarels { 171226127Skarels dp->b_forw = NULL; 171326127Skarels if (um->um_tab.b_actf == NULL) 171426127Skarels um->um_tab.b_actf = dp; 171526127Skarels else 171626127Skarels um->um_tab.b_actl->b_forw = dp; 171726127Skarels um->um_tab.b_actl = dp; 171826127Skarels dp->b_active = 1; 171926127Skarels } 172026127Skarels /* 172126127Skarels * If the controller is not active, start it. 172226127Skarels */ 172326127Skarels if (um->um_tab.b_active == 0) 172426127Skarels { 172526135Skarels # if defined(VAX750) 172626135Skarels if (cpu == VAX_750 172726135Skarels && tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) 172826127Skarels { 172926127Skarels if (um->um_ubinfo != 0) 173026135Skarels log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n", 173126135Skarels um->um_ubinfo); 173226127Skarels else 173326135Skarels um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); 173426127Skarels } 173526127Skarels # endif 173626127Skarels # ifdef DEBUG 173726135Skarels printd10("tmscpstrategy: Controller not active, starting it\n"); 173826127Skarels # endif 173926127Skarels (void) tmscpstart(um); 174026127Skarels } 174126127Skarels splx(s); 174226127Skarels return; 174326127Skarels } 174426135Skarels 174526127Skarels #define DBSIZE 32 174626135Skarels 174726127Skarels #define ca_Rspdsc ca_rspdsc[0] 174826127Skarels #define ca_Cmddsc ca_rspdsc[1] 174926127Skarels #define tmscp_Rsp tmscp_rsp[0] 175026127Skarels #define tmscp_Cmd tmscp_cmd[0] 175126135Skarels 175226127Skarels struct tmscp tmscpd[NTMSCP]; 175326135Skarels 175426127Skarels tmscpdump(dev) 175526127Skarels dev_t dev; 175626127Skarels { 175726127Skarels struct tmscpdevice *tmscpaddr; 175826127Skarels struct tmscp *tmscp_ubaddr; 175926127Skarels char *start; 176026127Skarels int num, blk, unit; 176126127Skarels register struct uba_regs *uba; 176226127Skarels register struct uba_device *ui; 176326127Skarels register struct tmscp *tmscpp; 176426127Skarels register struct pte *io; 176526127Skarels register int i; 176626135Skarels 176726127Skarels unit = minor(dev) & 03; 176826135Skarels if (unit >= NTMS) 176926127Skarels return (ENXIO); 177026127Skarels # define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 177126127Skarels ui = phys(struct uba_device *, tmsdinfo[unit]); 177226127Skarels if (ui->ui_alive == 0) 177326127Skarels return (ENXIO); 177426127Skarels uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 177526135Skarels ubainit(uba); 177626127Skarels tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; 177726127Skarels DELAY(2000000); 177826127Skarels tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); 177926135Skarels 178026127Skarels num = btoc(sizeof(struct tmscp)) + 1; 178126127Skarels io = &uba->uba_map[NUBMREG-num]; 178226127Skarels for(i = 0; i<num; i++) 178326127Skarels *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); 178426135Skarels tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9)); 178526135Skarels 178626127Skarels tmscpaddr->tmscpip = 0; 178726127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 178826127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 178926127Skarels tmscpaddr->tmscpsa = TMSCP_ERR; 179026127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) 179126127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 179226127Skarels tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; 179326127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) 179426127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 179526135Skarels tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); 179626127Skarels while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) 179726127Skarels if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); 179826127Skarels tmscpaddr->tmscpsa = TMSCP_GO; 179926135Skarels tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref; 180026135Skarels tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref; 180126127Skarels tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ 180226127Skarels tmscpp->tmscp_Cmd.mscp_cntflgs = 0; 180326127Skarels tmscpp->tmscp_Cmd.mscp_version = 0; 180426127Skarels if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { 180526127Skarels return(EFAULT); 180626127Skarels } 180726127Skarels tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; 180826127Skarels if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { 180926127Skarels return(EFAULT); 181026127Skarels } 181126135Skarels 181226127Skarels num = maxfree; 181326127Skarels start = 0; 181426127Skarels while (num > 0) 181526127Skarels { 181626127Skarels blk = num > DBSIZE ? DBSIZE : num; 181726127Skarels io = uba->uba_map; 181826127Skarels for (i = 0; i < blk; i++) 181926127Skarels *(int *)io++ = (btop(start)+i) | UBAMR_MRV; 182026127Skarels *(int *)io = 0; 182126127Skarels tmscpp->tmscp_Cmd.mscp_lbn = btop(start); 182226127Skarels tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; 182326127Skarels tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG; 182426127Skarels # ifdef MVAX 182526127Skarels if( cpu == MVAX_I ) 182626127Skarels tmscpp->tmscp_Cmd.mscp_buffer = (long) start; 182726127Skarels else 182826127Skarels # endif MVAX 182926127Skarels tmscpp->tmscp_Cmd.mscp_buffer = 0; 183026127Skarels if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) 183126127Skarels return(EIO); 183226127Skarels start += blk*NBPG; 183326127Skarels num -= blk; 183426127Skarels } 183526127Skarels return (0); 183626127Skarels } 183726135Skarels 183826135Skarels 183926127Skarels /* 184026127Skarels * Perform a standalone tmscp command. This routine is only used by tmscpdump. 184126127Skarels */ 184226135Skarels 184326127Skarels tmscpcmd(op, tmscpp, tmscpaddr) 184426127Skarels int op; 184526127Skarels register struct tmscp *tmscpp; 184626127Skarels struct tmscpdevice *tmscpaddr; 184726127Skarels { 184826127Skarels int i; 184926135Skarels 185026135Skarels 185126127Skarels tmscpp->tmscp_Cmd.mscp_opcode = op; 185226127Skarels tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; 185326127Skarels tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; 185426127Skarels tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; 185526127Skarels tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; 185626127Skarels if (tmscpaddr->tmscpsa&TMSCP_ERR) 185726127Skarels printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); 185826127Skarels i = tmscpaddr->tmscpip; 185926293Skarels #ifdef lint 186026293Skarels i = i; 186126293Skarels #endif 186226127Skarels for (;;) 186326127Skarels { 186426127Skarels if (tmscpp->tmscp_ca.ca_cmdint) 186526127Skarels tmscpp->tmscp_ca.ca_cmdint = 0; 186626127Skarels if (tmscpp->tmscp_ca.ca_rspint) 186726127Skarels break; 186826127Skarels } 186926127Skarels tmscpp->tmscp_ca.ca_rspint = 0; 187026127Skarels if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || 187126127Skarels (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) 187226127Skarels { 187326127Skarels printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, 187426135Skarels tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status); 187526127Skarels return(0); 187626127Skarels } 187726127Skarels return(1); 187826127Skarels } 187926135Skarels 188026135Skarels 188126127Skarels /* 188226127Skarels * Perform raw read 188326127Skarels */ 188426135Skarels 188526127Skarels tmscpread(dev, uio) 188626127Skarels dev_t dev; 188726127Skarels struct uio *uio; 188826127Skarels { 188926127Skarels register int unit = TMSUNIT(dev); 189026135Skarels 189126135Skarels if (unit >= NTMS) 189226127Skarels return (ENXIO); 189326135Skarels return (physio(tmscpstrategy, &rtmsbuf[unit], dev, B_READ, minphys, uio)); 189426127Skarels } 189526135Skarels 189626135Skarels 189726127Skarels /* 189826127Skarels * Perform raw write 189926127Skarels */ 190026135Skarels 190126127Skarels tmscpwrite(dev, uio) 190226127Skarels dev_t dev; 190326127Skarels struct uio *uio; 190426127Skarels { 190526127Skarels register int unit = TMSUNIT(dev); 190626135Skarels 190726135Skarels if (unit >= NTMS) 190826127Skarels return (ENXIO); 190926135Skarels return (physio(tmscpstrategy, &rtmsbuf[unit], dev, B_WRITE, minphys, uio)); 191026127Skarels } 191126135Skarels 191226135Skarels 191326127Skarels /* 191426127Skarels * Catch ioctl commands, and call the "command" routine to do them. 191526127Skarels */ 191626135Skarels 191726293Skarels /* ARGSUSED */ 191826127Skarels tmscpioctl(dev, cmd, data, flag) 191926127Skarels dev_t dev; 192026127Skarels int cmd; 192126127Skarels caddr_t data; 192226127Skarels int flag; 192326127Skarels { 192426127Skarels register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; 192526127Skarels register callcount; /* number of times to call cmd routine */ 192626127Skarels register struct uba_device *ui; 192726135Skarels register struct tms_info *tms; 192826127Skarels int fcount; /* number of files (or records) to space */ 192926293Skarels register struct mtop *mtop; /* mag tape cmd op to perform */ 193026293Skarels register struct mtget *mtget; /* mag tape struct to get info in */ 193126135Skarels 193226127Skarels /* we depend of the values and order of the TMS ioctl codes here */ 193326127Skarels static tmsops[] = 193426127Skarels {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, 193526127Skarels TMS_CACHE,TMS_NOCACHE}; 193626135Skarels 193726127Skarels switch (cmd) { 193826127Skarels case MTIOCTOP: /* tape operation */ 193926127Skarels mtop = (struct mtop *)data; 194026127Skarels switch (mtop->mt_op) { 194126135Skarels 194226127Skarels case MTWEOF: 194326127Skarels callcount = mtop->mt_count; 194426127Skarels fcount = 1; 194526127Skarels break; 194626127Skarels case MTFSF: case MTBSF: 194726127Skarels case MTFSR: case MTBSR: 194826127Skarels callcount = 1; 194926127Skarels fcount = mtop->mt_count; 195026127Skarels break; 195126127Skarels case MTREW: case MTOFFL: case MTNOP: 195226127Skarels case MTCACHE: case MTNOCACHE: 195326127Skarels callcount = 1; 195426127Skarels fcount = 1; /* wait for this rewind */ 195526127Skarels break; 195626127Skarels default: 195726127Skarels return (ENXIO); 195826127Skarels } /* end switch mtop->mt_op */ 195926135Skarels 196026127Skarels if (callcount <= 0 || fcount <= 0) 196126127Skarels return (EINVAL); 196226127Skarels while (--callcount >= 0) 196326127Skarels { 196426127Skarels tmscpcommand(dev, tmsops[mtop->mt_op], fcount); 196526127Skarels if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 196626127Skarels bp->b_resid) 196726127Skarels return (EIO); 196826127Skarels if (bp->b_flags & B_ERROR) /* like hitting BOT */ 196926127Skarels break; 197026127Skarels } 197126127Skarels return (geterror(bp)); 197226135Skarels 197326127Skarels case MTIOCGET: 197426127Skarels /* 197526127Skarels * Return status info associated with the particular UNIT. 197626127Skarels */ 197726127Skarels ui = tmsdinfo[TMSUNIT(dev)]; 197826135Skarels tms = &tms_info[ui->ui_unit]; 197926127Skarels mtget = (struct mtget *)data; 198026127Skarels mtget->mt_type = MT_ISTMSCP; 198126135Skarels mtget->mt_dsreg = tms->tms_flags << 8; 198226135Skarels mtget->mt_dsreg |= tms->tms_endcode; 198326135Skarels mtget->mt_erreg = tms->tms_status; 198426135Skarels mtget->mt_resid = tms->tms_resid; 198526127Skarels break; 198626135Skarels 198726127Skarels default: 198826127Skarels return (ENXIO); 198926127Skarels } 199026127Skarels return (0); 199126127Skarels } 199226135Skarels 199326135Skarels 199426127Skarels /* 199526127Skarels * Reset (for raw mode use only). 199626127Skarels */ 199726135Skarels 199826127Skarels tmscpreset (uban) 199926127Skarels int uban; 200026127Skarels { 200126127Skarels register struct uba_ctlr *um; 200226127Skarels register struct uba_device *ui; 200326127Skarels register struct buf *bp, *dp; 200426127Skarels register int unit; 200526127Skarels struct buf *nbp; 200626127Skarels int d; 200726135Skarels 200826127Skarels for (d = 0; d < NTMSCP; d++) 200926127Skarels { 201026127Skarels if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || 201126127Skarels um->um_alive == 0) 201226127Skarels continue; 201326127Skarels printf(" tmscp%d", d); 201426127Skarels um->um_tab.b_active = 0; 201526127Skarels um->um_tab.b_actf = um->um_tab.b_actl = 0; 201626127Skarels tmscp_softc[d].sc_state = S_IDLE; 201726127Skarels tmscp_softc[d].sc_mapped = 0; 201826135Skarels for (unit = 0; unit < NTMS; unit++) 201926127Skarels { 202026127Skarels if ((ui = tmsdinfo[unit]) == 0) 202126127Skarels continue; 202226127Skarels if (ui->ui_alive == 0 || ui->ui_mi != um) 202326127Skarels continue; 202426127Skarels tmsutab[unit].b_active = 0; 202526127Skarels tmsutab[unit].b_qsize = 0; 202626127Skarels } 202726127Skarels for (bp = tmscpwtab[d].av_forw; bp != &tmscpwtab[d]; bp = nbp) 202826127Skarels { 202926127Skarels nbp = bp->av_forw; 203026127Skarels bp->b_ubinfo = 0; 203126127Skarels /* 203226127Skarels * Link the buffer onto the drive queue 203326127Skarels */ 203426127Skarels dp = &tmsutab[TMSUNIT(bp->b_dev)]; 203526127Skarels if (dp->b_actf == 0) 203626127Skarels dp->b_actf = bp; 203726127Skarels else 203826127Skarels dp->b_actl->av_forw = bp; 203926127Skarels dp->b_actl = bp; 204026127Skarels bp->av_forw = 0; 204126127Skarels /* 204226127Skarels * Link the drive onto the controller queue 204326127Skarels */ 204426127Skarels if (dp->b_active == 0) 204526127Skarels { 204626127Skarels dp->b_forw = NULL; 204726127Skarels if (um->um_tab.b_actf == NULL) 204826127Skarels um->um_tab.b_actf = dp; 204926127Skarels else 205026127Skarels um->um_tab.b_actl->b_forw = dp; 205126127Skarels um->um_tab.b_actl = dp; 205226127Skarels dp->b_active = 1; 205326127Skarels } 205426127Skarels } 205526370Skarels (void)tmscpinit(d); 205626127Skarels } 205726127Skarels } 205826135Skarels 205926135Skarels 206026127Skarels /* 206126127Skarels * Process an error log message 206226127Skarels * 206326127Skarels * Only minimal decoding is done, only "useful" 206426127Skarels * information is printed. Eventually should 206526127Skarels * send message to an error logger. 206626127Skarels */ 206726135Skarels 206826127Skarels tmserror(um, mp) 206926127Skarels register struct uba_ctlr *um; 207026127Skarels register struct mslg *mp; 207126127Skarels { 207226127Skarels register i; 207326135Skarels 207426127Skarels # ifdef DEBUG 207526127Skarels printd("tmserror:\n"); 207626127Skarels # endif 207726127Skarels if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) 207826135Skarels log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr, 207926127Skarels mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); 208026135Skarels 208126127Skarels switch (mp->mslg_format) { 208226135Skarels 208326127Skarels case M_FM_CNTERR: 208426135Skarels log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event); 208526127Skarels break; 208626127Skarels case M_FM_BUSADDR: 208726135Skarels log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", 208826127Skarels mp->mslg_event, mp->mslg_busaddr); 208926127Skarels break; 209026127Skarels case M_FM_TAPETRN: 209126135Skarels log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", 209226127Skarels mp->mslg_unit, mp->mslg_group, mp->mslg_event); 209326127Skarels break; 209426127Skarels case M_FM_STIERR: 209526135Skarels log(TMS_PRI, "STI error, unit %d, event 0%o\n", 209626127Skarels mp->mslg_unit, mp->mslg_event); 209726135Skarels #ifdef notdef 209826135Skarels /* too painful to do with log() */ 209926127Skarels for(i = 0; i < 62;i++) 210026127Skarels mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); 210126127Skarels mprintf("\n"); 210226135Skarels #endif 210326127Skarels break; 210426127Skarels case M_FM_STIDEL: 210526135Skarels log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n", 210626127Skarels mp->mslg_unit, mp->mslg_event); 210726127Skarels break; 210826127Skarels case M_FM_STIFEL: 210926135Skarels log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n", 211026127Skarels mp->mslg_unit, mp->mslg_event); 211126127Skarels break; 211226127Skarels default: 211326135Skarels log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n", 211426127Skarels mp->mslg_unit, mp->mslg_format, mp->mslg_event); 211526127Skarels } 211626135Skarels 211726127Skarels if (tmscperror) 211826127Skarels { 211926127Skarels register long *p = (long *)mp; 212026135Skarels 212126127Skarels for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) 212226127Skarels printf("%x ", *p++); 212326127Skarels printf("\n"); 212426127Skarels } 212526127Skarels } 212626127Skarels #endif 2127