1f6a4e19cec6ea9f9dae159a1fb9d97fb808a501
[dragonfly.git] / sys / net / i4b / layer2 / i4b_l2.c
1 /*
2  * Copyright (c) 1997, 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_l2.c - ISDN layer 2 (Q.921)
28  *      -------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer2/i4b_l2.c,v 1.6.2.1 2001/08/10 14:08:41 obrien Exp $
31  * $DragonFly: src/sys/net/i4b/layer2/i4b_l2.c,v 1.4 2004/02/13 17:45:50 joerg Exp $
32  *
33  *      last edit-date: [Fri Jan 12 16:43:31 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #if defined(__DragonFly__) || defined(__FreeBSD__)
38 #include "use_i4bq921.h"
39 #else
40 #define NI4BQ921        1
41 #endif
42 #if NI4BQ921 > 0
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <net/if.h>
49
50 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
51 #include <sys/callout.h>
52 #endif
53
54 #if defined(__DragonFly__) || defined(__FreeBSD__)
55 #include <net/i4b/include/machine/i4b_debug.h>
56 #else
57 #include <i4b/i4b_debug.h>
58 #include <i4b/i4b_ioctl.h>
59 #endif
60
61 #include "../include/i4b_l1l2.h"
62 #include "../include/i4b_l2l3.h"
63 #include "../include/i4b_mbuf.h"
64 #include "../include/i4b_global.h"
65
66 #include "i4b_l2.h"
67 #include "i4b_l2fsm.h"
68
69 int i4b_dl_establish_ind(int);
70 int i4b_dl_establish_cnf(int);
71 int i4b_dl_release_ind(int);
72 int i4b_dl_release_cnf(int);
73 int i4b_dl_data_ind(int, struct mbuf *);
74 int i4b_dl_unit_data_ind(int, struct mbuf *);
75
76 static int i4b_mdl_command_req(int, int, void *);
77
78 /* from layer 2 */
79
80 extern int i4b_mdl_status_ind(int, int, int);
81
82 /* this layers debug level */
83
84 unsigned int i4b_l2_debug = L2_DEBUG_DEFAULT;
85
86 struct i4b_l2l3_func i4b_l2l3_func = {
87
88         /* Layer 2 --> Layer 3 */
89         
90         (int (*)(int))                          i4b_dl_establish_ind,
91         (int (*)(int))                          i4b_dl_establish_cnf,
92         (int (*)(int))                          i4b_dl_release_ind,
93         (int (*)(int))                          i4b_dl_release_cnf,
94         (int (*)(int, struct mbuf *))           i4b_dl_data_ind,
95         (int (*)(int, struct mbuf *))           i4b_dl_unit_data_ind,
96
97         /* Layer 3 --> Layer 2 */
98
99         (int (*)(int))                          i4b_dl_establish_req,
100         (int (*)(int))                          i4b_dl_release_req,
101         (int (*)(int, struct mbuf *))           i4b_dl_data_req,
102         (int (*)(int, struct mbuf *))           i4b_dl_unit_data_req,
103
104         /* Layer 2 --> Layer 3 management */
105         
106         (int (*)(int, int, int))                i4b_mdl_status_ind,
107
108         /* Layer 3  --> Layer 2 management */
109         
110         (int (*)(int, int, void *))             i4b_mdl_command_req     
111 };
112
113 /*---------------------------------------------------------------------------*
114  *      DL_ESTABLISH_REQ from layer 3
115  *---------------------------------------------------------------------------*/
116 int i4b_dl_establish_req(int unit)
117 {
118         l2_softc_t *l2sc = &l2_softc[unit];
119         
120         NDBGL2(L2_PRIM, "unit %d",unit);
121         i4b_l1_activate(l2sc);
122         i4b_next_l2state(l2sc, EV_DLESTRQ);
123         return(0);
124 }
125
126 /*---------------------------------------------------------------------------*
127  *      DL_RELEASE_REQ from layer 3
128  *---------------------------------------------------------------------------*/
129 int i4b_dl_release_req(int unit)
130 {
131         l2_softc_t *l2sc = &l2_softc[unit];
132
133         NDBGL2(L2_PRIM, "unit %d",unit);        
134         i4b_next_l2state(l2sc, EV_DLRELRQ);
135         return(0);      
136 }
137
138 /*---------------------------------------------------------------------------*
139  *      DL UNIT DATA REQUEST from Layer 3
140  *---------------------------------------------------------------------------*/
141 int i4b_dl_unit_data_req(int unit, struct mbuf *m)
142 {
143 #ifdef NOTDEF
144         NDBGL2(L2_PRIM, "unit %d",unit);
145 #endif
146         return(0);
147 }
148
149 /*---------------------------------------------------------------------------*
150  *      DL DATA REQUEST from Layer 3
151  *---------------------------------------------------------------------------*/
152 int i4b_dl_data_req(int unit, struct mbuf *m)
153 {
154         l2_softc_t *l2sc = &l2_softc[unit];
155
156 #ifdef NOTDEF
157         NDBGL2(L2_PRIM, "unit %d",unit);
158 #endif
159         switch(l2sc->Q921_state)
160         {
161                 case ST_AW_EST:
162                 case ST_MULTIFR:
163                 case ST_TIMREC:
164                 
165                         if(_IF_QFULL(&l2sc->i_queue))
166                         {
167                                 NDBGL2(L2_ERROR, "i_queue full!!");
168                                 i4b_Dfreembuf(m);
169                         }
170                         else
171                         {
172                                 CRIT_VAR;
173
174                                 CRIT_BEG;
175                                 IF_ENQUEUE(&l2sc->i_queue, m);
176                                 CRIT_END;
177
178                                 i4b_i_frame_queued_up(l2sc);
179                         }
180                         break;
181                         
182                 default:
183                         NDBGL2(L2_ERROR, "unit %d ERROR in state [%s], freeing mbuf", unit, i4b_print_l2state(l2sc));
184                         i4b_Dfreembuf(m);
185                         break;
186         }               
187         return(0);
188 }
189
190 /*---------------------------------------------------------------------------*
191  *      i4b_ph_activate_ind - link activation indication from layer 1
192  *---------------------------------------------------------------------------*/
193 int
194 i4b_ph_activate_ind(int unit)
195 {
196         l2_softc_t *l2sc = &l2_softc[unit];
197
198         NDBGL1(L1_PRIM, "unit %d",unit);
199         l2sc->ph_active = PH_ACTIVE;
200         return(0);
201 }
202
203 /*---------------------------------------------------------------------------*
204  *      i4b_ph_deactivate_ind - link deactivation indication from layer 1
205  *---------------------------------------------------------------------------*/
206 int
207 i4b_ph_deactivate_ind(int unit)
208 {
209         l2_softc_t *l2sc = &l2_softc[unit];
210
211         NDBGL1(L1_PRIM, "unit %d",unit);
212         l2sc->ph_active = PH_INACTIVE;
213         return(0);
214 }
215
216
217 /*---------------------------------------------------------------------------*
218  *      i4b_l2_unit_init - place layer 2 unit into known state
219  *---------------------------------------------------------------------------*/
220 static void
221 i4b_l2_unit_init(int unit)
222 {
223         l2_softc_t *l2sc = &l2_softc[unit];
224         CRIT_VAR;
225
226         CRIT_BEG;
227         l2sc->Q921_state = ST_TEI_UNAS;
228         l2sc->tei_valid = TEI_INVALID;
229         l2sc->vr = 0;
230         l2sc->vs = 0;
231         l2sc->va = 0;
232         l2sc->ack_pend = 0;
233         l2sc->rej_excpt = 0;
234         l2sc->peer_busy = 0;
235         l2sc->own_busy = 0;
236         l2sc->l3initiated = 0;
237
238         l2sc->rxd_CR = 0;
239         l2sc->rxd_PF = 0;
240         l2sc->rxd_NR = 0;
241         l2sc->RC = 0;
242         l2sc->iframe_sent = 0;
243                 
244         l2sc->postfsmfunc = NULL;
245
246         if(l2sc->ua_num != UA_EMPTY)
247         {
248                 i4b_Dfreembuf(l2sc->ua_frame);
249                 l2sc->ua_num = UA_EMPTY;
250                 l2sc->ua_frame = NULL;
251         }
252
253         i4b_T200_stop(l2sc);
254         i4b_T202_stop(l2sc);
255         i4b_T203_stop(l2sc);
256
257         CRIT_END;       
258 }
259
260 /*---------------------------------------------------------------------------*
261  *      i4b_mph_status_ind - status indication upward
262  *---------------------------------------------------------------------------*/
263 int
264 i4b_mph_status_ind(int unit, int status, int parm)
265 {
266         l2_softc_t *l2sc = &l2_softc[unit];
267         CRIT_VAR;
268         int sendup = 1;
269         
270         CRIT_BEG;
271
272         NDBGL1(L1_PRIM, "unit %d, status=%d, parm=%d", unit, status, parm);
273
274         switch(status)
275         {
276                 case STI_ATTACH:
277                         l2sc->unit = unit;
278                         l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN;
279
280 #if defined(__FreeBSD__) && __FreeBSD__ > 4
281                         mtx_init(&l2sc->i_queue.ifq_mtx, "i4b_l2sc", MTX_DEF);
282 #endif
283                         l2sc->ua_frame = NULL;
284                         bzero(&l2sc->stat, sizeof(lapdstat_t));                 
285                         i4b_l2_unit_init(unit);
286                         
287 #if defined(__DragonFly__) || defined(__FreeBSD__)
288                         /* initialize the callout handles for timeout routines */
289                         callout_handle_init(&l2sc->T200_callout);
290                         callout_handle_init(&l2sc->T202_callout);
291                         callout_handle_init(&l2sc->T203_callout);
292                         callout_handle_init(&l2sc->IFQU_callout);
293 #endif
294 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
295                         /* initialize the callout handles for timeout routines */
296                         callout_init(&l2sc->T200_callout);
297                         callout_init(&l2sc->T202_callout);
298                         callout_init(&l2sc->T203_callout);
299                         callout_init(&l2sc->IFQU_callout);
300 #endif
301
302                         break;
303
304                 case STI_L1STAT:        /* state of layer 1 */
305                         break;
306                 
307                 case STI_PDEACT:        /* Timer 4 expired */
308 /*XXX*/                 if((l2sc->Q921_state >= ST_AW_EST) &&
309                            (l2sc->Q921_state <= ST_TIMREC))
310                         {
311                                 NDBGL2(L2_ERROR, "unit %d, persistent deactivation!", unit);
312                                 i4b_l2_unit_init(unit);
313                         }
314                         else
315                         {
316                                 sendup = 0;
317                         }
318                         break;
319
320                 case STI_NOL1ACC:
321                         i4b_l2_unit_init(unit);
322                         NDBGL2(L2_ERROR, "unit %d, cannot access S0 bus!", unit);
323                         break;
324                         
325                 default:
326                         NDBGL2(L2_ERROR, "ERROR, unit %d, unknown status message!", unit);
327                         break;
328         }
329         
330         if(sendup)
331                 MDL_Status_Ind(unit, status, parm);  /* send up to layer 3 */
332
333         CRIT_END;
334         
335         return(0);
336 }
337
338 /*---------------------------------------------------------------------------*
339  *      MDL_COMMAND_REQ from layer 3
340  *---------------------------------------------------------------------------*/
341 int i4b_mdl_command_req(int unit, int command, void * parm)
342 {
343         NDBGL2(L2_PRIM, "unit %d, command=%d, parm=%d", unit, command, (unsigned int)parm);
344
345         switch(command)
346         {
347                 case CMR_DOPEN:
348                         i4b_l2_unit_init(unit);
349                         break;
350         }               
351
352         MPH_Command_Req(unit, command, parm);
353         
354         return(0);
355 }
356
357 /*---------------------------------------------------------------------------*
358  *      i4b_ph_data_ind - process a rx'd frame got from layer 1
359  *---------------------------------------------------------------------------*/
360 int
361 i4b_ph_data_ind(int unit, struct mbuf *m)
362 {
363         l2_softc_t *l2sc = &l2_softc[unit];
364 #ifdef NOTDEF
365         NDBGL1(L1_PRIM, "unit %d", unit);
366 #endif
367         u_char *ptr = m->m_data;
368
369         if ( (*(ptr + OFF_CNTL) & 0x01) == 0 )
370         {
371                 if(m->m_len < 4)        /* 6 oct - 2 chksum oct */
372                 {
373                         l2sc->stat.err_rx_len++;
374                         NDBGL2(L2_ERROR, "ERROR, I-frame < 6 octetts!");
375                         i4b_Dfreembuf(m);
376                         return(0);
377                 }
378                 i4b_rxd_i_frame(unit, m);
379         }
380         else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x01 )
381         {
382                 if(m->m_len < 4)        /* 6 oct - 2 chksum oct */
383                 {
384                         l2sc->stat.err_rx_len++;
385                         NDBGL2(L2_ERROR, "ERROR, S-frame < 6 octetts!");
386                         i4b_Dfreembuf(m);
387                         return(0);
388                 }
389                 i4b_rxd_s_frame(unit, m);
390         }
391         else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x03 )
392         {
393                 if(m->m_len < 3)        /* 5 oct - 2 chksum oct */
394                 {
395                         l2sc->stat.err_rx_len++;
396                         NDBGL2(L2_ERROR, "ERROR, U-frame < 5 octetts!");
397                         i4b_Dfreembuf(m);
398                         return(0);
399                 }
400                 i4b_rxd_u_frame(unit, m);
401         }
402         else
403         {
404                 l2sc->stat.err_rx_badf++;
405                 NDBGL2(L2_ERROR, "ERROR, bad frame rx'd - ");
406                 i4b_print_frame(m->m_len, m->m_data);
407                 i4b_Dfreembuf(m);
408         }
409         return(0);
410 }
411
412 #endif /* NI4BQ921 > 0 */