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 * --------------------------------------------------
32 * last edit-date: [Wed Jan 10 16:43:24 2001]
34 *---------------------------------------------------------------------------*/
43 #include <sys/param.h>
44 #include <sys/systm.h>
46 #include <machine/i4b_debug.h>
47 #include <machine/i4b_ioctl.h>
48 #include <machine/i4b_trace.h>
50 #include <i4b/layer1/i4b_l1.h>
52 #include <i4b/include/i4b_l1l2.h>
53 #include <i4b/include/i4b_global.h>
56 * this code is nothing but a big dynamic switch to multiplex and demultiplex
57 * layer 1 hardware isdn drivers to a common layer 2.
59 * when a card is successfully attached at system boot time, the driver for
60 * this card calls the routine i4b_l1_mph_status_ind() with status = STI_ATTACH.
62 * This command is used to setup the tables for converting a "driver unit" and
63 * "driver type" pair (encoded in the calls from the hardware driver to the
64 * routines in this source file) to a "unit number" used in layer 2 and the
65 * layers above (up to and including the isdnd daemon) and for converting
66 * layer 2 units back to calling the appropriate driver and driver unit
69 * Example: in my setup, a Winbond (iwic) card is probed first and gets
70 * driver unit number 0, driver type 1 in layer 1. This becomes unit
71 * number 0 in layer 2 and up. The second card probed is a Teles card
72 * (isic) and gets driver unit number 0, driver type 0 in layer 1. This
73 * becomes unit number 1 in layer 1 and up.
75 * To add support for a new driver, add a new driver number to i4b_l1.h:
76 * currently we have L1DRVR_ISIC and L1DRVR_IWIC, so you would add
77 * L1DRVR_FOO. More you would want to add a L0FOOUNIT to encode unit
78 * numbers in your driver. You then have to add a l1foounittab[] and
79 * add an entry to the getl1tab() routine for your driver. The only
80 * thing left now is to write your driver with the support functions
81 * for this multiplexer ;-)
84 unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
87 static int l1isicunittab[MAXL1UNITS];
91 static int l1iwicunittab[MAXL1UNITS];
95 static int l1ifpiunittab[MAXL1UNITS];
99 static int l1ihfcunittab[MAXL1UNITS];
103 static int l1ifpnpunittab[MAXL1UNITS];
107 static int l1itjcunittab[MAXL1UNITS];
110 static int numl1units = 0;
112 static int l1drvunittab[MAXL1UNITS];
113 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
115 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
116 static int i4b_l1_ph_activate_req(int);
118 /* from i4btrc driver i4b_trace.c */
119 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
122 int i4b_ph_data_ind(int unit, struct mbuf *m);
123 int i4b_ph_activate_ind(int unit);
124 int i4b_ph_deactivate_ind(int unit);
125 int i4b_mph_status_ind(int, int, int);
128 int i4b_l1_mph_command_req(int, int, void *);
130 /*---------------------------------------------------------------------------*
131 * jump table: interface function pointers L1/L2 interface
132 *---------------------------------------------------------------------------*/
133 struct i4b_l1l2_func i4b_l1l2_func = {
135 /* Layer 1 --> Layer 2 */
137 (int (*)(int, struct mbuf *)) i4b_ph_data_ind,
138 (int (*)(int)) i4b_ph_activate_ind,
139 (int (*)(int)) i4b_ph_deactivate_ind,
141 /* Layer 2 --> Layer 1 */
143 (int (*)(int, struct mbuf *, int)) i4b_l1_ph_data_req,
145 (int (*)(int)) i4b_l1_ph_activate_req,
147 /* Layer 1 --> trace interface driver, ISDN trace data */
149 (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
151 /* Driver control and status information */
153 (int (*)(int, int, int)) i4b_mph_status_ind,
154 (int (*)(int, int, void *)) i4b_l1_mph_command_req,
157 /*---------------------------------------------------------------------------*
158 * return a pointer to a layer 0 drivers unit tab
159 *---------------------------------------------------------------------------*/
160 static __inline int *
167 return(l1isicunittab);
172 return(l1iwicunittab);
177 return(l1ifpiunittab);
182 return(l1ihfcunittab);
187 return(l1ifpnpunittab);
192 return(l1itjcunittab);
201 /*===========================================================================*
202 * B - Channel (data transfer)
203 *===========================================================================*/
205 /*---------------------------------------------------------------------------*
206 * return the address of ISDN drivers linktab
207 *---------------------------------------------------------------------------*/
209 i4b_l1_ret_linktab(int unit, int channel)
211 int drv_unit, ch_unit;
213 drv_unit = L0DRVR(l1drvunittab[unit]);
214 ch_unit = L0UNIT(l1drvunittab[unit]);
216 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
218 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
219 || l1mux_func[drv_unit]->ret_linktab == NULL)
220 panic("i4b_l1_ret_linktab: unknown driver type %d\n", drv_unit);
222 return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
225 /*---------------------------------------------------------------------------*
226 * set the ISDN driver linktab
227 *---------------------------------------------------------------------------*/
229 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
231 int drv_unit, ch_unit;
233 drv_unit = L0DRVR(l1drvunittab[unit]);
234 ch_unit = L0UNIT(l1drvunittab[unit]);
236 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
238 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
239 || l1mux_func[drv_unit]->set_linktab == NULL)
240 panic("i4b_l1_set_linktab: unknown driver type %d\n", drv_unit);
242 l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
245 /*===========================================================================*
246 * trace D- and B-Channel support
247 *===========================================================================*/
249 /*---------------------------------------------------------------------------*
250 * L0 -> L1 trace information to trace driver
251 *---------------------------------------------------------------------------*/
253 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
257 if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
258 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
260 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
262 hdr->unit = tab[L0UNIT(hdr->unit)];
264 return(MPH_Trace_Ind(hdr, len, data));
267 /*===========================================================================*
268 * D - Channel (signalling)
269 *===========================================================================*/
271 /*---------------------------------------------------------------------------*
272 * L0 -> L1 status indication from hardware
273 *---------------------------------------------------------------------------*/
275 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
280 * in case the status STI_ATTACH is sent from the hardware, the
281 * driver has just attached itself and we need to initialize
282 * the tables and assorted variables.
285 if(status == STI_ATTACH)
287 if (l1mux_func_p == (struct i4b_l1mux_func *)0)
288 panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
290 if(numl1units < MAXL1UNITS)
292 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
293 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
295 tab[L0UNIT(drv_unit)] = numl1units;
297 l1drvunittab[numl1units] = drv_unit;
299 l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
301 switch(L0DRVR(drv_unit))
305 printf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
310 printf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
315 printf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
320 printf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
325 printf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
330 printf("itjc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
335 NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
341 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
342 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
344 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
346 return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
349 /*---------------------------------------------------------------------------*
350 * L0 -> L1 data from hardware
351 *---------------------------------------------------------------------------*/
353 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
357 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
358 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
361 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
364 return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
367 /*---------------------------------------------------------------------------*
368 * L0 -> L1 activate indication from hardware
369 *---------------------------------------------------------------------------*/
371 i4b_l1_ph_activate_ind(int drv_unit)
375 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
376 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
378 NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
380 return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
383 /*---------------------------------------------------------------------------*
384 * L0 -> L1 deactivate indication from hardware
385 *---------------------------------------------------------------------------*/
387 i4b_l1_ph_deactivate_ind(int drv_unit)
391 if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
392 panic("i4b_l1_ph_deactivate_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_Deact_Ind(tab[L0UNIT(drv_unit)]));
399 /*---------------------------------------------------------------------------*
400 * L2 -> L1 command to hardware
401 *---------------------------------------------------------------------------*/
403 i4b_l1_mph_command_req(int unit, int command, void * parm)
405 register int drv_unit = L0DRVR(l1drvunittab[unit]);
406 register int ch_unit = L0UNIT(l1drvunittab[unit]);
408 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
410 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
411 || l1mux_func[drv_unit]->mph_command_req == NULL)
412 panic("i4b_l1_mph_command_req: unknown driver type %d\n", drv_unit);
414 return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
417 /*---------------------------------------------------------------------------*
418 * L2 -> L1 data to be transmitted to hardware
419 *---------------------------------------------------------------------------*/
421 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
423 register int drv_unit = L0DRVR(l1drvunittab[unit]);
424 register int ch_unit = L0UNIT(l1drvunittab[unit]);
427 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
430 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
431 || l1mux_func[drv_unit]->ph_data_req == NULL)
432 panic("i4b_l1_ph_data_req: unknown driver type %d\n", drv_unit);
434 return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
437 /*---------------------------------------------------------------------------*
438 * L2 -> L1 activate request to hardware
439 *---------------------------------------------------------------------------*/
441 i4b_l1_ph_activate_req(int unit)
443 register int drv_unit = L0DRVR(l1drvunittab[unit]);
444 register int ch_unit = L0UNIT(l1drvunittab[unit]);
446 NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
448 if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
449 || l1mux_func[drv_unit]->ph_activate_req == NULL)
450 panic("i4b_l1_ph_activate_req: unknown driver type %d\n", drv_unit);
452 return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));