diff options
Diffstat (limited to 'sys/i4b/layer1/i4b_l1dmux.c')
-rw-r--r-- | sys/i4b/layer1/i4b_l1dmux.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/sys/i4b/layer1/i4b_l1dmux.c b/sys/i4b/layer1/i4b_l1dmux.c new file mode 100644 index 0000000..115ae3a --- /dev/null +++ b/sys/i4b/layer1/i4b_l1dmux.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2000 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l1dmux.c - isdn4bsd layer 1 driver multiplexer + * -------------------------------------------------- + * + * $Id: i4b_l1dmux.c,v 1.12 2000/06/02 16:14:36 hm Exp $ + * + * $FreeBSD$ + * + * last edit-date: [Fri Jun 2 14:37:39 2000] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "iwic.h" +#include "ifpi.h" +#include "ifpnp.h" +#include "ihfc.h" + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +/* + * this code is nothing but a big dynamic switch to multiplex and demultiplex + * layer 1 hardware isdn drivers to a common layer 2. + * + * when a card is successfully attached at system boot time, the driver for + * this card calls the routine i4b_l1_mph_status_ind() with status = STI_ATTACH. + * + * This command is used to setup the tables for converting a "driver unit" and + * "driver type" pair (encoded in the calls from the hardware driver to the + * routines in this source file) to a "unit number" used in layer 2 and the + * layers above (up to and including the isdnd daemon) and for converting + * layer 2 units back to calling the appropriate driver and driver unit + * number. + * + * Example: in my setup, a Winbond (iwic) card is probed first and gets + * driver unit number 0, driver type 1 in layer 1. This becomes unit + * number 0 in layer 2 and up. The second card probed is a Teles card + * (isic) and gets driver unit number 0, driver type 0 in layer 1. This + * becomes unit number 1 in layer 1 and up. + * + * To add support for a new driver, add a new driver number to i4b_l1.h: + * currently we have L1DRVR_ISIC and L1DRVR_IWIC, so you would add + * L1DRVR_FOO. More you would want to add a L0FOOUNIT to encode unit + * numbers in your driver. You then have to add a l1foounittab[] and + * add an entry to the getl1tab() routine for your driver. The only + * thing left now is to write your driver with the support functions + * for this multiplexer ;-) + */ + +unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT; + +#if NISIC > 0 +static int l1isicunittab[MAXL1UNITS]; +#endif + +#if NIWIC > 0 +static int l1iwicunittab[MAXL1UNITS]; +#endif + +#if NIFPI > 0 +static int l1ifpiunittab[MAXL1UNITS]; +#endif + +#if NIHFC > 0 +static int l1ihfcunittab[MAXL1UNITS]; +#endif + +#if NIFPNP > 0 +static int l1ifpnpunittab[MAXL1UNITS]; +#endif + +static int numl1units = 0; + +static int l1drvunittab[MAXL1UNITS]; +static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR]; + +static int i4b_l1_ph_data_req(int, struct mbuf *, int); +static int i4b_l1_ph_activate_req(int); + +/* from i4btrc driver i4b_trace.c */ +int get_trace_data_from_l1(int unit, int what, int len, char *buf); + +/* from layer 2 */ +int i4b_ph_data_ind(int unit, struct mbuf *m); +int i4b_ph_activate_ind(int unit); +int i4b_ph_deactivate_ind(int unit); +int i4b_mph_status_ind(int, int, int); + +/* layer 1 lme */ +int i4b_l1_mph_command_req(int, int, void *); + +/*---------------------------------------------------------------------------* + * jump table: interface function pointers L1/L2 interface + *---------------------------------------------------------------------------*/ +struct i4b_l1l2_func i4b_l1l2_func = { + + /* Layer 1 --> Layer 2 */ + + (int (*)(int, struct mbuf *)) i4b_ph_data_ind, + (int (*)(int)) i4b_ph_activate_ind, + (int (*)(int)) i4b_ph_deactivate_ind, + + /* Layer 2 --> Layer 1 */ + + (int (*)(int, struct mbuf *, int)) i4b_l1_ph_data_req, + + (int (*)(int)) i4b_l1_ph_activate_req, + + /* Layer 1 --> trace interface driver, ISDN trace data */ + + (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1, + + /* Driver control and status information */ + + (int (*)(int, int, int)) i4b_mph_status_ind, + (int (*)(int, int, void *)) i4b_l1_mph_command_req, +}; + +/*---------------------------------------------------------------------------* + * return a pointer to a layer 0 drivers unit tab + *---------------------------------------------------------------------------*/ +static __inline int * +getl1tab(int drv) +{ + switch(drv) + { +#if NISIC > 0 + case L1DRVR_ISIC: + return(l1isicunittab); + break; +#endif +#if NIWIC > 0 + case L1DRVR_IWIC: + return(l1iwicunittab); + break; +#endif +#if NIFPI > 0 + case L1DRVR_IFPI: + return(l1ifpiunittab); + break; +#endif +#if NIHFC > 0 + case L1DRVR_IHFC: + return(l1ihfcunittab); + break; +#endif +#if NIFPNP > 0 + case L1DRVR_IFPNP: + return(l1ifpnpunittab); + break; +#endif + default: + return(NULL); + break; + } +} + +/*===========================================================================* + * B - Channel (data transfer) + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * return the address of ISDN drivers linktab + *---------------------------------------------------------------------------*/ +isdn_link_t * +i4b_l1_ret_linktab(int unit, int channel) +{ + int drv_unit, ch_unit; + + drv_unit = L0DRVR(l1drvunittab[unit]); + ch_unit = L0UNIT(l1drvunittab[unit]); + + NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit); + + if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL + || l1mux_func[drv_unit]->ret_linktab == NULL) + panic("i4b_l1_ret_linktab: unknown driver type %d\n", drv_unit); + + return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel)); +} + +/*---------------------------------------------------------------------------* + * set the ISDN driver linktab + *---------------------------------------------------------------------------*/ +void +i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt) +{ + int drv_unit, ch_unit; + + drv_unit = L0DRVR(l1drvunittab[unit]); + ch_unit = L0UNIT(l1drvunittab[unit]); + + NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit); + + if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL + || l1mux_func[drv_unit]->set_linktab == NULL) + panic("i4b_l1_set_linktab: unknown driver type %d\n", drv_unit); + + l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt); +} + +/*===========================================================================* + * trace D- and B-Channel support + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * L0 -> L1 trace information to trace driver + *---------------------------------------------------------------------------*/ +int +i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data) +{ + register int *tab; + + if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL) + panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit)); + + NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]); + + hdr->unit = tab[L0UNIT(hdr->unit)]; + + return(MPH_Trace_Ind(hdr, len, data)); +} + +/*===========================================================================* + * D - Channel (signalling) + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * L0 -> L1 status indication from hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p) +{ + register int *tab; + + /* + * in case the status STI_ATTACH is sent from the hardware, the + * driver has just attached itself and we need to initialize + * the tables and assorted variables. + */ + + if(status == STI_ATTACH) + { + if (l1mux_func_p == (struct i4b_l1mux_func *)0) + panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n"); + + if(numl1units < MAXL1UNITS) + { + if((tab = getl1tab(L0DRVR(drv_unit))) == NULL) + panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit)); + + tab[L0UNIT(drv_unit)] = numl1units; + + l1drvunittab[numl1units] = drv_unit; + + l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p; + + switch(L0DRVR(drv_unit)) + { +#if NISIC > 0 + case L1DRVR_ISIC: + printf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units); + break; +#endif +#if NIWIC > 0 + case L1DRVR_IWIC: + printf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units); + break; +#endif +#if NIFPI > 0 + case L1DRVR_IFPI: + printf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units); + break; +#endif +#if NIFPNP > 0 + case L1DRVR_IFPNP: + printf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units); + break; +#endif +#if NIHFC > 0 + case L1DRVR_IHFC: + printf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units); +#endif + } + + NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units); + + numl1units++; + } + } + + if((tab = getl1tab(L0DRVR(drv_unit))) == NULL) + panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit)); + + NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]); + + return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm)); +} + +/*---------------------------------------------------------------------------* + * L0 -> L1 data from hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data) +{ + register int *tab; + + if((tab = getl1tab(L0DRVR(drv_unit))) == NULL) + panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit)); + +#if 0 + NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]); +#endif + + return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data)); +} + +/*---------------------------------------------------------------------------* + * L0 -> L1 activate indication from hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_ph_activate_ind(int drv_unit) +{ + register int *tab; + + if((tab = getl1tab(L0DRVR(drv_unit))) == NULL) + panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit)); + + NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]); + + return(PH_Act_Ind(tab[L0UNIT(drv_unit)])); +} + +/*---------------------------------------------------------------------------* + * L0 -> L1 deactivate indication from hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_ph_deactivate_ind(int drv_unit) +{ + register int *tab; + + if((tab = getl1tab(L0DRVR(drv_unit))) == NULL) + panic("i4b_l1_ph_deactivate_ind: unknown driver type %d\n", L0DRVR(drv_unit)); + + NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]); + + return(PH_Deact_Ind(tab[L0UNIT(drv_unit)])); +} + +/*---------------------------------------------------------------------------* + * L2 -> L1 command to hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_mph_command_req(int unit, int command, void * parm) +{ + register int drv_unit = L0DRVR(l1drvunittab[unit]); + register int ch_unit = L0UNIT(l1drvunittab[unit]); + + NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit); + + if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL + || l1mux_func[drv_unit]->mph_command_req == NULL) + panic("i4b_l1_mph_command_req: unknown driver type %d\n", drv_unit); + + return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm)); +} + +/*---------------------------------------------------------------------------* + * L2 -> L1 data to be transmitted to hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag) +{ + register int drv_unit = L0DRVR(l1drvunittab[unit]); + register int ch_unit = L0UNIT(l1drvunittab[unit]); + +#if 0 + NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit); +#endif + + if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL + || l1mux_func[drv_unit]->ph_data_req == NULL) + panic("i4b_l1_ph_data_req: unknown driver type %d\n", drv_unit); + + return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag)); +} + +/*---------------------------------------------------------------------------* + * L2 -> L1 activate request to hardware + *---------------------------------------------------------------------------*/ +int +i4b_l1_ph_activate_req(int unit) +{ + register int drv_unit = L0DRVR(l1drvunittab[unit]); + register int ch_unit = L0UNIT(l1drvunittab[unit]); + + NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit); + + if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL + || l1mux_func[drv_unit]->ph_activate_req == NULL) + panic("i4b_l1_ph_activate_req: unknown driver type %d\n", drv_unit); + + return(l1mux_func[drv_unit]->ph_activate_req(ch_unit)); +} + +/* EOF */ |