6b27b34d943748bc6f2ca3d9e0a28a130dec3447
[dragonfly.git] / sys / net / i4b / layer1 / i4b_l1dmux.c
1 /*
2  * Copyright (c) 2000, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_l1dmux.c - isdn4bsd layer 1 driver multiplexer
28  *      --------------------------------------------------
29  *
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 $
32  *
33  *      last edit-date: [Wed Jan 10 16:43:24 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_isic.h"
38 #include "use_iwic.h"
39 #include "use_ifpi.h"
40 #include "use_ifpi2.h"
41 #include "use_ifpnp.h"
42 #include "use_ihfc.h"
43 #include "use_itjc.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47
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>
51
52 #include "i4b_l1.h"
53
54 #include "../include/i4b_l1l2.h"
55 #include "../include/i4b_global.h"
56
57 /*
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.
60  *
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.
63  *
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
69  * number.
70  *
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.
76  *
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 ;-)
84  */
85  
86 unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
87
88 #if NISIC > 0
89 static int l1isicunittab[MAXL1UNITS];
90 #endif
91
92 #if NIWIC > 0
93 static int l1iwicunittab[MAXL1UNITS];
94 #endif
95
96 #if NIFPI > 0
97 static int l1ifpiunittab[MAXL1UNITS];
98 #endif
99
100 #if NIFPI2 > 0
101 static int l1ifpi2unittab[MAXL1UNITS];
102 #endif
103
104 #if NIHFC > 0
105 static int l1ihfcunittab[MAXL1UNITS];
106 #endif
107
108 #if NIFPNP > 0
109 static int l1ifpnpunittab[MAXL1UNITS];
110 #endif
111
112 #if NITJC > 0
113 static int l1itjcunittab[MAXL1UNITS];
114 #endif
115
116 static int numl1units = 0;
117
118 static int l1drvunittab[MAXL1UNITS];
119 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
120
121 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
122 static int i4b_l1_ph_activate_req(int);
123
124 /* from i4btrc driver i4b_trace.c */
125 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
126
127 /* from layer 2 */
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);
132
133 /* layer 1 lme */
134 int i4b_l1_mph_command_req(int, int, void *);
135
136 /*---------------------------------------------------------------------------*
137  *      jump table: interface function pointers L1/L2 interface 
138  *---------------------------------------------------------------------------*/
139 struct i4b_l1l2_func i4b_l1l2_func = {
140
141         /* Layer 1 --> Layer 2 */
142         
143         (int (*)(int, struct mbuf *))           i4b_ph_data_ind,
144         (int (*)(int))                          i4b_ph_activate_ind,
145         (int (*)(int))                          i4b_ph_deactivate_ind,
146
147         /* Layer 2 --> Layer 1 */
148
149         (int (*)(int, struct mbuf *, int))      i4b_l1_ph_data_req,
150
151         (int (*)(int))                          i4b_l1_ph_activate_req,
152
153         /* Layer 1 --> trace interface driver, ISDN trace data */
154
155         (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
156
157         /* Driver control and status information */
158
159         (int (*)(int, int, int))                i4b_mph_status_ind,
160         (int (*)(int, int, void *))             i4b_l1_mph_command_req,
161 };
162
163 /*---------------------------------------------------------------------------*
164  *      return a pointer to a layer 0 drivers unit tab
165  *---------------------------------------------------------------------------*/
166 static __inline int *
167 getl1tab(int drv)
168 {
169         switch(drv)
170         {
171 #if NISIC > 0
172                 case L1DRVR_ISIC:
173                         return(l1isicunittab);
174                         break;
175 #endif
176 #if NIWIC > 0
177                 case L1DRVR_IWIC:
178                         return(l1iwicunittab);
179                         break;
180 #endif
181 #if NIFPI > 0
182                 case L1DRVR_IFPI:
183                         return(l1ifpiunittab);
184                         break;
185 #endif
186 #if NIFPI2 > 0
187                 case L1DRVR_IFPI2:
188                         return(l1ifpi2unittab);
189                         break;
190 #endif
191 #if NIHFC > 0
192                 case L1DRVR_IHFC:
193                         return(l1ihfcunittab);
194                         break;
195 #endif
196 #if NIFPNP > 0
197                 case L1DRVR_IFPNP:
198                         return(l1ifpnpunittab);
199                         break;
200 #endif
201 #if NITJC > 0
202                 case L1DRVR_ITJC:
203                         return(l1itjcunittab);
204                         break;
205 #endif
206                 default:
207                         return(NULL);
208                         break;
209         }
210 }
211
212 /*===========================================================================*
213  *      B - Channel (data transfer)
214  *===========================================================================*/
215
216 /*---------------------------------------------------------------------------*
217  *      return the address of ISDN drivers linktab      
218  *---------------------------------------------------------------------------*/
219 isdn_link_t *
220 i4b_l1_ret_linktab(int unit, int channel)
221 {
222         int drv_unit, ch_unit;
223  
224         drv_unit = L0DRVR(l1drvunittab[unit]);
225         ch_unit = L0UNIT(l1drvunittab[unit]);
226  
227         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
228
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);
232
233         return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
234 }
235  
236 /*---------------------------------------------------------------------------*
237  *      set the ISDN driver linktab
238  *---------------------------------------------------------------------------*/
239 void
240 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
241 {
242         int drv_unit, ch_unit;
243  
244         drv_unit = L0DRVR(l1drvunittab[unit]);
245         ch_unit = L0UNIT(l1drvunittab[unit]);
246  
247         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
248
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);
252
253         l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
254 }
255
256 /*===========================================================================*
257  *      trace D- and B-Channel support
258  *===========================================================================*/
259
260 /*---------------------------------------------------------------------------*
261  *      L0 -> L1 trace information to trace driver
262  *---------------------------------------------------------------------------*/
263 int
264 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
265 {
266         int *tab;
267         
268         if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
269                 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
270
271         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
272         
273         hdr->unit = tab[L0UNIT(hdr->unit)];
274
275         return(MPH_Trace_Ind(hdr, len, data));
276 }
277
278 /*===========================================================================*
279  *      D - Channel (signalling)
280  *===========================================================================*/
281
282 /*---------------------------------------------------------------------------*
283  *      L0 -> L1 status indication from hardware
284  *---------------------------------------------------------------------------*/
285 int
286 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
287 {
288         int *tab;
289         
290         /*
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.
294          */
295
296         if(status == STI_ATTACH)
297         {
298                 if (l1mux_func_p == (struct i4b_l1mux_func *)0)
299                         panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
300
301                 if(numl1units < MAXL1UNITS)
302                 {
303                         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
304                                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
305                         
306                         tab[L0UNIT(drv_unit)] = numl1units;
307
308                         l1drvunittab[numl1units] = drv_unit;
309
310                         l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
311
312                         switch(L0DRVR(drv_unit))
313                         {
314 #if NISIC > 0
315                                 case L1DRVR_ISIC:
316                                         kprintf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
317                                         break;
318 #endif
319 #if NIWIC > 0
320                                 case L1DRVR_IWIC:
321                                         kprintf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
322                                         break;
323 #endif
324 #if NIFPI > 0
325                                 case L1DRVR_IFPI:
326                                         kprintf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
327                                         break;
328 #endif
329 #if NIFPI2 > 0
330                                 case L1DRVR_IFPI2:
331                                         kprintf("ifpi2-%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
332                                         break;
333 #endif
334 #if NIFPNP > 0
335                                 case L1DRVR_IFPNP:
336                                         kprintf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
337                                         break;
338 #endif
339 #if NIHFC > 0
340                                 case L1DRVR_IHFC:
341                                         kprintf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
342                                         break;
343 #endif
344 #if NITJC > 0
345                                 case L1DRVR_ITJC:
346                                         kprintf("itjc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
347                                         break;
348 #endif
349                         }
350                         
351                         NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
352
353                         numl1units++;                   
354                 }
355         }
356
357         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
358                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
359
360         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
361         
362         return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
363 }
364
365 /*---------------------------------------------------------------------------*
366  *      L0 -> L1 data from hardware
367  *---------------------------------------------------------------------------*/
368 int
369 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
370 {
371         int *tab;
372
373         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
374                 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
375
376 #if 0
377         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
378 #endif
379
380         return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
381 }
382
383 /*---------------------------------------------------------------------------*
384  *      L0 -> L1 activate indication from hardware
385  *---------------------------------------------------------------------------*/
386 int
387 i4b_l1_ph_activate_ind(int drv_unit)
388 {
389         int *tab;
390
391         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
392                 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
393
394         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
395
396         return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
397 }
398
399 /*---------------------------------------------------------------------------*
400  *      L0 -> L1 deactivate indication from hardware
401  *---------------------------------------------------------------------------*/
402 int
403 i4b_l1_ph_deactivate_ind(int drv_unit)
404 {
405         int *tab;
406         
407         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
408                 panic("i4b_l1_ph_deactivate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
409
410         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);         
411
412         return(PH_Deact_Ind(tab[L0UNIT(drv_unit)]));
413 }
414         
415 /*---------------------------------------------------------------------------*
416  *      L2 -> L1 command to hardware
417  *---------------------------------------------------------------------------*/
418 int
419 i4b_l1_mph_command_req(int unit, int command, void * parm)
420 {
421         int drv_unit = L0DRVR(l1drvunittab[unit]);
422         int ch_unit = L0UNIT(l1drvunittab[unit]);
423  
424         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
425
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);
429  
430         return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
431 }
432
433 /*---------------------------------------------------------------------------*
434  *      L2 -> L1 data to be transmitted to hardware
435  *---------------------------------------------------------------------------*/
436 int
437 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
438 {
439         int drv_unit = L0DRVR(l1drvunittab[unit]);
440         int ch_unit = L0UNIT(l1drvunittab[unit]);
441
442 #if 0
443         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
444 #endif
445         
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);
449
450         return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
451 }
452
453 /*---------------------------------------------------------------------------*
454  *      L2 -> L1 activate request to hardware
455  *---------------------------------------------------------------------------*/
456 int
457 i4b_l1_ph_activate_req(int unit)
458 {
459         int drv_unit = L0DRVR(l1drvunittab[unit]);
460         int ch_unit = L0UNIT(l1drvunittab[unit]);
461  
462         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
463
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);
467
468         return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));
469 }
470
471 /* EOF */