1
2 /* @(#)tmscp.c 7.7 (Berkeley) 05/04/91 */
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 */
tmscpopen(io)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 */
tmscpclose(io)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 *
tmscpcmd(op,mod)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 */
tmscpstrategy(io,func)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 == F_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