Silence warnings regarding yyunput being defined and never used.
[dragonfly.git] / sys / net / i4b / driver / i4b_trace.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 *---------------------------------------------------------------------------
26 *
27 * i4btrc - device driver for trace data read device
28 * ---------------------------------------------------
29 *
30 * last edit-date: [Sat Aug 11 18:07:15 2001]
31 *
32 * $FreeBSD: src/sys/i4b/driver/i4b_trace.c,v 1.9.2.3 2001/08/12 16:22:48 hm Exp $
fef8985e 33 * $DragonFly: src/sys/net/i4b/driver/i4b_trace.c,v 1.15 2006/07/28 02:17:40 dillon Exp $
984263bc
MD
34 *
35 *---------------------------------------------------------------------------*/
36
1f2de5d4 37#include "use_i4btrc.h"
984263bc
MD
38
39#if NI4BTRC > 0
40
41#include <sys/param.h>
42#include <sys/systm.h>
984263bc 43#include <sys/ioccom.h>
984263bc
MD
44#include <sys/conf.h>
45#include <sys/uio.h>
46#include <sys/kernel.h>
47#include <sys/mbuf.h>
48#include <sys/socket.h>
49#include <net/if.h>
50#include <sys/tty.h>
817cdab6 51#include <sys/thread2.h>
984263bc 52
1f2de5d4
MD
53#include <net/i4b/include/machine/i4b_trace.h>
54#include <net/i4b/include/machine/i4b_ioctl.h>
984263bc 55
1f2de5d4
MD
56#include "../include/i4b_mbuf.h"
57#include "../include/i4b_global.h"
58#include "../include/i4b_l3l4.h"
984263bc 59
984263bc
MD
60static struct ifqueue trace_queue[NI4BTRC];
61static int device_state[NI4BTRC];
62#define ST_IDLE 0x00
63#define ST_ISOPEN 0x01
64#define ST_WAITDATA 0x02
65
984263bc
MD
66static int analyzemode = 0;
67static int rxunit = -1;
68static int txunit = -1;
69static int outunit = -1;
70
984263bc
MD
71#define PDEVSTATIC static
72static d_open_t i4btrcopen;
73static d_close_t i4btrcclose;
74static d_read_t i4btrcread;
75static d_ioctl_t i4btrcioctl;
76
984263bc
MD
77static d_poll_t i4btrcpoll;
78#define POLLFIELD i4btrcpoll
984263bc
MD
79
80#define CDEV_MAJOR 59
81
fef8985e
MD
82static struct dev_ops i4btrc_ops = {
83 { "i4btrc", CDEV_MAJOR, 0 },
84 .d_open = i4btrcopen,
85 .d_close = i4btrcclose,
86 .d_read = i4btrcread,
87 .d_ioctl = i4btrcioctl,
88 .d_poll = POLLFIELD,
984263bc
MD
89};
90
91/*---------------------------------------------------------------------------*
92 * interface init routine
93 *---------------------------------------------------------------------------*/
3bf25ce1
SW
94static void
95i4btrcinit(void *unused)
984263bc 96{
fef8985e 97 dev_ops_add(&i4btrc_ops, 0, 0);
984263bc
MD
98}
99
100SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
101 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
102
103static void i4btrcattach(void *);
104PSEUDO_SET(i4btrcattach, i4b_trace);
105
984263bc
MD
106int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
107
108/*---------------------------------------------------------------------------*
109 * interface attach routine
110 *---------------------------------------------------------------------------*/
111PDEVSTATIC void
984263bc 112i4btrcattach(void *dummy)
984263bc
MD
113{
114 int i;
115
116 printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
117
118 for(i=0; i < NI4BTRC; i++)
119 {
120
fef8985e 121 make_dev(&i4btrc_ops, i,
984263bc 122 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
984263bc
MD
123 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
124
984263bc
MD
125 device_state[i] = ST_IDLE;
126 }
127}
128
129/*---------------------------------------------------------------------------*
130 * get_trace_data_from_l1()
131 * ------------------------
132 * is called from layer 1, adds timestamp to trace data and puts
133 * it into a queue, from which it can be read from the i4btrc
134 * device. The unit number in the trace header selects the minor
135 * device's queue the data is put into.
136 *---------------------------------------------------------------------------*/
137int
138get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
139{
140 struct mbuf *m;
984263bc
MD
141 int unit;
142 int trunc = 0;
143 int totlen = len + sizeof(i4b_trace_hdr_t);
144
145 /*
146 * for telephony (or better non-HDLC HSCX mode) we get
147 * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
148 * to put into the queue to userland. because of this
149 * we detect this situation, strip the length to MCLBYTES
150 * max size, and infor the userland program of this fact
151 * by putting the no of truncated bytes into hdr->trunc.
152 */
153
154 if(totlen > MCLBYTES)
155 {
156 trunc = 1;
157 hdr->trunc = totlen - MCLBYTES;
158 totlen = MCLBYTES;
159 }
160 else
161 {
162 hdr->trunc = 0;
163 }
164
165 /* set length of trace record */
166
167 hdr->length = totlen;
168
169 /* check valid unit no */
170
171 if((unit = hdr->unit) > NI4BTRC)
172 {
173 printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
174 return(0);
175 }
176
177 /* get mbuf */
178
179 if(!(m = i4b_Bgetmbuf(totlen)))
180 {
181 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
182 return(0);
183 }
184
185 /* check if we are in analyzemode */
186
187 if(analyzemode && (unit == rxunit || unit == txunit))
188 {
189 if(unit == rxunit)
190 hdr->dir = FROM_NT;
191 else
192 hdr->dir = FROM_TE;
193 unit = outunit;
194 }
195
fd81ccf9 196 if(IF_QFULL(&trace_queue[unit]))
984263bc
MD
197 {
198 struct mbuf *m1;
199
817cdab6 200 crit_enter();
fd81ccf9 201 IF_DEQUEUE(&trace_queue[unit], m1);
817cdab6 202 crit_exit();
984263bc
MD
203
204 i4b_Bfreembuf(m1);
205 }
206
207 /* copy trace header */
208 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
209
210 /* copy trace data */
211 if(trunc)
212 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
213 else
214 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
215
817cdab6 216 crit_enter();
984263bc 217
fd81ccf9 218 IF_ENQUEUE(&trace_queue[unit], m);
984263bc
MD
219
220 if(device_state[unit] & ST_WAITDATA)
221 {
222 device_state[unit] &= ~ST_WAITDATA;
223 wakeup((caddr_t) &trace_queue[unit]);
224 }
225
817cdab6 226 crit_exit();
984263bc
MD
227
228 return(1);
229}
230
231/*---------------------------------------------------------------------------*
232 * open trace device
233 *---------------------------------------------------------------------------*/
234PDEVSTATIC int
fef8985e 235i4btrcopen(struct dev_open_args *ap)
984263bc 236{
fef8985e 237 dev_t dev = ap->a_head.a_dev;
984263bc
MD
238 int unit = minor(dev);
239
240 if(unit >= NI4BTRC)
241 return(ENXIO);
242
243 if(device_state[unit] & ST_ISOPEN)
244 return(EBUSY);
245
246 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
247 return(EBUSY);
248
817cdab6 249 crit_enter();
984263bc
MD
250
251 device_state[unit] = ST_ISOPEN;
252
817cdab6 253 crit_exit();
984263bc
MD
254
255 return(0);
256}
257
258/*---------------------------------------------------------------------------*
259 * close trace device
260 *---------------------------------------------------------------------------*/
261PDEVSTATIC int
fef8985e 262i4btrcclose(struct dev_close_args *ap)
984263bc 263{
fef8985e 264 dev_t dev = ap->a_head.a_dev;
984263bc 265 int unit = minor(dev);
817cdab6 266 int i;
984263bc
MD
267 int cno = -1;
268
269 for(i=0; i < nctrl; i++)
270 {
271 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
272 (ctrl_desc[i].unit == unit))
273 {
274 cno = i;
275 break;
276 }
277 }
278
279 if(analyzemode && (unit == outunit))
280 {
281 analyzemode = 0;
282 outunit = -1;
283
284 if(cno >= 0)
285 {
286 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
287 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
288 }
289 rxunit = -1;
290 txunit = -1;
291 }
292
293 if(cno >= 0)
294 {
295 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
296 }
297
817cdab6 298 crit_enter();
984263bc 299 device_state[unit] = ST_IDLE;
817cdab6 300 crit_exit();
984263bc
MD
301
302 return(0);
303}
304
305/*---------------------------------------------------------------------------*
306 * read from trace device
307 *---------------------------------------------------------------------------*/
308PDEVSTATIC int
fef8985e 309i4btrcread(struct dev_read_args *ap)
984263bc 310{
fef8985e
MD
311 dev_t dev = ap->a_head.a_dev;
312 struct uio *uio = ap->a_uio;
984263bc 313 struct mbuf *m;
984263bc
MD
314 int error = 0;
315 int unit = minor(dev);
316
317 if(!(device_state[unit] & ST_ISOPEN))
318 return(EIO);
319
817cdab6 320 crit_enter();
984263bc 321
984263bc
MD
322 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
323 {
324 device_state[unit] |= ST_WAITDATA;
325
984263bc 326 if((error = tsleep((caddr_t) &trace_queue[unit],
377d4740 327 PCATCH, "bitrc", 0 )) != 0)
984263bc
MD
328 {
329 device_state[unit] &= ~ST_WAITDATA;
817cdab6 330 crit_exit();
984263bc
MD
331 return(error);
332 }
333 }
334
fd81ccf9 335 IF_DEQUEUE(&trace_queue[unit], m);
984263bc
MD
336
337 if(m && m->m_len)
338 error = uiomove(m->m_data, m->m_len, uio);
339 else
340 error = EIO;
341
342 if(m)
343 i4b_Bfreembuf(m);
344
817cdab6 345 crit_exit();
984263bc
MD
346
347 return(error);
348}
349
984263bc
MD
350/*---------------------------------------------------------------------------*
351 * poll device
352 *---------------------------------------------------------------------------*/
353PDEVSTATIC int
fef8985e 354i4btrcpoll(struct dev_poll_args *ap)
984263bc
MD
355{
356 return(ENODEV);
357}
984263bc
MD
358
359/*---------------------------------------------------------------------------*
360 * device driver ioctl routine
361 *---------------------------------------------------------------------------*/
362PDEVSTATIC int
fef8985e 363i4btrcioctl(struct dev_ioctl_args *ap)
984263bc 364{
fef8985e 365 dev_t dev = ap->a_head.a_dev;
984263bc
MD
366 int error = 0;
367 int unit = minor(dev);
368 i4b_trace_setupa_t *tsa;
369 int i;
370 int cno = -1;
371
372 /* find the first passive controller matching our unit no */
373
374 for(i=0; i < nctrl; i++)
375 {
376 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
377 (ctrl_desc[i].unit == unit))
378 {
379 cno = i;
380 break;
381 }
382 }
383
fef8985e 384 switch(ap->a_cmd)
984263bc
MD
385 {
386 case I4B_TRC_SET:
387 if(cno < 0)
388 return ENOTTY;
fef8985e 389 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)ap->a_data);
984263bc
MD
390 break;
391
392 case I4B_TRC_SETA:
fef8985e 393 tsa = (i4b_trace_setupa_t *)ap->a_data;
984263bc
MD
394
395 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
396 rxunit = tsa->rxunit;
397 else
398 error = EINVAL;
399
400 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
401 txunit = tsa->txunit;
402 else
403 error = EINVAL;
404
405 if(error)
406 {
407 outunit = -1;
408 rxunit = -1;
409 txunit = -1;
410 }
411 else
412 {
413 if(cno < 0)
414 return ENOTTY;
415
416 outunit = unit;
417 analyzemode = 1;
418 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, (int *)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
419 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, (int *)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
420 }
421 break;
422
423 case I4B_TRC_RESETA:
424 analyzemode = 0;
425 outunit = -1;
426 rxunit = -1;
427 txunit = -1;
428 break;
429
430 default:
431 error = ENOTTY;
432 break;
433 }
434 return(error);
435}
436
437#endif /* NI4BTRC > 0 */