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