Fix a minor bug that prevented compilation.
[dragonfly.git] / sys / net / i4b / driver / i4b_trace.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3 *
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.
12 *
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.
24 *
25 *---------------------------------------------------------------------------
26 *
27 * i4btrc - device driver for trace data read device
28 * ---------------------------------------------------
29 *
30 * last edit-date: [Sat Aug 11 18:07:15 2001]
31 *
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.14 2006/01/14 11:05:18 swildner Exp $
34 *
35 *---------------------------------------------------------------------------*/
36
37#include "use_i4btrc.h"
38
39#if NI4BTRC > 0
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/ioccom.h>
44#include <sys/conf.h>
45#include <sys/uio.h>
46#include <sys/kernel.h>
47#include <sys/mbuf.h>
48#include <sys/socket.h>
49#include <net/if.h>
50#include <sys/tty.h>
51#include <sys/thread2.h>
52
53#include <net/i4b/include/machine/i4b_trace.h>
54#include <net/i4b/include/machine/i4b_ioctl.h>
55
56#include "../include/i4b_mbuf.h"
57#include "../include/i4b_global.h"
58#include "../include/i4b_l3l4.h"
59
60static struct ifqueue trace_queue[NI4BTRC];
61static int device_state[NI4BTRC];
62#define ST_IDLE 0x00
63#define ST_ISOPEN 0x01
64#define ST_WAITDATA 0x02
65
66static int analyzemode = 0;
67static int rxunit = -1;
68static int txunit = -1;
69static int outunit = -1;
70
71#define PDEVSTATIC static
72static d_open_t i4btrcopen;
73static d_close_t i4btrcclose;
74static d_read_t i4btrcread;
75static d_ioctl_t i4btrcioctl;
76
77static d_poll_t i4btrcpoll;
78#define POLLFIELD i4btrcpoll
79
80#define CDEV_MAJOR 59
81
82static struct cdevsw i4btrc_cdevsw = {
83 /* name */ "i4btrc",
84 /* maj */ CDEV_MAJOR,
85 /* flags */ 0,
86 /* port */ NULL,
87 /* clone */ NULL,
88
89 /* open */ i4btrcopen,
90 /* close */ i4btrcclose,
91 /* read */ i4btrcread,
92 /* write */ nowrite,
93 /* ioctl */ i4btrcioctl,
94 /* poll */ POLLFIELD,
95 /* mmap */ nommap,
96 /* strategy */ nostrategy,
97 /* dump */ nodump,
98 /* psize */ nopsize
99};
100
101/*---------------------------------------------------------------------------*
102 * interface init routine
103 *---------------------------------------------------------------------------*/
104static void
105i4btrcinit(void *unused)
106{
107 cdevsw_add(&i4btrc_cdevsw, 0, 0);
108}
109
110SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
111 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
112
113static void i4btrcattach(void *);
114PSEUDO_SET(i4btrcattach, i4b_trace);
115
116int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
117
118/*---------------------------------------------------------------------------*
119 * interface attach routine
120 *---------------------------------------------------------------------------*/
121PDEVSTATIC void
122i4btrcattach(void *dummy)
123{
124 int i;
125
126 printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
127
128 for(i=0; i < NI4BTRC; i++)
129 {
130
131 make_dev(&i4btrc_cdevsw, i,
132 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
133 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
134
135 device_state[i] = ST_IDLE;
136 }
137}
138
139/*---------------------------------------------------------------------------*
140 * get_trace_data_from_l1()
141 * ------------------------
142 * is called from layer 1, adds timestamp to trace data and puts
143 * it into a queue, from which it can be read from the i4btrc
144 * device. The unit number in the trace header selects the minor
145 * device's queue the data is put into.
146 *---------------------------------------------------------------------------*/
147int
148get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
149{
150 struct mbuf *m;
151 int unit;
152 int trunc = 0;
153 int totlen = len + sizeof(i4b_trace_hdr_t);
154
155 /*
156 * for telephony (or better non-HDLC HSCX mode) we get
157 * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
158 * to put into the queue to userland. because of this
159 * we detect this situation, strip the length to MCLBYTES
160 * max size, and infor the userland program of this fact
161 * by putting the no of truncated bytes into hdr->trunc.
162 */
163
164 if(totlen > MCLBYTES)
165 {
166 trunc = 1;
167 hdr->trunc = totlen - MCLBYTES;
168 totlen = MCLBYTES;
169 }
170 else
171 {
172 hdr->trunc = 0;
173 }
174
175 /* set length of trace record */
176
177 hdr->length = totlen;
178
179 /* check valid unit no */
180
181 if((unit = hdr->unit) > NI4BTRC)
182 {
183 printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
184 return(0);
185 }
186
187 /* get mbuf */
188
189 if(!(m = i4b_Bgetmbuf(totlen)))
190 {
191 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
192 return(0);
193 }
194
195 /* check if we are in analyzemode */
196
197 if(analyzemode && (unit == rxunit || unit == txunit))
198 {
199 if(unit == rxunit)
200 hdr->dir = FROM_NT;
201 else
202 hdr->dir = FROM_TE;
203 unit = outunit;
204 }
205
206 if(IF_QFULL(&trace_queue[unit]))
207 {
208 struct mbuf *m1;
209
210 crit_enter();
211 IF_DEQUEUE(&trace_queue[unit], m1);
212 crit_exit();
213
214 i4b_Bfreembuf(m1);
215 }
216
217 /* copy trace header */
218 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
219
220 /* copy trace data */
221 if(trunc)
222 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
223 else
224 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
225
226 crit_enter();
227
228 IF_ENQUEUE(&trace_queue[unit], m);
229
230 if(device_state[unit] & ST_WAITDATA)
231 {
232 device_state[unit] &= ~ST_WAITDATA;
233 wakeup((caddr_t) &trace_queue[unit]);
234 }
235
236 crit_exit();
237
238 return(1);
239}
240
241/*---------------------------------------------------------------------------*
242 * open trace device
243 *---------------------------------------------------------------------------*/
244PDEVSTATIC int
245i4btrcopen(dev_t dev, int flag, int fmt, struct thread *td)
246{
247 int unit = minor(dev);
248
249 if(unit >= NI4BTRC)
250 return(ENXIO);
251
252 if(device_state[unit] & ST_ISOPEN)
253 return(EBUSY);
254
255 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
256 return(EBUSY);
257
258 crit_enter();
259
260 device_state[unit] = ST_ISOPEN;
261
262 crit_exit();
263
264 return(0);
265}
266
267/*---------------------------------------------------------------------------*
268 * close trace device
269 *---------------------------------------------------------------------------*/
270PDEVSTATIC int
271i4btrcclose(dev_t dev, int flag, int fmt, struct thread *td)
272{
273 int unit = minor(dev);
274 int i;
275 int cno = -1;
276
277 for(i=0; i < nctrl; i++)
278 {
279 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
280 (ctrl_desc[i].unit == unit))
281 {
282 cno = i;
283 break;
284 }
285 }
286
287 if(analyzemode && (unit == outunit))
288 {
289 analyzemode = 0;
290 outunit = -1;
291
292 if(cno >= 0)
293 {
294 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
295 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
296 }
297 rxunit = -1;
298 txunit = -1;
299 }
300
301 if(cno >= 0)
302 {
303 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
304 }
305
306 crit_enter();
307 device_state[unit] = ST_IDLE;
308 crit_exit();
309
310 return(0);
311}
312
313/*---------------------------------------------------------------------------*
314 * read from trace device
315 *---------------------------------------------------------------------------*/
316PDEVSTATIC int
317i4btrcread(dev_t dev, struct uio * uio, int ioflag)
318{
319 struct mbuf *m;
320 int error = 0;
321 int unit = minor(dev);
322
323 if(!(device_state[unit] & ST_ISOPEN))
324 return(EIO);
325
326 crit_enter();
327
328 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
329 {
330 device_state[unit] |= ST_WAITDATA;
331
332 if((error = tsleep((caddr_t) &trace_queue[unit],
333 PCATCH, "bitrc", 0 )) != 0)
334 {
335 device_state[unit] &= ~ST_WAITDATA;
336 crit_exit();
337 return(error);
338 }
339 }
340
341 IF_DEQUEUE(&trace_queue[unit], m);
342
343 if(m && m->m_len)
344 error = uiomove(m->m_data, m->m_len, uio);
345 else
346 error = EIO;
347
348 if(m)
349 i4b_Bfreembuf(m);
350
351 crit_exit();
352
353 return(error);
354}
355
356/*---------------------------------------------------------------------------*
357 * poll device
358 *---------------------------------------------------------------------------*/
359PDEVSTATIC int
360i4btrcpoll(dev_t dev, int events, struct thread *td)
361{
362 return(ENODEV);
363}
364
365/*---------------------------------------------------------------------------*
366 * device driver ioctl routine
367 *---------------------------------------------------------------------------*/
368PDEVSTATIC int
369i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
370{
371 int error = 0;
372 int unit = minor(dev);
373 i4b_trace_setupa_t *tsa;
374 int i;
375 int cno = -1;
376
377 /* find the first passive controller matching our unit no */
378
379 for(i=0; i < nctrl; i++)
380 {
381 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
382 (ctrl_desc[i].unit == unit))
383 {
384 cno = i;
385 break;
386 }
387 }
388
389 switch(cmd)
390 {
391 case I4B_TRC_SET:
392 if(cno < 0)
393 return ENOTTY;
394 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)data);
395 break;
396
397 case I4B_TRC_SETA:
398 tsa = (i4b_trace_setupa_t *)data;
399
400 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
401 rxunit = tsa->rxunit;
402 else
403 error = EINVAL;
404
405 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
406 txunit = tsa->txunit;
407 else
408 error = EINVAL;
409
410 if(error)
411 {
412 outunit = -1;
413 rxunit = -1;
414 txunit = -1;
415 }
416 else
417 {
418 if(cno < 0)
419 return ENOTTY;
420
421 outunit = unit;
422 analyzemode = 1;
423 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, (int *)(tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
424 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, (int *)(tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)));
425 }
426 break;
427
428 case I4B_TRC_RESETA:
429 analyzemode = 0;
430 outunit = -1;
431 rxunit = -1;
432 txunit = -1;
433 break;
434
435 default:
436 error = ENOTTY;
437 break;
438 }
439 return(error);
440}
441
442#endif /* NI4BTRC > 0 */