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
dk_ccsinit()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)¬ify) ;
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
dk_takedown(chan)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
dkctime()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)¬ify) ;
187 notify.srv = 0 ;
188 }
189
190 timeout(dkctime, (caddr_t) 0, 5*hz) ;
191 splx(s);
192 return;
193 }
194
dkfpack(msg)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*/
dkfdone(cb)214 dkfdone(cb)
215 {
216 dkc1omplete++ ;
217 dkcstall = 0;
218 }
219
220
221
222 /*ARGSUSED*/
dkcin(param,channel,rlen,code,ctlchr)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 */
dkabtreq(chan,err,usrerr)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 *
dkfcanon(fmt,from,to)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 *
dktcanon(fmt,from,to)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