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.12 2005/06/03 16:49:57 dillon Exp $
35 *---------------------------------------------------------------------------*/
37 #include "use_i4btrc.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
44 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
45 #include <sys/ioccom.h>
47 #include <sys/ioctl.h>
52 #include <sys/kernel.h>
54 #include <sys/socket.h>
57 #include <sys/thread2.h>
59 #if defined(__DragonFly__) || defined(__FreeBSD__)
62 #include <sys/devfsext.h>
65 #include <net/i4b/include/machine/i4b_trace.h>
66 #include <net/i4b/include/machine/i4b_ioctl.h>
70 #include <i4b/i4b_trace.h>
71 #include <i4b/i4b_ioctl.h>
75 #include "../include/i4b_mbuf.h"
76 #include "../include/i4b_global.h"
77 #include "../include/i4b_l3l4.h"
79 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
80 #define memcpy(d,s,l) bcopy(s,d,l)
83 static struct ifqueue trace_queue[NI4BTRC];
84 static int device_state[NI4BTRC];
86 #define ST_ISOPEN 0x01
87 #define ST_WAITDATA 0x02
89 #if defined(__FreeBSD__) && __FreeBSD__ == 3
91 static void *devfs_token[NI4BTRC];
95 static int analyzemode = 0;
96 static int rxunit = -1;
97 static int txunit = -1;
98 static int outunit = -1;
100 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
102 #define PDEVSTATIC /* - not static - */
103 void i4btrcattach (void);
104 int i4btrcopen (dev_t dev, int flag, int fmt, struct proc *p);
105 int i4btrcclose (dev_t dev, int flag, int fmt, struct proc *p);
106 int i4btrcread (dev_t dev, struct uio * uio, int ioflag);
109 int i4btrcioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
111 int i4btrcioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
116 #if defined(__DragonFly__) || (BSD > 199306 && defined(__FreeBSD__))
117 #define PDEVSTATIC static
118 static d_open_t i4btrcopen;
119 static d_close_t i4btrcclose;
120 static d_read_t i4btrcread;
121 static d_ioctl_t i4btrcioctl;
124 static d_poll_t i4btrcpoll;
125 #define POLLFIELD i4btrcpoll
127 #define POLLFIELD noselect
130 #define CDEV_MAJOR 59
132 static struct cdevsw i4btrc_cdevsw = {
134 /* maj */ CDEV_MAJOR,
139 /* open */ i4btrcopen,
140 /* close */ i4btrcclose,
141 /* read */ i4btrcread,
143 /* ioctl */ i4btrcioctl,
144 /* poll */ POLLFIELD,
146 /* strategy */ nostrategy,
151 /*---------------------------------------------------------------------------*
152 * interface init routine
153 *---------------------------------------------------------------------------*/
155 void i4btrcinit(void *unused)
157 cdevsw_add(&i4btrc_cdevsw, 0, 0);
160 SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
161 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
163 static void i4btrcattach(void *);
164 PSEUDO_SET(i4btrcattach, i4b_trace);
166 #endif /* BSD > 199306 && defined(__FreeBSD__) */
169 #include <sys/device.h>
170 int i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux);
171 void dummy_i4btrcattach(struct device*, struct device *, void *);
173 #define CDEV_MAJOR 60
175 static struct cfdriver i4btrccd =
176 { NULL, "i4btrc", i4btrcmatch, dummy_i4btrcattach, DV_DULL,
177 sizeof(struct cfdriver) };
178 struct devsw i4btrcsw =
180 i4btrcopen, i4btrcclose, i4btrcread, nowrite,
181 i4btrcioctl, seltrue, nommap, nostrat,
182 nodump, nopsize, 0, nostop
186 i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux)
188 printf("i4btrcmatch: aux=0x%x\n", aux);
192 dummy_i4btrcattach(struct device *parent, struct device *self, void *aux)
194 printf("dummy_i4btrcattach: aux=0x%x\n", aux);
196 #endif /* __bsdi__ */
198 int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
200 /*---------------------------------------------------------------------------*
201 * interface attach routine
202 *---------------------------------------------------------------------------*/
204 #if defined(__DragonFly__) || defined(__FreeBSD__)
205 i4btrcattach(void *dummy)
212 printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
214 for(i=0; i < NI4BTRC; i++)
217 #if defined(__DragonFly__) || defined(__FreeBSD__)
218 make_dev(&i4btrc_cdevsw, i,
219 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
221 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
223 #if defined(__FreeBSD__) && __FreeBSD__ > 4
224 mtx_init(&trace_queue[i].ifq_mtx, "i4b_trace", MTX_DEF);
226 device_state[i] = ST_IDLE;
230 /*---------------------------------------------------------------------------*
231 * get_trace_data_from_l1()
232 * ------------------------
233 * is called from layer 1, adds timestamp to trace data and puts
234 * it into a queue, from which it can be read from the i4btrc
235 * device. The unit number in the trace header selects the minor
236 * device's queue the data is put into.
237 *---------------------------------------------------------------------------*/
239 get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
244 int totlen = len + sizeof(i4b_trace_hdr_t);
247 * for telephony (or better non-HDLC HSCX mode) we get
248 * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
249 * to put into the queue to userland. because of this
250 * we detect this situation, strip the length to MCLBYTES
251 * max size, and infor the userland program of this fact
252 * by putting the no of truncated bytes into hdr->trunc.
255 if(totlen > MCLBYTES)
258 hdr->trunc = totlen - MCLBYTES;
266 /* set length of trace record */
268 hdr->length = totlen;
270 /* check valid unit no */
272 if((unit = hdr->unit) > NI4BTRC)
274 printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
280 if(!(m = i4b_Bgetmbuf(totlen)))
282 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
286 /* check if we are in analyzemode */
288 if(analyzemode && (unit == rxunit || unit == txunit))
297 if(IF_QFULL(&trace_queue[unit]))
302 IF_DEQUEUE(&trace_queue[unit], m1);
308 /* copy trace header */
309 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
311 /* copy trace data */
313 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
315 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
319 IF_ENQUEUE(&trace_queue[unit], m);
321 if(device_state[unit] & ST_WAITDATA)
323 device_state[unit] &= ~ST_WAITDATA;
324 wakeup((caddr_t) &trace_queue[unit]);
332 /*---------------------------------------------------------------------------*
334 *---------------------------------------------------------------------------*/
336 i4btrcopen(dev_t dev, int flag, int fmt, struct thread *td)
338 int unit = minor(dev);
343 if(device_state[unit] & ST_ISOPEN)
346 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
351 device_state[unit] = ST_ISOPEN;
358 /*---------------------------------------------------------------------------*
360 *---------------------------------------------------------------------------*/
362 i4btrcclose(dev_t dev, int flag, int fmt, struct thread *td)
364 int unit = minor(dev);
368 for(i=0; i < nctrl; i++)
370 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
371 (ctrl_desc[i].unit == unit))
378 if(analyzemode && (unit == outunit))
385 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
386 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
394 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
398 device_state[unit] = ST_IDLE;
404 /*---------------------------------------------------------------------------*
405 * read from trace device
406 *---------------------------------------------------------------------------*/
408 i4btrcread(dev_t dev, struct uio * uio, int ioflag)
412 int unit = minor(dev);
414 if(!(device_state[unit] & ST_ISOPEN))
419 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
421 device_state[unit] |= ST_WAITDATA;
423 #if defined (__FreeBSD__) && __FreeBSD__ > 4
424 if((error = msleep((caddr_t) &trace_queue[unit],
425 &trace_queue[unit].ifq_mtx,
429 if((error = tsleep((caddr_t) &trace_queue[unit],
430 PCATCH, "bitrc", 0 )) != 0)
433 device_state[unit] &= ~ST_WAITDATA;
439 IF_DEQUEUE(&trace_queue[unit], m);
442 error = uiomove(m->m_data, m->m_len, uio);
454 #if (defined(__DragonFly__) || defined(__FreeBSD__)) && defined(OS_USES_POLL)
455 /*---------------------------------------------------------------------------*
457 *---------------------------------------------------------------------------*/
459 i4btrcpoll(dev_t dev, int events, struct thread *td)
465 /*---------------------------------------------------------------------------*
466 * device driver ioctl routine
467 *---------------------------------------------------------------------------*/
469 #if defined(__DragonFly__) || (defined (__FreeBSD_version) && __FreeBSD_version >= 300003)
470 i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
471 #elif defined(__bsdi__)
472 i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
474 i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
478 int unit = minor(dev);
479 i4b_trace_setupa_t *tsa;
483 /* find the first passive controller matching our unit no */
485 for(i=0; i < nctrl; i++)
487 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
488 (ctrl_desc[i].unit == unit))
500 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)data);
504 tsa = (i4b_trace_setupa_t *)data;
506 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
507 rxunit = tsa->rxunit;
511 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
512 txunit = tsa->txunit;
529 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, (int *)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
530 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, (int *)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
548 #endif /* NI4BTRC > 0 */