2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
25 *---------------------------------------------------------------------------
27 * i4b_i4bdrv.c - i4b userland interface driver
28 * --------------------------------------------
30 * $Id: i4b_i4bdrv.c,v 1.52 1999/12/13 21:25:28 hm Exp $
34 * last edit-date: [Mon Dec 13 22:06:11 1999]
36 *---------------------------------------------------------------------------*/
49 #error "only 1 (one) i4b device possible!"
54 #include <sys/param.h>
56 #if defined(__FreeBSD__)
57 #include <sys/ioccom.h>
58 #include <sys/malloc.h>
61 #include <sys/ioctl.h>
64 #include <sys/kernel.h>
65 #include <sys/systm.h>
69 #include <sys/fcntl.h>
70 #include <sys/socket.h>
71 #include <sys/select.h>
75 #include <machine/i4b_debug.h>
76 #include <machine/i4b_ioctl.h>
77 #include <machine/i4b_cause.h>
79 #include <i4b/i4b_debug.h>
80 #include <i4b/i4b_ioctl.h>
81 #include <i4b/i4b_cause.h>
84 #include <i4b/include/i4b_l3l4.h>
85 #include <i4b/include/i4b_mbuf.h>
86 #include <i4b/include/i4b_global.h>
88 #include <i4b/layer4/i4b_l4.h>
94 struct selinfo select_rd_info;
96 static struct ifqueue i4b_rdqueue;
97 static int openflag = 0;
98 static int selflag = 0;
99 static int readflag = 0;
101 #if defined(__FreeBSD__) && __FreeBSD__ == 3
106 #define PDEVSTATIC /* - not static - */
107 PDEVSTATIC void i4battach __P((void));
108 PDEVSTATIC int i4bopen __P((dev_t dev, int flag, int fmt, struct proc *p));
109 PDEVSTATIC int i4bclose __P((dev_t dev, int flag, int fmt, struct proc *p));
110 PDEVSTATIC int i4bread __P((dev_t dev, struct uio *uio, int ioflag));
113 PDEVSTATIC int i4bioctl __P((dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p));
115 PDEVSTATIC int i4bioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
119 PDEVSTATIC int i4bpoll __P((dev_t dev, int events, struct proc *p));
121 PDEVSTATIC int i4bselect __P((dev_t dev, int rw, struct proc *p));
124 #endif /* #ifndef __FreeBSD__ */
126 #if BSD > 199306 && defined(__FreeBSD__)
128 #define PDEVSTATIC static
130 PDEVSTATIC d_open_t i4bopen;
131 PDEVSTATIC d_close_t i4bclose;
132 PDEVSTATIC d_read_t i4bread;
133 PDEVSTATIC d_ioctl_t i4bioctl;
136 PDEVSTATIC d_poll_t i4bpoll;
137 #define POLLFIELD i4bpoll
139 PDEVSTATIC d_select_t i4bselect;
140 #define POLLFIELD i4bselect
143 #define CDEV_MAJOR 60
145 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
146 static struct cdevsw i4b_cdevsw = {
148 /* close */ i4bclose,
151 /* ioctl */ i4bioctl,
152 /* poll */ POLLFIELD,
154 /* strategy */ nostrategy,
156 /* maj */ CDEV_MAJOR,
163 static struct cdevsw i4b_cdevsw = {
164 i4bopen, i4bclose, i4bread, nowrite,
165 i4bioctl, nostop, nullreset, nodevtotty,
166 POLLFIELD, nommap, NULL, "i4b", NULL, -1
170 PDEVSTATIC void i4battach(void *);
171 PSEUDO_SET(i4battach, i4b_i4bdrv);
174 i4b_drvinit(void *unused)
176 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
177 cdevsw_add(&i4b_cdevsw);
179 static int i4b_devsw_installed = 0;
182 if( ! i4b_devsw_installed )
184 dev = makedev(CDEV_MAJOR,0);
185 cdevsw_add(&dev,&i4b_cdevsw,NULL);
186 i4b_devsw_installed = 1;
191 SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL)
193 #endif /* BSD > 199306 && defined(__FreeBSD__) */
196 #include <sys/device.h>
197 int i4bmatch(struct device *parent, struct cfdata *cf, void *aux);
198 void dummy_i4battach(struct device*, struct device *, void *);
200 #define CDEV_MAJOR 65
202 static struct cfdriver i4bcd =
203 { NULL, "i4b", i4bmatch, dummy_i4battach, DV_DULL,
204 sizeof(struct cfdriver) };
207 i4bopen, i4bclose, i4bread, nowrite,
208 i4bioctl, i4bselect, nommap, nostrat,
209 nodump, nopsize, 0, nostop
213 i4bmatch(struct device *parent, struct cfdata *cf, void *aux)
215 printf("i4bmatch: aux=0x%x\n", aux);
219 dummy_i4battach(struct device *parent, struct device *self, void *aux)
221 printf("dummy_i4battach: aux=0x%x\n", aux);
223 #endif /* __bsdi__ */
225 /*---------------------------------------------------------------------------*
226 * interface attach routine
227 *---------------------------------------------------------------------------*/
230 i4battach(void *dummy)
235 #ifndef HACK_NO_PSEUDO_ATTACH_MSG
236 printf("i4b: ISDN call control device attached\n");
238 i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
240 #if defined(__FreeBSD__)
245 make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
250 /*---------------------------------------------------------------------------*
251 * i4bopen - device driver open routine
252 *---------------------------------------------------------------------------*/
254 i4bopen(dev_t dev, int flag, int fmt, struct proc *p)
266 i4b_l4_daemon_attached();
272 /*---------------------------------------------------------------------------*
273 * i4bclose - device driver close routine
274 *---------------------------------------------------------------------------*/
276 i4bclose(dev_t dev, int flag, int fmt, struct proc *p)
280 i4b_l4_daemon_detached();
281 i4b_Dcleanifq(&i4b_rdqueue);
286 /*---------------------------------------------------------------------------*
287 * i4bread - device driver read routine
288 *---------------------------------------------------------------------------*/
290 i4bread(dev_t dev, struct uio *uio, int ioflag)
299 while(IF_QEMPTY(&i4b_rdqueue))
304 tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0);
309 IF_DEQUEUE(&i4b_rdqueue, m);
314 error = uiomove(m->m_data, m->m_len, uio);
324 /*---------------------------------------------------------------------------*
325 * i4bioctl - device driver ioctl routine
326 *---------------------------------------------------------------------------*/
328 #if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
329 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
330 #elif defined(__bsdi__)
331 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
333 i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
344 /* cdid request, reserve cd and return cdid */
349 mir = (msg_cdid_req_t *)data;
351 mir->cdid = cd->cdid;
355 /* connect request, dial out to remote */
357 case I4B_CONNECT_REQ:
359 msg_connect_req_t *mcr;
360 mcr = (msg_connect_req_t *)data; /* setup ptr */
362 if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
364 DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_REQ ioctl, cdid not found!\n"));
369 /* prevent dialling on leased lines */
370 if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
372 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
373 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
374 i4b_l4_disconnect_ind(cd);
379 cd->controller = mcr->controller; /* fill cd */
380 cd->bprot = mcr->bprot;
381 cd->driver = mcr->driver;
382 cd->driver_unit = mcr->driver_unit;
383 cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
385 cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
386 cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time;
387 cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time;
388 cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
390 cd->last_aocd_time = 0;
391 if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
398 cd->max_idle_time = 0; /* this is outgoing */
400 cd->dir = DIR_OUTGOING;
402 DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld\n",
403 (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
404 (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time));
406 strcpy(cd->dst_telno, mcr->dst_telno);
407 strcpy(cd->src_telno, mcr->src_telno);
408 cd->display[0] = '\0';
410 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
411 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
417 if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
418 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
422 if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) &&
423 (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE))
424 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
428 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
432 cd->channelid = mcr->channel;
434 cd->isdntxdelay = mcr->txdelay;
436 /* check whether we have a pointer. Seems like */
437 /* this should be adequate. GJ 19.09.97 */
438 if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
439 /*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
441 if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
443 i4b_l4_disconnect_ind(cd);
448 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
453 /* connect response, accept/reject/ignore incoming call */
455 case I4B_CONNECT_RESP:
457 msg_connect_resp_t *mcrsp;
459 mcrsp = (msg_connect_resp_t *)data;
461 if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
463 DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_RESP ioctl, cdid not found!\n"));
470 cd->driver = mcrsp->driver;
471 cd->driver_unit = mcrsp->driver_unit;
472 cd->max_idle_time = mcrsp->max_idle_time;
474 cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
475 cd->shorthold_data.unitlen_time = 0; /* this is incoming */
476 cd->shorthold_data.idle_time = 0;
477 cd->shorthold_data.earlyhup_time = 0;
479 cd->isdntxdelay = mcrsp->txdelay;
481 DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_RESP max_idle_time set to %ld seconds\n", (long)cd->max_idle_time));
483 (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
487 /* disconnect request, actively terminate connection */
489 case I4B_DISCONNECT_REQ:
491 msg_discon_req_t *mdr;
493 mdr = (msg_discon_req_t *)data;
495 if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
497 DBGL4(L4_ERR, "i4bioctl", ("I4B_DISCONNECT_REQ ioctl, cdid not found!\n"));
502 /* preset causes with our cause */
503 cd->cause_in = cd->cause_out = mdr->cause;
505 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
509 /* controller info request */
511 case I4B_CTRL_INFO_REQ:
513 msg_ctrl_info_req_t *mcir;
515 mcir = (msg_ctrl_info_req_t *)data;
516 mcir->ncontroller = nctrl;
518 if(mcir->controller > nctrl)
520 mcir->ctrl_type = -1;
521 mcir->card_type = -1;
526 ctrl_desc[mcir->controller].ctrl_type;
528 ctrl_desc[mcir->controller].card_type;
530 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
531 mcir->tei = ctrl_desc[mcir->controller].tei;
540 case I4B_DIALOUT_RESP:
542 drvr_link_t *dlt = NULL;
543 msg_dialout_resp_t *mdrsp;
545 mdrsp = (msg_dialout_resp_t *)data;
547 switch(mdrsp->driver)
551 dlt = ipr_ret_linktab(mdrsp->driver_unit);
557 dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
563 dlt = tel_ret_linktab(mdrsp->driver_unit);
569 dlt = ibc_ret_linktab(mdrsp->driver_unit);
575 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
579 /* update timeout value */
581 case I4B_TIMEOUT_UPD:
583 msg_timeout_upd_t *mtu;
586 mtu = (msg_timeout_upd_t *)data;
588 DBGL4(L4_TIMO, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!\n",
589 mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
590 mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time ));
592 if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
594 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, cdid not found!\n"));
599 switch( mtu->shorthold_data.shorthold_algorithm )
603 * For this algorithm unitlen_time,
604 * idle_time and earlyhup_time are used.
607 if(!(mtu->shorthold_data.unitlen_time >= 0 &&
608 mtu->shorthold_data.idle_time >= 0 &&
609 mtu->shorthold_data.earlyhup_time >= 0))
611 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!\n"));
618 * For this algorithm unitlen_time and
619 * idle_time are used. both must be
620 * positive integers. earlyhup_time is
621 * not used and must be 0.
624 if(!(mtu->shorthold_data.unitlen_time > 0 &&
625 mtu->shorthold_data.idle_time >= 0 &&
626 mtu->shorthold_data.earlyhup_time == 0))
628 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!\n"));
634 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid algorithm!\n"));
640 * any error set above requires us to break
641 * out of the outer switch
647 cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
648 cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
649 cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
650 cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
655 /* soft enable/disable interface */
659 msg_updown_ind_t *mui;
661 mui = (msg_updown_ind_t *)data;
664 if(mui->driver == BDRV_IPR)
667 dlt = ipr_ret_linktab(mui->driver_unit);
668 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
674 /* send ALERT request */
678 msg_alert_req_t *mar;
680 mar = (msg_alert_req_t *)data;
682 if((cd = cd_by_cdid(mar->cdid)) == NULL)
684 DBGL4(L4_ERR, "i4bioctl", ("I4B_ALERT_REQ ioctl, cdid not found!\n"));
691 (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
696 /* version/release number request */
702 mvr = (msg_vr_req_t *)data;
704 mvr->version = VERSION;
710 /* set D-channel protocol for a controller */
716 mpi = (msg_prot_ind_t *)data;
718 ctrl_desc[mpi->controller].protocol = mpi->protocol;
723 /* Download request */
725 case I4B_CTRL_DOWNLOAD:
727 struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
728 struct isdn_download_request *r =
729 (struct isdn_download_request*)data;
732 if (r->controller < 0 || r->controller >= nctrl)
738 if(!ctrl_desc[r->controller].N_DOWNLOAD)
744 prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
747 prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
750 if(!prots || !prots2)
756 copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
758 for(i = 0; i < r->numprotos; i++)
760 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
761 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
762 prots2[i].bytecount = prots[i].bytecount;
765 error = ctrl_desc[r->controller].N_DOWNLOAD(
766 ctrl_desc[r->controller].unit,
767 r->numprotos, prots2);
772 for(i = 0; i < r->numprotos; i++)
774 if(prots2[i].microcode)
776 free(prots2[i].microcode, M_DEVBUF);
779 free(prots2, M_DEVBUF);
784 free(prots, M_DEVBUF);
789 /* Diagnostic request */
791 case I4B_ACTIVE_DIAGNOSTIC:
793 struct isdn_diagnostic_request req, *r =
794 (struct isdn_diagnostic_request*)data;
796 req.in_param = req.out_param = NULL;
797 if (r->controller < 0 || r->controller >= nctrl)
803 if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
809 memcpy(&req, r, sizeof(req));
813 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
820 error = copyin(r->in_param, req.in_param, req.in_param_len);
825 if(req.out_param_len)
827 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
836 error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
838 if(!error && req.out_param_len)
839 error = copyout(req.out_param, r->out_param, req.out_param_len);
843 free(req.in_param, M_DEVBUF);
846 free(req.out_param, M_DEVBUF);
861 #ifdef OS_USES_SELECT
863 /*---------------------------------------------------------------------------*
864 * i4bselect - device driver select routine
865 *---------------------------------------------------------------------------*/
867 i4bselect(dev_t dev, int rw, struct proc *p)
877 if(!IF_QEMPTY(&i4b_rdqueue))
880 selrecord(p, &select_rd_info);
893 #else /* OS_USES_SELECT */
895 /*---------------------------------------------------------------------------*
896 * i4bpoll - device driver poll routine
897 *---------------------------------------------------------------------------*/
899 i4bpoll(dev_t dev, int events, struct proc *p)
906 if((events & POLLIN) || (events & POLLRDNORM))
908 if(!IF_QEMPTY(&i4b_rdqueue))
912 selrecord(p, &select_rd_info);
917 else if((events & POLLOUT) || (events & POLLWRNORM))
925 #endif /* OS_USES_SELECT */
927 /*---------------------------------------------------------------------------*
928 * i4bputqueue - put message into queue to userland
929 *---------------------------------------------------------------------------*/
931 i4bputqueue(struct mbuf *m)
943 if(IF_QFULL(&i4b_rdqueue))
946 IF_DEQUEUE(&i4b_rdqueue, m1);
948 DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n"));
951 IF_ENQUEUE(&i4b_rdqueue, m);
958 wakeup((caddr_t) &i4b_rdqueue);
964 selwakeup(&select_rd_info);
968 /*---------------------------------------------------------------------------*
969 * i4bputqueue_hipri - put message into front of queue to userland
970 *---------------------------------------------------------------------------*/
972 i4bputqueue_hipri(struct mbuf *m)
984 if(IF_QFULL(&i4b_rdqueue))
987 IF_DEQUEUE(&i4b_rdqueue, m1);
989 DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n"));
992 IF_PREPEND(&i4b_rdqueue, m);
999 wakeup((caddr_t) &i4b_rdqueue);
1005 selwakeup(&select_rd_info);
1009 #endif /* NI4B > 0 */