]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i4b/layer1/i4b_l1dmux.c
This commit was generated by cvs2svn to compensate for changes in r69450,
[FreeBSD/FreeBSD.git] / sys / i4b / layer1 / i4b_l1dmux.c
1 /*
2  * Copyright (c) 2000 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  *      $Id: i4b_l1dmux.c,v 1.12 2000/06/02 16:14:36 hm Exp $
31  *
32  * $FreeBSD$
33  *
34  *      last edit-date: [Fri Jun  2 14:37:39 2000]
35  *
36  *---------------------------------------------------------------------------*/
37
38 #include "isic.h"
39 #include "iwic.h"
40 #include "ifpi.h"
41 #include "ifpnp.h"
42 #include "ihfc.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46
47
48 #include <machine/i4b_debug.h>
49 #include <machine/i4b_ioctl.h>
50 #include <machine/i4b_trace.h>
51
52 #include <i4b/layer1/i4b_l1.h>
53
54 #include <i4b/include/i4b_l1l2.h>
55 #include <i4b/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 NIHFC > 0
101 static int l1ihfcunittab[MAXL1UNITS];
102 #endif
103
104 #if NIFPNP > 0
105 static int l1ifpnpunittab[MAXL1UNITS];
106 #endif
107
108 static int numl1units = 0;
109
110 static int l1drvunittab[MAXL1UNITS];
111 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
112
113 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
114 static int i4b_l1_ph_activate_req(int);
115
116 /* from i4btrc driver i4b_trace.c */
117 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
118
119 /* from layer 2 */
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);
124
125 /* layer 1 lme */
126 int i4b_l1_mph_command_req(int, int, void *);
127
128 /*---------------------------------------------------------------------------*
129  *      jump table: interface function pointers L1/L2 interface 
130  *---------------------------------------------------------------------------*/
131 struct i4b_l1l2_func i4b_l1l2_func = {
132
133         /* Layer 1 --> Layer 2 */
134         
135         (int (*)(int, struct mbuf *))           i4b_ph_data_ind,
136         (int (*)(int))                          i4b_ph_activate_ind,
137         (int (*)(int))                          i4b_ph_deactivate_ind,
138
139         /* Layer 2 --> Layer 1 */
140
141         (int (*)(int, struct mbuf *, int))      i4b_l1_ph_data_req,
142
143         (int (*)(int))                          i4b_l1_ph_activate_req,
144
145         /* Layer 1 --> trace interface driver, ISDN trace data */
146
147         (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
148
149         /* Driver control and status information */
150
151         (int (*)(int, int, int))                i4b_mph_status_ind,
152         (int (*)(int, int, void *))             i4b_l1_mph_command_req,
153 };
154
155 /*---------------------------------------------------------------------------*
156  *      return a pointer to a layer 0 drivers unit tab
157  *---------------------------------------------------------------------------*/
158 static __inline int *
159 getl1tab(int drv)
160 {
161         switch(drv)
162         {
163 #if NISIC > 0
164                 case L1DRVR_ISIC:
165                         return(l1isicunittab);
166                         break;
167 #endif
168 #if NIWIC > 0
169                 case L1DRVR_IWIC:
170                         return(l1iwicunittab);
171                         break;
172 #endif
173 #if NIFPI > 0
174                 case L1DRVR_IFPI:
175                         return(l1ifpiunittab);
176                         break;
177 #endif
178 #if NIHFC > 0
179                 case L1DRVR_IHFC:
180                         return(l1ihfcunittab);
181                         break;
182 #endif
183 #if NIFPNP > 0
184                 case L1DRVR_IFPNP:
185                         return(l1ifpnpunittab);
186                         break;
187 #endif
188                 default:
189                         return(NULL);
190                         break;
191         }
192 }
193
194 /*===========================================================================*
195  *      B - Channel (data transfer)
196  *===========================================================================*/
197
198 /*---------------------------------------------------------------------------*
199  *      return the address of ISDN drivers linktab      
200  *---------------------------------------------------------------------------*/
201 isdn_link_t *
202 i4b_l1_ret_linktab(int unit, int channel)
203 {
204         int drv_unit, ch_unit;
205  
206         drv_unit = L0DRVR(l1drvunittab[unit]);
207         ch_unit = L0UNIT(l1drvunittab[unit]);
208  
209         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
210
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);
214
215         return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
216 }
217  
218 /*---------------------------------------------------------------------------*
219  *      set the ISDN driver linktab
220  *---------------------------------------------------------------------------*/
221 void
222 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
223 {
224         int drv_unit, ch_unit;
225  
226         drv_unit = L0DRVR(l1drvunittab[unit]);
227         ch_unit = L0UNIT(l1drvunittab[unit]);
228  
229         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
230
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);
234
235         l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
236 }
237
238 /*===========================================================================*
239  *      trace D- and B-Channel support
240  *===========================================================================*/
241
242 /*---------------------------------------------------------------------------*
243  *      L0 -> L1 trace information to trace driver
244  *---------------------------------------------------------------------------*/
245 int
246 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
247 {
248         register int *tab;
249         
250         if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
251                 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
252
253         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
254         
255         hdr->unit = tab[L0UNIT(hdr->unit)];
256
257         return(MPH_Trace_Ind(hdr, len, data));
258 }
259
260 /*===========================================================================*
261  *      D - Channel (signalling)
262  *===========================================================================*/
263
264 /*---------------------------------------------------------------------------*
265  *      L0 -> L1 status indication from hardware
266  *---------------------------------------------------------------------------*/
267 int
268 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
269 {
270         register int *tab;
271         
272         /*
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.
276          */
277
278         if(status == STI_ATTACH)
279         {
280                 if (l1mux_func_p == (struct i4b_l1mux_func *)0)
281                         panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
282
283                 if(numl1units < MAXL1UNITS)
284                 {
285                         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
286                                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
287                         
288                         tab[L0UNIT(drv_unit)] = numl1units;
289
290                         l1drvunittab[numl1units] = drv_unit;
291
292                         l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
293
294                         switch(L0DRVR(drv_unit))
295                         {
296 #if NISIC > 0
297                                 case L1DRVR_ISIC:
298                                         printf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
299                                         break;
300 #endif
301 #if NIWIC > 0
302                                 case L1DRVR_IWIC:
303                                         printf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
304                                         break;
305 #endif
306 #if NIFPI > 0
307                                 case L1DRVR_IFPI:
308                                         printf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
309                                         break;
310 #endif
311 #if NIFPNP > 0
312                                 case L1DRVR_IFPNP:
313                                         printf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
314                                         break;
315 #endif
316 #if NIHFC > 0
317                                 case L1DRVR_IHFC:
318                                         printf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
319 #endif
320                         }
321                         
322                         NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
323
324                         numl1units++;                   
325                 }
326         }
327
328         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
329                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
330
331         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
332         
333         return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
334 }
335
336 /*---------------------------------------------------------------------------*
337  *      L0 -> L1 data from hardware
338  *---------------------------------------------------------------------------*/
339 int
340 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
341 {
342         register int *tab;
343
344         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
345                 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
346
347 #if 0
348         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
349 #endif
350
351         return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
352 }
353
354 /*---------------------------------------------------------------------------*
355  *      L0 -> L1 activate indication from hardware
356  *---------------------------------------------------------------------------*/
357 int
358 i4b_l1_ph_activate_ind(int drv_unit)
359 {
360         register int *tab;
361
362         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
363                 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
364
365         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
366
367         return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
368 }
369
370 /*---------------------------------------------------------------------------*
371  *      L0 -> L1 deactivate indication from hardware
372  *---------------------------------------------------------------------------*/
373 int
374 i4b_l1_ph_deactivate_ind(int drv_unit)
375 {
376         register int *tab;
377         
378         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
379                 panic("i4b_l1_ph_deactivate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
380
381         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);         
382
383         return(PH_Deact_Ind(tab[L0UNIT(drv_unit)]));
384 }
385         
386 /*---------------------------------------------------------------------------*
387  *      L2 -> L1 command to hardware
388  *---------------------------------------------------------------------------*/
389 int
390 i4b_l1_mph_command_req(int unit, int command, void * parm)
391 {
392         register int drv_unit = L0DRVR(l1drvunittab[unit]);
393         register int ch_unit = L0UNIT(l1drvunittab[unit]);
394  
395         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
396
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);
400  
401         return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
402 }
403
404 /*---------------------------------------------------------------------------*
405  *      L2 -> L1 data to be transmitted to hardware
406  *---------------------------------------------------------------------------*/
407 int
408 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
409 {
410         register int drv_unit = L0DRVR(l1drvunittab[unit]);
411         register int ch_unit = L0UNIT(l1drvunittab[unit]);
412
413 #if 0
414         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
415 #endif
416         
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);
420
421         return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
422 }
423
424 /*---------------------------------------------------------------------------*
425  *      L2 -> L1 activate request to hardware
426  *---------------------------------------------------------------------------*/
427 int
428 i4b_l1_ph_activate_req(int unit)
429 {
430         register int drv_unit = L0DRVR(l1drvunittab[unit]);
431         register int ch_unit = L0UNIT(l1drvunittab[unit]);
432  
433         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
434
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);
438
439         return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));
440 }
441
442 /* EOF */