xref: /original-bsd/sys/vax/stand/tmscp.c (revision 95407d66)
1 
2 /*	@(#)tmscp.c	7.6 (Berkeley) 12/16/90 */
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 "sys/param.h"
47 
48 #include "../include/pte.h"
49 
50 #include "stand/saio.h"
51 #include "savax.h"
52 
53 /*
54  * Parameters for the communications area
55  * (Only 1 cmd & 1 rsp packet)
56  */
57 #define	NRSPL2	0
58 #define	NCMDL2	0
59 #define	NRSP	(1<<NRSPL2)
60 #define	NCMD	(1<<NCMDL2)
61 
62 #include "../uba/tmscpreg.h"
63 #include "../uba/ubareg.h"
64 #include "../vax/tmscp.h"
65 
66 #define	MAXCTLR		1		/* all addresses must be specified */
67 u_short tmscpstd[MAXCTLR] = { 0174500 };
68 
69 struct iob	ctmscpbuf;
70 
71 struct tmscpdevice *tmscpaddr = 0;
72 
73 struct tmscp {
74 	struct tmscpca	tmscp_ca;
75 	struct mscp	tmscp_rsp;
76 	struct mscp	tmscp_cmd;
77 } tmscp;
78 
79 struct tmscp *tmscp_ubaddr;		/* Unibus address of tmscp structure */
80 
81 struct mscp *tmscpcmd();
82 
83 int tmscp_offline = 1;		/* Flag to prevent multiple STCON */
84 int tms_offline[4] = {1,1,1,1}; /* Flag to prevent multiple ONLIN */
85 
86 /*
87  * Open a tmscp device. Initialize the controller and set the unit online.
88  */
89 tmscpopen(io)
90 	register struct iob *io;
91 {
92 	register struct mscp *mp;
93 	int i;
94 
95 	if ((u_int)io->i_ctlr >= MAXCTLR)
96 		return (ECTLR);
97 	/*
98 	 * Have the tmscp controller characteristics already been set up
99 	 * (STCON)?
100 	 */
101 	if (tmscp_offline) {
102 		if (tmscpaddr == 0)
103 			tmscpaddr = (struct tmscpdevice *)ubamem(io->i_adapt, tmscpstd[0]);
104 		if (tmscp_ubaddr == 0) {
105 			ctmscpbuf = *io;
106 			ctmscpbuf.i_ma = (caddr_t)&tmscp;
107 			ctmscpbuf.i_cc = sizeof(tmscp);
108 			tmscp_ubaddr = (struct tmscp *)ubasetup(&ctmscpbuf, 2);
109 		}
110 		/*
111 		 * Initialize the tmscp device and wait for the 4 steps
112 		 * to complete.
113 		 */
114 		tmscpaddr->tmscpip = 0;
115 		while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0);
116 		tmscpaddr->tmscpsa =TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8);
117 
118 		while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0);
119 #		define STEP1MASK 0174377
120 #		define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
121 		if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
122 			printf("tmscpopen: step 1 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff);
123 		tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase;
124 
125 		while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0);
126 #		define STEP2MASK 0174377
127 #		define STEP2GOOD (TMSCP_STEP3)
128 		if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
129 			printf("tmscpopen: step 2 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff);
130 		tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16);
131 
132 		while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0);
133 #		define STEP3MASK 0174000
134 #		define STEP3GOOD TMSCP_STEP4
135 		if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
136 			printf("tmscpopen: step 3 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff);
137 		tmscpaddr->tmscpsa = TMSCP_GO;
138 
139 		/*
140 		 * Init cmd & rsp area
141 		 */
142 		tmscp.tmscp_ca.ca_cmddsc[0] = (long)&tmscp_ubaddr->tmscp_cmd.mscp_cmdref;
143 		tmscp.tmscp_cmd.mscp_dscptr = tmscp.tmscp_ca.ca_cmddsc;
144 		tmscp.tmscp_cmd.mscp_header.tmscp_vcid = 1;	/* for tape */
145 
146 		tmscp.tmscp_ca.ca_rspdsc[0] = (long)&tmscp_ubaddr->tmscp_rsp.mscp_cmdref;
147 		tmscp.tmscp_rsp.mscp_dscptr = tmscp.tmscp_ca.ca_rspdsc;
148 		tmscp.tmscp_cmd.mscp_cntflgs = 0;
149 		if (tmscpcmd(M_OP_STCON, 0) == 0) {
150 			printf("tms: open error, STCON\n");
151 			return (EIO);
152 		}
153 		tmscp_offline = 0;
154 	}
155 	tmscp.tmscp_cmd.mscp_unit = io->i_unit&03;
156 	/*
157 	 * Has this unit been issued an ONLIN?
158 	 */
159 	if (tms_offline[tmscp.tmscp_cmd.mscp_unit]) {
160 		if ((mp = tmscpcmd(M_OP_ONLIN, 0)) == 0) {
161 			_stop("tms: open error, ONLIN\n");
162 			return (EIO);
163 		}
164 		tms_offline[tmscp.tmscp_cmd.mscp_unit] = 0;
165 	}
166 	/*
167 	 * This makes no sense, but I could be wrong... KB
168 	 *
169 	 *	if ((u_int)io->i_part > 3)
170 	 *		return (EPART);
171 	 */
172 	if (io->i_part) {
173 		/*
174 		 * Skip forward the appropriate number of files on the tape.
175 		 */
176 		tmscp.tmscp_cmd.mscp_tmkcnt = io->i_part;
177 		(void)tmscpcmd(M_OP_REPOS, 0);
178 		tmscp.tmscp_cmd.mscp_tmkcnt = 0;
179 	}
180 	return (0);
181 }
182 
183 /*
184  * Close the device (rewind it to BOT)
185  */
186 tmscpclose(io)
187 	register struct iob *io;
188 {
189 	(void)tmscpcmd(M_OP_REPOS, M_MD_REWND);
190 }
191 
192 /*
193  * Set up tmscp command packet.  Cause the controller to poll to pick up
194  * the command.
195  */
196 struct mscp *
197 tmscpcmd(op,mod)
198 	int op, mod;			/* opcode and modifier (usu 0) */
199 {
200 	struct mscp *mp;		/* ptr to cmd packet */
201 	int i;				/* read into to init polling */
202 
203 	tmscp.tmscp_cmd.mscp_opcode = op;
204 	tmscp.tmscp_cmd.mscp_modifier = mod;
205 	tmscp.tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen;
206 	tmscp.tmscp_ca.ca_cmddsc[0] |= TMSCP_OWN;	/* | TMSCP_INT */
207 	tmscp.tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen;
208 	tmscp.tmscp_ca.ca_rspdsc[0] |= TMSCP_OWN;	/* | TMSCP_INT */
209 
210 	i = tmscpaddr->tmscpip;
211 	for (;;) {
212 		if (tmscpaddr->tmscpsa & TMSCP_ERR) {
213 			printf("tmscpcmd: Fatal error sa=%o\n", tmscpaddr->tmscpsa & 0xffff);
214 			return(0);
215 		}
216 
217 		if (tmscp.tmscp_ca.ca_cmdint)
218 			tmscp.tmscp_ca.ca_cmdint = 0;
219 		/*
220 		 * This is to handle the case of devices not setting the
221 		 * interrupt field in the communications area. Some
222 		 * devices (early TU81's) only clear the ownership field
223 		 * in the Response Descriptor.
224 		 *
225 		 *
226 		 *	if (tmscp.tmscp_ca.ca_rspint)
227 		 *		break;
228 		 */
229 		if (!(tmscp.tmscp_ca.ca_rspdsc[0] & (TMSCP_OWN)))
230 			break;
231 	}
232 	tmscp.tmscp_ca.ca_rspint = 0;
233 	mp = &tmscp.tmscp_rsp;
234 	if (mp->mscp_opcode != (op|M_OP_END) ||
235 	   (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) {
236 		/*
237 		 * Detect hitting tape mark.  This signifies the end of the
238 		 * tape mini-root file.  We don't want to return an error
239 		 * condition to the strategy routine.
240 		 */
241 		if ((mp->mscp_status & M_ST_MASK) != M_ST_TAPEM)
242 			return(0);
243 	}
244 	return(mp);
245 }
246 
247 /*
248  * Set up to do reads and writes; call tmscpcmd to issue the cmd.
249  */
250 tmscpstrategy(io, func)
251 	register struct iob *io;
252 	int func;
253 {
254 	register struct mscp *mp;
255 	int ubinfo;
256 
257 	ubinfo = ubasetup(io, 1);
258 	mp = &tmscp.tmscp_cmd;
259 	mp->mscp_lbn = io->i_bn;
260 	mp->mscp_unit = io->i_unit&03;
261 	mp->mscp_bytecnt = io->i_cc;
262 	mp->mscp_buffer = (ubinfo & 0x3fffff) | (((ubinfo>>28)&0xf)<<24);
263 	if ((mp = tmscpcmd(func == READ ? M_OP_READ : M_OP_WRITE, 0)) == 0) {
264 		ubafree(io, ubinfo);
265 		printf("tms: I/O error\n");
266 		return(-1);
267 	}
268 	ubafree(io, ubinfo);
269 	/*
270 	 * Detect hitting tape mark so we do it gracefully and return a
271 	 * character count of 0 to signify end of copy.  Rewind the tape
272 	 * before returning.
273 	 */
274 	if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM)
275 		return(0);
276 	return(io->i_cc);
277 }
278