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