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