1:
2: /* @(#)tmscp.c 7.1 (Berkeley) 6/5/86 */
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 "../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:
69: u_short tmscpstd[] = { 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: /*
90: * Open a tmscp device. Initialize the controller and set the unit online.
91: */
92: tmscpopen(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: */
193: tmscpclose(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: */
204: struct mscp *
205: tmscpcmd(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: */
262: tmscpstrategy(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*/
293: tmscpioctl(io, cmd, arg)
294: struct iob *io;
295: int cmd;
296: caddr_t arg;
297: {
298: return (ECMD);
299: }
Defined functions
Defined variables
tmscp
defined in line
79; used 27 times
Defined struct's
tmscp
defined in line
75; used 4 times
Defined macros
NCMD
defined in line
63;
never used
NRSP
defined in line
62;
never used