xref: /original-bsd/sys/vax/stand/tmscp.c (revision 57124d5e)
1 
2 /*	@(#)tmscp.c	7.1 (Berkeley) 06/05/86 */
3 
4 /****************************************************************
5  *                                                              *
6  *        Licensed from Digital Equipment Corporation           *
7  *                       Copyright (c)                          *
8  *               Digital Equipment Corporation                  *
9  *                   Maynard, Massachusetts                     *
10  *                         1985, 1986                           *
11  *                    All rights reserved.                      *
12  *                                                              *
13  *        The Information in this software is subject to change *
14  *   without notice and should not be construed as a commitment *
15  *   by  Digital  Equipment  Corporation.   Digital   makes  no *
16  *   representations about the suitability of this software for *
17  *   any purpose.  It is supplied "As Is" without expressed  or *
18  *   implied  warranty.                                         *
19  *                                                              *
20  *        If the Regents of the University of California or its *
21  *   licensees modify the software in a manner creating         *
22  *   diriviative copyright rights, appropriate copyright        *
23  *   legends may be placed on  the drivative work in addition   *
24  *   to that set forth above.                                   *
25  ***************************************************************/
26 /*
27  * tmscp.c - TMSCP (TK50/TU81) standalone driver
28  */
29 
30 # ifndef lint
31 static char *sccsid = "@(#)tmscp.c	1.5	(ULTRIX)	4/18/86";
32 # endif not lint
33 
34 /* ------------------------------------------------------------------------
35  * Modification History: /sys/stand/tmscp.c
36  *
37  * 3-15-85  afd
38  *	Don't ask for an interrupt when commands are issued and
39  *	check ownership bit in the response descriptor to detect when a
40  *	command is complete.  Necessary due to the TU81's failure to set
41  *	the response interrupt field in the communications area.
42  *
43  * ------------------------------------------------------------------------
44  */
45 
46 #include "../machine/pte.h"
47 
48 #include "../h/param.h"
49 #include "../h/gnode.h"
50 #include "../h/devio.h"
51 
52 #include "savax.h"
53 
54 #include "saio.h"
55 
56 /*
57  * Parameters for the communications area
58  * (Only 1 cmd & 1 rsp packet)
59  */
60 #define	NRSPL2	0
61 #define	NCMDL2	0
62 #define	NRSP	(1<<NRSPL2)
63 #define	NCMD	(1<<NCMDL2)
64 
65 #include "../vaxuba/tmscpreg.h"
66 #include "../vaxuba/ubareg.h"
67 #include "../vax/tmscp.h"
68 
69 u_short tmscpstd[] = { 0174500 };
70 
71 struct iob	ctmscpbuf;
72 
73 struct tmscpdevice *tmscpaddr = 0;
74 
75 struct tmscp {
76 	struct tmscpca	tmscp_ca;
77 	struct mscp	tmscp_rsp;
78 	struct mscp	tmscp_cmd;
79 	} tmscp;
80 
81 struct tmscp *tmscp_ubaddr;		/* Unibus address of tmscp structure */
82 
83 struct mscp *tmscpcmd();
84 
85 int tmscp_offline = 1;		/* Flag to prevent multiple STCON */
86 int tms_offline[4] = {1,1,1,1}; /* Flag to prevent multiple ONLIN */
87 
88 
89 /*
90  * Open a tmscp device. Initialize the controller and set the unit online.
91  */
92 tmscpopen(io)
93 	register struct iob *io;
94 {
95 	register struct mscp *mp;
96 	int i;
97 
98 	/*
99 	 * Have the tmscp controller characteristics already been set up
100 	 * (STCON)?
101 	 */
102 	if (tmscp_offline)
103 		{
104 		if (tmscpaddr == 0)
105 			tmscpaddr = (struct tmscpdevice *)ubamem(io->i_unit, tmscpstd[0]);
106 		if (tmscp_ubaddr == 0)
107 			{
108 			ctmscpbuf.i_unit = io->i_unit;
109 			ctmscpbuf.i_ma = (caddr_t)&tmscp;
110 			ctmscpbuf.i_cc = sizeof(tmscp);
111 			tmscp_ubaddr = (struct tmscp *)ubasetup(&ctmscpbuf, 2);
112 			}
113 		/*
114 		 * Initialize the tmscp device and wait for the 4 steps
115 		 * to complete.
116 		 */
117 		tmscpaddr->tmscpip = 0;
118 		while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0)
119 			;
120 		tmscpaddr->tmscpsa =TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8);
121 
122 		while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0)
123 			;
124 #		define STEP1MASK 0174377
125 #		define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
126 		if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
127 			printf("tmscpopen: step 1 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff);
128 		tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase;
129 
130 		while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
131 			;
132 #		define STEP2MASK 0174377
133 #		define STEP2GOOD (TMSCP_STEP3)
134 		if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
135 			printf("tmscpopen: step 2 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff);
136 		tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16);
137 
138 		while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
139 			;
140 #		define STEP3MASK 0174000
141 #		define STEP3GOOD TMSCP_STEP4
142 		if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
143 			printf("tmscpopen: step 3 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff);
144 		tmscpaddr->tmscpsa = TMSCP_GO;
145 
146 		/*
147 		 * Init cmd & rsp area
148 		 */
149 		tmscp.tmscp_ca.ca_cmddsc[0] = (long)&tmscp_ubaddr->tmscp_cmd.mscp_cmdref;
150 		tmscp.tmscp_cmd.mscp_dscptr = tmscp.tmscp_ca.ca_cmddsc;
151 		tmscp.tmscp_cmd.mscp_header.tmscp_vcid = 1;	/* for tape */
152 
153 		tmscp.tmscp_ca.ca_rspdsc[0] = (long)&tmscp_ubaddr->tmscp_rsp.mscp_cmdref;
154 		tmscp.tmscp_rsp.mscp_dscptr = tmscp.tmscp_ca.ca_rspdsc;
155 		tmscp.tmscp_cmd.mscp_cntflgs = 0;
156 		if (tmscpcmd(M_OP_STCON, 0) == 0)
157 			{
158 			_stop("tms: open error, STCON");
159 			return;
160 			}
161 		tmscp_offline = 0;
162 		}
163 	tmscp.tmscp_cmd.mscp_unit = io->i_unit&03;
164 	/*
165 	 * Has this unit been issued an ONLIN?
166 	 */
167 	if (tms_offline[tmscp.tmscp_cmd.mscp_unit])
168 		{
169 		if ((mp = tmscpcmd(M_OP_ONLIN, 0)) == 0)
170 			{
171 			_stop("tms: open error, ONLIN");
172 			return;
173 			}
174 		tms_offline[tmscp.tmscp_cmd.mscp_unit] = 0;
175 		}
176 	if (io->i_boff < 0 || io->i_boff > 3)
177 		_stop("tms: bad offset");
178 	else if (io->i_boff > 0)
179 		/*
180 		 * Skip forward the appropriate number of files on the tape.
181 		 */
182 		{
183 		tmscp.tmscp_cmd.mscp_tmkcnt = io->i_boff;
184 		tmscpcmd(M_OP_REPOS, 0);
185 		tmscp.tmscp_cmd.mscp_tmkcnt = 0;
186 		}
187 }
188 
189 
190 /*
191  * Close the device (rewind it to BOT)
192  */
193 tmscpclose(io)
194 	register struct iob *io;
195 {
196 	tmscpcmd(M_OP_REPOS, M_MD_REWND);
197 }
198 
199 
200 /*
201  * Set up tmscp command packet.  Cause the controller to poll to pick up
202  * the command.
203  */
204 struct mscp *
205 tmscpcmd(op,mod)
206 	int op, mod;			/* opcode and modifier (usu 0) */
207 {
208 	struct mscp *mp;		/* ptr to cmd packet */
209 	int i;				/* read into to init polling */
210 
211 	tmscp.tmscp_cmd.mscp_opcode = op;
212 	tmscp.tmscp_cmd.mscp_modifier = mod;
213 	tmscp.tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen;
214 	tmscp.tmscp_ca.ca_cmddsc[0] |= TMSCP_OWN;	/* | TMSCP_INT */
215 	tmscp.tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen;
216 	tmscp.tmscp_ca.ca_rspdsc[0] |= TMSCP_OWN;	/* | TMSCP_INT */
217 
218 	i = tmscpaddr->tmscpip;
219 	for (;;)
220 		{
221 		if (tmscpaddr->tmscpsa & TMSCP_ERR)
222 			{
223 			printf("tmscpcmd: Fatal error sa=%o\n", tmscpaddr->tmscpsa & 0xffff);
224 			return(0);
225 			}
226 
227 		if (tmscp.tmscp_ca.ca_cmdint)
228 			tmscp.tmscp_ca.ca_cmdint = 0;
229 		/*
230 		 * This is to handle the case of devices not setting the
231 		 * interrupt field in the communications area. Some
232 		 * devices (early TU81's) only clear the ownership field
233 		 * in the Response Descriptor.
234 		 */
235 /*
236 		if (tmscp.tmscp_ca.ca_rspint)
237 			break;
238 */
239 		if (!(tmscp.tmscp_ca.ca_rspdsc[0] & (TMSCP_OWN)))
240 			break;
241 		}
242 	tmscp.tmscp_ca.ca_rspint = 0;
243 	mp = &tmscp.tmscp_rsp;
244 	if (mp->mscp_opcode != (op|M_OP_END) ||
245 	   (mp->mscp_status&M_ST_MASK) != M_ST_SUCC)
246 		{
247 		/* Detect hitting tape mark.  This signifies the end of the
248 		 * tape mini-root file.  We don't want to return an error
249 		 * condition to the strategy routine.
250 		 */
251 		if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM)
252 			return(mp);
253 		return(0);
254 		}
255 	return(mp);
256 }
257 
258 
259 /*
260  * Set up to do reads and writes; call tmscpcmd to issue the cmd.
261  */
262 tmscpstrategy(io, func)
263 	register struct iob *io;
264 	int func;
265 {
266 	register struct mscp *mp;
267 	int ubinfo;
268 
269 	ubinfo = ubasetup(io, 1);
270 	mp = &tmscp.tmscp_cmd;
271 	mp->mscp_lbn = io->i_bn;
272 	mp->mscp_unit = io->i_unit&03;
273 	mp->mscp_bytecnt = io->i_cc;
274 	mp->mscp_buffer = (ubinfo & 0x3fffff) | (((ubinfo>>28)&0xf)<<24);
275 	if ((mp = tmscpcmd(func == READ ? M_OP_READ : M_OP_WRITE, 0)) == 0)
276 		{
277 		ubafree(io, ubinfo);
278 		printf("tms: I/O error\n");
279 		return(-1);
280 		}
281 	ubafree(io, ubinfo);
282 	/*
283 	 * Detect hitting tape mark so we do it gracefully and return a
284 	 * character count of 0 to signify end of copy.  Rewind the tape
285 	 * before returning.
286 	 */
287 	if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM)
288 		return(0);
289 	return(io->i_cc);
290 }
291 
292 /*ARGSUSED*/
293 tmscpioctl(io, cmd, arg)
294 	struct iob *io;
295 	int cmd;
296 	caddr_t arg;
297 {
298 	return (ECMD);
299 }
300