/contrib/ntp/libparse/parsesolaris.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1200 lines · 793 code · 155 blank · 252 comment · 126 complexity · a117ef4402ed1dce6253c8232466e897 MD5 · raw file

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