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.10 2004/05/19 22:53:00 dillon Exp $
35 * NOTE: the code assumes that SPLI4B >= splimp !
37 *---------------------------------------------------------------------------*/
39 #include "use_i4btrc.h"
43 #include <sys/param.h>
44 #include <sys/systm.h>
46 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
47 #include <sys/ioccom.h>
49 #include <sys/ioctl.h>
54 #include <sys/kernel.h>
56 #include <sys/socket.h>
60 #if defined(__DragonFly__) || defined(__FreeBSD__)
63 #include <sys/devfsext.h>
66 #include <net/i4b/include/machine/i4b_trace.h>
67 #include <net/i4b/include/machine/i4b_ioctl.h>
71 #include <i4b/i4b_trace.h>
72 #include <i4b/i4b_ioctl.h>
76 #include "../include/i4b_mbuf.h"
77 #include "../include/i4b_global.h"
78 #include "../include/i4b_l3l4.h"
80 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
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;
101 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
103 #define PDEVSTATIC /* - not static - */
104 void i4btrcattach (void);
105 int i4btrcopen (dev_t dev, int flag, int fmt, struct proc *p);
106 int i4btrcclose (dev_t dev, int flag, int fmt, struct proc *p);
107 int i4btrcread (dev_t dev, struct uio * uio, int ioflag);
110 int i4btrcioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
112 int i4btrcioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
117 #if defined(__DragonFly__) || (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 = {
135 /* maj */ CDEV_MAJOR,
140 /* open */ i4btrcopen,
141 /* close */ i4btrcclose,
142 /* read */ i4btrcread,
144 /* ioctl */ i4btrcioctl,
145 /* poll */ POLLFIELD,
147 /* strategy */ nostrategy,
152 /*---------------------------------------------------------------------------*
153 * interface init routine
154 *---------------------------------------------------------------------------*/
156 void i4btrcinit(void *unused)
158 cdevsw_add(&i4btrc_cdevsw, 0, 0);
161 SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
162 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
164 static void i4btrcattach(void *);
165 PSEUDO_SET(i4btrcattach, i4b_trace);
167 #endif /* BSD > 199306 && defined(__FreeBSD__) */
170 #include <sys/device.h>
171 int i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux);
172 void dummy_i4btrcattach(struct device*, struct device *, void *);
174 #define CDEV_MAJOR 60
176 static struct cfdriver i4btrccd =
177 { NULL, "i4btrc", i4btrcmatch, dummy_i4btrcattach, DV_DULL,
178 sizeof(struct cfdriver) };
179 struct devsw i4btrcsw =
181 i4btrcopen, i4btrcclose, i4btrcread, nowrite,
182 i4btrcioctl, seltrue, nommap, nostrat,
183 nodump, nopsize, 0, nostop
187 i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux)
189 printf("i4btrcmatch: aux=0x%x\n", aux);
193 dummy_i4btrcattach(struct device *parent, struct device *self, void *aux)
195 printf("dummy_i4btrcattach: aux=0x%x\n", aux);
197 #endif /* __bsdi__ */
199 int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
201 /*---------------------------------------------------------------------------*
202 * interface attach routine
203 *---------------------------------------------------------------------------*/
205 #if defined(__DragonFly__) || defined(__FreeBSD__)
206 i4btrcattach(void *dummy)
213 printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
215 for(i=0; i < NI4BTRC; i++)
218 #if defined(__DragonFly__) || defined(__FreeBSD__)
219 make_dev(&i4btrc_cdevsw, i,
220 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
222 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
224 #if defined(__FreeBSD__) && __FreeBSD__ > 4
225 mtx_init(&trace_queue[i].ifq_mtx, "i4b_trace", MTX_DEF);
227 device_state[i] = ST_IDLE;
231 /*---------------------------------------------------------------------------*
232 * get_trace_data_from_l1()
233 * ------------------------
234 * is called from layer 1, adds timestamp to trace data and puts
235 * it into a queue, from which it can be read from the i4btrc
236 * device. The unit number in the trace header selects the minor
237 * device's queue the data is put into.
238 *---------------------------------------------------------------------------*/
240 get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
246 int totlen = len + sizeof(i4b_trace_hdr_t);
249 * for telephony (or better non-HDLC HSCX mode) we get
250 * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
251 * to put into the queue to userland. because of this
252 * we detect this situation, strip the length to MCLBYTES
253 * max size, and infor the userland program of this fact
254 * by putting the no of truncated bytes into hdr->trunc.
257 if(totlen > MCLBYTES)
260 hdr->trunc = totlen - MCLBYTES;
268 /* set length of trace record */
270 hdr->length = totlen;
272 /* check valid unit no */
274 if((unit = hdr->unit) > NI4BTRC)
276 printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
282 if(!(m = i4b_Bgetmbuf(totlen)))
284 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
288 /* check if we are in analyzemode */
290 if(analyzemode && (unit == rxunit || unit == txunit))
299 IF_LOCK(&trace_queue[unit]);
300 if(_IF_QFULL(&trace_queue[unit]))
305 _IF_DEQUEUE(&trace_queue[unit], m1);
311 /* copy trace header */
312 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
314 /* copy trace data */
316 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
318 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
322 _IF_ENQUEUE(&trace_queue[unit], m);
323 IF_UNLOCK(&trace_queue[unit]);
325 if(device_state[unit] & ST_WAITDATA)
327 device_state[unit] &= ~ST_WAITDATA;
328 wakeup((caddr_t) &trace_queue[unit]);
336 /*---------------------------------------------------------------------------*
338 *---------------------------------------------------------------------------*/
340 i4btrcopen(dev_t dev, int flag, int fmt, struct thread *td)
343 int unit = minor(dev);
348 if(device_state[unit] & ST_ISOPEN)
351 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
356 device_state[unit] = ST_ISOPEN;
363 /*---------------------------------------------------------------------------*
365 *---------------------------------------------------------------------------*/
367 i4btrcclose(dev_t dev, int flag, int fmt, struct thread *td)
369 int unit = minor(dev);
373 for(i=0; i < nctrl; i++)
375 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
376 (ctrl_desc[i].unit == unit))
383 if(analyzemode && (unit == outunit))
390 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
391 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
399 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
403 device_state[unit] = ST_IDLE;
409 /*---------------------------------------------------------------------------*
410 * read from trace device
411 *---------------------------------------------------------------------------*/
413 i4btrcread(dev_t dev, struct uio * uio, int ioflag)
418 int unit = minor(dev);
420 if(!(device_state[unit] & ST_ISOPEN))
425 IF_LOCK(&trace_queue[unit]);
426 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
428 device_state[unit] |= ST_WAITDATA;
430 #if defined (__FreeBSD__) && __FreeBSD__ > 4
431 if((error = msleep((caddr_t) &trace_queue[unit],
432 &trace_queue[unit].ifq_mtx,
436 if((error = tsleep((caddr_t) &trace_queue[unit],
437 PCATCH, "bitrc", 0 )) != 0)
440 device_state[unit] &= ~ST_WAITDATA;
441 IF_UNLOCK(&trace_queue[unit]);
447 _IF_DEQUEUE(&trace_queue[unit], m);
448 IF_UNLOCK(&trace_queue[unit]);
451 error = uiomove(m->m_data, m->m_len, uio);
463 #if (defined(__DragonFly__) || defined(__FreeBSD__)) && defined(OS_USES_POLL)
464 /*---------------------------------------------------------------------------*
466 *---------------------------------------------------------------------------*/
468 i4btrcpoll(dev_t dev, int events, struct thread *td)
474 /*---------------------------------------------------------------------------*
475 * device driver ioctl routine
476 *---------------------------------------------------------------------------*/
478 #if defined(__DragonFly__) || (defined (__FreeBSD_version) && __FreeBSD_version >= 300003)
479 i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
480 #elif defined(__bsdi__)
481 i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
483 i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
487 int unit = minor(dev);
488 i4b_trace_setupa_t *tsa;
492 /* find the first passive controller matching our unit no */
494 for(i=0; i < nctrl; i++)
496 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
497 (ctrl_desc[i].unit == unit))
509 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)data);
513 tsa = (i4b_trace_setupa_t *)data;
515 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
516 rxunit = tsa->rxunit;
520 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
521 txunit = tsa->txunit;
538 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, (int *)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
539 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, (int *)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
557 #endif /* NI4BTRC > 0 */