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
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 * $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 $");
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
48 #include <sys/ioccom.h>
50 #include <sys/ioctl.h>
55 #include <sys/kernel.h>
57 #include <sys/socket.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
];
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
);
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 *---------------------------------------------------------------------------*/
102 isdntrcattach(void *dummy
)
109 for(i
=0; i
< NISDNTRC
; i
++)
112 #if defined(__FreeBSD__)
117 = devfs_add_devswf(&i4btrc_cdevsw
, i
, DV_CHR
,
118 UID_ROOT
, GID_WHEEL
, 0600,
123 make_dev(&i4btrc_cdevsw
, i
,
124 UID_ROOT
, GID_WHEEL
, 0600, "isdntrc%d", i
);
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
)
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
)
163 hdr
->trunc
= totlen
- MCLBYTES
;
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");
185 if(!(m
= i4b_Bgetmbuf(totlen
)))
187 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
191 /* check if we are in analyzemode */
193 if(analyzemode
&& (isdnif
== rxunit
|| isdnif
== txunit
))
202 if(IF_QFULL(&trace_queue
[isdnif
]))
207 IF_DEQUEUE(&trace_queue
[isdnif
], m1
);
213 /* copy trace header */
214 memcpy(m
->m_data
, hdr
, sizeof(i4b_trace_hdr
));
216 /* copy trace data */
218 memcpy(&m
->m_data
[sizeof(i4b_trace_hdr
)], buf
, totlen
-sizeof(i4b_trace_hdr
));
220 memcpy(&m
->m_data
[sizeof(i4b_trace_hdr
)], buf
, len
);
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
]);
237 /*---------------------------------------------------------------------------*
239 *---------------------------------------------------------------------------*/
241 isdntrcopen(dev_t dev
, int flag
, int fmt
,
245 int unit
= minor(dev
);
250 if(device_state
[unit
] & ST_ISOPEN
)
253 if(analyzemode
&& (unit
== outunit
|| unit
== rxunit
|| unit
== txunit
))
259 device_state
[unit
] = ST_ISOPEN
;
266 /*---------------------------------------------------------------------------*
268 *---------------------------------------------------------------------------*/
270 isdntrcclose(dev_t dev
, int flag
, int fmt
,
273 int isdnif
= minor(dev
);
276 if (analyzemode
&& (isdnif
== outunit
)) {
277 l2_softc_t
* rx_l2sc
, * tx_l2sc
;
281 rx_l2sc
= (l2_softc_t
*)isdn_find_softc_by_isdnif(rxunit
);
282 tx_l2sc
= (l2_softc_t
*)isdn_find_softc_by_isdnif(txunit
);
285 rx_l2sc
->driver
->mph_command_req(rx_l2sc
->l1_token
, CMR_SETTRACE
, TRACE_OFF
);
287 tx_l2sc
->driver
->mph_command_req(tx_l2sc
->l1_token
, CMR_SETTRACE
, TRACE_OFF
);
290 device_state
[rxunit
] = ST_IDLE
;
291 device_state
[txunit
] = ST_IDLE
;
296 l2_softc_t
* l2sc
= (l2_softc_t
*)isdn_find_softc_by_isdnif(isdnif
);
298 l2sc
->driver
->mph_command_req(l2sc
->l1_token
, CMR_SETTRACE
, TRACE_OFF
);
300 device_state
[isdnif
] = ST_IDLE
;
307 /*---------------------------------------------------------------------------*
308 * read from trace device
309 *---------------------------------------------------------------------------*/
311 isdntrcread(dev_t dev
, struct uio
* uio
, int ioflag
)
316 int unit
= minor(dev
);
318 if(!(device_state
[unit
] & ST_ISOPEN
))
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
],
331 device_state
[unit
] &= ~ST_WAITDATA
;
337 IF_DEQUEUE(&trace_queue
[unit
], m
);
340 error
= uiomove(m
->m_data
, m
->m_len
, uio
);
352 #if defined(__FreeBSD__) && defined(OS_USES_POLL)
353 /*---------------------------------------------------------------------------*
355 *---------------------------------------------------------------------------*/
357 i4btrcpoll(dev_t dev
, int events
, struct proc
*p
)
363 /*---------------------------------------------------------------------------*
364 * device driver ioctl routine
365 *---------------------------------------------------------------------------*/
367 isdntrcioctl(dev_t dev
, u_long cmd
, void *data
, int flag
,
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
);
380 l2sc
->driver
->mph_command_req(l2sc
->l1_token
, CMR_SETTRACE
, (void *)*(unsigned long *)data
);
384 tsa
= (i4b_trace_setupa_t
*)data
;
386 if(tsa
->rxunit
>= 0 && tsa
->rxunit
< NISDNTRC
)
387 rxunit
= tsa
->rxunit
;
391 if(tsa
->txunit
>= 0 && tsa
->txunit
< NISDNTRC
)
392 txunit
= tsa
->txunit
;
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
)
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
)));
432 #endif /* NISDNTRC > 0 */