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