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