Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / netisdn / i4b_trace.c
blob80267611098481ebd027c4c64e6302f6165aa11f
1 /*
2 * Copyright (c) 1997, 2000 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
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.
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.
25 *---------------------------------------------------------------------------
27 * i4btrc - device driver for trace data read device
28 * ---------------------------------------------------
30 * $Id: i4b_trace.c,v 1.20 2009/03/18 10:22:44 cegger Exp $
32 * last edit-date: [Fri Jan 5 11:33:47 2001]
35 *---------------------------------------------------------------------------*/
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: i4b_trace.c,v 1.19 2009/03/14 14:46:11 dsl Exp $");
40 #include "isdntrc.h"
42 #if NISDNTRC > 0
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
48 #include <sys/ioccom.h>
49 #else
50 #include <sys/ioctl.h>
51 #endif
53 #include <sys/conf.h>
54 #include <sys/uio.h>
55 #include <sys/kernel.h>
56 #include <sys/mbuf.h>
57 #include <sys/socket.h>
58 #include <net/if.h>
59 #include <sys/proc.h>
60 #include <sys/tty.h>
62 #include <netisdn/i4b_trace.h>
63 #include <netisdn/i4b_ioctl.h>
65 #include <netisdn/i4b_mbuf.h>
66 #include <netisdn/i4b_global.h>
67 #include <netisdn/i4b_debug.h>
68 #include <netisdn/i4b_l3l4.h>
69 #include <netisdn/i4b_l2.h>
70 #include <netisdn/i4b_l1l2.h>
72 static struct ifqueue trace_queue[NISDNTRC];
73 static int device_state[NISDNTRC];
74 #define ST_IDLE 0x00
75 #define ST_ISOPEN 0x01
76 #define ST_WAITDATA 0x02
78 static int analyzemode = 0; /* we are in anlyzer mode */
79 static int rxunit = -1; /* l2 isdnif of receiving driver */
80 static int txunit = -1; /* l2 isdnif of transmitting driver */
81 static int outunit = -1; /* output device for trace data */
83 #define PDEVSTATIC /* - not static - */
84 void isdntrcattach(void);
85 int isdntrcopen(dev_t dev, int flag, int fmt, struct lwp *l);
86 int isdntrcclose(dev_t dev, int flag, int fmt, struct lwp *l);
87 int isdntrcread(dev_t dev, struct uio * uio, int ioflag);
88 int isdntrcioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l);
90 #ifdef __NetBSD__
91 const struct cdevsw isdntrc_cdevsw = {
92 isdntrcopen, isdntrcclose, isdntrcread, nowrite, isdntrcioctl,
93 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
95 #endif /* __NetBSD__ */
97 /*---------------------------------------------------------------------------*
98 * interface attach routine
99 *---------------------------------------------------------------------------*/
100 PDEVSTATIC void
101 #ifdef __FreeBSD__
102 isdntrcattach(void *dummy)
103 #else
104 isdntrcattach(void)
105 #endif
107 int i;
109 for(i=0; i < NISDNTRC; i++)
112 #if defined(__FreeBSD__)
113 #if __FreeBSD__ < 4
115 #ifdef DEVFS
116 devfs_token[i]
117 = devfs_add_devswf(&i4btrc_cdevsw, i, DV_CHR,
118 UID_ROOT, GID_WHEEL, 0600,
119 "isdntrc%d", i);
120 #endif
122 #else
123 make_dev(&i4btrc_cdevsw, i,
124 UID_ROOT, GID_WHEEL, 0600, "isdntrc%d", i);
125 #endif
126 #endif
127 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
128 device_state[i] = ST_IDLE;
132 /*---------------------------------------------------------------------------*
133 * isdn_layer2_trace_ind
134 * ---------------------
135 * is called from layer 1, adds timestamp to trace data and puts
136 * it into a queue, from which it can be read from the i4btrc
137 * device. The unit number in the trace header selects the minor
138 * device's queue the data is put into.
139 *---------------------------------------------------------------------------*/
141 isdn_layer2_trace_ind(struct l2_softc *sc, struct isdn_l3_driver *drv, i4b_trace_hdr *hdr, size_t len, unsigned char *buf)
143 struct mbuf *m;
144 int isdnif, x;
145 int trunc = 0;
146 int totlen = len + sizeof(i4b_trace_hdr);
148 MICROTIME(hdr->time);
149 hdr->isdnif = sc->drv->isdnif;
152 * for telephony (or better non-HDLC HSCX mode) we get
153 * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
154 * to put into the queue to userland. because of this
155 * we detect this situation, strip the length to MCLBYTES
156 * max size, and infor the userland program of this fact
157 * by putting the no of truncated bytes into hdr->trunc.
160 if(totlen > MCLBYTES)
162 trunc = 1;
163 hdr->trunc = totlen - MCLBYTES;
164 totlen = MCLBYTES;
166 else
168 hdr->trunc = 0;
171 /* set length of trace record */
173 hdr->length = totlen;
175 /* check valid interface */
177 if((isdnif = hdr->isdnif) > NISDNTRC)
179 printf("i4b_trace: get_trace_data_from_l1 - isdnif > NISDNTRC!\n");
180 return(0);
183 /* get mbuf */
185 if(!(m = i4b_Bgetmbuf(totlen)))
187 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
188 return(0);
191 /* check if we are in analyzemode */
193 if(analyzemode && (isdnif == rxunit || isdnif == txunit))
195 if(isdnif == rxunit)
196 hdr->dir = FROM_NT;
197 else
198 hdr->dir = FROM_TE;
199 isdnif = outunit;
202 if(IF_QFULL(&trace_queue[isdnif]))
204 struct mbuf *m1;
206 x = splnet();
207 IF_DEQUEUE(&trace_queue[isdnif], m1);
208 splx(x);
210 i4b_Bfreembuf(m1);
213 /* copy trace header */
214 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr));
216 /* copy trace data */
217 if(trunc)
218 memcpy(&m->m_data[sizeof(i4b_trace_hdr)], buf, totlen-sizeof(i4b_trace_hdr));
219 else
220 memcpy(&m->m_data[sizeof(i4b_trace_hdr)], buf, len);
222 x = splnet();
224 IF_ENQUEUE(&trace_queue[isdnif], m);
226 if(device_state[isdnif] & ST_WAITDATA)
228 device_state[isdnif] &= ~ST_WAITDATA;
229 wakeup((void *) &trace_queue[isdnif]);
232 splx(x);
234 return(1);
237 /*---------------------------------------------------------------------------*
238 * open trace device
239 *---------------------------------------------------------------------------*/
240 PDEVSTATIC int
241 isdntrcopen(dev_t dev, int flag, int fmt,
242 struct lwp *l)
244 int x;
245 int unit = minor(dev);
247 if(unit >= NISDNTRC)
248 return(ENXIO);
250 if(device_state[unit] & ST_ISOPEN)
251 return(EBUSY);
253 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
254 return(EBUSY);
257 x = splnet();
259 device_state[unit] = ST_ISOPEN;
261 splx(x);
263 return(0);
266 /*---------------------------------------------------------------------------*
267 * close trace device
268 *---------------------------------------------------------------------------*/
269 PDEVSTATIC int
270 isdntrcclose(dev_t dev, int flag, int fmt,
271 struct lwp *l)
273 int isdnif = minor(dev);
274 int x;
276 if (analyzemode && (isdnif == outunit)) {
277 l2_softc_t * rx_l2sc, * tx_l2sc;
278 analyzemode = 0;
279 outunit = -1;
281 rx_l2sc = (l2_softc_t*)isdn_find_softc_by_isdnif(rxunit);
282 tx_l2sc = (l2_softc_t*)isdn_find_softc_by_isdnif(txunit);
284 if (rx_l2sc != NULL)
285 rx_l2sc->driver->mph_command_req(rx_l2sc->l1_token, CMR_SETTRACE, TRACE_OFF);
286 if (tx_l2sc != NULL)
287 tx_l2sc->driver->mph_command_req(tx_l2sc->l1_token, CMR_SETTRACE, TRACE_OFF);
289 x = splnet();
290 device_state[rxunit] = ST_IDLE;
291 device_state[txunit] = ST_IDLE;
292 splx(x);
293 rxunit = -1;
294 txunit = -1;
295 } else {
296 l2_softc_t * l2sc = (l2_softc_t*)isdn_find_softc_by_isdnif(isdnif);
297 if (l2sc != NULL) {
298 l2sc->driver->mph_command_req(l2sc->l1_token, CMR_SETTRACE, TRACE_OFF);
299 x = splnet();
300 device_state[isdnif] = ST_IDLE;
301 splx(x);
304 return(0);
307 /*---------------------------------------------------------------------------*
308 * read from trace device
309 *---------------------------------------------------------------------------*/
310 PDEVSTATIC int
311 isdntrcread(dev_t dev, struct uio * uio, int ioflag)
313 struct mbuf *m;
314 int x;
315 int error = 0;
316 int unit = minor(dev);
318 if(!(device_state[unit] & ST_ISOPEN))
319 return(EIO);
321 x = splnet();
323 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
325 device_state[unit] |= ST_WAITDATA;
327 if((error = tsleep((void *) &trace_queue[unit],
328 TTIPRI | PCATCH,
329 "bitrc", 0 )) != 0)
331 device_state[unit] &= ~ST_WAITDATA;
332 splx(x);
333 return(error);
337 IF_DEQUEUE(&trace_queue[unit], m);
339 if(m && m->m_len)
340 error = uiomove(m->m_data, m->m_len, uio);
341 else
342 error = EIO;
344 if(m)
345 i4b_Bfreembuf(m);
347 splx(x);
349 return(error);
352 #if defined(__FreeBSD__) && defined(OS_USES_POLL)
353 /*---------------------------------------------------------------------------*
354 * poll device
355 *---------------------------------------------------------------------------*/
356 PDEVSTATIC int
357 i4btrcpoll(dev_t dev, int events, struct proc *p)
359 return(ENODEV);
361 #endif
363 /*---------------------------------------------------------------------------*
364 * device driver ioctl routine
365 *---------------------------------------------------------------------------*/
366 PDEVSTATIC int
367 isdntrcioctl(dev_t dev, u_long cmd, void *data, int flag,
368 struct lwp *l)
370 int error = 0;
371 int isdnif = minor(dev);
372 i4b_trace_setupa_t *tsa;
373 l2_softc_t * l2sc = (l2_softc_t*)isdn_find_softc_by_isdnif(isdnif);
375 switch(cmd)
377 case I4B_TRC_SET:
378 if (l2sc == NULL)
379 return ENOTTY;
380 l2sc->driver->mph_command_req(l2sc->l1_token, CMR_SETTRACE, (void *)*(unsigned long *)data);
381 break;
383 case I4B_TRC_SETA:
384 tsa = (i4b_trace_setupa_t *)data;
386 if(tsa->rxunit >= 0 && tsa->rxunit < NISDNTRC)
387 rxunit = tsa->rxunit;
388 else
389 error = EINVAL;
391 if(tsa->txunit >= 0 && tsa->txunit < NISDNTRC)
392 txunit = tsa->txunit;
393 else
394 error = EINVAL;
396 if(error)
398 outunit = -1;
399 rxunit = -1;
400 txunit = -1;
402 else
404 l2_softc_t * rx_l2sc, * tx_l2sc;
405 rx_l2sc = (l2_softc_t*)(l2_softc_t*)isdn_find_softc_by_isdnif(rxunit);
406 tx_l2sc = (l2_softc_t*)(l2_softc_t*)isdn_find_softc_by_isdnif(txunit);
408 if (l2sc == NULL || rx_l2sc == NULL || tx_l2sc == NULL)
409 return ENOTTY;
411 outunit = isdnif;
412 analyzemode = 1;
413 rx_l2sc->driver->mph_command_req(rx_l2sc->l1_token, CMR_SETTRACE, (void *)(unsigned long)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
414 tx_l2sc->driver->mph_command_req(tx_l2sc->l1_token, CMR_SETTRACE, (void *)(unsigned long)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
416 break;
418 case I4B_TRC_RESETA:
419 analyzemode = 0;
420 outunit = -1;
421 rxunit = -1;
422 txunit = -1;
423 break;
425 default:
426 error = ENOTTY;
427 break;
429 return(error);
432 #endif /* NISDNTRC > 0 */