2 * Copyright (c) 2000 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 * $Id: i4b_l1dmux.c,v 1.12 2000/06/02 16:14:36 hm Exp $
34 * last edit-date: [Fri Jun 2 14:37:39 2000]
36 *---------------------------------------------------------------------------*/
44 #include <sys/param.h>
45 #include <sys/systm.h>
48 #include <machine/i4b_debug.h>
49 #include <machine/i4b_ioctl.h>
50 #include <machine/i4b_trace.h>
52 #include <i4b/layer1/i4b_l1.h>
54 #include <i4b/include/i4b_l1l2.h>
55 #include <i4b/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 l1ihfcunittab[MAXL1UNITS];
105 static int l1ifpnpunittab[MAXL1UNITS];
108 static int numl1units = 0;
110 static int l1drvunittab[MAXL1UNITS];
111 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
113 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
114 static int i4b_l1_ph_activate_req(int);
116 /* from i4btrc driver i4b_trace.c */
117 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
120 int i4b_ph_data_ind(int unit, struct mbuf *m);
121 int i4b_ph_activate_ind(int unit);
122 int i4b_ph_deactivate_ind(int unit);
123 int i4b_mph_status_ind(int, int, int);
126 int i4b_l1_mph_command_req(int, int, void *);
128 /*---------------------------------------------------------------------------*
129 * jump table: interface function pointers L1/L2 interface
130 *---------------------------------------------------------------------------*/
131 struct i4b_l1l2_func i4b_l1l2_func = {
133 /* Layer 1 --> Layer 2 */
135 (int (*)(int, struct mbuf *)) i4b_ph_data_ind,
136 (int (*)(int)) i4b_ph_activate_ind,
137 (int (*)(int)) i4b_ph_deactivate_ind,
139 /* Layer 2 --> Layer 1 */
141 (int (*)(int, struct mbuf *, int)) i4b_l1_ph_data_req,
143 (int (*)(int)) i4b_l1_ph_activate_req,
145 /* Layer 1 --> trace interface driver, ISDN trace data */
147 (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
149 /* Driver control and status information */
151 (int (*)(int, int, int)) i4b_mph_status_ind,
152 (int (*)(int, int, void *)) i4b_l1_mph_command_req,
155 /*---------------------------------------------------------------------------*
156 * return a pointer to a layer 0 drivers unit tab
157 *---------------------------------------------------------------------------*/
158 static __inline int *
165 return(l1isicunittab);
170 return(l1iwicunittab);
175 return(l1ifpiunittab);
180 return(l1ihfcunittab);
185 return(l1ifpnpunittab);
194 /*===========================================================================*
195 * B - Channel (data transfer)
196 *===========================================================================*/
198 /*---------------------------------------------------------------------------*
199 * return the address of ISDN drivers linktab
200 *---------------------------------------------------------------------------*/
202 i4b_l1_ret_linktab(int unit, int channel)
204 int drv_unit, ch_unit;
206 drv_unit = L0DRVR(l1drvunittab[unit]);
207 ch_unit = L0UNIT(l1drvunittab[unit]);
209 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
211 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
212 || l1mux_func[drv_unit]->ret_linktab == NULL)
213 panic("i4b_l1_ret_linktab: unknown driver type %d\n", drv_unit);
215 return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
218 /*---------------------------------------------------------------------------*
219 * set the ISDN driver linktab
220 *---------------------------------------------------------------------------*/
222 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
224 int drv_unit, ch_unit;
226 drv_unit = L0DRVR(l1drvunittab[unit]);
227 ch_unit = L0UNIT(l1drvunittab[unit]);
229 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
231 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
232 || l1mux_func[drv_unit]->set_linktab == NULL)
233 panic("i4b_l1_set_linktab: unknown driver type %d\n", drv_unit);
235 l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
238 /*===========================================================================*
239 * trace D- and B-Channel support
240 *===========================================================================*/
242 /*---------------------------------------------------------------------------*
243 * L0 -> L1 trace information to trace driver
244 *---------------------------------------------------------------------------*/
246 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
250 if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
251 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
253 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
255 hdr->unit = tab[L0UNIT(hdr->unit)];
257 return(MPH_Trace_Ind(hdr, len, data));
260 /*===========================================================================*
261 * D - Channel (signalling)
262 *===========================================================================*/
264 /*---------------------------------------------------------------------------*
265 * L0 -> L1 status indication from hardware
266 *---------------------------------------------------------------------------*/
268 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
273 * in case the status STI_ATTACH is sent from the hardware, the
274 * driver has just attached itself and we need to initialize
275 * the tables and assorted variables.
278 if(status == STI_ATTACH)
280 if (l1mux_func_p == (struct i4b_l1mux_func *)0)
281 panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
283 if(numl1units < MAXL1UNITS)
285 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
286 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
288 tab[L0UNIT(drv_unit)] = numl1units;
290 l1drvunittab[numl1units] = drv_unit;
292 l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
294 switch(L0DRVR(drv_unit))
298 printf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
303 printf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
308 printf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
313 printf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
318 printf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
322 NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
328 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
329 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
331 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
333 return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
336 /*---------------------------------------------------------------------------*
337 * L0 -> L1 data from hardware
338 *---------------------------------------------------------------------------*/
340 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
344 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
345 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
348 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
351 return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
354 /*---------------------------------------------------------------------------*
355 * L0 -> L1 activate indication from hardware
356 *---------------------------------------------------------------------------*/
358 i4b_l1_ph_activate_ind(int drv_unit)
362 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
363 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
365 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
367 return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
370 /*---------------------------------------------------------------------------*
371 * L0 -> L1 deactivate indication from hardware
372 *---------------------------------------------------------------------------*/
374 i4b_l1_ph_deactivate_ind(int drv_unit)
378 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
379 panic("i4b_l1_ph_deactivate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
381 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
383 return(PH_Deact_Ind(tab[L0UNIT(drv_unit)]));
386 /*---------------------------------------------------------------------------*
387 * L2 -> L1 command to hardware
388 *---------------------------------------------------------------------------*/
390 i4b_l1_mph_command_req(int unit, int command, void * parm)
392 register int drv_unit = L0DRVR(l1drvunittab[unit]);
393 register int ch_unit = L0UNIT(l1drvunittab[unit]);
395 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
397 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
398 || l1mux_func[drv_unit]->mph_command_req == NULL)
399 panic("i4b_l1_mph_command_req: unknown driver type %d\n", drv_unit);
401 return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
404 /*---------------------------------------------------------------------------*
405 * L2 -> L1 data to be transmitted to hardware
406 *---------------------------------------------------------------------------*/
408 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
410 register int drv_unit = L0DRVR(l1drvunittab[unit]);
411 register int ch_unit = L0UNIT(l1drvunittab[unit]);
414 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
417 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
418 || l1mux_func[drv_unit]->ph_data_req == NULL)
419 panic("i4b_l1_ph_data_req: unknown driver type %d\n", drv_unit);
421 return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
424 /*---------------------------------------------------------------------------*
425 * L2 -> L1 activate request to hardware
426 *---------------------------------------------------------------------------*/
428 i4b_l1_ph_activate_req(int unit)
430 register int drv_unit = L0DRVR(l1drvunittab[unit]);
431 register int ch_unit = L0UNIT(l1drvunittab[unit]);
433 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
435 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
436 || l1mux_func[drv_unit]->ph_activate_req == NULL)
437 panic("i4b_l1_ph_activate_req: unknown driver type %d\n", drv_unit);
439 return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));