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)¬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 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)¬ify) ; 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