File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / kernel / tty_clk_STREAMS.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /* tty_clk_STREAMS.c,v 3.1 1993/07/06 01:07:34 jbj Exp
    2:  * Timestamp STREAMS module for SunOS 4.1
    3:  *
    4:  * Copyright 1991, Nick Sayer
    5:  *
    6:  * Special thanks to Greg Onufer for his debug assists.
    7:  *
    8:  * Should be PUSHed directly on top of a serial I/O channel.
    9:  * For any character in a user-designated set, adds a kernel
   10:  * timestamp to that character.
   11:  *
   12:  * BUGS:
   13:  *
   14:  * Only so many characters can be timestamped. This number, however,
   15:  * is adjustable.
   16:  *
   17:  * The null character ($00) cannot be timestamped.
   18:  *
   19:  * The M_DATA messages passed upstream will not be the same
   20:  * size as when they arrive from downstream, even if no
   21:  * timestamp character is in the message. This, however,
   22:  * should not affect anything.
   23:  *
   24:  */
   25: 
   26: #include "clk.h"
   27: #if NCLK > 0
   28: /*
   29:  * How big should the messages we pass upstream be?
   30:  */
   31: #define MESSAGE_SIZE 128
   32: 
   33: #include <string.h>
   34: #include <sys/types.h>
   35: #include <sys/stream.h>
   36: #include <sys/param.h>
   37: #include <sys/time.h>
   38: #include <sys/kernel.h>
   39: #include <sys/user.h>
   40: #include <sys/errno.h>
   41: #include <sys/syslog.h>
   42: 
   43: #include <sys/clkdefs.h>
   44: 
   45: static struct module_info rminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
   46: static struct module_info wminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
   47: static int clkopen(), clkrput(), clkwput(), clkclose();
   48: 
   49: static struct qinit rinit = { clkrput, NULL, clkopen, clkclose, NULL,
   50: 	&rminfo, NULL };
   51: 
   52: static struct qinit winit = { clkwput, NULL, NULL, NULL, NULL,
   53: 	&wminfo, NULL };
   54: 
   55: struct streamtab clkinfo = { &rinit, &winit, NULL, NULL };
   56: 
   57: struct priv_data_type
   58: {
   59:   char in_use;
   60:   char string[CLK_MAXSTRSIZE];
   61: } priv_data[NCLK];
   62: 
   63: char first_open=1;
   64: 
   65: /*
   66:  * God only knows why, but linking with strchr() fails
   67:  * on my system, so here's a renamed copy.
   68:  */
   69: 
   70: u_char *str_chr(s,c)
   71: u_char *s;
   72: int c;
   73: {
   74:   while (*s)
   75:     if(*s++ == c)
   76:       return (s-1);
   77:   return NULL;
   78: }
   79: 
   80: /*ARGSUSED*/
   81: static int clkopen(q, dev, flag, sflag)
   82: queue_t *q;
   83: dev_t dev;
   84: int flag;
   85: int sflag;
   86: {
   87:   int i;
   88: 
   89: /* Damn it! We can't even have the global data struct properly
   90:    initialized! So we have a mark to tell us to init the global
   91:    data on the first open */
   92: 
   93:   if (first_open)
   94:   {
   95:     first_open=0;
   96: 
   97:     for(i=0;i<NCLK;i++)
   98:       priv_data[i].in_use=0;
   99:   }
  100: 
  101:   for(i=0;i<NCLK;i++)
  102:     if(!priv_data[i].in_use)
  103:     {
  104:       priv_data[i].in_use++;
  105:       ((struct priv_data_type *) (q->q_ptr))=priv_data+i;
  106:       priv_data[i].string[0]=0;
  107:       return (0);
  108:     }
  109:   u.u_error = EBUSY;
  110:   return (OPENFAIL);
  111: }
  112: 
  113: /*ARGSUSED*/
  114: static int clkclose(q, flag)
  115: queue_t *q;
  116: int flag;
  117: {
  118:   ((struct priv_data_type *) (q->q_ptr))->in_use=0;
  119: 
  120:   return (0);
  121: }
  122: 
  123: /*
  124:  * Now the crux of the biscuit.
  125:  *
  126:  * If it's an M_DATA package, we take each character and pass
  127:  * it to clkchar.
  128:  */
  129: 
  130: void clkchar();
  131: 
  132: static int clkrput(q, mp)
  133: queue_t *q;
  134: mblk_t *mp;
  135: {
  136:   mblk_t *bp;
  137: 
  138:   switch(mp->b_datap->db_type)
  139:   {
  140:     case M_DATA:
  141:       clkchar(0,q,2);
  142:       for(bp=mp; bp!=NULL; bp=bp->b_cont)
  143:       {
  144: 	while(bp->b_rptr < bp->b_wptr)
  145: 	  clkchar( ((u_char)*(bp->b_rptr++)) , q , 0 );
  146:       }
  147:       clkchar(0,q,1);
  148:       freemsg(mp);
  149:     break;
  150:     default:
  151:       putnext(q,mp);
  152:     break;
  153:   }
  154: 
  155: }
  156: 
  157: /*
  158:  * If it's a matching M_IOCTL, handle it.
  159:  */
  160: 
  161: static int clkwput(q, mp)
  162: queue_t *q;
  163: mblk_t *mp;
  164: {
  165:   struct iocblk *iocp;
  166: 
  167:   switch(mp->b_datap->db_type)
  168:   {
  169:     case M_IOCTL:
  170:       iocp=(struct iocblk*) mp->b_rptr;
  171:       if (iocp->ioc_cmd==CLK_SETSTR)
  172:       {
  173:         strncpy( ((struct priv_data_type *) (RD(q)->q_ptr))->string,
  174: 	  (char *) mp->b_cont->b_rptr,CLK_MAXSTRSIZE);
  175:         /* make sure it's null terminated */
  176: 	((struct priv_data_type *) (RD(q)->q_ptr))->string[CLK_MAXSTRSIZE-1]=0;
  177: 	mp->b_datap->db_type = M_IOCACK;
  178: 	qreply(q,mp);
  179:       }
  180:       else
  181: 	putnext(q,mp);
  182:     break;
  183:     default:
  184:       putnext(q,mp);
  185:     break;
  186:   }
  187: }
  188: 
  189: /*
  190:  * Now clkchar. It takes a character, a queue pointer and an action
  191:  * flag and depending on the flag either:
  192:  *
  193:  * 0 - adds the character to the current message. If there's a
  194:  * timestamp to be done, do that too. If the message is less than
  195:  * 8 chars from being full, link in a new one, and set it up for
  196:  * the next call.
  197:  *
  198:  * 1 - sends the whole mess to Valhala.
  199:  *
  200:  * 2 - set things up.
  201:  *
  202:  * Yeah, it's an ugly hack. Complaints may be filed with /dev/null.
  203:  */
  204: 
  205: 
  206: void clkchar(c,q,f)
  207: 	register u_char c;
  208: 	queue_t *q;
  209: 	char f;
  210: {
  211:   static char error;
  212:   static mblk_t *message,*mp;
  213:   struct timeval tv;
  214: 
  215: /* Get a timestamp ASAP! */
  216:   uniqtime(&tv);
  217: 
  218:   switch(f)
  219:   {
  220:     case 1:
  221:       if (!error)
  222:         putnext(q,message);
  223:     break;
  224:     case 2:
  225:       mp=message= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
  226:       error=(message==NULL);
  227:       if (error)
  228: 	log(LOG_ERR,"clk: cannot allocate message - data lost");
  229:     break;
  230:     case 0:
  231:       if (error) /* If we had an error, forget it. */
  232: 	return;
  233: 
  234:       *mp->b_wptr++=c; /* Put the char away first.
  235: 
  236:       /* If it's in the special string, append a struct timeval */
  237: 
  238:       if (str_chr( ((struct priv_data_type *) (q->q_ptr))->string ,
  239:         c )!=NULL)
  240:       {
  241: 	  int i;
  242: 
  243: 	  for (i=0;i<sizeof(struct timeval);i++)
  244: 	    *mp->b_wptr++= *( ((char*)&tv) + i );
  245:       }
  246: 
  247:       /* If we don't have space for a complete struct timeval, and a
  248:          char, it's time for a new mp block */
  249: 
  250:       if (((mp->b_wptr-mp->b_rptr)+sizeof(struct timeval)+2)>MESSAGE_SIZE)
  251:       {
  252: 	  mp->b_cont= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
  253: 	  error=(mp->b_cont==NULL);
  254: 	  if (error)
  255: 	  {
  256: 	    log(LOG_ERR,"clk: cannot allocate message - data lost");
  257: 	    freemsg(message);
  258:           }
  259:           mp=mp->b_cont;
  260:       }
  261: 
  262:     break;
  263:   }
  264: }
  265: 
  266: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>