sf_buf_ref() needs a critical section. Note that the function is not
[dragonfly.git] / sys / net / i4b / driver / i4b_trace.c
CommitLineData
984263bc
MD
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 $
9a7f3897 33 * $DragonFly: src/sys/net/i4b/driver/i4b_trace.c,v 1.8 2004/02/13 17:45:49 joerg Exp $
984263bc
MD
34 *
35 * NOTE: the code assumes that SPLI4B >= splimp !
36 *
37 *---------------------------------------------------------------------------*/
38
1f2de5d4 39#include "use_i4btrc.h"
984263bc
MD
40
41#if NI4BTRC > 0
42
43#include <sys/param.h>
44#include <sys/systm.h>
45
9a7f3897 46#if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
984263bc
MD
47#include <sys/ioccom.h>
48#else
49#include <sys/ioctl.h>
50#endif
51
52#include <sys/conf.h>
53#include <sys/uio.h>
54#include <sys/kernel.h>
55#include <sys/mbuf.h>
56#include <sys/socket.h>
57#include <net/if.h>
58#include <sys/tty.h>
59
9a7f3897 60#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
61
62#ifdef DEVFS
63#include <sys/devfsext.h>
64#endif
65
1f2de5d4
MD
66#include <net/i4b/include/machine/i4b_trace.h>
67#include <net/i4b/include/machine/i4b_ioctl.h>
984263bc
MD
68
69#else
70
71#include <i4b/i4b_trace.h>
72#include <i4b/i4b_ioctl.h>
73
74#endif
75
1f2de5d4
MD
76#include "../include/i4b_mbuf.h"
77#include "../include/i4b_global.h"
78#include "../include/i4b_l3l4.h"
984263bc 79
9a7f3897 80#if !defined(__DragonFly__) && !defined(__FreeBSD__)
984263bc
MD
81#define memcpy(d,s,l) bcopy(s,d,l)
82#endif
83
84static struct ifqueue trace_queue[NI4BTRC];
85static int device_state[NI4BTRC];
86#define ST_IDLE 0x00
87#define ST_ISOPEN 0x01
88#define ST_WAITDATA 0x02
89
90#if defined(__FreeBSD__) && __FreeBSD__ == 3
91#ifdef DEVFS
92static void *devfs_token[NI4BTRC];
93#endif
94#endif
95
96static int analyzemode = 0;
97static int rxunit = -1;
98static int txunit = -1;
99static int outunit = -1;
100
9a7f3897 101#if !defined(__DragonFly__) && !defined(__FreeBSD__)
984263bc
MD
102
103#define PDEVSTATIC /* - not static - */
158abb01
RG
104void i4btrcattach (void);
105int i4btrcopen (dev_t dev, int flag, int fmt, struct proc *p);
106int i4btrcclose (dev_t dev, int flag, int fmt, struct proc *p);
107int i4btrcread (dev_t dev, struct uio * uio, int ioflag);
984263bc
MD
108
109#ifdef __bsdi__
158abb01 110int i4btrcioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
984263bc 111#else
158abb01 112int i4btrcioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
984263bc
MD
113#endif
114
115#endif
116
9a7f3897 117#if defined(__DragonFly__) || (BSD > 199306 && defined(__FreeBSD__))
984263bc
MD
118#define PDEVSTATIC static
119static d_open_t i4btrcopen;
120static d_close_t i4btrcclose;
121static d_read_t i4btrcread;
122static d_ioctl_t i4btrcioctl;
123
124#ifdef OS_USES_POLL
125static d_poll_t i4btrcpoll;
126#define POLLFIELD i4btrcpoll
127#else
128#define POLLFIELD noselect
129#endif
130
131#define CDEV_MAJOR 59
132
133static struct cdevsw i4btrc_cdevsw = {
fabb8ceb
MD
134 /* name */ "i4btrc",
135 /* maj */ CDEV_MAJOR,
136 /* flags */ 0,
137 /* port */ NULL,
138 /* autoq */ 0,
139
984263bc
MD
140 /* open */ i4btrcopen,
141 /* close */ i4btrcclose,
142 /* read */ i4btrcread,
143 /* write */ nowrite,
144 /* ioctl */ i4btrcioctl,
145 /* poll */ POLLFIELD,
146 /* mmap */ nommap,
147 /* strategy */ nostrategy,
984263bc 148 /* dump */ nodump,
fabb8ceb 149 /* psize */ nopsize
984263bc
MD
150};
151
152/*---------------------------------------------------------------------------*
153 * interface init routine
154 *---------------------------------------------------------------------------*/
155static
156void i4btrcinit(void *unused)
157{
158 cdevsw_add(&i4btrc_cdevsw);
159}
160
161SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
162 SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
163
164static void i4btrcattach(void *);
165PSEUDO_SET(i4btrcattach, i4b_trace);
166
167#endif /* BSD > 199306 && defined(__FreeBSD__) */
168
169#ifdef __bsdi__
170#include <sys/device.h>
171int i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux);
172void dummy_i4btrcattach(struct device*, struct device *, void *);
173
174#define CDEV_MAJOR 60
175
176static struct cfdriver i4btrccd =
177 { NULL, "i4btrc", i4btrcmatch, dummy_i4btrcattach, DV_DULL,
178 sizeof(struct cfdriver) };
179struct devsw i4btrcsw =
180 { &i4btrccd,
181 i4btrcopen, i4btrcclose, i4btrcread, nowrite,
182 i4btrcioctl, seltrue, nommap, nostrat,
183 nodump, nopsize, 0, nostop
184};
185
186int
187i4btrcmatch(struct device *parent, struct cfdata *cf, void *aux)
188{
189 printf("i4btrcmatch: aux=0x%x\n", aux);
190 return 1;
191}
192void
193dummy_i4btrcattach(struct device *parent, struct device *self, void *aux)
194{
195 printf("dummy_i4btrcattach: aux=0x%x\n", aux);
196}
197#endif /* __bsdi__ */
198
199int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
200
201/*---------------------------------------------------------------------------*
202 * interface attach routine
203 *---------------------------------------------------------------------------*/
204PDEVSTATIC void
9a7f3897 205#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
206i4btrcattach(void *dummy)
207#else
208i4btrcattach()
209#endif
210{
211 int i;
212
213 printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
214
215 for(i=0; i < NI4BTRC; i++)
216 {
217
9a7f3897 218#if defined(__DragonFly__) || defined(__FreeBSD__)
984263bc
MD
219 make_dev(&i4btrc_cdevsw, i,
220 UID_ROOT, GID_WHEEL, 0600, "i4btrc%d", i);
221#endif
222 trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
223
9a7f3897 224#if defined(__FreeBSD__) && __FreeBSD__ > 4
984263bc
MD
225 mtx_init(&trace_queue[i].ifq_mtx, "i4b_trace", MTX_DEF);
226#endif
227 device_state[i] = ST_IDLE;
228 }
229}
230
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 *---------------------------------------------------------------------------*/
239int
240get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
241{
242 struct mbuf *m;
243 int x;
244 int unit;
245 int trunc = 0;
246 int totlen = len + sizeof(i4b_trace_hdr_t);
247
248 /*
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.
255 */
256
257 if(totlen > MCLBYTES)
258 {
259 trunc = 1;
260 hdr->trunc = totlen - MCLBYTES;
261 totlen = MCLBYTES;
262 }
263 else
264 {
265 hdr->trunc = 0;
266 }
267
268 /* set length of trace record */
269
270 hdr->length = totlen;
271
272 /* check valid unit no */
273
274 if((unit = hdr->unit) > NI4BTRC)
275 {
276 printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
277 return(0);
278 }
279
280 /* get mbuf */
281
282 if(!(m = i4b_Bgetmbuf(totlen)))
283 {
284 printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
285 return(0);
286 }
287
288 /* check if we are in analyzemode */
289
290 if(analyzemode && (unit == rxunit || unit == txunit))
291 {
292 if(unit == rxunit)
293 hdr->dir = FROM_NT;
294 else
295 hdr->dir = FROM_TE;
296 unit = outunit;
297 }
298
299 IF_LOCK(&trace_queue[unit]);
300 if(_IF_QFULL(&trace_queue[unit]))
301 {
302 struct mbuf *m1;
303
304 x = SPLI4B();
305 _IF_DEQUEUE(&trace_queue[unit], m1);
306 splx(x);
307
308 i4b_Bfreembuf(m1);
309 }
310
311 /* copy trace header */
312 memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
313
314 /* copy trace data */
315 if(trunc)
316 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
317 else
318 memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
319
320 x = SPLI4B();
321
322 _IF_ENQUEUE(&trace_queue[unit], m);
323 IF_UNLOCK(&trace_queue[unit]);
324
325 if(device_state[unit] & ST_WAITDATA)
326 {
327 device_state[unit] &= ~ST_WAITDATA;
328 wakeup((caddr_t) &trace_queue[unit]);
329 }
330
331 splx(x);
332
333 return(1);
334}
335
336/*---------------------------------------------------------------------------*
337 * open trace device
338 *---------------------------------------------------------------------------*/
339PDEVSTATIC int
7b95be2a 340i4btrcopen(dev_t dev, int flag, int fmt, struct thread *td)
984263bc
MD
341{
342 int x;
343 int unit = minor(dev);
344
345 if(unit >= NI4BTRC)
346 return(ENXIO);
347
348 if(device_state[unit] & ST_ISOPEN)
349 return(EBUSY);
350
351 if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
352 return(EBUSY);
353
354 x = SPLI4B();
355
356 device_state[unit] = ST_ISOPEN;
357
358 splx(x);
359
360 return(0);
361}
362
363/*---------------------------------------------------------------------------*
364 * close trace device
365 *---------------------------------------------------------------------------*/
366PDEVSTATIC int
7b95be2a 367i4btrcclose(dev_t dev, int flag, int fmt, struct thread *td)
984263bc
MD
368{
369 int unit = minor(dev);
370 int i, x;
371 int cno = -1;
372
373 for(i=0; i < nctrl; i++)
374 {
375 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
376 (ctrl_desc[i].unit == unit))
377 {
378 cno = i;
379 break;
380 }
381 }
382
383 if(analyzemode && (unit == outunit))
384 {
385 analyzemode = 0;
386 outunit = -1;
387
388 if(cno >= 0)
389 {
390 (*ctrl_desc[cno].N_MGMT_COMMAND)(rxunit, CMR_SETTRACE, TRACE_OFF);
391 (*ctrl_desc[cno].N_MGMT_COMMAND)(txunit, CMR_SETTRACE, TRACE_OFF);
392 }
393 rxunit = -1;
394 txunit = -1;
395 }
396
397 if(cno >= 0)
398 {
399 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, TRACE_OFF);
400 }
401
402 x = SPLI4B();
403 device_state[unit] = ST_IDLE;
404 splx(x);
405
406 return(0);
407}
408
409/*---------------------------------------------------------------------------*
410 * read from trace device
411 *---------------------------------------------------------------------------*/
412PDEVSTATIC int
413i4btrcread(dev_t dev, struct uio * uio, int ioflag)
414{
415 struct mbuf *m;
416 int x;
417 int error = 0;
418 int unit = minor(dev);
419
420 if(!(device_state[unit] & ST_ISOPEN))
421 return(EIO);
422
423 x = SPLI4B();
424
425 IF_LOCK(&trace_queue[unit]);
426 while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
427 {
428 device_state[unit] |= ST_WAITDATA;
429
430#if defined (__FreeBSD__) && __FreeBSD__ > 4
431 if((error = msleep((caddr_t) &trace_queue[unit],
432 &trace_queue[unit].ifq_mtx,
433 TTIPRI | PCATCH,
434 "bitrc", 0 )) != 0)
435#else
436 if((error = tsleep((caddr_t) &trace_queue[unit],
377d4740 437 PCATCH, "bitrc", 0 )) != 0)
984263bc
MD
438#endif
439 {
440 device_state[unit] &= ~ST_WAITDATA;
441 IF_UNLOCK(&trace_queue[unit]);
442 splx(x);
443 return(error);
444 }
445 }
446
447 _IF_DEQUEUE(&trace_queue[unit], m);
448 IF_UNLOCK(&trace_queue[unit]);
449
450 if(m && m->m_len)
451 error = uiomove(m->m_data, m->m_len, uio);
452 else
453 error = EIO;
454
455 if(m)
456 i4b_Bfreembuf(m);
457
458 splx(x);
459
460 return(error);
461}
462
9a7f3897 463#if (defined(__DragonFly__) || defined(__FreeBSD__)) && defined(OS_USES_POLL)
984263bc
MD
464/*---------------------------------------------------------------------------*
465 * poll device
466 *---------------------------------------------------------------------------*/
467PDEVSTATIC int
7b95be2a 468i4btrcpoll(dev_t dev, int events, struct thread *td)
984263bc
MD
469{
470 return(ENODEV);
471}
472#endif
473
474/*---------------------------------------------------------------------------*
475 * device driver ioctl routine
476 *---------------------------------------------------------------------------*/
477PDEVSTATIC int
9a7f3897 478#if defined(__DragonFly__) || (defined (__FreeBSD_version) && __FreeBSD_version >= 300003)
7b95be2a 479i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
984263bc
MD
480#elif defined(__bsdi__)
481i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
482#else
483i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
484#endif
485{
486 int error = 0;
487 int unit = minor(dev);
488 i4b_trace_setupa_t *tsa;
489 int i;
490 int cno = -1;
491
492 /* find the first passive controller matching our unit no */
493
494 for(i=0; i < nctrl; i++)
495 {
496 if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
497 (ctrl_desc[i].unit == unit))
498 {
499 cno = i;
500 break;
501 }
502 }
503
504 switch(cmd)
505 {
506 case I4B_TRC_SET:
507 if(cno < 0)
508 return ENOTTY;
509 (*ctrl_desc[cno].N_MGMT_COMMAND)(ctrl_desc[cno].unit, CMR_SETTRACE, (void *)*(unsigned int *)data);
510 break;
511
512 case I4B_TRC_SETA:
513 tsa = (i4b_trace_setupa_t *)data;
514
515 if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
516 rxunit = tsa->rxunit;
517 else
518 error = EINVAL;
519
520 if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
521 txunit = tsa->txunit;
522 else
523 error = EINVAL;
524
525 if(error)
526 {
527 outunit = -1;
528 rxunit = -1;
529 txunit = -1;
530 }
531 else
532 {
533 if(cno < 0)
534 return ENOTTY;
535
536 outunit = unit;
537 analyzemode = 1;
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)));
540 }
541 break;
542
543 case I4B_TRC_RESETA:
544 analyzemode = 0;
545 outunit = -1;
546 rxunit = -1;
547 txunit = -1;
548 break;
549
550 default:
551 error = ENOTTY;
552 break;
553 }
554 return(error);
555}
556
557#endif /* NI4BTRC > 0 */