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