]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/i4b_l1dmux.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / 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  *
28  *      i4b_l1dmux.c - isdn4bsd layer 1 driver multiplexer
29  *      --------------------------------------------------
30  *      last edit-date: [Wed Jan 10 16:43:24 2001]
31  *
32  *---------------------------------------------------------------------------*/
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39
40 #include <i4b/include/i4b_debug.h>
41 #include <i4b/include/i4b_ioctl.h>
42 #include <i4b/include/i4b_trace.h>
43
44 #include <i4b/layer1/i4b_l1.h>
45
46 #include <i4b/include/i4b_l1l2.h>
47 #include <i4b/include/i4b_global.h>
48
49 /*
50  * this code is nothing but a big dynamic switch to multiplex and demultiplex
51  * layer 1 hardware isdn drivers to a common layer 2.
52  *
53  * when a card is successfully attached at system boot time, the driver for
54  * this card calls the routine i4b_l1_mph_status_ind() with status = STI_ATTACH.
55  *
56  * This command is used to setup the tables for converting a "driver unit" and
57  * "driver type" pair (encoded in the calls from the hardware driver to the
58  * routines in this source file) to a "unit number" used in layer 2 and the
59  * layers above (up to and including the isdnd daemon) and for converting
60  * layer 2 units back to calling the appropriate driver and driver unit
61  * number.
62  *
63  * Example: in my setup, a Winbond (iwic) card is probed first and gets
64  * driver unit number 0, driver type 1 in layer 1. This becomes unit
65  * number 0 in layer 2 and up. The second card probed is a Teles card
66  * (isic) and gets driver unit number 0, driver type 0 in layer 1. This
67  * becomes unit number 1 in layer 1 and up.
68  *
69  * To add support for a new driver, add a new driver number to i4b_l1.h:
70  * currently we have L1DRVR_ISIC and L1DRVR_IWIC, so you would add
71  * L1DRVR_FOO. More you would want to add a L0FOOUNIT to encode unit
72  * numbers in your driver. You then have to add a l1foounittab[] and
73  * add an entry to the getl1tab() routine for your driver. The only
74  * thing left now is to write your driver with the support functions
75  * for this multiplexer ;-)
76  */
77  
78 unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
79
80 static int l1isicunittab[MAXL1UNITS];
81
82 static int l1iwicunittab[MAXL1UNITS];
83
84 static int l1ifpiunittab[MAXL1UNITS];
85
86 static int l1ifpi2unittab[MAXL1UNITS];
87
88 static int l1ihfcunittab[MAXL1UNITS];
89
90 static int l1ifpnpunittab[MAXL1UNITS];
91
92 static int l1itjcunittab[MAXL1UNITS];
93
94 static int numl1units = 0;
95
96 static int l1drvunittab[MAXL1UNITS];
97 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
98
99 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
100 static int i4b_l1_ph_activate_req(int);
101
102 /* from i4btrc driver i4b_trace.c */
103 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
104
105 /* from layer 2 */
106 int i4b_ph_data_ind(int unit, struct mbuf *m);
107 int i4b_ph_activate_ind(int unit);
108 int i4b_ph_deactivate_ind(int unit);
109 int i4b_mph_status_ind(int, int, int);
110
111 /* layer 1 lme */
112 int i4b_l1_mph_command_req(int, int, void *);
113
114 /*---------------------------------------------------------------------------*
115  *      jump table: interface function pointers L1/L2 interface 
116  *---------------------------------------------------------------------------*/
117 struct i4b_l1l2_func i4b_l1l2_func = {
118
119         /* Layer 1 --> Layer 2 */
120         
121         (int (*)(int, struct mbuf *))           i4b_ph_data_ind,
122         (int (*)(int))                          i4b_ph_activate_ind,
123         (int (*)(int))                          i4b_ph_deactivate_ind,
124
125         /* Layer 2 --> Layer 1 */
126
127         (int (*)(int, struct mbuf *, int))      i4b_l1_ph_data_req,
128
129         (int (*)(int))                          i4b_l1_ph_activate_req,
130
131         /* Layer 1 --> trace interface driver, ISDN trace data */
132
133         (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
134
135         /* Driver control and status information */
136
137         (int (*)(int, int, int))                i4b_mph_status_ind,
138         (int (*)(int, int, void *))             i4b_l1_mph_command_req,
139 };
140
141 /*---------------------------------------------------------------------------*
142  *      return a pointer to a layer 0 drivers unit tab
143  *---------------------------------------------------------------------------*/
144 static __inline int *
145 getl1tab(int drv)
146 {
147         switch(drv)
148         {
149                 case L1DRVR_ISIC:
150                         return(l1isicunittab);
151                         break;
152                 case L1DRVR_IWIC:
153                         return(l1iwicunittab);
154                         break;
155                 case L1DRVR_IFPI:
156                         return(l1ifpiunittab);
157                         break;
158                 case L1DRVR_IFPI2:
159                         return(l1ifpi2unittab);
160                         break;
161                 case L1DRVR_IHFC:
162                         return(l1ihfcunittab);
163                         break;
164                 case L1DRVR_IFPNP:
165                         return(l1ifpnpunittab);
166                         break;
167                 case L1DRVR_ITJC:
168                         return(l1itjcunittab);
169                         break;
170                 default:
171                         return(NULL);
172                         break;
173         }
174 }
175
176 /*===========================================================================*
177  *      B - Channel (data transfer)
178  *===========================================================================*/
179
180 /*---------------------------------------------------------------------------*
181  *      return the address of ISDN drivers linktab      
182  *---------------------------------------------------------------------------*/
183 isdn_link_t *
184 i4b_l1_ret_linktab(int unit, int channel)
185 {
186         int drv_unit, ch_unit;
187  
188         drv_unit = L0DRVR(l1drvunittab[unit]);
189         ch_unit = L0UNIT(l1drvunittab[unit]);
190  
191         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
192
193         if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
194             || l1mux_func[drv_unit]->ret_linktab == NULL)
195                 panic("i4b_l1_ret_linktab: unknown driver type %d\n", drv_unit);
196
197         return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
198 }
199  
200 /*---------------------------------------------------------------------------*
201  *      set the ISDN driver linktab
202  *---------------------------------------------------------------------------*/
203 void
204 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
205 {
206         int drv_unit, ch_unit;
207  
208         drv_unit = L0DRVR(l1drvunittab[unit]);
209         ch_unit = L0UNIT(l1drvunittab[unit]);
210  
211         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
212
213         if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
214             || l1mux_func[drv_unit]->set_linktab == NULL)
215                 panic("i4b_l1_set_linktab: unknown driver type %d\n", drv_unit);
216
217         l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
218 }
219
220 /*===========================================================================*
221  *      trace D- and B-Channel support
222  *===========================================================================*/
223
224 /*---------------------------------------------------------------------------*
225  *      L0 -> L1 trace information to trace driver
226  *---------------------------------------------------------------------------*/
227 int
228 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
229 {
230         register int *tab;
231         
232         if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
233                 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
234
235         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
236         
237         hdr->unit = tab[L0UNIT(hdr->unit)];
238
239         return(MPH_Trace_Ind(hdr, len, data));
240 }
241
242 /*===========================================================================*
243  *      D - Channel (signalling)
244  *===========================================================================*/
245
246 /*---------------------------------------------------------------------------*
247  *      L0 -> L1 status indication from hardware
248  *---------------------------------------------------------------------------*/
249 int
250 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
251 {
252         register int *tab;
253         
254         /*
255          * in case the status STI_ATTACH is sent from the hardware, the
256          * driver has just attached itself and we need to initialize
257          * the tables and assorted variables.
258          */
259
260         if(status == STI_ATTACH)
261         {
262                 if (l1mux_func_p == (struct i4b_l1mux_func *)0)
263                         panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
264
265                 if(numl1units < MAXL1UNITS)
266                 {
267                         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
268                                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
269                         
270                         tab[L0UNIT(drv_unit)] = numl1units;
271
272                         l1drvunittab[numl1units] = drv_unit;
273
274                         l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
275
276                         switch(L0DRVR(drv_unit))
277                         {
278                                 case L1DRVR_ISIC:
279                                         printf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
280                                         break;
281                                 case L1DRVR_IWIC:
282                                         printf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
283                                         break;
284                                 case L1DRVR_IFPI:
285                                         printf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
286                                         break;
287                                 case L1DRVR_IFPI2:
288                                         printf("ifpi2-%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
289                                         break;
290                                 case L1DRVR_IFPNP:
291                                         printf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
292                                         break;
293                                 case L1DRVR_IHFC:
294                                         printf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
295                                         break;
296                                 case L1DRVR_ITJC:
297                                         printf("itjc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
298                                         break;
299                         }
300                         
301                         NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
302
303                         numl1units++;                   
304                 }
305         }
306
307         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
308                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
309
310         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
311         
312         return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
313 }
314
315 /*---------------------------------------------------------------------------*
316  *      L0 -> L1 data from hardware
317  *---------------------------------------------------------------------------*/
318 int
319 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
320 {
321         register int *tab;
322
323         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
324                 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
325
326 #if 0
327         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
328 #endif
329
330         return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
331 }
332
333 /*---------------------------------------------------------------------------*
334  *      L0 -> L1 activate indication from hardware
335  *---------------------------------------------------------------------------*/
336 int
337 i4b_l1_ph_activate_ind(int drv_unit)
338 {
339         register int *tab;
340
341         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
342                 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
343
344         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
345
346         return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
347 }
348
349 /*---------------------------------------------------------------------------*
350  *      L0 -> L1 deactivate indication from hardware
351  *---------------------------------------------------------------------------*/
352 int
353 i4b_l1_ph_deactivate_ind(int drv_unit)
354 {
355         register int *tab;
356         
357         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
358                 panic("i4b_l1_ph_deactivate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
359
360         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);         
361
362         return(PH_Deact_Ind(tab[L0UNIT(drv_unit)]));
363 }
364         
365 /*---------------------------------------------------------------------------*
366  *      L2 -> L1 command to hardware
367  *---------------------------------------------------------------------------*/
368 int
369 i4b_l1_mph_command_req(int unit, int command, void * parm)
370 {
371         register int drv_unit = L0DRVR(l1drvunittab[unit]);
372         register int ch_unit = L0UNIT(l1drvunittab[unit]);
373  
374         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
375
376         if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
377             || l1mux_func[drv_unit]->mph_command_req == NULL)
378                 panic("i4b_l1_mph_command_req: unknown driver type %d\n", drv_unit);
379  
380         return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
381 }
382
383 /*---------------------------------------------------------------------------*
384  *      L2 -> L1 data to be transmitted to hardware
385  *---------------------------------------------------------------------------*/
386 static int
387 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
388 {
389         register int drv_unit = L0DRVR(l1drvunittab[unit]);
390         register int ch_unit = L0UNIT(l1drvunittab[unit]);
391
392 #if 0
393         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
394 #endif
395         
396         if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
397             || l1mux_func[drv_unit]->ph_data_req == NULL)
398                 panic("i4b_l1_ph_data_req: unknown driver type %d\n", drv_unit);
399
400         return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
401 }
402
403 /*---------------------------------------------------------------------------*
404  *      L2 -> L1 activate request to hardware
405  *---------------------------------------------------------------------------*/
406 static int
407 i4b_l1_ph_activate_req(int unit)
408 {
409         register int drv_unit = L0DRVR(l1drvunittab[unit]);
410         register int ch_unit = L0UNIT(l1drvunittab[unit]);
411  
412         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
413
414         if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
415             || l1mux_func[drv_unit]->ph_activate_req == NULL)
416                 panic("i4b_l1_ph_activate_req: unknown driver type %d\n", drv_unit);
417
418         return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));
419 }
420
421 /* EOF */