kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / net / i4b / layer2 / i4b_tei.c
1 /*
2  * Copyright (c) 1997, 2000 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_tei.c - tei handling procedures
28  *      -----------------------------------
29  *
30  *      $Id: i4b_tei.c,v 1.25 2000/09/01 14:11:51 hm Exp $ 
31  *
32  * $FreeBSD: src/sys/i4b/layer2/i4b_tei.c,v 1.6.2.2 2001/08/10 14:08:41 obrien Exp $
33  * $DragonFly: src/sys/net/i4b/layer2/i4b_tei.c,v 1.4 2003/08/07 21:17:29 dillon Exp $
34  *
35  *      last edit-date: [Fri Oct 13 15:56:35 2000]
36  *
37  *---------------------------------------------------------------------------*/
38
39 #ifdef __FreeBSD__
40 #include "use_i4bq921.h"
41 #else
42 #define NI4BQ921        1
43 #endif
44 #if NI4BQ921 > 0
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/syslog.h>
49 #include <sys/mbuf.h>
50 #include <sys/socket.h>
51 #include <net/if.h>
52
53 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
54 #include <sys/callout.h>
55 #endif
56
57 #ifdef __FreeBSD__
58 #include <net/i4b/include/machine/i4b_debug.h>
59 #else
60 #include <i4b/i4b_debug.h>
61 #include <i4b/i4b_ioctl.h>
62 #endif
63
64 #include "../include/i4b_global.h"
65 #include "../include/i4b_l1l2.h"
66 #include "../include/i4b_l2l3.h"
67 #include "../include/i4b_mbuf.h"
68
69 #include "i4b_l2.h"
70 #include "i4b_l2fsm.h"
71
72 /*---------------------------------------------------------------------------*
73  *      handle a received TEI management frame
74  *---------------------------------------------------------------------------*/
75 void
76 i4b_tei_rxframe(int unit, struct mbuf *m)
77 {
78         l2_softc_t *l2sc = &l2_softc[unit];
79         u_char *ptr = m->m_data;
80         
81         switch(*(ptr + OFF_MT))
82         {
83                 case MT_ID_ASSIGN:
84                         if( (*(ptr + OFF_RIL) == l2sc->last_ril) &&
85                             (*(ptr + OFF_RIH) == l2sc->last_rih))
86                         {
87                                 l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI));
88                                 l2sc->tei_valid = TEI_VALID;
89
90                                 if(l2sc->T202 == TIMER_ACTIVE)
91                                         i4b_T202_stop(l2sc);
92
93                                 MDL_Status_Ind(l2sc->unit, STI_TEIASG, l2sc->tei);
94
95                                 log(LOG_INFO, "i4b: unit %d, assigned TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei);
96
97                                 NDBGL2(L2_TEI_MSG, "TEI ID Assign - TEI = %d", l2sc->tei);
98
99                                 i4b_next_l2state(l2sc, EV_MDASGRQ);
100                         }
101                         break;
102                         
103                 case MT_ID_DENY:
104                         if( (*(ptr + OFF_RIL) == l2sc->last_ril) &&
105                             (*(ptr + OFF_RIH) == l2sc->last_rih))
106                         {
107                                 l2sc->tei_valid = TEI_INVALID;
108                                 l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI));
109
110                                 if(l2sc->tei == GROUP_TEI)
111                                 {
112                                         log(LOG_WARNING, "i4b: unit %d, denied TEI, no TEI values available from exchange!\n", l2sc->unit);
113                                         NDBGL2(L2_TEI_ERR, "TEI ID Denied, No TEI values available from exchange!");
114                                 }
115                                 else
116                                 {
117                                         log(LOG_WARNING, "i4b: unit %d, denied TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei);
118                                         NDBGL2(L2_TEI_ERR, "TEI ID Denied - TEI = %d", l2sc->tei);
119                                 }                                       
120                                 MDL_Status_Ind(l2sc->unit, STI_TEIASG, -1);
121                                 i4b_next_l2state(l2sc, EV_MDERRRS);
122                         }
123                         break;
124                         
125                 case MT_ID_CHK_REQ:
126                         if( (l2sc->tei_valid == TEI_VALID) &&
127                             ( (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))) ||
128                               (GROUP_TEI == GET_TEIFROMAI(*(ptr+OFF_AI))) ))
129                         {
130                                 static int lasttei = -1;
131
132                                 if(l2sc->tei != lasttei)
133                                 {
134                                         NDBGL2(L2_TEI_MSG, "TEI ID Check Req - TEI = %d", l2sc->tei);
135                                         lasttei = l2sc->tei;
136                                 }
137                                 
138                                 if(l2sc->T202 == TIMER_ACTIVE)
139                                         i4b_T202_stop(l2sc);
140                                 i4b_tei_chkresp(l2sc);
141                         }
142                         break;
143                         
144                 case MT_ID_REMOVE:
145                         if( (l2sc->tei_valid == TEI_VALID) &&
146                             ( (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))) ||
147                               (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI)))))
148                         {
149                                 l2sc->tei_valid = TEI_INVALID;
150                                 l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI));
151
152                                 log(LOG_INFO, "i4b: unit %d, removed TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei);
153                                 NDBGL2(L2_TEI_MSG, "TEI ID Remove - TEI = %d", l2sc->tei);
154                                 MDL_Status_Ind(l2sc->unit, STI_TEIASG, -1);
155                                 i4b_next_l2state(l2sc, EV_MDREMRQ);
156                         }
157                         break;
158                         
159                 default:
160                         NDBGL2(L2_TEI_ERR, "UNKNOWN TEI MGMT Frame, type = 0x%x", *(ptr + OFF_MT));
161                         i4b_print_frame(m->m_len, m->m_data);
162                         break;
163         }
164         i4b_Dfreembuf(m);
165 }
166
167 /*---------------------------------------------------------------------------*
168  *      allocate and fill up a TEI management frame for sending
169  *---------------------------------------------------------------------------*/
170 static struct mbuf *
171 build_tei_mgmt_frame(l2_softc_t *l2sc, unsigned char type)
172 {
173         struct mbuf *m;
174         
175         if((m = i4b_Dgetmbuf(TEI_MGMT_FRM_LEN)) == NULL)
176                 return(NULL);
177
178         m->m_data[TEIM_SAPIO] = 0xfc;   /* SAPI = 63, CR = 0, EA = 0 */
179         m->m_data[TEIM_TEIO]  = 0xff;   /* TEI = 127, EA = 1 */
180         m->m_data[TEIM_UIO]   = UI;     /* UI */
181         m->m_data[TEIM_MEIO]  = MEI;    /* MEI */
182         m->m_data[TEIM_MTO]   = type;   /* message type */
183         
184         switch(type)
185         {
186                 case MT_ID_REQEST:
187                         i4b_make_rand_ri(l2sc);
188                         m->m_data[TEIM_RILO] = l2sc->last_ril;
189                         m->m_data[TEIM_RIHO] = l2sc->last_rih;
190                         m->m_data[TEIM_AIO] = (GROUP_TEI << 1) | 0x01;
191                         break;
192
193                 case MT_ID_CHK_RSP:
194                         i4b_make_rand_ri(l2sc);
195                         m->m_data[TEIM_RILO] = l2sc->last_ril;
196                         m->m_data[TEIM_RIHO] = l2sc->last_rih;
197                         m->m_data[TEIM_AIO] = (l2sc->tei << 1) | 0x01;
198                         break;
199                         
200                 case MT_ID_VERIFY:
201                         m->m_data[TEIM_RILO] = 0;
202                         m->m_data[TEIM_RIHO] = 0;
203                         m->m_data[TEIM_AIO] = (l2sc->tei << 1) | 0x01;
204                         break;
205
206                 default:
207                         i4b_Dfreembuf(m);
208                         panic("build_tei_mgmt_frame: invalid type");
209                         break;
210         }
211         l2sc->stat.tx_tei++;
212         return(m);
213 }
214
215 /*---------------------------------------------------------------------------*
216  *      i4b_tei_assign - TEI assignment procedure (Q.921, 5.3.2, pp 24)
217  *      T202func and N202 _MUST_ be set prior to calling this function !
218  *---------------------------------------------------------------------------*/
219 void
220 i4b_tei_assign(l2_softc_t *l2sc)
221 {
222         struct mbuf *m;
223
224         NDBGL2(L2_TEI_MSG, "tx TEI ID_Request");
225         
226         m = build_tei_mgmt_frame(l2sc, MT_ID_REQEST);
227
228         if(m == NULL)
229                 panic("i4b_tei_assign: no mbuf");               
230
231         i4b_T202_start(l2sc);
232         
233         PH_Data_Req(l2sc->unit, m, MBUF_FREE);
234 }
235
236 /*---------------------------------------------------------------------------*
237  *      i4b_tei_assign - TEI verify procedure (Q.921, 5.3.5, pp 29)
238  *      T202func and N202 _MUST_ be set prior to calling this function !
239  *---------------------------------------------------------------------------*/
240 void
241 i4b_tei_verify(l2_softc_t *l2sc)
242 {
243         struct mbuf *m;
244
245         NDBGL2(L2_TEI_MSG, "tx TEI ID_Verify");
246
247         m = build_tei_mgmt_frame(l2sc, MT_ID_VERIFY);
248
249         if(m == NULL)
250                 panic("i4b_tei_verify: no mbuf");               
251
252         i4b_T202_start(l2sc);
253         
254         PH_Data_Req(l2sc->unit, m, MBUF_FREE);
255 }
256
257 /*---------------------------------------------------------------------------*
258  *      i4b_tei_chkresp - TEI check response procedure (Q.921, 5.3.5, pp 29)
259  *---------------------------------------------------------------------------*/
260 void
261 i4b_tei_chkresp(l2_softc_t *l2sc)
262 {
263         struct mbuf *m;
264         static int lasttei = 0;
265
266         if(l2sc->tei != lasttei)
267         {
268                 lasttei = l2sc->tei;
269                 NDBGL2(L2_TEI_MSG, "tx TEI ID_Check_Response");
270         }
271
272         m = build_tei_mgmt_frame(l2sc, MT_ID_CHK_RSP);
273
274         if(m == NULL)
275                 panic("i4b_tei_chkresp: no mbuf");              
276
277         PH_Data_Req(l2sc->unit, m, MBUF_FREE);
278 }
279
280 /*---------------------------------------------------------------------------*
281  *      generate some 16 bit "random" number used for TEI mgmt Ri field
282  *---------------------------------------------------------------------------*/
283 void
284 i4b_make_rand_ri(l2_softc_t *l2sc)
285 {
286
287 #if defined(__FreeBSD__)
288
289         u_short val;
290
291 #ifdef RANDOMDEV
292         read_random((char *)&val, sizeof(val));
293 #else
294         val = (u_short)random();
295 #endif /* RANDOMDEV */ 
296
297 #else
298
299         u_short val;
300         int i;
301         static int called = 42;
302         
303         val = (l2sc->last_rih << 8) | l2sc->last_ril;
304
305         val += ++called;
306         
307         for(i=0; i < 50 ; i++, val++)
308         {
309                 val |= l2sc->unit+i;
310                 val <<= i;
311                 val ^= (time.tv_sec >> 16) ^ time.tv_usec;
312                 val <<= i;
313                 val ^= time.tv_sec ^ (time.tv_usec >> 16);
314
315                 if(val != 0 && val != 0xffff)
316                         break;
317         }
318 #endif
319         l2sc->last_rih = (val >> 8) & 0x00ff;
320         l2sc->last_ril = val & 0x00ff;
321 }
322
323 #endif /* NI4BQ921 > 0 */