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