mv pcs750.bin to /usr/src/etc/vax
[unix-history] / usr / src / sys / vax / stand / tmscp.c
CommitLineData
8e292a1d 1
77fd7284 2/* @(#)tmscp.c 7.4 (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
39c71180
MK
46#include "param.h"
47#include "inode.h"
48#include "fs.h"
49
50#include "../vax/pte.h"
51
8e292a1d 52#include "savax.h"
8e292a1d
KD
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
cf703c6c
KB
68#define MAXCTLR 1 /* all addresses must be specified */
69u_short tmscpstd[MAXCTLR] = { 0174500 };
8e292a1d
KD
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;
cf703c6c 79} tmscp;
8e292a1d
KD
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
8e292a1d
KD
88/*
89 * Open a tmscp device. Initialize the controller and set the unit online.
90 */
91tmscpopen(io)
92 register struct iob *io;
93{
94 register struct mscp *mp;
95 int i;
96
cf703c6c
KB
97 if ((u_int)io->i_ctlr >= MAXCTLR)
98 return (ECTLR);
8e292a1d
KD
99 /*
100 * Have the tmscp controller characteristics already been set up
101 * (STCON)?
102 */
cf703c6c 103 if (tmscp_offline) {
8e292a1d 104 if (tmscpaddr == 0)
cf703c6c
KB
105 tmscpaddr = (struct tmscpdevice *)ubamem(io->i_adapt, tmscpstd[0]);
106 if (tmscp_ubaddr == 0) {
77fd7284 107 ctmscpbuf = *io;
8e292a1d
KD
108 ctmscpbuf.i_ma = (caddr_t)&tmscp;
109 ctmscpbuf.i_cc = sizeof(tmscp);
110 tmscp_ubaddr = (struct tmscp *)ubasetup(&ctmscpbuf, 2);
cf703c6c 111 }
8e292a1d
KD
112 /*
113 * Initialize the tmscp device and wait for the 4 steps
114 * to complete.
115 */
116 tmscpaddr->tmscpip = 0;
cf703c6c 117 while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0);
8e292a1d
KD
118 tmscpaddr->tmscpsa =TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8);
119
cf703c6c 120 while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0);
8e292a1d
KD
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
cf703c6c 127 while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0);
8e292a1d
KD
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
cf703c6c 134 while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0);
8e292a1d
KD
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;
cf703c6c 151 if (tmscpcmd(M_OP_STCON, 0) == 0) {
39c71180
MK
152 printf("tms: open error, STCON\n");
153 return (EIO);
8e292a1d 154 }
cf703c6c
KB
155 tmscp_offline = 0;
156 }
8e292a1d
KD
157 tmscp.tmscp_cmd.mscp_unit = io->i_unit&03;
158 /*
159 * Has this unit been issued an ONLIN?
160 */
cf703c6c
KB
161 if (tms_offline[tmscp.tmscp_cmd.mscp_unit]) {
162 if ((mp = tmscpcmd(M_OP_ONLIN, 0)) == 0) {
39c71180
MK
163 _stop("tms: open error, ONLIN\n");
164 return (EIO);
8e292a1d 165 }
cf703c6c 166 tms_offline[tmscp.tmscp_cmd.mscp_unit] = 0;
39c71180 167 }
cf703c6c
KB
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) {
8e292a1d
KD
175 /*
176 * Skip forward the appropriate number of files on the tape.
177 */
cf703c6c
KB
178 tmscp.tmscp_cmd.mscp_tmkcnt = io->i_part;
179 (void)tmscpcmd(M_OP_REPOS, 0);
8e292a1d 180 tmscp.tmscp_cmd.mscp_tmkcnt = 0;
cf703c6c 181 }
39c71180 182 return (0);
8e292a1d
KD
183}
184
8e292a1d
KD
185/*
186 * Close the device (rewind it to BOT)
187 */
188tmscpclose(io)
189 register struct iob *io;
190{
cf703c6c 191 (void)tmscpcmd(M_OP_REPOS, M_MD_REWND);
8e292a1d
KD
192}
193
8e292a1d
KD
194/*
195 * Set up tmscp command packet. Cause the controller to poll to pick up
196 * the command.
197 */
198struct mscp *
199tmscpcmd(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;
cf703c6c
KB
213 for (;;) {
214 if (tmscpaddr->tmscpsa & TMSCP_ERR) {
8e292a1d
KD
215 printf("tmscpcmd: Fatal error sa=%o\n", tmscpaddr->tmscpsa & 0xffff);
216 return(0);
cf703c6c 217 }
8e292a1d
KD
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.
cf703c6c
KB
226 *
227 *
228 * if (tmscp.tmscp_ca.ca_rspint)
229 * break;
8e292a1d 230 */
8e292a1d
KD
231 if (!(tmscp.tmscp_ca.ca_rspdsc[0] & (TMSCP_OWN)))
232 break;
cf703c6c 233 }
8e292a1d
KD
234 tmscp.tmscp_ca.ca_rspint = 0;
235 mp = &tmscp.tmscp_rsp;
236 if (mp->mscp_opcode != (op|M_OP_END) ||
cf703c6c
KB
237 (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) {
238 /*
239 * Detect hitting tape mark. This signifies the end of the
8e292a1d
KD
240 * tape mini-root file. We don't want to return an error
241 * condition to the strategy routine.
242 */
cf703c6c
KB
243 if ((mp->mscp_status & M_ST_MASK) != M_ST_TAPEM)
244 return(0);
245 }
8e292a1d
KD
246 return(mp);
247}
248
8e292a1d
KD
249/*
250 * Set up to do reads and writes; call tmscpcmd to issue the cmd.
251 */
252tmscpstrategy(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);
cf703c6c 265 if ((mp = tmscpcmd(func == READ ? M_OP_READ : M_OP_WRITE, 0)) == 0) {
8e292a1d
KD
266 ubafree(io, ubinfo);
267 printf("tms: I/O error\n");
268 return(-1);
cf703c6c 269 }
8e292a1d
KD
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}