]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i4b/layer1/i4b_l1dmux.c
Update the iwic driver: fix error handling for rx errors on the D-channel
[FreeBSD/FreeBSD.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  *      i4b_l1dmux.c - isdn4bsd layer 1 driver multiplexer
28  *      --------------------------------------------------
29  *
30  * $FreeBSD$
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 "ifpnp.h"
40 #include "ihfc.h"
41 #include "itjc.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45
46 #include <machine/i4b_debug.h>
47 #include <machine/i4b_ioctl.h>
48 #include <machine/i4b_trace.h>
49
50 #include <i4b/layer1/i4b_l1.h>
51
52 #include <i4b/include/i4b_l1l2.h>
53 #include <i4b/include/i4b_global.h>
54
55 /*
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.
58  *
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.
61  *
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
67  * number.
68  *
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.
74  *
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 ;-)
82  */
83  
84 unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
85
86 #if NISIC > 0
87 static int l1isicunittab[MAXL1UNITS];
88 #endif
89
90 #if NIWIC > 0
91 static int l1iwicunittab[MAXL1UNITS];
92 #endif
93
94 #if NIFPI > 0
95 static int l1ifpiunittab[MAXL1UNITS];
96 #endif
97
98 #if NIHFC > 0
99 static int l1ihfcunittab[MAXL1UNITS];
100 #endif
101
102 #if NIFPNP > 0
103 static int l1ifpnpunittab[MAXL1UNITS];
104 #endif
105
106 #if NITJC > 0
107 static int l1itjcunittab[MAXL1UNITS];
108 #endif
109
110 static int numl1units = 0;
111
112 static int l1drvunittab[MAXL1UNITS];
113 static struct i4b_l1mux_func *l1mux_func[MAXL1DRVR];
114
115 static int i4b_l1_ph_data_req(int, struct mbuf *, int);
116 static int i4b_l1_ph_activate_req(int);
117
118 /* from i4btrc driver i4b_trace.c */
119 int get_trace_data_from_l1(int unit, int what, int len, char *buf);
120
121 /* from layer 2 */
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);
126
127 /* layer 1 lme */
128 int i4b_l1_mph_command_req(int, int, void *);
129
130 /*---------------------------------------------------------------------------*
131  *      jump table: interface function pointers L1/L2 interface 
132  *---------------------------------------------------------------------------*/
133 struct i4b_l1l2_func i4b_l1l2_func = {
134
135         /* Layer 1 --> Layer 2 */
136         
137         (int (*)(int, struct mbuf *))           i4b_ph_data_ind,
138         (int (*)(int))                          i4b_ph_activate_ind,
139         (int (*)(int))                          i4b_ph_deactivate_ind,
140
141         /* Layer 2 --> Layer 1 */
142
143         (int (*)(int, struct mbuf *, int))      i4b_l1_ph_data_req,
144
145         (int (*)(int))                          i4b_l1_ph_activate_req,
146
147         /* Layer 1 --> trace interface driver, ISDN trace data */
148
149         (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
150
151         /* Driver control and status information */
152
153         (int (*)(int, int, int))                i4b_mph_status_ind,
154         (int (*)(int, int, void *))             i4b_l1_mph_command_req,
155 };
156
157 /*---------------------------------------------------------------------------*
158  *      return a pointer to a layer 0 drivers unit tab
159  *---------------------------------------------------------------------------*/
160 static __inline int *
161 getl1tab(int drv)
162 {
163         switch(drv)
164         {
165 #if NISIC > 0
166                 case L1DRVR_ISIC:
167                         return(l1isicunittab);
168                         break;
169 #endif
170 #if NIWIC > 0
171                 case L1DRVR_IWIC:
172                         return(l1iwicunittab);
173                         break;
174 #endif
175 #if NIFPI > 0
176                 case L1DRVR_IFPI:
177                         return(l1ifpiunittab);
178                         break;
179 #endif
180 #if NIHFC > 0
181                 case L1DRVR_IHFC:
182                         return(l1ihfcunittab);
183                         break;
184 #endif
185 #if NIFPNP > 0
186                 case L1DRVR_IFPNP:
187                         return(l1ifpnpunittab);
188                         break;
189 #endif
190 #if NITJC > 0
191                 case L1DRVR_ITJC:
192                         return(l1itjcunittab);
193                         break;
194 #endif
195                 default:
196                         return(NULL);
197                         break;
198         }
199 }
200
201 /*===========================================================================*
202  *      B - Channel (data transfer)
203  *===========================================================================*/
204
205 /*---------------------------------------------------------------------------*
206  *      return the address of ISDN drivers linktab      
207  *---------------------------------------------------------------------------*/
208 isdn_link_t *
209 i4b_l1_ret_linktab(int unit, int channel)
210 {
211         int drv_unit, ch_unit;
212  
213         drv_unit = L0DRVR(l1drvunittab[unit]);
214         ch_unit = L0UNIT(l1drvunittab[unit]);
215  
216         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
217
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);
221
222         return(l1mux_func[drv_unit]->ret_linktab(ch_unit, channel));
223 }
224  
225 /*---------------------------------------------------------------------------*
226  *      set the ISDN driver linktab
227  *---------------------------------------------------------------------------*/
228 void
229 i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
230 {
231         int drv_unit, ch_unit;
232  
233         drv_unit = L0DRVR(l1drvunittab[unit]);
234         ch_unit = L0UNIT(l1drvunittab[unit]);
235  
236         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
237
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);
241
242         l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
243 }
244
245 /*===========================================================================*
246  *      trace D- and B-Channel support
247  *===========================================================================*/
248
249 /*---------------------------------------------------------------------------*
250  *      L0 -> L1 trace information to trace driver
251  *---------------------------------------------------------------------------*/
252 int
253 i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
254 {
255         register int *tab;
256         
257         if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
258                 panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));
259
260         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
261         
262         hdr->unit = tab[L0UNIT(hdr->unit)];
263
264         return(MPH_Trace_Ind(hdr, len, data));
265 }
266
267 /*===========================================================================*
268  *      D - Channel (signalling)
269  *===========================================================================*/
270
271 /*---------------------------------------------------------------------------*
272  *      L0 -> L1 status indication from hardware
273  *---------------------------------------------------------------------------*/
274 int
275 i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
276 {
277         register int *tab;
278         
279         /*
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.
283          */
284
285         if(status == STI_ATTACH)
286         {
287                 if (l1mux_func_p == (struct i4b_l1mux_func *)0)
288                         panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");
289
290                 if(numl1units < MAXL1UNITS)
291                 {
292                         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
293                                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
294                         
295                         tab[L0UNIT(drv_unit)] = numl1units;
296
297                         l1drvunittab[numl1units] = drv_unit;
298
299                         l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;
300
301                         switch(L0DRVR(drv_unit))
302                         {
303 #if NISIC > 0
304                                 case L1DRVR_ISIC:
305                                         printf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
306                                         break;
307 #endif
308 #if NIWIC > 0
309                                 case L1DRVR_IWIC:
310                                         printf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
311                                         break;
312 #endif
313 #if NIFPI > 0
314                                 case L1DRVR_IFPI:
315                                         printf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
316                                         break;
317 #endif
318 #if NIFPNP > 0
319                                 case L1DRVR_IFPNP:
320                                         printf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
321                                         break;
322 #endif
323 #if NIHFC > 0
324                                 case L1DRVR_IHFC:
325                                         printf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
326                                         break;
327 #endif
328 #if NITJC > 0
329                                 case L1DRVR_ITJC:
330                                         printf("itjc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
331                                         break;
332 #endif
333                         }
334                         
335                         NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);
336
337                         numl1units++;                   
338                 }
339         }
340
341         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
342                 panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
343
344         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
345         
346         return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
347 }
348
349 /*---------------------------------------------------------------------------*
350  *      L0 -> L1 data from hardware
351  *---------------------------------------------------------------------------*/
352 int
353 i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
354 {
355         register int *tab;
356
357         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
358                 panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));
359
360 #if 0
361         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
362 #endif
363
364         return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
365 }
366
367 /*---------------------------------------------------------------------------*
368  *      L0 -> L1 activate indication from hardware
369  *---------------------------------------------------------------------------*/
370 int
371 i4b_l1_ph_activate_ind(int drv_unit)
372 {
373         register int *tab;
374
375         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)  
376                 panic("i4b_l1_ph_activate_ind: unknown driver type %d\n", L0DRVR(drv_unit));
377
378         NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
379
380         return(PH_Act_Ind(tab[L0UNIT(drv_unit)]));
381 }
382
383 /*---------------------------------------------------------------------------*
384  *      L0 -> L1 deactivate indication from hardware
385  *---------------------------------------------------------------------------*/
386 int
387 i4b_l1_ph_deactivate_ind(int drv_unit)
388 {
389         register int *tab;
390         
391         if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
392                 panic("i4b_l1_ph_deactivate_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_Deact_Ind(tab[L0UNIT(drv_unit)]));
397 }
398         
399 /*---------------------------------------------------------------------------*
400  *      L2 -> L1 command to hardware
401  *---------------------------------------------------------------------------*/
402 int
403 i4b_l1_mph_command_req(int unit, int command, void * parm)
404 {
405         register int drv_unit = L0DRVR(l1drvunittab[unit]);
406         register int ch_unit = L0UNIT(l1drvunittab[unit]);
407  
408         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
409
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);
413  
414         return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
415 }
416
417 /*---------------------------------------------------------------------------*
418  *      L2 -> L1 data to be transmitted to hardware
419  *---------------------------------------------------------------------------*/
420 int
421 i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
422 {
423         register int drv_unit = L0DRVR(l1drvunittab[unit]);
424         register int ch_unit = L0UNIT(l1drvunittab[unit]);
425
426 #if 0
427         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
428 #endif
429         
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);
433
434         return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
435 }
436
437 /*---------------------------------------------------------------------------*
438  *      L2 -> L1 activate request to hardware
439  *---------------------------------------------------------------------------*/
440 int
441 i4b_l1_ph_activate_req(int unit)
442 {
443         register int drv_unit = L0DRVR(l1drvunittab[unit]);
444         register int ch_unit = L0UNIT(l1drvunittab[unit]);
445  
446         NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
447
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);
451
452         return(l1mux_func[drv_unit]->ph_activate_req(ch_unit));
453 }
454
455 /* EOF */