1 1.6 christos /* $NetBSD: parsestreams.c,v 1.6 2020/05/25 20:47:25 christos Exp $ */ 2 1.1 kardel 3 1.1 kardel /* 4 1.1 kardel * /src/NTP/ntp4-dev/libparse/parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A 5 1.3 christos * 6 1.1 kardel * parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A 7 1.1 kardel * 8 1.1 kardel * STREAMS module for reference clocks 9 1.1 kardel * (SunOS4.x) 10 1.1 kardel * 11 1.1 kardel * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> 12 1.3 christos * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 13 1.1 kardel * 14 1.1 kardel * Redistribution and use in source and binary forms, with or without 15 1.1 kardel * modification, are permitted provided that the following conditions 16 1.1 kardel * are met: 17 1.1 kardel * 1. Redistributions of source code must retain the above copyright 18 1.1 kardel * notice, this list of conditions and the following disclaimer. 19 1.1 kardel * 2. Redistributions in binary form must reproduce the above copyright 20 1.1 kardel * notice, this list of conditions and the following disclaimer in the 21 1.1 kardel * documentation and/or other materials provided with the distribution. 22 1.1 kardel * 3. Neither the name of the author nor the names of its contributors 23 1.1 kardel * may be used to endorse or promote products derived from this software 24 1.1 kardel * without specific prior written permission. 25 1.1 kardel * 26 1.1 kardel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27 1.1 kardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 1.1 kardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 1.1 kardel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30 1.1 kardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 1.1 kardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 1.1 kardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 1.1 kardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 1.1 kardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 1.1 kardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 1.1 kardel * SUCH DAMAGE. 37 1.1 kardel * 38 1.1 kardel */ 39 1.1 kardel 40 1.1 kardel #define KERNEL /* MUST */ 41 1.1 kardel #define VDDRV /* SHOULD */ 42 1.1 kardel 43 1.1 kardel #ifdef HAVE_CONFIG_H 44 1.1 kardel # include "config.h" 45 1.1 kardel #endif 46 1.1 kardel 47 1.1 kardel #ifndef lint 48 1.1 kardel static char rcsid[] = "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"; 49 1.1 kardel #endif 50 1.1 kardel 51 1.1 kardel #ifndef KERNEL 52 1.1 kardel #include "Bletch: MUST COMPILE WITH KERNEL DEFINE" 53 1.1 kardel #endif 54 1.1 kardel 55 1.1 kardel #include <sys/types.h> 56 1.1 kardel #include <sys/conf.h> 57 1.1 kardel #include <sys/buf.h> 58 1.1 kardel #include <sys/param.h> 59 1.1 kardel #include <sys/sysmacros.h> 60 1.1 kardel #include <sys/time.h> 61 1.1 kardel #include <sundev/mbvar.h> 62 1.1 kardel #include <sun/autoconf.h> 63 1.1 kardel #include <sys/stream.h> 64 1.1 kardel #include <sys/stropts.h> 65 1.1 kardel #include <sys/dir.h> 66 1.1 kardel #include <sys/signal.h> 67 1.1 kardel #include <sys/termios.h> 68 1.1 kardel #include <sys/termio.h> 69 1.1 kardel #include <sys/ttold.h> 70 1.1 kardel #include <sys/user.h> 71 1.1 kardel #include <sys/tty.h> 72 1.1 kardel 73 1.1 kardel #ifdef VDDRV 74 1.1 kardel #include <sun/vddrv.h> 75 1.1 kardel #endif 76 1.1 kardel 77 1.1 kardel #include "ntp_stdlib.h" 78 1.1 kardel #include "ntp_fp.h" 79 1.1 kardel /* 80 1.1 kardel * just make checking compilers more silent 81 1.1 kardel */ 82 1.1 kardel extern int printf (const char *, ...); 83 1.1 kardel extern int putctl1 (queue_t *, int, int); 84 1.1 kardel extern int canput (queue_t *); 85 1.1 kardel extern void putbq (queue_t *, mblk_t *); 86 1.1 kardel extern void freeb (mblk_t *); 87 1.1 kardel extern void qreply (queue_t *, mblk_t *); 88 1.1 kardel extern void freemsg (mblk_t *); 89 1.1 kardel extern void panic (const char *, ...); 90 1.1 kardel extern void usec_delay (int); 91 1.1 kardel 92 1.1 kardel #include "parse.h" 93 1.1 kardel #include "sys/parsestreams.h" 94 1.1 kardel 95 1.1 kardel /* 96 1.1 kardel * use microtime instead of uniqtime if advised to 97 1.1 kardel */ 98 1.1 kardel #ifdef MICROTIME 99 1.1 kardel #define uniqtime microtime 100 1.1 kardel #endif 101 1.1 kardel 102 1.1 kardel #ifdef VDDRV 103 1.1 kardel static unsigned int parsebusy = 0; 104 1.1 kardel 105 1.1 kardel /*--------------- loadable driver section -----------------------------*/ 106 1.1 kardel 107 1.1 kardel extern struct streamtab parseinfo; 108 1.1 kardel 109 1.1 kardel 110 1.1 kardel #ifdef PPS_SYNC 111 1.1 kardel static char mnam[] = "PARSEPPS "; /* name this baby - keep room for revision number */ 112 1.1 kardel #else 113 1.1 kardel static char mnam[] = "PARSE "; /* name this baby - keep room for revision number */ 114 1.1 kardel #endif 115 1.3 christos struct vdldrv parsesync_vd = 116 1.1 kardel { 117 1.1 kardel VDMAGIC_PSEUDO, /* nothing like a real driver - a STREAMS module */ 118 1.1 kardel mnam, 119 1.1 kardel }; 120 1.1 kardel 121 1.1 kardel /* 122 1.1 kardel * strings support usually not in kernel 123 1.1 kardel */ 124 1.1 kardel static int 125 1.1 kardel Strlen( 126 1.1 kardel register const char *s 127 1.1 kardel ) 128 1.1 kardel { 129 1.1 kardel register int c; 130 1.1 kardel 131 1.1 kardel c = 0; 132 1.1 kardel if (s) 133 1.1 kardel { 134 1.1 kardel while (*s++) 135 1.1 kardel { 136 1.1 kardel c++; 137 1.1 kardel } 138 1.1 kardel } 139 1.1 kardel return c; 140 1.1 kardel } 141 1.1 kardel 142 1.1 kardel static void 143 1.1 kardel Strncpy( 144 1.1 kardel register char *t, 145 1.1 kardel register char *s, 146 1.1 kardel register int c 147 1.1 kardel ) 148 1.1 kardel { 149 1.1 kardel if (s && t) 150 1.1 kardel { 151 1.1 kardel while ((c-- > 0) && (*t++ = *s++)) 152 1.1 kardel ; 153 1.1 kardel } 154 1.1 kardel } 155 1.1 kardel 156 1.1 kardel static int 157 1.1 kardel Strcmp( 158 1.1 kardel register const char *s, 159 1.1 kardel register const char *t 160 1.1 kardel ) 161 1.1 kardel { 162 1.1 kardel register int c = 0; 163 1.1 kardel 164 1.1 kardel if (!s || !t || (s == t)) 165 1.1 kardel { 166 1.1 kardel return 0; 167 1.1 kardel } 168 1.1 kardel 169 1.1 kardel while (!(c = *s++ - *t++) && *s && *t) 170 1.1 kardel /* empty loop */; 171 1.3 christos 172 1.1 kardel return c; 173 1.1 kardel } 174 1.1 kardel 175 1.1 kardel static int 176 1.1 kardel Strncmp( 177 1.1 kardel register char *s, 178 1.1 kardel register char *t, 179 1.1 kardel register int n 180 1.1 kardel ) 181 1.1 kardel { 182 1.1 kardel register int c = 0; 183 1.1 kardel 184 1.1 kardel if (!s || !t || (s == t)) 185 1.1 kardel { 186 1.1 kardel return 0; 187 1.1 kardel } 188 1.1 kardel 189 1.1 kardel while (n-- && !(c = *s++ - *t++) && *s && *t) 190 1.1 kardel /* empty loop */; 191 1.3 christos 192 1.1 kardel return c; 193 1.1 kardel } 194 1.3 christos 195 1.1 kardel void 196 1.1 kardel ntp_memset( 197 1.1 kardel char *a, 198 1.1 kardel int x, 199 1.1 kardel int c 200 1.1 kardel ) 201 1.1 kardel { 202 1.1 kardel while (c-- > 0) 203 1.1 kardel *a++ = x; 204 1.1 kardel } 205 1.1 kardel 206 1.1 kardel /* 207 1.1 kardel * driver init routine 208 1.1 kardel * since no mechanism gets us into and out of the fmodsw, we have to 209 1.1 kardel * do it ourselves 210 1.1 kardel */ 211 1.1 kardel /*ARGSUSED*/ 212 1.1 kardel int 213 1.1 kardel xxxinit( 214 1.1 kardel unsigned int fc, 215 1.1 kardel struct vddrv *vdp, 216 1.1 kardel addr_t vdin, 217 1.1 kardel struct vdstat *vds 218 1.1 kardel ) 219 1.1 kardel { 220 1.1 kardel extern struct fmodsw fmodsw[]; 221 1.1 kardel extern int fmodcnt; 222 1.3 christos 223 1.1 kardel struct fmodsw *fm = fmodsw; 224 1.1 kardel struct fmodsw *fmend = &fmodsw[fmodcnt]; 225 1.1 kardel struct fmodsw *ifm = (struct fmodsw *)0; 226 1.1 kardel char *mname = parseinfo.st_rdinit->qi_minfo->mi_idname; 227 1.3 christos 228 1.1 kardel switch (fc) 229 1.1 kardel { 230 1.1 kardel case VDLOAD: 231 1.1 kardel vdp->vdd_vdtab = (struct vdlinkage *)&parsesync_vd; 232 1.1 kardel /* 233 1.1 kardel * now, jog along fmodsw scanning for an empty slot 234 1.1 kardel * and deposit our name there 235 1.1 kardel */ 236 1.1 kardel while (fm <= fmend) 237 1.1 kardel { 238 1.3 christos if (!Strncmp(fm->f_name, mname, FMNAMESZ)) 239 1.1 kardel { 240 1.1 kardel printf("vddrinit[%s]: STREAMS module already loaded.\n", mname); 241 1.1 kardel return(EBUSY); 242 1.1 kardel } 243 1.1 kardel else 244 1.3 christos if ((ifm == (struct fmodsw *)0) && 245 1.1 kardel (fm->f_name[0] == '\0') && 246 1.1 kardel (fm->f_str == (struct streamtab *)0)) 247 1.1 kardel { 248 1.1 kardel /* 249 1.1 kardel * got one - so move in 250 1.1 kardel */ 251 1.1 kardel ifm = fm; 252 1.1 kardel break; 253 1.1 kardel } 254 1.1 kardel fm++; 255 1.1 kardel } 256 1.1 kardel 257 1.1 kardel if (ifm == (struct fmodsw *)0) 258 1.1 kardel { 259 1.1 kardel printf("vddrinit[%s]: no slot free for STREAMS module\n", mname); 260 1.1 kardel return (ENOSPC); 261 1.1 kardel } 262 1.1 kardel else 263 1.1 kardel { 264 1.1 kardel static char revision[] = "4.7"; 265 1.1 kardel char *s, *S, *t; 266 1.3 christos 267 1.1 kardel s = rcsid; /* NOOP - keep compilers happy */ 268 1.1 kardel 269 1.1 kardel Strncpy(ifm->f_name, mname, FMNAMESZ); 270 1.1 kardel ifm->f_name[FMNAMESZ] = '\0'; 271 1.1 kardel ifm->f_str = &parseinfo; 272 1.1 kardel /* 273 1.1 kardel * copy RCS revision into Drv_name 274 1.1 kardel * 275 1.1 kardel * are we forcing RCS here to do things it was not built for ? 276 1.1 kardel */ 277 1.1 kardel s = revision; 278 1.1 kardel if (*s == '$') 279 1.1 kardel { 280 1.1 kardel /* 281 1.1 kardel * skip "$Revision: " 282 1.1 kardel * if present. - not necessary on a -kv co (cvs export) 283 1.1 kardel */ 284 1.1 kardel while (*s && (*s != ' ')) 285 1.1 kardel { 286 1.1 kardel s++; 287 1.1 kardel } 288 1.1 kardel if (*s == ' ') s++; 289 1.1 kardel } 290 1.3 christos 291 1.3 christos t = parsesync_vd.Drv_name; 292 1.1 kardel while (*t && (*t != ' ')) 293 1.1 kardel { 294 1.1 kardel t++; 295 1.1 kardel } 296 1.1 kardel if (*t == ' ') t++; 297 1.3 christos 298 1.1 kardel S = s; 299 1.1 kardel while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.'))) 300 1.1 kardel { 301 1.1 kardel S++; 302 1.1 kardel } 303 1.3 christos 304 1.1 kardel if (*s && *t && (S > s)) 305 1.1 kardel { 306 1.1 kardel if (Strlen(t) >= (S - s)) 307 1.1 kardel { 308 1.1 kardel (void) Strncpy(t, s, S - s); 309 1.1 kardel } 310 1.1 kardel } 311 1.1 kardel return (0); 312 1.3 christos } 313 1.1 kardel break; 314 1.3 christos 315 1.1 kardel case VDUNLOAD: 316 1.1 kardel if (parsebusy > 0) 317 1.1 kardel { 318 1.1 kardel printf("vddrinit[%s]: STREAMS module has still %d instances active.\n", mname, parsebusy); 319 1.1 kardel return (EBUSY); 320 1.1 kardel } 321 1.1 kardel else 322 1.1 kardel { 323 1.1 kardel while (fm <= fmend) 324 1.1 kardel { 325 1.1 kardel if (!Strncmp(fm->f_name, mname, FMNAMESZ)) 326 1.1 kardel { 327 1.1 kardel /* 328 1.1 kardel * got it - kill entry 329 1.1 kardel */ 330 1.1 kardel fm->f_name[0] = '\0'; 331 1.1 kardel fm->f_str = (struct streamtab *)0; 332 1.1 kardel fm++; 333 1.3 christos 334 1.1 kardel break; 335 1.1 kardel } 336 1.1 kardel fm++; 337 1.1 kardel } 338 1.1 kardel if (fm > fmend) 339 1.1 kardel { 340 1.1 kardel printf("vddrinit[%s]: cannot find entry for STREAMS module\n", mname); 341 1.1 kardel return (ENXIO); 342 1.1 kardel } 343 1.1 kardel else 344 1.1 kardel return (0); 345 1.1 kardel } 346 1.3 christos 347 1.1 kardel 348 1.1 kardel case VDSTAT: 349 1.1 kardel return (0); 350 1.1 kardel 351 1.1 kardel default: 352 1.1 kardel return (EIO); 353 1.3 christos 354 1.1 kardel } 355 1.1 kardel return EIO; 356 1.1 kardel } 357 1.1 kardel 358 1.1 kardel #endif 359 1.1 kardel 360 1.1 kardel /*--------------- stream module definition ----------------------------*/ 361 1.1 kardel 362 1.1 kardel static int parseopen (queue_t *, dev_t, int, int); 363 1.1 kardel static int parseclose (queue_t *, int); 364 1.1 kardel static int parsewput (queue_t *, mblk_t *); 365 1.1 kardel static int parserput (queue_t *, mblk_t *); 366 1.1 kardel static int parsersvc (queue_t *); 367 1.1 kardel 368 1.1 kardel static char mn[] = "parse"; 369 1.1 kardel 370 1.1 kardel static struct module_info driverinfo = 371 1.1 kardel { 372 1.1 kardel 0, /* module ID number */ 373 1.1 kardel mn, /* module name */ 374 1.1 kardel 0, /* minimum accepted packet size */ 375 1.1 kardel INFPSZ, /* maximum accepted packet size */ 376 1.1 kardel 1, /* high water mark - flow control */ 377 1.1 kardel 0 /* low water mark - flow control */ 378 1.1 kardel }; 379 1.1 kardel 380 1.1 kardel static struct qinit rinit = /* read queue definition */ 381 1.1 kardel { 382 1.1 kardel parserput, /* put procedure */ 383 1.1 kardel parsersvc, /* service procedure */ 384 1.1 kardel parseopen, /* open procedure */ 385 1.1 kardel parseclose, /* close procedure */ 386 1.1 kardel NULL, /* admin procedure - NOT USED FOR NOW */ 387 1.1 kardel &driverinfo, /* information structure */ 388 1.1 kardel NULL /* statistics */ 389 1.1 kardel }; 390 1.1 kardel 391 1.1 kardel static struct qinit winit = /* write queue definition */ 392 1.1 kardel { 393 1.1 kardel parsewput, /* put procedure */ 394 1.1 kardel NULL, /* service procedure */ 395 1.1 kardel NULL, /* open procedure */ 396 1.1 kardel NULL, /* close procedure */ 397 1.1 kardel NULL, /* admin procedure - NOT USED FOR NOW */ 398 1.1 kardel &driverinfo, /* information structure */ 399 1.1 kardel NULL /* statistics */ 400 1.1 kardel }; 401 1.1 kardel 402 1.1 kardel struct streamtab parseinfo = /* stream info element for dpr driver */ 403 1.1 kardel { 404 1.1 kardel &rinit, /* read queue */ 405 1.1 kardel &winit, /* write queue */ 406 1.1 kardel NULL, /* read mux */ 407 1.1 kardel NULL, /* write mux */ 408 1.1 kardel NULL /* module auto push */ 409 1.1 kardel }; 410 1.1 kardel 411 1.1 kardel /*--------------- driver data structures ----------------------------*/ 412 1.1 kardel 413 1.1 kardel /* 414 1.1 kardel * we usually have an inverted signal - but you 415 1.1 kardel * can change this to suit your needs 416 1.1 kardel */ 417 1.1 kardel int cd_invert = 1; /* invert status of CD line - PPS support via CD input */ 418 1.1 kardel 419 1.1 kardel int parsedebug = ~0; 420 1.1 kardel 421 1.1 kardel extern void uniqtime (struct timeval *); 422 1.1 kardel 423 1.1 kardel /*--------------- module implementation -----------------------------*/ 424 1.1 kardel 425 1.1 kardel #define TIMEVAL_USADD(_X_, _US_) {\ 426 1.1 kardel (_X_)->tv_usec += (_US_);\ 427 1.1 kardel if ((_X_)->tv_usec >= 1000000)\ 428 1.1 kardel {\ 429 1.1 kardel (_X_)->tv_sec++;\ 430 1.1 kardel (_X_)->tv_usec -= 1000000;\ 431 1.1 kardel }\ 432 1.1 kardel } while (0) 433 1.1 kardel 434 1.1 kardel static int init_linemon (queue_t *); 435 1.1 kardel static void close_linemon (queue_t *, queue_t *); 436 1.1 kardel 437 1.1 kardel #define M_PARSE 0x0001 438 1.1 kardel #define M_NOPARSE 0x0002 439 1.1 kardel 440 1.1 kardel static int 441 1.1 kardel setup_stream( 442 1.1 kardel queue_t *q, 443 1.1 kardel int mode 444 1.1 kardel ) 445 1.1 kardel { 446 1.1 kardel mblk_t *mp; 447 1.1 kardel 448 1.1 kardel mp = allocb(sizeof(struct stroptions), BPRI_MED); 449 1.1 kardel if (mp) 450 1.1 kardel { 451 1.1 kardel struct stroptions *str = (struct stroptions *)(void *)mp->b_rptr; 452 1.1 kardel 453 1.1 kardel str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT; 454 1.1 kardel str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM; 455 1.1 kardel str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256; 456 1.1 kardel str->so_lowat = 0; 457 1.1 kardel mp->b_datap->db_type = M_SETOPTS; 458 1.1 kardel mp->b_wptr += sizeof(struct stroptions); 459 1.1 kardel putnext(q, mp); 460 1.1 kardel return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM : 461 1.1 kardel MC_SERVICEDEF); 462 1.1 kardel } 463 1.1 kardel else 464 1.1 kardel { 465 1.3 christos parseprintf(DD_OPEN,("parse: setup_stream - FAILED - no MEMORY for allocb\n")); 466 1.1 kardel return 0; 467 1.1 kardel } 468 1.1 kardel } 469 1.1 kardel 470 1.1 kardel /*ARGSUSED*/ 471 1.1 kardel static int 472 1.1 kardel parseopen( 473 1.1 kardel queue_t *q, 474 1.1 kardel dev_t dev, 475 1.1 kardel int flag, 476 1.1 kardel int sflag 477 1.1 kardel ) 478 1.1 kardel { 479 1.1 kardel register parsestream_t *parse; 480 1.1 kardel static int notice = 0; 481 1.3 christos 482 1.3 christos parseprintf(DD_OPEN,("parse: OPEN\n")); 483 1.3 christos 484 1.1 kardel if (sflag != MODOPEN) 485 1.1 kardel { /* open only for modules */ 486 1.3 christos parseprintf(DD_OPEN,("parse: OPEN - FAILED - not MODOPEN\n")); 487 1.1 kardel return OPENFAIL; 488 1.1 kardel } 489 1.1 kardel 490 1.1 kardel if (q->q_ptr != (caddr_t)NULL) 491 1.1 kardel { 492 1.1 kardel u.u_error = EBUSY; 493 1.3 christos parseprintf(DD_OPEN,("parse: OPEN - FAILED - EXCLUSIVE ONLY\n")); 494 1.1 kardel return OPENFAIL; 495 1.1 kardel } 496 1.1 kardel 497 1.1 kardel #ifdef VDDRV 498 1.1 kardel parsebusy++; 499 1.1 kardel #endif 500 1.3 christos 501 1.1 kardel q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t)); 502 1.1 kardel if (q->q_ptr == (caddr_t)0) 503 1.1 kardel { 504 1.3 christos parseprintf(DD_OPEN,("parse: OPEN - FAILED - no memory\n")); 505 1.1 kardel #ifdef VDDRV 506 1.1 kardel parsebusy--; 507 1.1 kardel #endif 508 1.1 kardel return OPENFAIL; 509 1.1 kardel } 510 1.1 kardel WR(q)->q_ptr = q->q_ptr; 511 1.3 christos 512 1.1 kardel parse = (parsestream_t *)(void *)q->q_ptr; 513 1.1 kardel bzero((caddr_t)parse, sizeof(*parse)); 514 1.1 kardel parse->parse_queue = q; 515 1.1 kardel parse->parse_status = PARSE_ENABLE; 516 1.1 kardel parse->parse_ppsclockev.tv.tv_sec = 0; 517 1.1 kardel parse->parse_ppsclockev.tv.tv_usec = 0; 518 1.1 kardel parse->parse_ppsclockev.serial = 0; 519 1.1 kardel 520 1.1 kardel if (!parse_ioinit(&parse->parse_io)) 521 1.1 kardel { 522 1.1 kardel /* 523 1.1 kardel * ok guys - beat it 524 1.1 kardel */ 525 1.1 kardel kmem_free((caddr_t)parse, sizeof(parsestream_t)); 526 1.1 kardel #ifdef VDDRV 527 1.1 kardel parsebusy--; 528 1.1 kardel #endif 529 1.1 kardel return OPENFAIL; 530 1.1 kardel } 531 1.1 kardel 532 1.1 kardel if (setup_stream(q, M_PARSE)) 533 1.1 kardel { 534 1.1 kardel (void) init_linemon(q); /* hook up PPS ISR routines if possible */ 535 1.1 kardel 536 1.3 christos parseprintf(DD_OPEN,("parse: OPEN - SUCCEEDED\n")); 537 1.1 kardel 538 1.1 kardel /* 539 1.1 kardel * I know that you know the delete key, but you didn't write this 540 1.1 kardel * code, did you ? - So, keep the message in here. 541 1.1 kardel */ 542 1.1 kardel if (!notice) 543 1.1 kardel { 544 1.1 kardel #ifdef VDDRV 545 1.1 kardel printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", parsesync_vd.Drv_name); 546 1.1 kardel #else 547 1.1 kardel printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"); 548 1.1 kardel #endif 549 1.1 kardel notice = 1; 550 1.1 kardel } 551 1.1 kardel 552 1.1 kardel return MODOPEN; 553 1.1 kardel } 554 1.1 kardel else 555 1.1 kardel { 556 1.1 kardel kmem_free((caddr_t)parse, sizeof(parsestream_t)); 557 1.1 kardel 558 1.1 kardel #ifdef VDDRV 559 1.1 kardel parsebusy--; 560 1.1 kardel #endif 561 1.1 kardel return OPENFAIL; 562 1.1 kardel } 563 1.1 kardel } 564 1.1 kardel 565 1.1 kardel /*ARGSUSED*/ 566 1.1 kardel static int 567 1.1 kardel parseclose( 568 1.1 kardel queue_t *q, 569 1.1 kardel int flags 570 1.1 kardel ) 571 1.1 kardel { 572 1.1 kardel register parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; 573 1.1 kardel register unsigned long s; 574 1.3 christos 575 1.1 kardel parseprintf(DD_CLOSE,("parse: CLOSE\n")); 576 1.3 christos 577 1.1 kardel s = splhigh(); 578 1.3 christos 579 1.1 kardel if (parse->parse_dqueue) 580 1.1 kardel close_linemon(parse->parse_dqueue, q); 581 1.1 kardel parse->parse_dqueue = (queue_t *)0; 582 1.1 kardel 583 1.1 kardel (void) splx(s); 584 1.3 christos 585 1.1 kardel parse_ioend(&parse->parse_io); 586 1.1 kardel 587 1.1 kardel kmem_free((caddr_t)parse, sizeof(parsestream_t)); 588 1.1 kardel 589 1.1 kardel q->q_ptr = (caddr_t)NULL; 590 1.1 kardel WR(q)->q_ptr = (caddr_t)NULL; 591 1.1 kardel 592 1.1 kardel #ifdef VDDRV 593 1.1 kardel parsebusy--; 594 1.1 kardel #endif 595 1.1 kardel return 0; 596 1.1 kardel } 597 1.1 kardel 598 1.1 kardel /* 599 1.1 kardel * move unrecognized stuff upward 600 1.1 kardel */ 601 1.1 kardel static int 602 1.1 kardel parsersvc( 603 1.1 kardel queue_t *q 604 1.1 kardel ) 605 1.1 kardel { 606 1.1 kardel mblk_t *mp; 607 1.3 christos 608 1.1 kardel while ((mp = getq(q))) 609 1.1 kardel { 610 1.1 kardel if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 611 1.1 kardel { 612 1.1 kardel putnext(q, mp); 613 1.1 kardel parseprintf(DD_RSVC,("parse: RSVC - putnext\n")); 614 1.1 kardel } 615 1.1 kardel else 616 1.1 kardel { 617 1.1 kardel putbq(q, mp); 618 1.1 kardel parseprintf(DD_RSVC,("parse: RSVC - flow control wait\n")); 619 1.1 kardel break; 620 1.1 kardel } 621 1.1 kardel } 622 1.1 kardel return 0; 623 1.1 kardel } 624 1.1 kardel 625 1.1 kardel /* 626 1.1 kardel * do ioctls and 627 1.1 kardel * send stuff down - dont care about 628 1.1 kardel * flow control 629 1.1 kardel */ 630 1.1 kardel static int 631 1.1 kardel parsewput( 632 1.1 kardel queue_t *q, 633 1.1 kardel register mblk_t *mp 634 1.1 kardel ) 635 1.1 kardel { 636 1.1 kardel register int ok = 1; 637 1.1 kardel register mblk_t *datap; 638 1.1 kardel register struct iocblk *iocp; 639 1.1 kardel parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; 640 1.3 christos 641 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput\n")); 642 1.3 christos 643 1.1 kardel switch (mp->b_datap->db_type) 644 1.1 kardel { 645 1.1 kardel default: 646 1.1 kardel putnext(q, mp); 647 1.1 kardel break; 648 1.3 christos 649 1.1 kardel case M_IOCTL: 650 1.1 kardel iocp = (struct iocblk *)(void *)mp->b_rptr; 651 1.1 kardel switch (iocp->ioc_cmd) 652 1.1 kardel { 653 1.1 kardel default: 654 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput - forward M_IOCTL\n")); 655 1.1 kardel putnext(q, mp); 656 1.1 kardel break; 657 1.1 kardel 658 1.1 kardel case CIOGETEV: 659 1.1 kardel /* 660 1.1 kardel * taken from Craig Leres ppsclock module (and modified) 661 1.1 kardel */ 662 1.1 kardel datap = allocb(sizeof(struct ppsclockev), BPRI_MED); 663 1.1 kardel if (datap == NULL || mp->b_cont) 664 1.1 kardel { 665 1.1 kardel mp->b_datap->db_type = M_IOCNAK; 666 1.1 kardel iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL; 667 1.1 kardel if (datap != NULL) 668 1.1 kardel freeb(datap); 669 1.1 kardel qreply(q, mp); 670 1.1 kardel break; 671 1.1 kardel } 672 1.1 kardel 673 1.1 kardel mp->b_cont = datap; 674 1.1 kardel *(struct ppsclockev *)(void *)datap->b_wptr = parse->parse_ppsclockev; 675 1.1 kardel datap->b_wptr += 676 1.1 kardel sizeof(struct ppsclockev) / sizeof(*datap->b_wptr); 677 1.1 kardel mp->b_datap->db_type = M_IOCACK; 678 1.1 kardel iocp->ioc_count = sizeof(struct ppsclockev); 679 1.1 kardel qreply(q, mp); 680 1.1 kardel break; 681 1.3 christos 682 1.1 kardel case PARSEIOC_ENABLE: 683 1.1 kardel case PARSEIOC_DISABLE: 684 1.1 kardel { 685 1.1 kardel parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) | 686 1.1 kardel (iocp->ioc_cmd == PARSEIOC_ENABLE) ? 687 1.1 kardel PARSE_ENABLE : 0; 688 1.1 kardel if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ? 689 1.1 kardel M_PARSE : M_NOPARSE)) 690 1.1 kardel { 691 1.1 kardel mp->b_datap->db_type = M_IOCNAK; 692 1.1 kardel } 693 1.1 kardel else 694 1.1 kardel { 695 1.1 kardel mp->b_datap->db_type = M_IOCACK; 696 1.1 kardel } 697 1.1 kardel qreply(q, mp); 698 1.1 kardel break; 699 1.3 christos } 700 1.1 kardel 701 1.1 kardel case PARSEIOC_TIMECODE: 702 1.1 kardel case PARSEIOC_SETFMT: 703 1.1 kardel case PARSEIOC_GETFMT: 704 1.1 kardel case PARSEIOC_SETCS: 705 1.1 kardel if (iocp->ioc_count == sizeof(parsectl_t)) 706 1.1 kardel { 707 1.1 kardel parsectl_t *dct = (parsectl_t *)(void *)mp->b_cont->b_rptr; 708 1.1 kardel 709 1.1 kardel switch (iocp->ioc_cmd) 710 1.1 kardel { 711 1.1 kardel case PARSEIOC_TIMECODE: 712 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_TIMECODE\n")); 713 1.1 kardel ok = parse_timecode(dct, &parse->parse_io); 714 1.1 kardel break; 715 1.3 christos 716 1.1 kardel case PARSEIOC_SETFMT: 717 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETFMT\n")); 718 1.1 kardel ok = parse_setfmt(dct, &parse->parse_io); 719 1.1 kardel break; 720 1.1 kardel 721 1.1 kardel case PARSEIOC_GETFMT: 722 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_GETFMT\n")); 723 1.1 kardel ok = parse_getfmt(dct, &parse->parse_io); 724 1.1 kardel break; 725 1.1 kardel 726 1.1 kardel case PARSEIOC_SETCS: 727 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETCS\n")); 728 1.1 kardel ok = parse_setcs(dct, &parse->parse_io); 729 1.1 kardel break; 730 1.1 kardel } 731 1.1 kardel mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK; 732 1.1 kardel } 733 1.1 kardel else 734 1.1 kardel { 735 1.1 kardel mp->b_datap->db_type = M_IOCNAK; 736 1.1 kardel } 737 1.1 kardel parseprintf(DD_WPUT,("parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK")); 738 1.1 kardel qreply(q, mp); 739 1.1 kardel break; 740 1.1 kardel } 741 1.1 kardel } 742 1.1 kardel return 0; 743 1.1 kardel } 744 1.1 kardel 745 1.1 kardel /* 746 1.1 kardel * read characters from streams buffers 747 1.1 kardel */ 748 1.1 kardel static unsigned long 749 1.1 kardel rdchar( 750 1.1 kardel register mblk_t **mp 751 1.1 kardel ) 752 1.1 kardel { 753 1.1 kardel while (*mp != (mblk_t *)NULL) 754 1.1 kardel { 755 1.1 kardel if ((*mp)->b_wptr - (*mp)->b_rptr) 756 1.1 kardel { 757 1.1 kardel return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++)); 758 1.1 kardel } 759 1.1 kardel else 760 1.1 kardel { 761 1.1 kardel register mblk_t *mmp = *mp; 762 1.3 christos 763 1.1 kardel *mp = (*mp)->b_cont; 764 1.1 kardel freeb(mmp); 765 1.1 kardel } 766 1.1 kardel } 767 1.1 kardel return (unsigned)~0; 768 1.1 kardel } 769 1.1 kardel 770 1.1 kardel /* 771 1.1 kardel * convert incoming data 772 1.1 kardel */ 773 1.1 kardel static int 774 1.1 kardel parserput( 775 1.1 kardel queue_t *q, 776 1.1 kardel mblk_t *mp 777 1.1 kardel ) 778 1.1 kardel { 779 1.1 kardel unsigned char type; 780 1.3 christos 781 1.1 kardel switch (type = mp->b_datap->db_type) 782 1.1 kardel { 783 1.1 kardel default: 784 1.1 kardel /* 785 1.1 kardel * anything we don't know will be put on queue 786 1.1 kardel * the service routine will move it to the next one 787 1.1 kardel */ 788 1.1 kardel parseprintf(DD_RPUT,("parse: parserput - forward type 0x%x\n", type)); 789 1.1 kardel if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 790 1.1 kardel { 791 1.1 kardel putnext(q, mp); 792 1.1 kardel } 793 1.1 kardel else 794 1.1 kardel putq(q, mp); 795 1.1 kardel break; 796 1.3 christos 797 1.1 kardel case M_BREAK: 798 1.1 kardel case M_DATA: 799 1.1 kardel { 800 1.1 kardel register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; 801 1.1 kardel register mblk_t *nmp; 802 1.1 kardel register unsigned long ch; 803 1.1 kardel timestamp_t ctime; 804 1.1 kardel 805 1.1 kardel /* 806 1.1 kardel * get time on packet delivery 807 1.1 kardel */ 808 1.1 kardel uniqtime(&ctime.tv); 809 1.1 kardel 810 1.1 kardel if (!(parse->parse_status & PARSE_ENABLE)) 811 1.1 kardel { 812 1.1 kardel parseprintf(DD_RPUT,("parse: parserput - parser disabled - forward type 0x%x\n", type)); 813 1.1 kardel if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 814 1.1 kardel { 815 1.1 kardel putnext(q, mp); 816 1.1 kardel } 817 1.1 kardel else 818 1.1 kardel putq(q, mp); 819 1.1 kardel } 820 1.1 kardel else 821 1.1 kardel { 822 1.1 kardel parseprintf(DD_RPUT,("parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK")); 823 1.1 kardel 824 1.1 kardel if (type == M_DATA) 825 1.1 kardel { 826 1.1 kardel /* 827 1.1 kardel * parse packet looking for start an end characters 828 1.1 kardel */ 829 1.1 kardel while (mp != (mblk_t *)NULL) 830 1.1 kardel { 831 1.1 kardel ch = rdchar(&mp); 832 1.1 kardel if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime)) 833 1.1 kardel { 834 1.1 kardel /* 835 1.1 kardel * up up and away (hopefully ...) 836 1.1 kardel * don't press it if resources are tight or nobody wants it 837 1.1 kardel */ 838 1.1 kardel nmp = (mblk_t *)NULL; 839 1.1 kardel if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) 840 1.1 kardel { 841 1.1 kardel bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); 842 1.1 kardel nmp->b_wptr += sizeof(parsetime_t); 843 1.1 kardel putnext(parse->parse_queue, nmp); 844 1.1 kardel } 845 1.1 kardel else 846 1.1 kardel if (nmp) freemsg(nmp); 847 1.1 kardel parse_iodone(&parse->parse_io); 848 1.1 kardel } 849 1.3 christos } 850 1.1 kardel } 851 1.1 kardel else 852 1.1 kardel { 853 1.1 kardel if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime)) 854 1.1 kardel { 855 1.1 kardel /* 856 1.1 kardel * up up and away (hopefully ...) 857 1.1 kardel * don't press it if resources are tight or nobody wants it 858 1.1 kardel */ 859 1.1 kardel nmp = (mblk_t *)NULL; 860 1.1 kardel if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) 861 1.1 kardel { 862 1.1 kardel bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); 863 1.1 kardel nmp->b_wptr += sizeof(parsetime_t); 864 1.1 kardel putnext(parse->parse_queue, nmp); 865 1.1 kardel } 866 1.1 kardel else 867 1.1 kardel if (nmp) freemsg(nmp); 868 1.1 kardel parse_iodone(&parse->parse_io); 869 1.1 kardel } 870 1.1 kardel freemsg(mp); 871 1.1 kardel } 872 1.1 kardel break; 873 1.1 kardel } 874 1.1 kardel } 875 1.1 kardel 876 1.1 kardel /* 877 1.1 kardel * CD PPS support for non direct ISR hack 878 1.1 kardel */ 879 1.1 kardel case M_HANGUP: 880 1.1 kardel case M_UNHANGUP: 881 1.1 kardel { 882 1.1 kardel register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; 883 1.1 kardel timestamp_t ctime; 884 1.1 kardel register mblk_t *nmp; 885 1.1 kardel register int status = cd_invert ^ (type == M_UNHANGUP); 886 1.1 kardel 887 1.1 kardel uniqtime(&ctime.tv); 888 1.3 christos 889 1.1 kardel parseprintf(DD_RPUT,("parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN")); 890 1.1 kardel 891 1.1 kardel if ((parse->parse_status & PARSE_ENABLE) && 892 1.1 kardel parse_iopps(&parse->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &ctime)) 893 1.1 kardel { 894 1.1 kardel nmp = (mblk_t *)NULL; 895 1.1 kardel if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) 896 1.1 kardel { 897 1.1 kardel bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); 898 1.1 kardel nmp->b_wptr += sizeof(parsetime_t); 899 1.1 kardel putnext(parse->parse_queue, nmp); 900 1.1 kardel } 901 1.1 kardel else 902 1.1 kardel if (nmp) freemsg(nmp); 903 1.1 kardel parse_iodone(&parse->parse_io); 904 1.1 kardel freemsg(mp); 905 1.1 kardel } 906 1.1 kardel else 907 1.1 kardel if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) 908 1.1 kardel { 909 1.1 kardel putnext(q, mp); 910 1.1 kardel } 911 1.1 kardel else 912 1.1 kardel putq(q, mp); 913 1.3 christos 914 1.1 kardel if (status) 915 1.1 kardel { 916 1.1 kardel parse->parse_ppsclockev.tv = ctime.tv; 917 1.1 kardel ++(parse->parse_ppsclockev.serial); 918 1.1 kardel } 919 1.1 kardel } 920 1.1 kardel } 921 1.1 kardel return 0; 922 1.1 kardel } 923 1.1 kardel 924 1.1 kardel static int init_zs_linemon (queue_t *, queue_t *); /* handle line monitor for "zs" driver */ 925 1.1 kardel static void close_zs_linemon (queue_t *, queue_t *); 926 1.1 kardel 927 1.1 kardel /*-------------------- CD isr status monitor ---------------*/ 928 1.1 kardel 929 1.1 kardel static int 930 1.1 kardel init_linemon( 931 1.1 kardel register queue_t *q 932 1.1 kardel ) 933 1.1 kardel { 934 1.1 kardel register queue_t *dq; 935 1.3 christos 936 1.1 kardel dq = WR(q); 937 1.1 kardel /* 938 1.1 kardel * we ARE doing very bad things down here (basically stealing ISR 939 1.1 kardel * hooks) 940 1.1 kardel * 941 1.1 kardel * so we chase down the STREAMS stack searching for the driver 942 1.1 kardel * and if this is a known driver we insert our ISR routine for 943 1.1 kardel * status changes in to the ExternalStatus handling hook 944 1.1 kardel */ 945 1.1 kardel while (dq->q_next) 946 1.1 kardel { 947 1.1 kardel dq = dq->q_next; /* skip down to driver */ 948 1.1 kardel } 949 1.1 kardel 950 1.1 kardel /* 951 1.1 kardel * find appropriate driver dependent routine 952 1.1 kardel */ 953 1.1 kardel if (dq->q_qinfo && dq->q_qinfo->qi_minfo) 954 1.1 kardel { 955 1.1 kardel register char *dname = dq->q_qinfo->qi_minfo->mi_idname; 956 1.1 kardel 957 1.1 kardel parseprintf(DD_INSTALL, ("init_linemon: driver is \"%s\"\n", dname)); 958 1.1 kardel 959 1.1 kardel #ifdef sun 960 1.1 kardel if (dname && !Strcmp(dname, "zs")) 961 1.1 kardel { 962 1.1 kardel return init_zs_linemon(dq, q); 963 1.1 kardel } 964 1.1 kardel else 965 1.1 kardel #endif 966 1.1 kardel { 967 1.1 kardel parseprintf(DD_INSTALL, ("init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname)); 968 1.1 kardel return 0; 969 1.1 kardel } 970 1.1 kardel } 971 1.1 kardel parseprintf(DD_INSTALL, ("init_linemon: cannot find driver\n")); 972 1.1 kardel return 0; 973 1.1 kardel } 974 1.1 kardel 975 1.1 kardel static void 976 1.1 kardel close_linemon( 977 1.1 kardel register queue_t *q, 978 1.1 kardel register queue_t *my_q 979 1.1 kardel ) 980 1.1 kardel { 981 1.1 kardel /* 982 1.1 kardel * find appropriate driver dependent routine 983 1.1 kardel */ 984 1.1 kardel if (q->q_qinfo && q->q_qinfo->qi_minfo) 985 1.1 kardel { 986 1.1 kardel register char *dname = q->q_qinfo->qi_minfo->mi_idname; 987 1.1 kardel 988 1.1 kardel #ifdef sun 989 1.1 kardel if (dname && !Strcmp(dname, "zs")) 990 1.1 kardel { 991 1.1 kardel close_zs_linemon(q, my_q); 992 1.1 kardel return; 993 1.1 kardel } 994 1.1 kardel parseprintf(DD_INSTALL, ("close_linemon: cannot find driver close routine for \"%s\"\n", dname)); 995 1.1 kardel #endif 996 1.1 kardel } 997 1.1 kardel parseprintf(DD_INSTALL, ("close_linemon: cannot find driver name\n")); 998 1.1 kardel } 999 1.1 kardel 1000 1.1 kardel #ifdef sun 1001 1.1 kardel 1002 1.1 kardel #include <sundev/zsreg.h> 1003 1.1 kardel #include <sundev/zscom.h> 1004 1.1 kardel #include <sundev/zsvar.h> 1005 1.1 kardel 1006 1.1 kardel static unsigned long cdmask = ZSRR0_CD; 1007 1.1 kardel 1008 1.1 kardel struct savedzsops 1009 1.1 kardel { 1010 1.1 kardel struct zsops zsops; 1011 1.1 kardel struct zsops *oldzsops; 1012 1.1 kardel }; 1013 1.1 kardel 1014 1.1 kardel struct zsops *emergencyzs; 1015 1.1 kardel extern void zsopinit (struct zscom *, struct zsops *); 1016 1.1 kardel static int zs_xsisr (struct zscom *); /* zs external status interupt handler */ 1017 1.1 kardel 1018 1.1 kardel static int 1019 1.1 kardel init_zs_linemon( 1020 1.1 kardel register queue_t *q, 1021 1.1 kardel register queue_t *my_q 1022 1.1 kardel ) 1023 1.1 kardel { 1024 1.1 kardel register struct zscom *zs; 1025 1.1 kardel register struct savedzsops *szs; 1026 1.1 kardel register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; 1027 1.1 kardel /* 1028 1.1 kardel * we expect the zsaline pointer in the q_data pointer 1029 1.1 kardel * from there on we insert our on EXTERNAL/STATUS ISR routine 1030 1.1 kardel * into the interrupt path, before the standard handler 1031 1.1 kardel */ 1032 1.1 kardel zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; 1033 1.1 kardel if (!zs) 1034 1.1 kardel { 1035 1.1 kardel /* 1036 1.1 kardel * well - not found on startup - just say no (shouldn't happen though) 1037 1.1 kardel */ 1038 1.1 kardel return 0; 1039 1.1 kardel } 1040 1.1 kardel else 1041 1.1 kardel { 1042 1.1 kardel unsigned long s; 1043 1.3 christos 1044 1.1 kardel /* 1045 1.1 kardel * we do a direct replacement, in case others fiddle also 1046 1.1 kardel * if somebody else grabs our hook and we disconnect 1047 1.1 kardel * we are in DEEP trouble - panic is likely to be next, sorry 1048 1.1 kardel */ 1049 1.1 kardel szs = (struct savedzsops *)(void *)kmem_alloc(sizeof(struct savedzsops)); 1050 1.1 kardel 1051 1.1 kardel if (szs == (struct savedzsops *)0) 1052 1.1 kardel { 1053 1.1 kardel parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n")); 1054 1.1 kardel 1055 1.1 kardel return 0; 1056 1.1 kardel } 1057 1.1 kardel else 1058 1.1 kardel { 1059 1.1 kardel parsestream->parse_data = (void *)szs; 1060 1.1 kardel 1061 1.1 kardel s = splhigh(); 1062 1.1 kardel 1063 1.1 kardel parsestream->parse_dqueue = q; /* remember driver */ 1064 1.1 kardel 1065 1.1 kardel szs->zsops = *zs->zs_ops; 1066 1.1 kardel szs->zsops.zsop_xsint = zs_xsisr; /* place our bastard */ 1067 1.1 kardel szs->oldzsops = zs->zs_ops; 1068 1.1 kardel emergencyzs = zs->zs_ops; 1069 1.3 christos 1070 1.1 kardel zsopinit(zs, &szs->zsops); /* hook it up */ 1071 1.3 christos 1072 1.1 kardel (void) splx(s); 1073 1.1 kardel 1074 1.1 kardel parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n")); 1075 1.1 kardel 1076 1.1 kardel return 1; 1077 1.1 kardel } 1078 1.1 kardel } 1079 1.1 kardel } 1080 1.1 kardel 1081 1.1 kardel /* 1082 1.1 kardel * unregister our ISR routine - must call under splhigh() 1083 1.1 kardel */ 1084 1.1 kardel static void 1085 1.1 kardel close_zs_linemon( 1086 1.1 kardel register queue_t *q, 1087 1.1 kardel register queue_t *my_q 1088 1.1 kardel ) 1089 1.1 kardel { 1090 1.1 kardel register struct zscom *zs; 1091 1.1 kardel register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; 1092 1.1 kardel 1093 1.1 kardel zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; 1094 1.1 kardel if (!zs) 1095 1.1 kardel { 1096 1.1 kardel /* 1097 1.1 kardel * well - not found on startup - just say no (shouldn't happen though) 1098 1.1 kardel */ 1099 1.1 kardel return; 1100 1.1 kardel } 1101 1.1 kardel else 1102 1.1 kardel { 1103 1.1 kardel register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; 1104 1.3 christos 1105 1.1 kardel zsopinit(zs, szs->oldzsops); /* reset to previous handler functions */ 1106 1.1 kardel 1107 1.1 kardel kmem_free((caddr_t)szs, sizeof (struct savedzsops)); 1108 1.3 christos 1109 1.1 kardel parseprintf(DD_INSTALL, ("close_zs_linemon: CD monitor deleted\n")); 1110 1.1 kardel return; 1111 1.1 kardel } 1112 1.1 kardel } 1113 1.1 kardel 1114 1.1 kardel #define MAXDEPTH 50 /* maximum allowed stream crawl */ 1115 1.1 kardel 1116 1.1 kardel #ifdef PPS_SYNC 1117 1.1 kardel extern void hardpps (struct timeval *, long); 1118 1.1 kardel #ifdef PPS_NEW 1119 1.1 kardel extern struct timeval timestamp; 1120 1.1 kardel #else 1121 1.1 kardel extern struct timeval pps_time; 1122 1.1 kardel #endif 1123 1.1 kardel #endif 1124 1.1 kardel 1125 1.1 kardel /* 1126 1.1 kardel * take external status interrupt (only CD interests us) 1127 1.1 kardel */ 1128 1.1 kardel static int 1129 1.1 kardel zs_xsisr( 1130 1.1 kardel struct zscom *zs 1131 1.1 kardel ) 1132 1.1 kardel { 1133 1.1 kardel register struct zsaline *za = (struct zsaline *)(void *)zs->zs_priv; 1134 1.1 kardel register struct zscc_device *zsaddr = zs->zs_addr; 1135 1.1 kardel register queue_t *q; 1136 1.1 kardel register unsigned char zsstatus; 1137 1.1 kardel register int loopcheck; 1138 1.1 kardel register char *dname; 1139 1.1 kardel #ifdef PPS_SYNC 1140 1.1 kardel register unsigned int s; 1141 1.1 kardel register long usec; 1142 1.1 kardel #endif 1143 1.1 kardel 1144 1.1 kardel /* 1145 1.1 kardel * pick up current state 1146 1.1 kardel */ 1147 1.1 kardel zsstatus = zsaddr->zscc_control; 1148 1.1 kardel 1149 1.1 kardel if ((za->za_rr0 ^ zsstatus) & (cdmask)) 1150 1.1 kardel { 1151 1.1 kardel timestamp_t cdevent; 1152 1.1 kardel register int status; 1153 1.3 christos 1154 1.1 kardel za->za_rr0 = (za->za_rr0 & ~(cdmask)) | (zsstatus & (cdmask)); 1155 1.1 kardel 1156 1.1 kardel #ifdef PPS_SYNC 1157 1.1 kardel s = splclock(); 1158 1.1 kardel #ifdef PPS_NEW 1159 1.1 kardel usec = timestamp.tv_usec; 1160 1.1 kardel #else 1161 1.1 kardel usec = pps_time.tv_usec; 1162 1.1 kardel #endif 1163 1.1 kardel #endif 1164 1.1 kardel /* 1165 1.1 kardel * time stamp 1166 1.1 kardel */ 1167 1.1 kardel uniqtime(&cdevent.tv); 1168 1.3 christos 1169 1.1 kardel #ifdef PPS_SYNC 1170 1.1 kardel (void)splx(s); 1171 1.1 kardel #endif 1172 1.1 kardel 1173 1.1 kardel /* 1174 1.1 kardel * logical state 1175 1.1 kardel */ 1176 1.1 kardel status = cd_invert ? (zsstatus & cdmask) == 0 : (zsstatus & cdmask) != 0; 1177 1.1 kardel 1178 1.1 kardel #ifdef PPS_SYNC 1179 1.1 kardel if (status) 1180 1.1 kardel { 1181 1.1 kardel usec = cdevent.tv.tv_usec - usec; 1182 1.1 kardel if (usec < 0) 1183 1.1 kardel usec += 1000000; 1184 1.1 kardel 1185 1.1 kardel hardpps(&cdevent.tv, usec); 1186 1.1 kardel } 1187 1.1 kardel #endif 1188 1.1 kardel 1189 1.1 kardel q = za->za_ttycommon.t_readq; 1190 1.1 kardel 1191 1.1 kardel /* 1192 1.1 kardel * ok - now the hard part - find ourself 1193 1.1 kardel */ 1194 1.1 kardel loopcheck = MAXDEPTH; 1195 1.3 christos 1196 1.1 kardel while (q) 1197 1.1 kardel { 1198 1.1 kardel if (q->q_qinfo && q->q_qinfo->qi_minfo) 1199 1.1 kardel { 1200 1.1 kardel dname = q->q_qinfo->qi_minfo->mi_idname; 1201 1.1 kardel 1202 1.1 kardel if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) 1203 1.1 kardel { 1204 1.1 kardel /* 1205 1.1 kardel * back home - phew (hopping along stream queues might 1206 1.1 kardel * prove dangerous to your health) 1207 1.1 kardel */ 1208 1.1 kardel 1209 1.1 kardel if ((((parsestream_t *)(void *)q->q_ptr)->parse_status & PARSE_ENABLE) && 1210 1.1 kardel parse_iopps(&((parsestream_t *)(void *)q->q_ptr)->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &cdevent)) 1211 1.1 kardel { 1212 1.1 kardel /* 1213 1.1 kardel * XXX - currently we do not pass up the message, as 1214 1.1 kardel * we should. 1215 1.1 kardel * for a correct behaviour wee need to block out 1216 1.1 kardel * processing until parse_iodone has been posted via 1217 1.1 kardel * a softcall-ed routine which does the message pass-up 1218 1.1 kardel * right now PPS information relies on input being 1219 1.1 kardel * received 1220 1.1 kardel */ 1221 1.1 kardel parse_iodone(&((parsestream_t *)(void *)q->q_ptr)->parse_io); 1222 1.1 kardel } 1223 1.3 christos 1224 1.1 kardel if (status) 1225 1.1 kardel { 1226 1.1 kardel ((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; 1227 1.1 kardel ++(((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.serial); 1228 1.1 kardel } 1229 1.1 kardel 1230 1.1 kardel parseprintf(DD_ISR, ("zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname)); 1231 1.1 kardel break; 1232 1.1 kardel } 1233 1.1 kardel } 1234 1.1 kardel 1235 1.1 kardel q = q->q_next; 1236 1.1 kardel 1237 1.1 kardel if (!loopcheck--) 1238 1.1 kardel { 1239 1.1 kardel panic("zs_xsisr: STREAMS Queue corrupted - CD event"); 1240 1.1 kardel } 1241 1.1 kardel } 1242 1.1 kardel 1243 1.1 kardel /* 1244 1.1 kardel * only pretend that CD has been handled 1245 1.1 kardel */ 1246 1.1 kardel ZSDELAY(2); 1247 1.1 kardel 1248 1.1 kardel if (!((za->za_rr0 ^ zsstatus) & ~(cdmask))) 1249 1.1 kardel { 1250 1.1 kardel /* 1251 1.1 kardel * all done - kill status indication and return 1252 1.1 kardel */ 1253 1.1 kardel zsaddr->zscc_control = ZSWR0_RESET_STATUS; /* might kill other conditions here */ 1254 1.1 kardel return 0; 1255 1.1 kardel } 1256 1.3 christos } 1257 1.1 kardel 1258 1.1 kardel if (zsstatus & cdmask) /* fake CARRIER status */ 1259 1.1 kardel za->za_flags |= ZAS_CARR_ON; 1260 1.1 kardel else 1261 1.1 kardel za->za_flags &= ~ZAS_CARR_ON; 1262 1.3 christos 1263 1.1 kardel /* 1264 1.1 kardel * we are now gathered here to process some unusual external status 1265 1.1 kardel * interrupts. 1266 1.1 kardel * any CD events have also been handled and shouldn't be processed 1267 1.1 kardel * by the original routine (unless we have a VERY busy port pin) 1268 1.1 kardel * some initializations are done here, which could have been done before for 1269 1.1 kardel * both code paths but have been avoided for minimum path length to 1270 1.1 kardel * the uniq_time routine 1271 1.1 kardel */ 1272 1.1 kardel dname = (char *) 0; 1273 1.1 kardel q = za->za_ttycommon.t_readq; 1274 1.1 kardel 1275 1.1 kardel loopcheck = MAXDEPTH; 1276 1.3 christos 1277 1.1 kardel /* 1278 1.1 kardel * the real thing for everything else ... 1279 1.1 kardel */ 1280 1.1 kardel while (q) 1281 1.1 kardel { 1282 1.1 kardel if (q->q_qinfo && q->q_qinfo->qi_minfo) 1283 1.1 kardel { 1284 1.1 kardel dname = q->q_qinfo->qi_minfo->mi_idname; 1285 1.1 kardel if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) 1286 1.1 kardel { 1287 1.1 kardel register int (*zsisr) (struct zscom *); 1288 1.3 christos 1289 1.1 kardel /* 1290 1.1 kardel * back home - phew (hopping along stream queues might 1291 1.1 kardel * prove dangerous to your health) 1292 1.1 kardel */ 1293 1.1 kardel if ((zsisr = ((struct savedzsops *)((parsestream_t *)(void *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) 1294 1.1 kardel return zsisr(zs); 1295 1.1 kardel else 1296 1.1 kardel panic("zs_xsisr: unable to locate original ISR"); 1297 1.3 christos 1298 1.1 kardel parseprintf(DD_ISR, ("zs_xsisr: non CD event was processed for \"%s\"\n", dname)); 1299 1.1 kardel /* 1300 1.1 kardel * now back to our program ... 1301 1.1 kardel */ 1302 1.1 kardel return 0; 1303 1.1 kardel } 1304 1.1 kardel } 1305 1.1 kardel 1306 1.1 kardel q = q->q_next; 1307 1.1 kardel 1308 1.1 kardel if (!loopcheck--) 1309 1.1 kardel { 1310 1.1 kardel panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); 1311 1.1 kardel } 1312 1.1 kardel } 1313 1.1 kardel 1314 1.1 kardel /* 1315 1.1 kardel * last resort - shouldn't even come here as it indicates 1316 1.1 kardel * corrupted TTY structures 1317 1.1 kardel */ 1318 1.1 kardel printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); 1319 1.3 christos 1320 1.1 kardel if (emergencyzs && emergencyzs->zsop_xsint) 1321 1.1 kardel emergencyzs->zsop_xsint(zs); 1322 1.1 kardel else 1323 1.1 kardel panic("zs_xsisr: no emergency ISR handler"); 1324 1.1 kardel return 0; 1325 1.1 kardel } 1326 1.1 kardel #endif /* sun */ 1327 1.1 kardel 1328 1.1 kardel /* 1329 1.1 kardel * History: 1330 1.1 kardel * 1331 1.1 kardel * parsestreams.c,v 1332 1.1 kardel * Revision 4.11 2005/04/16 17:32:10 kardel 1333 1.1 kardel * update copyright 1334 1.1 kardel * 1335 1.1 kardel * Revision 4.10 2004/11/14 16:06:08 kardel 1336 1.1 kardel * update Id tags 1337 1.1 kardel * 1338 1.1 kardel * Revision 4.9 2004/11/14 15:29:41 kardel 1339 1.1 kardel * support PPSAPI, upgrade Copyright to Berkeley style 1340 1.1 kardel * 1341 1.1 kardel * Revision 4.7 1999/11/28 09:13:53 kardel 1342 1.1 kardel * RECON_4_0_98F 1343 1.1 kardel * 1344 1.1 kardel * Revision 4.6 1998/12/20 23:45:31 kardel 1345 1.1 kardel * fix types and warnings 1346 1.1 kardel * 1347 1.1 kardel * Revision 4.5 1998/11/15 21:23:38 kardel 1348 1.1 kardel * ntp_memset() replicated in Sun kernel files 1349 1.1 kardel * 1350 1.1 kardel * Revision 4.4 1998/06/13 12:15:59 kardel 1351 1.1 kardel * superfluous variable removed 1352 1.1 kardel * 1353 1.1 kardel * Revision 4.3 1998/06/12 15:23:08 kardel 1354 1.1 kardel * fix prototypes 1355 1.1 kardel * adjust for ansi2knr 1356 1.1 kardel * 1357 1.1 kardel * Revision 4.2 1998/05/24 18:16:22 kardel 1358 1.1 kardel * moved copy of shadow status to the beginning 1359 1.1 kardel * 1360 1.1 kardel * Revision 4.1 1998/05/24 09:38:47 kardel 1361 1.1 kardel * streams initiated iopps calls (M_xHANGUP) are now consistent with the 1362 1.1 kardel * respective calls from zs_xsisr() 1363 1.1 kardel * simulation of CARRIER status to avoid unecessary M_xHANGUP messages 1364 1.1 kardel * 1365 1.1 kardel * Revision 4.0 1998/04/10 19:45:38 kardel 1366 1.1 kardel * Start 4.0 release version numbering 1367 1.1 kardel * 1368 1.1 kardel * from V3 3.37 log info deleted 1998/04/11 kardel 1369 1.1 kardel */ 1370