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