xref: /csrg-svn/sys/vax/uba/tmscp.c (revision 26135)
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