xref: /original-bsd/sys/vax/datakit/dkctl.c (revision 6d57652c)
1 /*
2  * Datakit driver
3  * Communication with control computer
4  */
5 
6 #include "datakit.h"
7 #if NDATAKIT>0
8 
9 #include "../include/pte.h"
10 #include "sys/param.h"
11 #include "sys/time.h"
12 #include "sys/kernel.h"
13 #include "sys/mbuf.h"
14 #include "sys/errno.h"
15 
16 #include "dkit.h"
17 #include "dkcmc.h"
18 #include "dk.h"
19 #include "dkdev.h"
20 #include "sys/syslog.h"
21 
22 
23 extern char *dkfcanon() ;
24 extern char *dktcanon() ;
25 
26 	static char	ProtocolVersion[] = S_HOSTVERSION;
27 
28 /*
29  *	configuration parameters
30  */
31 
32 	extern int			dk_nchan;
33 	extern struct dksetupreq	*dkreq[];
34 
35 short	dkcactive = 0 ;
36 short	dkc1omplete = 0 ;
37 short	dkc2omplete = 0 ;
38 int	dkcstall = 0;
39 int	dkctldebug = 512;
40 
41 #ifdef	RADIAN
42 int	commchan = 4;		/* Supervisory control channel */
43 #else
44 int	commchan = 1;		/* Supervisory control channel */
45 #endif
46 
47 
48 /*
49  *	messages to send to control
50  */
51 	static struct lmsg	closepack =	{T_CHG, D_CLOSE, 0, 0, 0, 0, 0};
52 	static struct lmsg	notify = 	{T_LSTNR, 0, 0, 0, 0, 0, 0};
53 	static struct lmsg	cmcmsg;
54 	static char		cmcinp[CMCSIZ];
55 
56 
57 dk_setup(chan, cmd, p1, p2, p3, p4, endfcn, endparm)
58 int (*endfcn)() ;
59 caddr_t endparm ;
60 {
61 register struct dksetupreq *req ;
62 struct mbuf *mb;
63 extern dkctime() ;
64 extern dkcin() ;
65 
66 #ifdef lint
67 	printf("Datakit protocol version %s\n", ProtocolVersion);
68 #endif
69 	if (chan >= dk_nchan || dkreq[chan])
70 		return -1 ;
71 	mb = m_get(M_DONTWAIT, DKMT_PCB);
72 	if (mb == NULL)
73 		return ENOBUFS ;
74 	mb->m_len = sizeof (struct dksetupreq);
75 	req = mtod(mb, struct dksetupreq *) ;
76 	req->rq_msg.type = cmd>>8 ;
77 	req->rq_msg.srv = cmd & 0377 ;
78 	req->rq_msg.param0 = chan ;
79 	req->rq_msg.param1 = p1 ;
80 	req->rq_msg.param2 = p2 ;
81 	req->rq_msg.param3 = p3 ;
82 	req->rq_msg.param4 = p4 ;
83 	req->rq_endfcn = endfcn ;
84 	req->rq_endparm = endparm ;
85 	if (dk_status(commchan) & DK_RESET) {
86 		(void) dk_close(commchan) ;
87 		dk_free(commchan) ;
88 		(void) dk_open(commchan, (int (*)()) NULL) ;
89 		(void) dk_recv(commchan, (caddr_t)cmcinp, CMCSIZ, 0, dkcin, (caddr_t) 0) ;
90 	}
91 	if (dkcactive == 0) dk_ccsinit();
92 	if ((dkcactive > 0) && (dkfpack((caddr_t)&req->rq_msg) < 0)) {
93 		if (chan > dkctldebug)
94 			log(LOG_ERR, "dk_setup %d: %x fail\n", chan, cmd);
95 		(void) m_free(dtom(req)) ;
96 		return -1 ;
97 	}
98 	dkreq[chan] = req ;
99 	if (chan > dkctldebug) log(LOG_ERR, "dk_setup %d: %x ok\n", chan, cmd);
100 	return 0 ;
101 }
102 
103 dk_ccsinit()
104 {
105 	if (dkcactive) return;
106 
107 	(void) dk_open(commchan, (int (*)()) NULL) ;
108 	notify.srv = 1 ;
109 	notify.param1 = dk_nchan;	/* tell max channel number */
110 	notify.param2 = HOSTVERSION;	/* tell version of host software */
111 	(void) dkfpack((caddr_t)&notify) ;
112 	notify.srv = 0 ;
113 	dkctime() ;
114 	dkcactive = 1 ;
115 	(void) dk_recv(commchan, (caddr_t)cmcinp, CMCSIZ, 0, dkcin, (caddr_t) 0) ;
116 }
117 
118 dk_takedown(chan)
119 {
120 	register s ;
121 	register struct dksetupreq *req ;
122 	extern struct dkdev	dkdev[];
123 	register struct	dkdev	*tp = &dkdev[chan];
124 	register struct mbuf *m;
125 
126 	if (dkcactive ) {
127 		s = spl5() ;
128 		if (req = dkreq[chan]) {
129 			dkreq[chan] = NULL ;
130 			if (req->rq_endfcn)
131 				(*req->rq_endfcn)(req->rq_endparm, chan, 2, -1, -1, -1) ;
132 			(void) m_free(dtom(req)) ;
133 		}
134 		if (tp->d_ctype) {
135 			MFREE(dtom(tp->d_ctype), m);
136 			tp->d_ctype = NULL;
137 		}
138 		splx(s) ;
139 		if ((dkcactive > 0) && (dk_status(commchan) & DK_OPEN)) {
140 			closepack.param0 = chan ;
141 			(void) dkfpack((caddr_t)&closepack) ;
142 		}
143 	} else
144 		dk_free(chan) ;
145 	return 0 ;
146 }
147 
148 
149 
150 dkctime()
151 {
152 	register chan ;
153 	register struct dksetupreq *req ;
154 	extern dkcin() ;
155 	int s = spl5();
156 
157 	if (dk_status(commchan) & DK_RESET) {
158 		(void) dk_close(commchan) ;
159 		dk_free(commchan) ;
160 		(void) dk_open(commchan, (int (*)()) NULL) ;
161 		(void) dk_recv(commchan, (caddr_t)cmcinp, CMCSIZ, 0, dkcin, (caddr_t) 0) ;
162 	}
163 	if (dkc1omplete == dkc2omplete) {
164 		dkcstall++;
165 		dkcactive = -1 ;
166 	}
167 	else {
168 		dkcstall = 0;
169 		dkcactive = 1 ;
170 	}
171 	dkc2omplete = dkc1omplete ;
172 
173 	if (dkcstall > 2)
174 		dk_cmd(commchan, (DKC_FLUSH | DKC_XINIT));
175 
176 	if ((dk_status(commchan) & (DK_BUSY|DK_OPEN)) == DK_OPEN) {
177 		for (chan = 2; chan < dk_nchan; chan++)   {
178 			if (dk_status(chan) & DK_LINGR) {
179 				closepack.param0 = chan ;
180 				(void) dkfpack((caddr_t) &closepack) ;
181 			}
182 			if (req = dkreq[chan])
183 				(void) dkfpack((caddr_t)&req->rq_msg) ;
184 		}
185 		notify.param1 = dk_nchan;
186 		(void) dkfpack((caddr_t)&notify) ;
187 		notify.srv = 0 ;
188 	}
189 
190 	timeout(dkctime, (caddr_t) 0, 5*hz) ;
191 	splx(s);
192 	return;
193 }
194 
195 dkfpack(msg)
196 caddr_t msg ;
197 {
198 struct mbuf *mb;
199 extern dkfdone() ;
200 
201 	mb = m_get(M_DONTWAIT, DKMT_DATA);
202 	if (mb == NULL)
203 		return -1 ;
204 	(void) dktcanon(CMCFMT, msg, mtod(mb, char *));
205 	mb->m_len = CMCSIZ;
206 	if (dk_xmit(commchan, mb, 1, 0, dkfdone, (caddr_t) 0) == 0) {
207 		return -1 ;
208 	}
209 	return 0 ;
210 }
211 
212 
213 /*ARGSUSED*/
214 dkfdone(cb)
215 {
216 	dkc1omplete++ ;
217 	dkcstall = 0;
218 }
219 
220 
221 
222 /*ARGSUSED*/
223 dkcin(param, channel, rlen, code, ctlchr)
224 {
225 register chan ;
226 register err ;
227 register struct dksetupreq *req ;
228 
229 	if (code == DKR_ABORT) {
230 		if (0 > dkctldebug) log(LOG_ERR, "dkcin: abort\n");
231 		for (chan=2; chan < dk_nchan; chan++)
232 			if (req = dkreq[chan]) {
233 				dkreq[chan] = NULL ;
234 				if (req->rq_endfcn)
235 					(*req->rq_endfcn)(req->rq_endparm, chan, 2, -1, -1, -1) ;
236 				(void) m_free(dtom(req)) ;
237 			}
238 		return(0);;
239 	}
240 	(void) dkfcanon(CMCFMT, cmcinp, (char *)&cmcmsg) ;
241 	if (cmcmsg.param0 < dk_nchan)
242 		chan = cmcmsg.param0 ;
243 	else
244 		chan = 0 ;
245 	if (chan > dkctldebug)
246 		log(LOG_ERR, "dkcin %d: type %d srv %o\n", chan, cmcmsg.type,
247 		    cmcmsg.srv);
248 	switch (cmcmsg.type) {
249 	case T_REPLY:
250 		if ((req = dkreq[chan]) == NULL)
251 			break ;
252 		dkreq[chan] = NULL ;
253 		err = 0 ;
254 		if (cmcmsg.srv == D_FAIL)
255 			err = 1 ;
256 		if (req->rq_endfcn != NULL)
257 			(*req->rq_endfcn)(req->rq_endparm, cmcmsg.param0, err,
258 				cmcmsg.param1, cmcmsg.param2, cmcmsg.param3) ;
259 		(void) m_free(dtom(req)) ;
260 		if (cmcmsg.srv == D_OPEN)
261 			dk_cmd(chan, DKC_XINIT);
262 		break;
263 	case T_RESTART:
264 		/*
265 		 * If the Common Control has fewer channels configured than
266 		 * we do, use its number.
267 		 */
268 		if (chan > dkctldebug)
269 			log(LOG_ERR, "Datakit restart: channels = %d (%d)\n", dk_nchan, cmcmsg.param1);
270 		if(cmcmsg.param1 > 0 && cmcmsg.param1 < dk_nchan)
271 			dk_nchan = cmcmsg.param1;
272 		dk_cmd(chan, DKC_XINIT) ;
273 		break ;
274 	case T_CHG:
275 		switch (cmcmsg.srv) {
276 		case D_CLOSE:
277 			if (dk_status(chan) & DK_OPEN) {
278 				dk_reset(chan) ;
279 				dkabtreq(chan, 1, 0) ;
280 			} else {
281 				closepack.param0 = cmcmsg.param0 ;
282 				(void) dkfpack((caddr_t)&closepack) ;
283 				(void) dk_close(chan) ;
284 			}
285 			break ;
286 		case D_ISCLOSED:
287 			if (dk_status(chan) & DK_LINGR) {
288 				(void) dk_close(chan) ;
289 				dk_free(chan) ;
290 			}
291 			break ;
292 		case D_CLOSEALL:
293 			for (chan = 2; chan < dk_nchan; chan++)
294 				if (dk_status(chan) & DK_OPEN) {
295 					dk_reset(chan) ;
296 					dkabtreq(chan, 1, 0) ;
297 				}
298 			break;
299 		}
300 		break;
301 	case T_SRV:
302 		if (cmcmsg.srv == D_REINIT)
303 			dkrsplice(chan) ;
304 		break ;
305 	}
306 	(void) dk_recv(commchan, (caddr_t)cmcinp, CMCSIZ, 0, dkcin, (caddr_t) 0) ;
307 	return 0 ;
308 }
309 
310 dk_splice(chan1, chan2, endfun, endp1, endp2)
311 int (*endfun) () ;
312 caddr_t endp1, endp2 ;
313 {
314 	static short splice = (T_CHG << 8 | D_SPLICE) ;
315 
316 	if (dk_setup(chan1, splice, chan2, 0, 0, 0, endfun, endp1) ||
317 		dk_setup(chan2, splice, chan1, 0, 0, 0, endfun, endp2))
318 			return -1 ;
319 	else
320 		return 0 ;
321 }
322 
323 /* If we are waiting on a setup request,
324  * abort it.
325  */
326 dkabtreq(chan, err, usrerr)
327 int chan;
328 int err, usrerr;
329 {
330 	register struct dksetupreq *req ;
331 
332 	if((req = dkreq[chan]) != NULL) {
333 		dkreq[chan] = NULL ;
334 		if(req->rq_endfcn != NULL)
335 			(*req->rq_endfcn)(req->rq_endparm, chan, err, usrerr, 0, 0);
336 		(void) m_free(dtom(req)) ;
337 	}
338 }
339 
340 
341 #ifdef	pdp11
342 #define	SALIGN(p)	(char *)(((int)p+1) & ~1)
343 #define	LALIGN(p)	(char *)(((int)p+1) & ~1)
344 #endif
345 #ifdef	vax
346 #define	SALIGN(p)	(char *)(((int)p+1) & ~1)
347 #define	LALIGN(p)	(char *)(((int)p+3) & ~3)
348 #endif
349 #ifdef	u3b
350 #define	SALIGN(p)	(char *)(((int)p+1) & ~1)
351 #define	LALIGN(p)	(char *)(((int)p+3) & ~3)
352 #endif
353 #define	SNEXT(p)	(char *)((int)p + sizeof (short))
354 #define	LNEXT(p)	(char *)((int)p + sizeof (long))
355 
356 
357 /*
358  * convert from canonical to
359  * local representation.
360  */
361 char *
362 dkfcanon(fmt, from, to)
363 register char *fmt, *from, *to;
364 {
365 short tmp;
366 long ltmp;
367 	while (*fmt) {
368 		switch(*fmt++) {
369 		case 's':			/* short */
370 			tmp = 0;
371 			tmp = (*from++)&0377;
372 			tmp |= ((*from++)&0377)<<8;
373 			to = SALIGN(to);
374 			*(short *)to = tmp;
375 			to = SNEXT(to);
376 			continue;
377 		case 'l':			/* long */
378 			ltmp = 0;
379 			ltmp = (*from++)&0377;
380 			ltmp |= (long)((*from++)&0377)<<8;
381 			ltmp |= (long)((*from++)&0377)<<16;
382 			ltmp |= (long)((*from++)&0377)<<24;
383 			to = LALIGN(to);
384 			*(long *)to = ltmp;
385 			to = LNEXT(to);
386 			continue;
387 		case 'b':			/* byte */
388 			*to++ = *from++;
389 			continue;
390 		default:
391 			return((char *)0);
392 		}
393 	}
394 	return(from);
395 }
396 
397 /*
398  * convert from local to
399  * canonical representation
400  */
401 char *
402 dktcanon(fmt, from, to)
403 register char *fmt, *from, *to;
404 {
405 short tmp;
406 long ltmp;
407 
408 	while (*fmt) {
409 		switch(*fmt++) {
410 		case 's':
411 			from = SALIGN(from);
412 			tmp = *(short *)from;
413 			from = SNEXT(from);
414 			*to++ = tmp;
415 			tmp >>=8;
416 			*to++ = tmp;
417 			continue;
418 		case 'l':
419 			from = LALIGN(from);
420 			ltmp = *(long *)from;
421 			*to++ = ltmp;
422 			ltmp >>= 8;
423 			*to++ = ltmp;
424 			ltmp >>= 8;
425 			*to++ = ltmp;
426 			ltmp >>= 8;
427 			*to++ = ltmp;
428 			from = LNEXT(from);
429 			continue;
430 		case 'b':
431 			*to++ = *from++;
432 			continue;
433 		default:
434 			return((char *)0);
435 		}
436 	}
437 	return(from);
438 }
439 #endif
440