4.3BSD release version
[unix-history] / usr / src / sys / vax / stand / tmscp.c
CommitLineData
8e292a1d 1
0880b18e 2/* @(#)tmscp.c 7.1 (Berkeley) %G% */
8e292a1d
KD
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
31static 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
69u_short tmscpstd[] = { 0174500 };
70
71struct iob ctmscpbuf;
72
73struct tmscpdevice *tmscpaddr = 0;
74
75struct tmscp {
76 struct tmscpca tmscp_ca;
77 struct mscp tmscp_rsp;
78 struct mscp tmscp_cmd;
79 } tmscp;
80
81struct tmscp *tmscp_ubaddr; /* Unibus address of tmscp structure */
82
83struct mscp *tmscpcmd();
84
85int tmscp_offline = 1; /* Flag to prevent multiple STCON */
86int 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 */
92tmscpopen(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 */
193tmscpclose(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 */
204struct mscp *
205tmscpcmd(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 */
262tmscpstrategy(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*/
293tmscpioctl(io, cmd, arg)
294 struct iob *io;
295 int cmd;
296 caddr_t arg;
297{
298 return (ECMD);
299}