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