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.3 2003/07/19 21:14:37 dillon Exp $
35 * NOTE: the code assumes that SPLI4B >= splimp !
37 *---------------------------------------------------------------------------*/
43 #include <sys/param.h>
44 #include <sys/systm.h>
46 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
47 #include <sys/ioccom.h>
49 #include <sys/ioctl.h>
54 #include <sys/kernel.h>
56 #include <sys/socket.h>
63 #include <sys/devfsext.h>
66 #include <machine/i4b_trace.h>
67 #include <machine/i4b_ioctl.h>
71 #include <i4b/i4b_trace.h>
72 #include <i4b/i4b_ioctl.h>
76 #include <i4b/include/i4b_mbuf.h>
77 #include <i4b/include/i4b_global.h>
78 #include <i4b/include/i4b_l3l4.h>
81 #define memcpy(d,s,l) bcopy(s,d,l)
84 static struct ifqueue trace_queue[NI4BTRC];
85 static int device_state[NI4BTRC];
87 #define ST_ISOPEN 0x01
88 #define ST_WAITDATA 0x02
90 #if defined(__FreeBSD__) && __FreeBSD__ == 3
92 static void *devfs_token[NI4BTRC];
96 static int analyzemode = 0;
97 static int rxunit = -1;
98 static int txunit = -1;
99 static int outunit = -1;
103 #define PDEVSTATIC /* - not static - */
104 void i4btrcattach __P((void));
105 int i4btrcopen __P((dev_t dev, int flag, int fmt, struct proc *p));
106 int i4btrcclose __P((dev_t dev, int flag, int fmt, struct proc *p));
107 int i4btrcread __P((dev_t dev, struct uio * uio, int ioflag));
110 int i4btrcioctl __P((dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p));
112 int i4btrcioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
117 #if BSD > 199306 && defined(__FreeBSD__)
118 #define PDEVSTATIC static
119 static d_open_t i4btrcopen;
120 static d_close_t i4btrcclose;
121 static d_read_t i4btrcread;
122 static d_ioctl_t i4btrcioctl;
125 static d_poll_t i4btrcpoll;
126 #define POLLFIELD i4btrcpoll
128 #define POLLFIELD noselect
131 #define CDEV_MAJOR 59
133 static struct cdevsw i4btrc_cdevsw = {
134 /* open */ i4btrcopen,
135 /* close */ i4btrcclose,
136 /* read */ i4btrcread,
138 /* ioctl */ i4btrcioctl,
139 /* poll */ POLLFIELD,
141 /* strategy */ nostrategy,
143 /* maj */ CDEV_MAJOR,
150 /*---------------------------------------------------------------------------*
151 * interface init routine
152 *---------------------------------------------------------------------------*/
154 void i4btrcinit(void *unused)
156 cdevsw_add(&i4btrc_cdevsw);
159 SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
160 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
162 static void i4btrcattach(void *);
163 PSEUDO_SET(i4btrcattach, i4b_trace);
165 #endif /* BSD > 199306 && defined(__FreeBSD__) */
168 #include <sys/device.h>
169 int i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux);
170 void dummy_i4btrcattach(struct device*, struct device *, void *);
172 #define CDEV_MAJOR 60
174 static struct cfdriver i4btrccd =
175 { NULL, "i4btrc", i4btrcmatch, dummy_i4btrcattach, DV_DULL,
176 sizeof(struct cfdriver) };
177 struct devsw i4btrcsw =
179 i4btrcopen, i4btrcclose, i4btrcread, nowrite,
180 i4btrcioctl, seltrue, nommap, nostrat,
181 nodump, nopsize, 0, nostop
185 i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux)
187 printf("i4btrcmatch: aux=0x%x\n", aux);
191 dummy_i4btrcattach(struct device *parent, struct device *self, void *aux)
193 printf("dummy_i4btrcattach: aux=0x%x\n", aux);
195 #endif /* __bsdi__ */
197 int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
199 /*---------------------------------------------------------------------------*
200 * interface attach routine
201 *---------------------------------------------------------------------------*/
204 i4btrcattach(void *dummy)
211 printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
213 for(i=0; i < NI4BTRC; i++)
216 #if defined(__FreeBSD__)
217 make_dev(&i4btrc_cdevsw, i,
218 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
220 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
223 mtx_init(&trace_queue[i].ifq_mtx, "i4b_trace", MTX_DEF);
225 device_state[i] = ST_IDLE;
229 /*---------------------------------------------------------------------------*
230 * get_trace_data_from_l1()
231 * ------------------------
232 * is called from layer 1, adds timestamp to trace data and puts
233 * it into a queue, from which it can be read from the i4btrc
234 * device. The unit number in the trace header selects the minor
235 * device's queue the data is put into.
236 *---------------------------------------------------------------------------*/
238 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_LOCK(&trace_queue[unit]);
298 if(_IF_QFULL(&trace_queue[unit]))
303 _IF_DEQUEUE(&trace_queue[unit], m1);
309 /* copy trace header */
310 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
312 /* copy trace data */
314 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
316 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
320 _IF_ENQUEUE(&trace_queue[unit], m);
321 IF_UNLOCK(&trace_queue[unit]);
323 if(device_state[unit] & ST_WAITDATA)
325 device_state[unit] &= ~ST_WAITDATA;
326 wakeup((caddr_t) &trace_queue[unit]);
334 /*---------------------------------------------------------------------------*
336 *---------------------------------------------------------------------------*/
338 i4btrcopen(dev_t dev, int flag, int fmt, struct proc *p)
341 int unit = minor(dev);
346 if(device_state[unit] & ST_ISOPEN)
349 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
354 device_state[unit] = ST_ISOPEN;
361 /*---------------------------------------------------------------------------*
363 *---------------------------------------------------------------------------*/
365 i4btrcclose(dev_t dev, int flag, int fmt, struct proc *p)
367 int unit = minor(dev);
371 for(i=0; i < nctrl; i++)
373 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
374 (ctrl_desc[i].unit == unit))
381 if(analyzemode && (unit == outunit))
388 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
389 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
397 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
401 device_state[unit] = ST_IDLE;
407 /*---------------------------------------------------------------------------*
408 * read from trace device
409 *---------------------------------------------------------------------------*/
411 i4btrcread(dev_t dev, struct uio * uio, int ioflag)
416 int unit = minor(dev);
418 if(!(device_state[unit] & ST_ISOPEN))
423 IF_LOCK(&trace_queue[unit]);
424 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
426 device_state[unit] |= ST_WAITDATA;
428 #if defined (__FreeBSD__) && __FreeBSD__ > 4
429 if((error = msleep((caddr_t) &trace_queue[unit],
430 &trace_queue[unit].ifq_mtx,
434 if((error = tsleep((caddr_t) &trace_queue[unit],
435 PCATCH, "bitrc", 0 )) != 0)
438 device_state[unit] &= ~ST_WAITDATA;
439 IF_UNLOCK(&trace_queue[unit]);
445 _IF_DEQUEUE(&trace_queue[unit], m);
446 IF_UNLOCK(&trace_queue[unit]);
449 error = uiomove(m->m_data, m->m_len, uio);
461 #if defined(__FreeBSD__) && defined(OS_USES_POLL)
462 /*---------------------------------------------------------------------------*
464 *---------------------------------------------------------------------------*/
466 i4btrcpoll(dev_t dev, int events, struct proc *p)
472 /*---------------------------------------------------------------------------*
473 * device driver ioctl routine
474 *---------------------------------------------------------------------------*/
476 #if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
477 i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
478 #elif defined(__bsdi__)
479 i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
481 i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
485 int unit = minor(dev);
486 i4b_trace_setupa_t *tsa;
490 /* find the first passive controller matching our unit no */
492 for(i=0; i < nctrl; i++)
494 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
495 (ctrl_desc[i].unit == unit))
507 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)data);
511 tsa = (i4b_trace_setupa_t *)data;
513 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
514 rxunit = tsa->rxunit;
518 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
519 txunit = tsa->txunit;
536 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, (int *)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
537 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, (int *)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
555 #endif /* NI4BTRC > 0 */