2 * Copyright (c) 2000, 2001 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_l1dmux.c - isdn4bsd layer 1 driver multiplexer
28 * --------------------------------------------------
30 * $FreeBSD: src/sys/i4b/layer1/i4b_l1dmux.c,v 1.3.2.2 2002/04/25 12:29:55 gj Exp $
31 * $DragonFly: src/sys/net/i4b/layer1/i4b_l1dmux.c,v 1.6 2006/12/22 23:44:55 swildner Exp $
33 * last edit-date: [Wed Jan 10 16:43:24 2001]
35 *---------------------------------------------------------------------------*/
40 #include "use_ifpi2.h"
41 #include "use_ifpnp.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <net/i4b/include/machine/i4b_debug.h>
49 #include <net/i4b/include/machine/i4b_ioctl.h>
50 #include <net/i4b/include/machine/i4b_trace.h>
54 #include "../include/i4b_l1l2.h"
55 #include "../include/i4b_global.h"
58 * this code is nothing but a big dynamic switch to multiplex and demultiplex
59 * layer 1 hardware isdn drivers to a common layer 2.
61 * when a card is successfully attached at system boot time, the driver for
62 * this card calls the routine i4b_l1_mph_status_ind() with status = STI_ATTACH.
64 * This command is used to setup the tables for converting a "driver unit" and
65 * "driver type" pair (encoded in the calls from the hardware driver to the
66 * routines in this source file) to a "unit number" used in layer 2 and the
67 * layers above (up to and including the isdnd daemon) and for converting
68 * layer 2 units back to calling the appropriate driver and driver unit
71 * Example: in my setup, a Winbond (iwic) card is probed first and gets
72 * driver unit number 0, driver type 1 in layer 1. This becomes unit
73 * number 0 in layer 2 and up. The second card probed is a Teles card
74 * (isic) and gets driver unit number 0, driver type 0 in layer 1. This
75 * becomes unit number 1 in layer 1 and up.
77 * To add support for a new driver, add a new driver number to i4b_l1.h:
78 * currently we have L1DRVR_ISIC and L1DRVR_IWIC, so you would add
79 * L1DRVR_FOO. More you would want to add a L0FOOUNIT to encode unit
80 * numbers in your driver. You then have to add a l1foounittab[] and
81 * add an entry to the getl1tab() routine for your driver. The only
82 * thing left now is to write your driver with the support functions
83 * for this multiplexer ;-)
86 unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
89 static int l1isicunittab[MAXL1UNITS];
93 static int l1iwicunittab[MAXL1UNITS];
97 static int l1ifpiunittab[MAXL1UNITS];
101 static int l1ifpi2unittab[MAXL1UNITS];
105 static int l1ihfcunittab[MAXL1UNITS];
109 static int l1ifpnpunittab[MAXL1UNITS];
113 static int l1itjcunittab[MAXL1UNITS];
116 static int numl1units = 0;
118 static int l1drvunittab[MAXL1UNITS];
119 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
121 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
122 static int i4b_l1_ph_activate_req(int);
124 /* from i4btrc driver i4b_trace.c */
125 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
128 int i4b_ph_data_ind(int unit, struct mbuf *m);
129 int i4b_ph_activate_ind(int unit);
130 int i4b_ph_deactivate_ind(int unit);
131 int i4b_mph_status_ind(int, int, int);
134 int i4b_l1_mph_command_req(int, int, void *);
136 /*---------------------------------------------------------------------------*
137 * jump table: interface function pointers L1/L2 interface
138 *---------------------------------------------------------------------------*/
139 struct i4b_l1l2_func i4b_l1l2_func = {
141 /* Layer 1 --> Layer 2 */
143 (int (*)(int, struct mbuf *)) i4b_ph_data_ind,
144 (int (*)(int)) i4b_ph_activate_ind,
145 (int (*)(int)) i4b_ph_deactivate_ind,
147 /* Layer 2 --> Layer 1 */
149 (int (*)(int, struct mbuf *, int)) i4b_l1_ph_data_req,
151 (int (*)(int)) i4b_l1_ph_activate_req,
153 /* Layer 1 --> trace interface driver, ISDN trace data */
155 (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
157 /* Driver control and status information */
159 (int (*)(int, int, int)) i4b_mph_status_ind,
160 (int (*)(int, int, void *)) i4b_l1_mph_command_req,
163 /*---------------------------------------------------------------------------*
164 * return a pointer to a layer 0 drivers unit tab
165 *---------------------------------------------------------------------------*/
166 static __inline int *
173 return(l1isicunittab);
178 return(l1iwicunittab);
183 return(l1ifpiunittab);
188 return(l1ifpi2unittab);
193 return(l1ihfcunittab);
198 return(l1ifpnpunittab);
203 return(l1itjcunittab);
212 /*===========================================================================*
213 * B - Channel (data transfer)
214 *===========================================================================*/
216 /*---------------------------------------------------------------------------*
217 * return the address of ISDN drivers linktab
218 *---------------------------------------------------------------------------*/
220 i4b_l1_ret_linktab(int unit, int channel)
222 int drv_unit, ch_unit;
224 drv_unit = L0DRVR(l1drvunittab[unit]);
225 ch_unit = L0UNIT(l1drvunittab[unit]);
227 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
229 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
230 || l1mux_func[drv_unit]->ret_linktab == NULL)
231 panic("i4b_l1_ret_linktab: unknown driver type %d\n", drv_unit);
233 return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
236 /*---------------------------------------------------------------------------*
237 * set the ISDN driver linktab
238 *---------------------------------------------------------------------------*/
240 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
242 int drv_unit, ch_unit;
244 drv_unit = L0DRVR(l1drvunittab[unit]);
245 ch_unit = L0UNIT(l1drvunittab[unit]);
247 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
249 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
250 || l1mux_func[drv_unit]->set_linktab == NULL)
251 panic("i4b_l1_set_linktab: unknown driver type %d\n", drv_unit);
253 l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
256 /*===========================================================================*
257 * trace D- and B-Channel support
258 *===========================================================================*/
260 /*---------------------------------------------------------------------------*
261 * L0 -> L1 trace information to trace driver
262 *---------------------------------------------------------------------------*/
264 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
268 if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
269 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
271 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
273 hdr->unit = tab[L0UNIT(hdr->unit)];
275 return(MPH_Trace_Ind(hdr, len, data));
278 /*===========================================================================*
279 * D - Channel (signalling)
280 *===========================================================================*/
282 /*---------------------------------------------------------------------------*
283 * L0 -> L1 status indication from hardware
284 *---------------------------------------------------------------------------*/
286 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
291 * in case the status STI_ATTACH is sent from the hardware, the
292 * driver has just attached itself and we need to initialize
293 * the tables and assorted variables.
296 if(status == STI_ATTACH)
298 if (l1mux_func_p == NULL)
299 panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
301 if(numl1units < MAXL1UNITS)
303 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
304 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
306 tab[L0UNIT(drv_unit)] = numl1units;
308 l1drvunittab[numl1units] = drv_unit;
310 l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
312 switch(L0DRVR(drv_unit))
316 kprintf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
321 kprintf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
326 kprintf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
331 kprintf("ifpi2-%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
336 kprintf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
341 kprintf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
346 kprintf("itjc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
351 NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
357 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
358 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
360 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
362 return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
365 /*---------------------------------------------------------------------------*
366 * L0 -> L1 data from hardware
367 *---------------------------------------------------------------------------*/
369 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
373 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
374 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
377 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
380 return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
383 /*---------------------------------------------------------------------------*
384 * L0 -> L1 activate indication from hardware
385 *---------------------------------------------------------------------------*/
387 i4b_l1_ph_activate_ind(int drv_unit)
391 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
392 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
394 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
396 return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
399 /*---------------------------------------------------------------------------*
400 * L0 -> L1 deactivate indication from hardware
401 *---------------------------------------------------------------------------*/
403 i4b_l1_ph_deactivate_ind(int drv_unit)
407 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
408 panic("i4b_l1_ph_deactivate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
410 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
412 return(PH_Deact_Ind(tab[L0UNIT(drv_unit)]));
415 /*---------------------------------------------------------------------------*
416 * L2 -> L1 command to hardware
417 *---------------------------------------------------------------------------*/
419 i4b_l1_mph_command_req(int unit, int command, void * parm)
421 int drv_unit = L0DRVR(l1drvunittab[unit]);
422 int ch_unit = L0UNIT(l1drvunittab[unit]);
424 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
426 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
427 || l1mux_func[drv_unit]->mph_command_req == NULL)
428 panic("i4b_l1_mph_command_req: unknown driver type %d\n", drv_unit);
430 return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
433 /*---------------------------------------------------------------------------*
434 * L2 -> L1 data to be transmitted to hardware
435 *---------------------------------------------------------------------------*/
437 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
439 int drv_unit = L0DRVR(l1drvunittab[unit]);
440 int ch_unit = L0UNIT(l1drvunittab[unit]);
443 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
446 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
447 || l1mux_func[drv_unit]->ph_data_req == NULL)
448 panic("i4b_l1_ph_data_req: unknown driver type %d\n", drv_unit);
450 return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
453 /*---------------------------------------------------------------------------*
454 * L2 -> L1 activate request to hardware
455 *---------------------------------------------------------------------------*/
457 i4b_l1_ph_activate_req(int unit)
459 int drv_unit = L0DRVR(l1drvunittab[unit]);
460 int ch_unit = L0UNIT(l1drvunittab[unit]);
462 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
464 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
465 || l1mux_func[drv_unit]->ph_activate_req == NULL)
466 panic("i4b_l1_ph_activate_req: unknown driver type %d\n", drv_unit);
468 return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));