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