/contrib/ntp/libparse/parsestreams.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1367 lines · 937 code · 172 blank · 258 comment · 158 complexity · 8a3b36be009b19d929acac0205fa5a1f MD5 · raw file

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