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