kernel - Remove D_KQFILTER flag
[dragonfly.git] / sys / net / i4b / layer4 / i4b_i4bdrv.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 * i4b_i4bdrv.c - i4b userland interface driver
28 * --------------------------------------------
29 *
30 * $FreeBSD: src/sys/i4b/layer4/i4b_i4bdrv.c,v 1.11.2.5 2001/12/16 15:12:59 hm Exp $
978400d3 31 * $DragonFly: src/sys/net/i4b/layer4/i4b_i4bdrv.c,v 1.20 2008/01/06 16:55:52 swildner Exp $
984263bc
MD
32 *
33 * last edit-date: [Sat Aug 11 18:08:10 2001]
34 *
35 *---------------------------------------------------------------------------*/
36
1f2de5d4
MD
37#include "use_i4b.h"
38#include "use_i4bipr.h"
39#include "use_i4btel.h"
984263bc
MD
40
41#if NI4B > 1
42#error "only 1 (one) i4b device possible!"
43#endif
44
45#if NI4B > 0
46
47#include <sys/param.h>
48
984263bc
MD
49#include <sys/malloc.h>
50#include <sys/uio.h>
984263bc
MD
51#include <sys/kernel.h>
52#include <sys/systm.h>
53#include <sys/conf.h>
fef8985e 54#include <sys/device.h>
984263bc
MD
55#include <sys/mbuf.h>
56#include <sys/socket.h>
817cdab6 57#include <sys/thread2.h>
984263bc 58
fe0184c1 59#include <net/if.h>
984263bc 60
1f2de5d4 61#include "use_i4bing.h"
1f2de5d4 62#include "use_i4bisppp.h"
984263bc 63
1f2de5d4
MD
64#include <net/i4b/include/machine/i4b_debug.h>
65#include <net/i4b/include/machine/i4b_ioctl.h>
66#include <net/i4b/include/machine/i4b_cause.h>
984263bc 67
1f2de5d4
MD
68#include "../include/i4b_l3l4.h"
69#include "../include/i4b_mbuf.h"
70#include "../include/i4b_global.h"
984263bc 71
1f2de5d4 72#include "i4b_l4.h"
984263bc 73
f678b81b 74#include <sys/event.h>
984263bc 75
5b22f1a7 76struct kqinfo kq_rd_info;
984263bc
MD
77
78static struct ifqueue i4b_rdqueue;
79static int openflag = 0;
984263bc
MD
80static int readflag = 0;
81
984263bc
MD
82#define PDEVSTATIC static
83
84PDEVSTATIC d_open_t i4bopen;
85PDEVSTATIC d_close_t i4bclose;
86PDEVSTATIC d_read_t i4bread;
87PDEVSTATIC d_ioctl_t i4bioctl;
f678b81b
SG
88PDEVSTATIC d_kqfilter_t i4bkqfilter;
89
90PDEVSTATIC void i4bkqfilt_detach(struct knote *);
91PDEVSTATIC int i4bkqfilt_read(struct knote *, long);
92PDEVSTATIC int i4bkqfilt_write(struct knote *, long);
984263bc 93
984263bc
MD
94#define CDEV_MAJOR 60
95
fef8985e 96static struct dev_ops i4b_ops = {
d4b8aec4 97 { "i4b", CDEV_MAJOR, 0 },
fef8985e
MD
98 .d_open = i4bopen,
99 .d_close = i4bclose,
100 .d_read = i4bread,
101 .d_ioctl = i4bioctl,
f678b81b 102 .d_kqfilter = i4bkqfilter
984263bc 103};
984263bc
MD
104
105PDEVSTATIC void i4battach(void *);
106PSEUDO_SET(i4battach, i4b_i4bdrv);
107
984263bc
MD
108/*---------------------------------------------------------------------------*
109 * interface attach routine
110 *---------------------------------------------------------------------------*/
111PDEVSTATIC void
984263bc 112i4battach(void *dummy)
984263bc 113{
4b1cf444 114 kprintf("i4b: ISDN call control device attached\n");
984263bc
MD
115
116 i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
117
fef8985e 118 make_dev(&i4b_ops, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
984263bc
MD
119}
120
121/*---------------------------------------------------------------------------*
122 * i4bopen - device driver open routine
123 *---------------------------------------------------------------------------*/
124PDEVSTATIC int
fef8985e 125i4bopen(struct dev_open_args *ap)
984263bc 126{
b13267a5 127 cdev_t dev = ap->a_head.a_dev;
984263bc 128
fef8985e
MD
129 if (minor(dev))
130 return(ENXIO);
131 if (openflag)
984263bc 132 return(EBUSY);
817cdab6 133 crit_enter();
984263bc
MD
134 openflag = 1;
135 i4b_l4_daemon_attached();
817cdab6 136 crit_exit();
984263bc
MD
137
138 return(0);
139}
140
141/*---------------------------------------------------------------------------*
142 * i4bclose - device driver close routine
143 *---------------------------------------------------------------------------*/
144PDEVSTATIC int
fef8985e 145i4bclose(struct dev_close_args *ap)
984263bc 146{
817cdab6 147 crit_enter();
984263bc
MD
148 openflag = 0;
149 i4b_l4_daemon_detached();
150 i4b_Dcleanifq(&i4b_rdqueue);
817cdab6 151 crit_exit();
984263bc
MD
152 return(0);
153}
154
155/*---------------------------------------------------------------------------*
156 * i4bread - device driver read routine
157 *---------------------------------------------------------------------------*/
158PDEVSTATIC int
fef8985e 159i4bread(struct dev_read_args *ap)
984263bc 160{
b13267a5 161 cdev_t dev = ap->a_head.a_dev;
984263bc 162 struct mbuf *m;
984263bc
MD
163 int error = 0;
164
fef8985e 165 if (minor(dev))
984263bc
MD
166 return(ENODEV);
167
817cdab6 168 crit_enter();
984263bc
MD
169 while(IF_QEMPTY(&i4b_rdqueue))
170 {
171 readflag = 1;
377d4740 172 error = tsleep((caddr_t) &i4b_rdqueue, PCATCH, "bird", 0);
984263bc 173 if (error != 0) {
817cdab6 174 crit_exit();
984263bc
MD
175 return error;
176 }
177 }
178
fd81ccf9 179 IF_DEQUEUE(&i4b_rdqueue, m);
984263bc 180
817cdab6 181 crit_exit();
984263bc
MD
182
183 if(m && m->m_len)
fef8985e 184 error = uiomove(m->m_data, m->m_len, ap->a_uio);
984263bc
MD
185 else
186 error = EIO;
187
188 if(m)
189 i4b_Dfreembuf(m);
190
191 return(error);
192}
193
194/*---------------------------------------------------------------------------*
195 * i4bioctl - device driver ioctl routine
196 *---------------------------------------------------------------------------*/
197PDEVSTATIC int
fef8985e 198i4bioctl(struct dev_ioctl_args *ap)
984263bc 199{
b13267a5 200 cdev_t dev = ap->a_head.a_dev;
fef8985e 201 caddr_t data = ap->a_data;
984263bc
MD
202 call_desc_t *cd;
203 int error = 0;
204
205 if(minor(dev))
206 return(ENODEV);
207
fef8985e 208 switch(ap->a_cmd)
984263bc
MD
209 {
210 /* cdid request, reserve cd and return cdid */
211
212 case I4B_CDID_REQ:
213 {
214 msg_cdid_req_t *mir;
215 mir = (msg_cdid_req_t *)data;
216 cd = reserve_cd();
217 mir->cdid = cd->cdid;
218 break;
219 }
220
221 /* connect request, dial out to remote */
222
223 case I4B_CONNECT_REQ:
224 {
225 msg_connect_req_t *mcr;
226 mcr = (msg_connect_req_t *)data; /* setup ptr */
227
228 if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
229 {
230 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!");
231 error = EINVAL;
232 break;
233 }
234
235 /* prevent dialling on leased lines */
236 if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
237 {
238 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
239 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
240 i4b_l4_disconnect_ind(cd);
241 freecd_by_cd(cd);
242 break;
243 }
244
245 cd->controller = mcr->controller; /* fill cd */
246 cd->bprot = mcr->bprot;
247 cd->driver = mcr->driver;
248 cd->driver_unit = mcr->driver_unit;
249 cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
250
251 cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
252 cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time;
253 cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time;
254 cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
255
256 cd->last_aocd_time = 0;
257 if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
258 cd->aocd_flag = 1;
259 else
260 cd->aocd_flag = 0;
261
262 cd->cunits = 0;
263
264 cd->max_idle_time = 0; /* this is outgoing */
265
266 cd->dir = DIR_OUTGOING;
267
268 NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
269 (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
270 (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
271
272 strcpy(cd->dst_telno, mcr->dst_telno);
273 strcpy(cd->src_telno, mcr->src_telno);
274
275 if(mcr->keypad[0] != '\0')
276 strcpy(cd->keypad, mcr->keypad);
277 else
278 cd->keypad[0] = '\0';
279
280 cd->display[0] = '\0';
281
282 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
283 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
284
285 switch(mcr->channel)
286 {
287 case CHAN_B1:
288 case CHAN_B2:
289 if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
290 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
291 break;
292
293 case CHAN_ANY:
294 {
295 int i;
296 for (i = 0;
297 i < ctrl_desc[mcr->controller].nbch &&
298 ctrl_desc[mcr->controller].bch_state[i] != BCH_ST_FREE;
299 i++);
300 if (i == ctrl_desc[mcr->controller].nbch)
301 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
302 /* else mcr->channel = i; XXX */
303 }
304 break;
305
306 default:
307 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
308 break;
309 }
310
311 cd->channelid = mcr->channel;
312
313 cd->isdntxdelay = mcr->txdelay;
314
315 /* check whether we have a pointer. Seems like */
316 /* this should be adequate. GJ 19.09.97 */
317 if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
318/*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
319
320 if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
321 {
322 i4b_l4_disconnect_ind(cd);
323 freecd_by_cd(cd);
324 }
325 else
326 {
327 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
328 }
329 break;
330 }
331
332 /* connect response, accept/reject/ignore incoming call */
333
334 case I4B_CONNECT_RESP:
335 {
336 msg_connect_resp_t *mcrsp;
337
338 mcrsp = (msg_connect_resp_t *)data;
339
340 if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
341 {
342 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!");
343 error = EINVAL;
344 break;
345 }
346
347 T400_stop(cd);
348
349 cd->driver = mcrsp->driver;
350 cd->driver_unit = mcrsp->driver_unit;
351 cd->max_idle_time = mcrsp->max_idle_time;
352
353 cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
354 cd->shorthold_data.unitlen_time = 0; /* this is incoming */
355 cd->shorthold_data.idle_time = 0;
356 cd->shorthold_data.earlyhup_time = 0;
357
358 cd->isdntxdelay = mcrsp->txdelay;
359
360 NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
361
362 (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
363 break;
364 }
365
366 /* disconnect request, actively terminate connection */
367
368 case I4B_DISCONNECT_REQ:
369 {
370 msg_discon_req_t *mdr;
371
372 mdr = (msg_discon_req_t *)data;
373
374 if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
375 {
376 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid not found!");
377 error = EINVAL;
378 break;
379 }
380
381 /* preset causes with our cause */
382 cd->cause_in = cd->cause_out = mdr->cause;
383
384 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
385 break;
386 }
387
388 /* controller info request */
389
390 case I4B_CTRL_INFO_REQ:
391 {
392 msg_ctrl_info_req_t *mcir;
393
394 mcir = (msg_ctrl_info_req_t *)data;
395 mcir->ncontroller = nctrl;
396
397 if(mcir->controller > nctrl)
398 {
399 mcir->ctrl_type = -1;
400 mcir->card_type = -1;
401 }
402 else
403 {
404 mcir->ctrl_type =
405 ctrl_desc[mcir->controller].ctrl_type;
406 mcir->card_type =
407 ctrl_desc[mcir->controller].card_type;
408 mcir->nbch =
409 ctrl_desc[mcir->controller].nbch;
410
411 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
412 mcir->tei = ctrl_desc[mcir->controller].tei;
413 else
414 mcir->tei = -1;
415 }
416 break;
417 }
418
419 /* dial response */
420
421 case I4B_DIALOUT_RESP:
422 {
423 drvr_link_t *dlt = NULL;
424 msg_dialout_resp_t *mdrsp;
425
426 mdrsp = (msg_dialout_resp_t *)data;
427
428 switch(mdrsp->driver)
429 {
430#if NI4BIPR > 0
431 case BDRV_IPR:
432 dlt = ipr_ret_linktab(mdrsp->driver_unit);
433 break;
434#endif
435
436#if NI4BISPPP > 0
437 case BDRV_ISPPP:
438 dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
439 break;
440#endif
441
442#if NI4BTEL > 0
443 case BDRV_TEL:
444 dlt = tel_ret_linktab(mdrsp->driver_unit);
445 break;
446#endif
447
984263bc
MD
448#if NI4BING > 0
449 case BDRV_ING:
450 dlt = ing_ret_linktab(mdrsp->driver_unit);
451 break;
452#endif
453 }
454
455 if(dlt != NULL)
456 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
457 break;
458 }
459
460 /* update timeout value */
461
462 case I4B_TIMEOUT_UPD:
463 {
464 msg_timeout_upd_t *mtu;
984263bc
MD
465
466 mtu = (msg_timeout_upd_t *)data;
467
468 NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
469 mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
470 mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time);
471
472 if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
473 {
474 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
475 error = EINVAL;
476 break;
477 }
478
479 switch( mtu->shorthold_data.shorthold_algorithm )
480 {
481 case SHA_FIXU:
482 /*
483 * For this algorithm unitlen_time,
484 * idle_time and earlyhup_time are used.
485 */
486
487 if(!(mtu->shorthold_data.unitlen_time >= 0 &&
488 mtu->shorthold_data.idle_time >= 0 &&
489 mtu->shorthold_data.earlyhup_time >= 0))
490 {
491 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
492 error = EINVAL;
493 }
494 break;
495
496 case SHA_VARU:
497 /*
498 * For this algorithm unitlen_time and
499 * idle_time are used. both must be
500 * positive integers. earlyhup_time is
501 * not used and must be 0.
502 */
503
504 if(!(mtu->shorthold_data.unitlen_time > 0 &&
505 mtu->shorthold_data.idle_time >= 0 &&
506 mtu->shorthold_data.earlyhup_time == 0))
507 {
508 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
509 error = EINVAL;
510 }
511 break;
512
513 default:
514 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
515 error = EINVAL;
516 break;
517 }
518
519 /*
520 * any error set above requires us to break
521 * out of the outer switch
522 */
523 if(error != 0)
524 break;
525
817cdab6 526 crit_enter();
984263bc
MD
527 cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
528 cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
529 cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
530 cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
817cdab6 531 crit_exit();
984263bc
MD
532 break;
533 }
534
535 /* soft enable/disable interface */
536
537 case I4B_UPDOWN_IND:
538 {
539 msg_updown_ind_t *mui;
540
541 mui = (msg_updown_ind_t *)data;
542
543#if NI4BIPR > 0
544 if(mui->driver == BDRV_IPR)
545 {
546 drvr_link_t *dlt;
547 dlt = ipr_ret_linktab(mui->driver_unit);
548 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
549 }
550#endif
551 break;
552 }
553
554 /* send ALERT request */
555
556 case I4B_ALERT_REQ:
557 {
558 msg_alert_req_t *mar;
559
560 mar = (msg_alert_req_t *)data;
561
562 if((cd = cd_by_cdid(mar->cdid)) == NULL)
563 {
564 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!");
565 error = EINVAL;
566 break;
567 }
568
569 T400_stop(cd);
570
571 (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
572
573 break;
574 }
575
576 /* version/release number request */
577
578 case I4B_VR_REQ:
579 {
580 msg_vr_req_t *mvr;
581
582 mvr = (msg_vr_req_t *)data;
583
584 mvr->version = VERSION;
585 mvr->release = REL;
586 mvr->step = STEP;
587 break;
588 }
589
590 /* set D-channel protocol for a controller */
591
592 case I4B_PROT_IND:
593 {
594 msg_prot_ind_t *mpi;
595
596 mpi = (msg_prot_ind_t *)data;
597
598 ctrl_desc[mpi->controller].protocol = mpi->protocol;
599
600 break;
601 }
602
603 /* Download request */
604
605 case I4B_CTRL_DOWNLOAD:
606 {
607 struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
608 struct isdn_download_request *r =
609 (struct isdn_download_request*)data;
610 int i;
611
612 if (r->controller < 0 || r->controller >= nctrl)
613 {
614 error = ENODEV;
615 goto download_done;
616 }
617
618 if(!ctrl_desc[r->controller].N_DOWNLOAD)
619 {
620 error = ENODEV;
621 goto download_done;
622 }
623
77652cad 624 prots = kmalloc(r->numprotos * sizeof(struct isdn_dr_prot),
984263bc
MD
625 M_DEVBUF, M_WAITOK);
626
77652cad 627 prots2 = kmalloc(r->numprotos * sizeof(struct isdn_dr_prot),
984263bc
MD
628 M_DEVBUF, M_WAITOK);
629
984263bc
MD
630 copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
631
632 for(i = 0; i < r->numprotos; i++)
633 {
efda3bd0 634 prots2[i].microcode = kmalloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
984263bc
MD
635 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
636 prots2[i].bytecount = prots[i].bytecount;
637 }
638
639 error = ctrl_desc[r->controller].N_DOWNLOAD(
640 ctrl_desc[r->controller].unit,
641 r->numprotos, prots2);
642
643download_done:
644 if(prots2)
645 {
646 for(i = 0; i < r->numprotos; i++)
647 {
648 if(prots2[i].microcode)
649 {
efda3bd0 650 kfree(prots2[i].microcode, M_DEVBUF);
984263bc
MD
651 }
652 }
efda3bd0 653 kfree(prots2, M_DEVBUF);
984263bc
MD
654 }
655
656 if(prots)
657 {
efda3bd0 658 kfree(prots, M_DEVBUF);
984263bc
MD
659 }
660 break;
661 }
662
663 /* Diagnostic request */
664
665 case I4B_ACTIVE_DIAGNOSTIC:
666 {
667 struct isdn_diagnostic_request req, *r =
668 (struct isdn_diagnostic_request*)data;
669
670 req.in_param = req.out_param = NULL;
671 if (r->controller < 0 || r->controller >= nctrl)
672 {
673 error = ENODEV;
674 goto diag_done;
675 }
676
677 if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
678 {
679 error = ENODEV;
680 goto diag_done;
681 }
682
683 memcpy(&req, r, sizeof(req));
684
685 if(req.in_param_len)
686 {
687 /* XXX arbitrary limit */
688 if (req.in_param_len >
689 I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN) {
690 error = EINVAL;
691 goto diag_done;
692 }
693
efda3bd0 694 req.in_param = kmalloc(r->in_param_len, M_DEVBUF, M_WAITOK);
984263bc 695
984263bc
MD
696 error = copyin(r->in_param, req.in_param, req.in_param_len);
697 if (error)
698 goto diag_done;
699 }
700
701 if(req.out_param_len)
efda3bd0 702 req.out_param = kmalloc(r->out_param_len, M_DEVBUF, M_WAITOK);
984263bc 703
984263bc
MD
704 error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
705
706 if(!error && req.out_param_len)
707 error = copyout(req.out_param, r->out_param, req.out_param_len);
708
709diag_done:
710 if(req.in_param)
efda3bd0 711 kfree(req.in_param, M_DEVBUF);
984263bc
MD
712
713 if(req.out_param)
efda3bd0 714 kfree(req.out_param, M_DEVBUF);
984263bc
MD
715
716 break;
717 }
718
719 /* default */
720
721 default:
722 error = ENOTTY;
723 break;
724 }
725
726 return(error);
727}
728
984263bc 729/*---------------------------------------------------------------------------*
163625b9 730 * i4bkqfilter - device driver poll routine
984263bc 731 *---------------------------------------------------------------------------*/
f678b81b 732static struct filterops i4bkqfiltops_read =
4c91dbc9 733 { FILTEROP_ISFD, NULL, i4bkqfilt_detach, i4bkqfilt_read };
f678b81b 734static struct filterops i4bkqfiltops_write =
4c91dbc9 735 { FILTEROP_ISFD, NULL, i4bkqfilt_detach, i4bkqfilt_write };
f678b81b
SG
736
737PDEVSTATIC int
738i4bkqfilter(struct dev_kqfilter_args *ap)
739{
740 cdev_t dev = ap->a_head.a_dev;
741 struct knote *kn = ap->a_kn;
742 struct klist *klist;
743
744 if (minor(dev))
745 return (1);
746
747 ap->a_result = 0;
748
749 switch (kn->kn_filter) {
750 case EVFILT_READ:
751 kn->kn_fop = &i4bkqfiltops_read;
752 break;
753 case EVFILT_WRITE:
754 kn->kn_fop = &i4bkqfiltops_write;
755 break;
756 default:
b287d649 757 ap->a_result = EOPNOTSUPP;
f678b81b
SG
758 return (0);
759 }
760
5b22f1a7
SG
761 klist = &kq_rd_info.ki_note;
762 knote_insert(klist, kn);
f678b81b
SG
763
764 return (0);
765}
766
767PDEVSTATIC void
768i4bkqfilt_detach(struct knote *kn)
769{
5b22f1a7 770 struct klist *klist = &kq_rd_info.ki_note;
f678b81b 771
5b22f1a7 772 knote_remove(klist, kn);
f678b81b
SG
773}
774
775PDEVSTATIC int
776i4bkqfilt_read(struct knote *kn, long hint)
777{
778 int ready = 0;
779
780 crit_enter();
781 if (!IF_QEMPTY(&i4b_rdqueue))
782 ready = 1;
783 crit_exit();
784
785 return (ready);
786}
787
788PDEVSTATIC int
789i4bkqfilt_write(struct knote *kn, long hint)
790{
791 return (1);
792}
793
984263bc
MD
794/*---------------------------------------------------------------------------*
795 * i4bputqueue - put message into queue to userland
796 *---------------------------------------------------------------------------*/
797void
798i4bputqueue(struct mbuf *m)
799{
984263bc
MD
800 if(!openflag)
801 {
802 i4b_Dfreembuf(m);
803 return;
804 }
805
817cdab6 806 crit_enter();
984263bc 807
fd81ccf9 808 if(IF_QFULL(&i4b_rdqueue))
984263bc
MD
809 {
810 struct mbuf *m1;
fd81ccf9 811 IF_DEQUEUE(&i4b_rdqueue, m1);
984263bc
MD
812 i4b_Dfreembuf(m1);
813 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
814 }
815
fd81ccf9 816 IF_ENQUEUE(&i4b_rdqueue, m);
984263bc 817
817cdab6 818 crit_exit();
984263bc
MD
819
820 if(readflag)
821 {
822 readflag = 0;
823 wakeup((caddr_t) &i4b_rdqueue);
824 }
825
5b22f1a7 826 KNOTE(&kq_rd_info.ki_note, 0);
984263bc
MD
827}
828
829/*---------------------------------------------------------------------------*
830 * i4bputqueue_hipri - put message into front of queue to userland
831 *---------------------------------------------------------------------------*/
832void
833i4bputqueue_hipri(struct mbuf *m)
834{
984263bc
MD
835 if(!openflag)
836 {
837 i4b_Dfreembuf(m);
838 return;
839 }
840
817cdab6 841 crit_enter();
984263bc 842
fd81ccf9 843 if(IF_QFULL(&i4b_rdqueue))
984263bc
MD
844 {
845 struct mbuf *m1;
fd81ccf9 846 IF_DEQUEUE(&i4b_rdqueue, m1);
984263bc
MD
847 i4b_Dfreembuf(m1);
848 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
849 }
850
fd81ccf9 851 IF_PREPEND(&i4b_rdqueue, m);
984263bc 852
817cdab6 853 crit_exit();
984263bc
MD
854
855 if(readflag)
856 {
857 readflag = 0;
858 wakeup((caddr_t) &i4b_rdqueue);
859 }
860
5b22f1a7 861 KNOTE(&kq_rd_info.ki_note, 0);
984263bc
MD
862}
863
864#endif /* NI4B > 0 */