2 * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
25 *---------------------------------------------------------------------------
27 * i4btrc - device driver for trace data read device
28 * ---------------------------------------------------
30 * last edit-date: [Sat Aug 11 18:07:15 2001]
32 * $FreeBSD: src/sys/i4b/driver/i4b_trace.c,v 1.9.2.3 2001/08/12 16:22:48 hm Exp $
33 * $DragonFly: src/sys/net/i4b/driver/i4b_trace.c,v 1.17 2006/12/22 23:44:55 swildner Exp $
35 *---------------------------------------------------------------------------*/
37 #include "use_i4btrc.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/ioccom.h>
46 #include <sys/kernel.h>
48 #include <sys/socket.h>
51 #include <sys/thread2.h>
53 #include <net/i4b/include/machine/i4b_trace.h>
54 #include <net/i4b/include/machine/i4b_ioctl.h>
56 #include "../include/i4b_mbuf.h"
57 #include "../include/i4b_global.h"
58 #include "../include/i4b_l3l4.h"
60 static struct ifqueue trace_queue[NI4BTRC];
61 static int device_state[NI4BTRC];
63 #define ST_ISOPEN 0x01
64 #define ST_WAITDATA 0x02
66 static int analyzemode = 0;
67 static int rxunit = -1;
68 static int txunit = -1;
69 static int outunit = -1;
71 #define PDEVSTATIC static
72 static d_open_t i4btrcopen;
73 static d_close_t i4btrcclose;
74 static d_read_t i4btrcread;
75 static d_ioctl_t i4btrcioctl;
77 static d_poll_t i4btrcpoll;
78 #define POLLFIELD i4btrcpoll
82 static struct dev_ops i4btrc_ops = {
83 { "i4btrc", CDEV_MAJOR, 0 },
85 .d_close = i4btrcclose,
87 .d_ioctl = i4btrcioctl,
91 /*---------------------------------------------------------------------------*
92 * interface init routine
93 *---------------------------------------------------------------------------*/
95 i4btrcinit(void *unused)
97 dev_ops_add(&i4btrc_ops, 0, 0);
100 SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
101 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
103 static void i4btrcattach(void *);
104 PSEUDO_SET(i4btrcattach, i4b_trace);
106 int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
108 /*---------------------------------------------------------------------------*
109 * interface attach routine
110 *---------------------------------------------------------------------------*/
112 i4btrcattach(void *dummy)
116 kprintf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
118 for(i=0; i < NI4BTRC; i++)
121 make_dev(&i4btrc_ops, i,
122 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
123 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
125 device_state[i] = ST_IDLE;
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 *---------------------------------------------------------------------------*/
138 get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
143 int totlen = len + sizeof(i4b_trace_hdr_t);
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.
154 if(totlen > MCLBYTES)
157 hdr->trunc = totlen - MCLBYTES;
165 /* set length of trace record */
167 hdr->length = totlen;
169 /* check valid unit no */
171 if((unit = hdr->unit) > NI4BTRC)
173 kprintf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
179 if(!(m = i4b_Bgetmbuf(totlen)))
181 kprintf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
185 /* check if we are in analyzemode */
187 if(analyzemode && (unit == rxunit || unit == txunit))
196 if(IF_QFULL(&trace_queue[unit]))
201 IF_DEQUEUE(&trace_queue[unit], m1);
207 /* copy trace header */
208 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
210 /* copy trace data */
212 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
214 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
218 IF_ENQUEUE(&trace_queue[unit], m);
220 if(device_state[unit] & ST_WAITDATA)
222 device_state[unit] &= ~ST_WAITDATA;
223 wakeup((caddr_t) &trace_queue[unit]);
231 /*---------------------------------------------------------------------------*
233 *---------------------------------------------------------------------------*/
235 i4btrcopen(struct dev_open_args *ap)
237 cdev_t dev = ap->a_head.a_dev;
238 int unit = minor(dev);
243 if(device_state[unit] & ST_ISOPEN)
246 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
251 device_state[unit] = ST_ISOPEN;
258 /*---------------------------------------------------------------------------*
260 *---------------------------------------------------------------------------*/
262 i4btrcclose(struct dev_close_args *ap)
264 cdev_t dev = ap->a_head.a_dev;
265 int unit = minor(dev);
269 for(i=0; i < nctrl; i++)
271 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
272 (ctrl_desc[i].unit == unit))
279 if(analyzemode && (unit == outunit))
286 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
287 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
295 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
299 device_state[unit] = ST_IDLE;
305 /*---------------------------------------------------------------------------*
306 * read from trace device
307 *---------------------------------------------------------------------------*/
309 i4btrcread(struct dev_read_args *ap)
311 cdev_t dev = ap->a_head.a_dev;
312 struct uio *uio = ap->a_uio;
315 int unit = minor(dev);
317 if(!(device_state[unit] & ST_ISOPEN))
322 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
324 device_state[unit] |= ST_WAITDATA;
326 if((error = tsleep((caddr_t) &trace_queue[unit],
327 PCATCH, "bitrc", 0 )) != 0)
329 device_state[unit] &= ~ST_WAITDATA;
335 IF_DEQUEUE(&trace_queue[unit], m);
338 error = uiomove(m->m_data, m->m_len, uio);
350 /*---------------------------------------------------------------------------*
352 *---------------------------------------------------------------------------*/
354 i4btrcpoll(struct dev_poll_args *ap)
359 /*---------------------------------------------------------------------------*
360 * device driver ioctl routine
361 *---------------------------------------------------------------------------*/
363 i4btrcioctl(struct dev_ioctl_args *ap)
365 cdev_t dev = ap->a_head.a_dev;
367 int unit = minor(dev);
368 i4b_trace_setupa_t *tsa;
372 /* find the first passive controller matching our unit no */
374 for(i=0; i < nctrl; i++)
376 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
377 (ctrl_desc[i].unit == unit))
389 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)ap->a_data);
393 tsa = (i4b_trace_setupa_t *)ap->a_data;
395 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
396 rxunit = tsa->rxunit;
400 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
401 txunit = tsa->txunit;
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)));
437 #endif /* NI4BTRC > 0 */