FreeCalypso > hg > fc-tourmaline
comparison src/g23m-gprs/llc/llc_uf.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:4e78acac3d88 | 1:fa8dc04885d8 |
---|---|
1 /* | |
2 +----------------------------------------------------------------------------- | |
3 | Project : | |
4 | Modul : | |
5 +----------------------------------------------------------------------------- | |
6 | Copyright 2002 Texas Instruments Berlin, AG | |
7 | All rights reserved. | |
8 | | |
9 | This file is confidential and a trade secret of Texas | |
10 | Instruments Berlin, AG | |
11 | The receipt of or possession of this file does not convey | |
12 | any rights to reproduce or disclose its contents or to | |
13 | manufacture, use, or sell anything it may describe, in | |
14 | whole, or in part, without the specific written consent of | |
15 | Texas Instruments Berlin, AG. | |
16 +----------------------------------------------------------------------------- | |
17 | Purpose : This modul is part of the entity LLC and implements all | |
18 | procedures and functions as described in the | |
19 | SDL-documentation (U-statemachine) | |
20 +----------------------------------------------------------------------------- | |
21 */ | |
22 | |
23 | |
24 #ifndef LLC_UF_C | |
25 #define LLC_UF_C | |
26 #endif | |
27 | |
28 #define ENTITY_LLC | |
29 | |
30 /*==== INCLUDES =============================================================*/ | |
31 | |
32 #include <string.h> /* to get memcpy() */ | |
33 | |
34 #include "typedefs.h" /* to get Condat data types */ | |
35 #include "vsi.h" /* to get a lot of macros */ | |
36 #include "macdef.h" | |
37 #include "gprs.h" | |
38 #include "gsm.h" /* to get a lot of macros */ | |
39 #include "cnf_llc.h" /* to get cnf-definitions */ | |
40 #include "mon_llc.h" /* to get mon-definitions */ | |
41 #include "prim.h" /* to get the definitions of used SAP and directions */ | |
42 #include "llc.h" /* to get the global entity definitions */ | |
43 | |
44 #include "llc_f.h" /* to get global functions, e.g. llc_init_parameters */ | |
45 #include "llc_uf.h" /* to get local XID definitions */ | |
46 #include "llc_t200s.h" /* to get signal interface to T200 */ | |
47 #include "llc_txs.h" /* to get signal interface to TX */ | |
48 | |
49 /*==== CONST ================================================================*/ | |
50 | |
51 /*==== LOCAL VARS ===========================================================*/ | |
52 | |
53 /*==== PRIVATE FUNCTIONS ====================================================*/ | |
54 | |
55 /*==== PUBLIC FUNCTIONS =====================================================*/ | |
56 | |
57 | |
58 /* | |
59 * CHECK_INSTANCE: | |
60 * v(ariable) - variable name of parameter | |
61 */ | |
62 #define CHECK_INSTANCE(v) \ | |
63 if (llc_data->decoded_xid.##v##.valid) \ | |
64 { \ | |
65 /* \ | |
66 * More than one instance of the same XID parameter type is included. \ | |
67 */ \ | |
68 if (cr_bit EQ SGSN_COMMAND) \ | |
69 { \ | |
70 /* \ | |
71 * XID command: Ignore all instances except the first. \ | |
72 * <R.LLC.XIDNEG_R.A.014> \ | |
73 */ \ | |
74 continue; \ | |
75 } \ | |
76 else /* SGSN_RESPONSE */ \ | |
77 { \ | |
78 /* \ | |
79 * XID response: The XID information field is regarded as invalid. \ | |
80 * <R.LLC.XID_INVA.A.012> \ | |
81 */ \ | |
82 TRACE_0_INFO ("More than one instance of an XID-IE in RSP"); \ | |
83 return FALSE; \ | |
84 } \ | |
85 } | |
86 | |
87 | |
88 /* | |
89 * CHECK_LENGTH_VALUE: | |
90 * l(ength) - default length of parameter | |
91 * c(ondition) - out-of-range value condition | |
92 * v(ariable) - variable name of parameter | |
93 * d(default) - default value of parameter | |
94 */ | |
95 #define CHECK_LENGTH_VALUE(l,c,v,d) \ | |
96 if ((length NEQ l) OR (c)) \ | |
97 { \ | |
98 /* \ | |
99 * Unsupported length or out-of-range values. \ | |
100 */ \ | |
101 if (cr_bit EQ SGSN_COMMAND) \ | |
102 { \ | |
103 /* \ | |
104 * XID command: Set the value for this type according to our \ | |
105 * preferences. \ | |
106 * <R.LLC.XIDNEG_R.A.003> \ | |
107 */ \ | |
108 llc_data->decoded_xid.##v##.valid = TRUE; \ | |
109 llc_data->decoded_xid.##v##.value = d; \ | |
110 break; \ | |
111 } \ | |
112 else /* SGSN_RESPONSE */ \ | |
113 { \ | |
114 /* \ | |
115 * XID response: The XID information field is regarded as invalid. \ | |
116 * <R.LLC.XID_INVA.A.007>, <R.LLC.XID_INVA.A.009> \ | |
117 */ \ | |
118 TRACE_0_INFO ("Unsupported length or out-of-range values in RSP"); \ | |
119 return FALSE; \ | |
120 } \ | |
121 } | |
122 | |
123 | |
124 /* | |
125 * CHECK_SENSE_OF_NEGOTIATION: | |
126 * d(ata) - received data value to check | |
127 * v(ariable) - variable name of parameter | |
128 * s(ense) - sense of negotiation (XID_SENSE_UP / XID_SENSE_DOWN) | |
129 */ | |
130 #define CHECK_SENSE_OF_NEGOTIATION(d,v,s) \ | |
131 { \ | |
132 /* \ | |
133 * XID response must not contain an XID parameter with a value that \ | |
134 * violates the sense of negotiation. \ | |
135 * <R.LLC.XID_INVA.A.008> \ | |
136 */ \ | |
137 if (cr_bit EQ SGSN_RESPONSE) \ | |
138 { \ | |
139 /* \ | |
140 * First compare the value with the requested value, if there is any \ | |
141 */ \ | |
142 if ( (llc_data->u->requested_xid.##v##.valid) AND \ | |
143 (llc_data->u->requested_xid.##v##.value s d) ) \ | |
144 { \ | |
145 TRACE_0_INFO ("Sense of negotiation error"); \ | |
146 return FALSE; \ | |
147 } \ | |
148 else if( !(llc_data->u->requested_xid.##v##.valid) AND \ | |
149 (*(llc_data->##v) s d) ) \ | |
150 { \ | |
151 /* \ | |
152 * If the value was not requested but included in response, compare \ | |
153 * it with the current value \ | |
154 */ \ | |
155 TRACE_0_INFO ("Value not requested, but sense of negotiation error"); \ | |
156 return FALSE; \ | |
157 } \ | |
158 } \ | |
159 } | |
160 | |
161 | |
162 /* | |
163 +------------------------------------------------------------------------------ | |
164 | Function : u_init | |
165 +------------------------------------------------------------------------------ | |
166 | Description : This procedure initialises all necessary variables of u_frames | |
167 | for all SAPIs. | |
168 | | |
169 | Parameters : | |
170 | | |
171 +------------------------------------------------------------------------------ | |
172 */ | |
173 GLOBAL void u_init (void) | |
174 { | |
175 TRACE_FUNCTION( "u_init" ); | |
176 | |
177 /* | |
178 * Initialise every incarnation of U with state TLLI_UNASSIGNED. | |
179 */ | |
180 SWITCH_SERVICE (llc, u, 0); | |
181 INIT_STATE (U_0, U_TLLI_UNASSIGNED); | |
182 | |
183 SWITCH_SERVICE (llc, u, 1); | |
184 INIT_STATE (U_1, U_TLLI_UNASSIGNED); | |
185 | |
186 SWITCH_SERVICE (llc, u, 2); | |
187 INIT_STATE (U_2, U_TLLI_UNASSIGNED); | |
188 | |
189 SWITCH_SERVICE (llc, u, 3); | |
190 INIT_STATE (U_3, U_TLLI_UNASSIGNED); | |
191 | |
192 SWITCH_SERVICE (llc, u, 4); | |
193 INIT_STATE (U_4, U_TLLI_UNASSIGNED); | |
194 | |
195 SWITCH_SERVICE (llc, u, 5); | |
196 INIT_STATE (U_5, U_TLLI_UNASSIGNED); | |
197 | |
198 return; | |
199 } /* u_init() */ | |
200 | |
201 | |
202 | |
203 /* | |
204 +------------------------------------------------------------------------------ | |
205 | Function : u_init_sapi | |
206 +------------------------------------------------------------------------------ | |
207 | Description : This procedure initialises all necessary variables of u_frames | |
208 | for the given SAPI after a TLLI assignment of LLC was occurred. | |
209 | | |
210 | Parameters : | |
211 | | |
212 +------------------------------------------------------------------------------ | |
213 */ | |
214 GLOBAL void u_init_sapi (void) | |
215 { | |
216 TRACE_FUNCTION( "u_init_sapi" ); | |
217 | |
218 /* | |
219 * Initial, no XID command is currently being sent. | |
220 */ | |
221 llc_data->u->xid_pending = FALSE; | |
222 | |
223 llc_data->u->xid_tag = 0L; | |
224 llc_data->u->xid_tag_negotiate = 0L; | |
225 llc_data->u->xid_tag_sent = 0L; | |
226 | |
227 llc_data->u->release_requested = FALSE; | |
228 llc_data->u->ll_xid_resp_pending = FALSE; | |
229 | |
230 return; | |
231 } /* u_init_sapi() */ | |
232 | |
233 /* | |
234 +------------------------------------------------------------------------------ | |
235 | Function : u_build_u_frame | |
236 +------------------------------------------------------------------------------ | |
237 | Description : This procedure fills the given sdu with a correct LLC frame, | |
238 | containing the address field and the control field (U format). | |
239 | The information field is not filled in by this procedure. | |
240 | The checksum field (FCS) is also not filled in by this | |
241 | procedure, it is filled in by the send_pdu service before | |
242 | sending. | |
243 | | |
244 | Parameters : sdu - a valid pointer to an SDU, containing enough octets for | |
245 | the requested command/response | |
246 | cr_bit - C/R bit for the frame | |
247 | sapi - a valid SAPI for unacknowledged operation | |
248 | pf_bit - P/F bit for the U frame | |
249 | command - a valid command/response for the U frame | |
250 | | |
251 +------------------------------------------------------------------------------ | |
252 */ | |
253 GLOBAL void u_build_u_frame | |
254 ( | |
255 #ifdef LL_DESC | |
256 T_desc_list3 *desc_list3, | |
257 #else | |
258 T_sdu *sdu, | |
259 #endif | |
260 T_BIT cr_bit, | |
261 UBYTE sapi, | |
262 T_BIT pf_bit, | |
263 T_COMMAND command | |
264 ) | |
265 { | |
266 #ifdef LL_DESC | |
267 T_desc3 *desc3; | |
268 UBYTE *desc_buf; | |
269 #endif | |
270 | |
271 TRACE_FUNCTION( "u_build_u_frame" ); | |
272 | |
273 #ifdef LL_DESC | |
274 /* | |
275 * Let every frame begin at the beginning. | |
276 */ | |
277 desc3 = (T_desc3*)desc_list3->first; | |
278 desc3->offset = 0; | |
279 desc_buf = (UBYTE*)desc3->buffer; | |
280 | |
281 /* | |
282 * Fill in address and control fields. | |
283 * NOTE: The values of the commands are chosen to correspond with the | |
284 * defined values of the Mx bits in the control field. Therefore the given | |
285 * command can be used to build the header, regardless of its actual value. | |
286 */ | |
287 desc_buf[0] = ((UBYTE)cr_bit << 6) | sapi; | |
288 desc_buf[1] = 0xE0 | ((UBYTE)pf_bit << 4) | (UBYTE)command; | |
289 | |
290 | |
291 /* | |
292 * Determine the length of the frame, depending on the command/ | |
293 * response. | |
294 */ | |
295 switch (command) | |
296 { | |
297 #ifdef REL99 | |
298 case U_NULL: | |
299 /* | |
300 * The NULL command contains no information field. The size | |
301 * of the frame is fixed. (FCS ist not yet considered in l_buf, will | |
302 * be included when FCS is appended to the frame.) | |
303 */ | |
304 desc3->len = U_NULL_SIZE_BITS/8; | |
305 break; | |
306 #endif /* REL99 */ | |
307 case U_DM: | |
308 /* | |
309 * The DM response contains no information field. The size | |
310 * of the frame is fixed. (FCS ist not yet considered in l_buf, will | |
311 * be included when FCS is appended to the frame.) | |
312 */ | |
313 desc3->len = U_DM_SIZE_BITS/8; | |
314 break; | |
315 case U_DISC: | |
316 /* | |
317 * The DISC response contains no information field. The size | |
318 * of the frame is fixed. (FCS ist not yet considered in l_buf, will | |
319 * be included when FCS is appended to the frame.) | |
320 */ | |
321 desc3->len = U_DISC_SIZE_BITS/8; | |
322 break; | |
323 case U_UA: | |
324 /* | |
325 * The UA response may contain an information field. Set only the | |
326 * size of the header (address + control fields). | |
327 */ | |
328 desc3->len = 2; | |
329 break; | |
330 case U_SABM: | |
331 /* | |
332 * The SABM command may contain an information field. Set only the | |
333 * size of the header (address + control fields). | |
334 */ | |
335 desc3->len = 2; | |
336 break; | |
337 case U_FRMR: | |
338 /* | |
339 * The FRMR response contains an information field of fixed size. | |
340 * u_insert_frmr_information() relies on a sane value in l_buf, | |
341 * therefore set only the size of the header (address + control field). | |
342 */ | |
343 desc3->len = 2; | |
344 break; | |
345 case U_XID: | |
346 /* | |
347 * The XID command/response contains an information field. Set only the | |
348 * size of the header (address + control fields). | |
349 */ | |
350 desc3->len = 2; | |
351 break; | |
352 default: | |
353 desc3->len = 0; | |
354 TRACE_ERROR ("Undefined Command specified"); | |
355 break; | |
356 } | |
357 | |
358 desc_list3->list_len = desc3->len; | |
359 | |
360 return; | |
361 | |
362 #else | |
363 /* | |
364 * Let every frame begin at the beginning. | |
365 */ | |
366 sdu->o_buf = 0; | |
367 | |
368 /* | |
369 * Fill in address and control fields. | |
370 * NOTE: The values of the commands are chosen to correspond with the | |
371 * defined values of the Mx bits in the control field. Therefore the given | |
372 * command can be used to build the header, regardless of its actual value. | |
373 */ | |
374 sdu->buf[0] = ((UBYTE)cr_bit << 6) | sapi; | |
375 sdu->buf[1] = 0xE0 | ((UBYTE)pf_bit << 4) | (UBYTE)command; | |
376 | |
377 | |
378 /* | |
379 * Determine the length of the frame, depending on the command/ | |
380 * response. | |
381 */ | |
382 switch (command) | |
383 { | |
384 #ifdef REL99 | |
385 case U_NULL: | |
386 /* | |
387 * The NULL command contains no information field. The size | |
388 * of the frame is fixed. (FCS ist not yet considered in l_buf, will | |
389 * be included when FCS is appended to the frame.) | |
390 */ | |
391 sdu->l_buf = U_NULL_SIZE_BITS; | |
392 break; | |
393 #endif /* REL99 */ | |
394 | |
395 case U_DM: | |
396 /* | |
397 * The DM response contains no information field. The size | |
398 * of the frame is fixed. (FCS ist not yet considered in l_buf, will | |
399 * be included when FCS is appended to the frame.) | |
400 */ | |
401 sdu->l_buf = U_DM_SIZE_BITS; | |
402 break; | |
403 case U_DISC: | |
404 /* | |
405 * The DISC response contains no information field. The size | |
406 * of the frame is fixed. (FCS ist not yet considered in l_buf, will | |
407 * be included when FCS is appended to the frame.) | |
408 */ | |
409 sdu->l_buf = U_DISC_SIZE_BITS; | |
410 break; | |
411 case U_UA: | |
412 /* | |
413 * The UA response may contain an information field. Set only the | |
414 * size of the header (address + control fields). | |
415 */ | |
416 sdu->l_buf = 2*8; | |
417 break; | |
418 case U_SABM: | |
419 /* | |
420 * The SABM command may contain an information field. Set only the | |
421 * size of the header (address + control fields). | |
422 */ | |
423 sdu->l_buf = 2*8; | |
424 break; | |
425 case U_FRMR: | |
426 /* | |
427 * The FRMR response contains an information field of fixed size. | |
428 * u_insert_frmr_information() relies on a sane value in l_buf, | |
429 * therefore set only the size of the header (address + control field). | |
430 */ | |
431 sdu->l_buf = 2*8; | |
432 break; | |
433 case U_XID: | |
434 /* | |
435 * The XID command/response contains an information field. Set only the | |
436 * size of the header (address + control fields). | |
437 */ | |
438 sdu->l_buf = 2*8; | |
439 break; | |
440 default: | |
441 sdu->l_buf = 0; | |
442 TRACE_ERROR ("Undefined Command specified"); | |
443 break; | |
444 } | |
445 | |
446 return; | |
447 #endif /* LL_DESC */ | |
448 } /* u_build_u_frame() */ | |
449 | |
450 | |
451 | |
452 /* | |
453 +------------------------------------------------------------------------------ | |
454 | Function : u_check_xid | |
455 +------------------------------------------------------------------------------ | |
456 | Description : This procedure checks the XID information field that is given | |
457 | in SDU. If it is invalid, rc_xid_valid is set to FALSE, | |
458 | otherwise to TRUE. All XID parameters are decoded and stored | |
459 | in llc_decoded_xid (global variable) if they are valid. The | |
460 | parameters cr_bit and command are necessary to distinguish | |
461 | between the different commands and responses. Each parameter | |
462 | is checked for multiple instances, correct sense of | |
463 | negotiation, and valid field length and value. | |
464 | | |
465 | Parameters : sdu - a valid pointer to an SDU | |
466 | cr_bit - C/R bit of the frame | |
467 | command - command/response of the U frame | |
468 | | |
469 +------------------------------------------------------------------------------ | |
470 */ | |
471 GLOBAL BOOL u_check_xid (T_sdu *sdu, | |
472 T_BIT cr_bit, | |
473 T_COMMAND command) | |
474 { | |
475 UBYTE *par; | |
476 BOOL xl; | |
477 UBYTE type; | |
478 UBYTE length = 0; | |
479 UBYTE *data; | |
480 ULONG value; | |
481 | |
482 | |
483 TRACE_FUNCTION( "u_check_xid" ); | |
484 | |
485 /* | |
486 * Initialise each valid flag to FALSE. | |
487 */ | |
488 llc_data->decoded_xid.version.valid = FALSE; | |
489 llc_data->decoded_xid.iov_ui.valid = FALSE; | |
490 llc_data->decoded_xid.iov_i.valid = FALSE; | |
491 llc_data->decoded_xid.t200.valid = FALSE; | |
492 llc_data->decoded_xid.n200.valid = FALSE; | |
493 llc_data->decoded_xid.n201_u.valid = FALSE; | |
494 llc_data->decoded_xid.n201_i.valid = FALSE; | |
495 llc_data->decoded_xid.md.valid = FALSE; | |
496 llc_data->decoded_xid.mu.valid = FALSE; | |
497 llc_data->decoded_xid.kd.valid = FALSE; | |
498 llc_data->decoded_xid.ku.valid = FALSE; | |
499 llc_data->decoded_xid.reset.valid = FALSE; | |
500 | |
501 llc_data->decoded_l3_xid.valid = FALSE; | |
502 | |
503 /* | |
504 * Initialise par with the first XID parameter. | |
505 * Process each XID parameter until the end of the list is reached: | |
506 * - Check if end of list is reached (max. SDU length). | |
507 * ...process XID parameter (set xl and length)... | |
508 * - Increment par to point to the next XID parameter (is incremented by | |
509 * (data) length plus header length). | |
510 */ | |
511 #ifdef TRACE_EVE | |
512 { | |
513 int i; | |
514 int l = sdu->l_buf/8; | |
515 int o = sdu->o_buf/8; | |
516 | |
517 vsi_o_ttrace(VSI_CALLER TC_EVENT, "XID sdu dump len:%d bytes", l); | |
518 | |
519 for (i=0; i<l; i+=10) | |
520 { | |
521 vsi_o_ttrace(VSI_CALLER TC_EVENT, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x", | |
522 sdu->buf[o+i+0], sdu->buf[o+i+1], | |
523 sdu->buf[o+i+2], sdu->buf[o+i+3], sdu->buf[o+i+4], | |
524 | |
525 sdu->buf[o+i+5], sdu->buf[o+i+6], | |
526 sdu->buf[o+i+7], sdu->buf[o+i+8], sdu->buf[o+i+9]); | |
527 } | |
528 } | |
529 #endif | |
530 | |
531 for (par = &(sdu->buf[sdu->o_buf/8]); | |
532 par < (&(sdu->buf[sdu->o_buf/8]) + sdu->l_buf/8); | |
533 par += length + (xl ? 2 : 1)) | |
534 { | |
535 /* | |
536 * Store XL bit in boolean xl. | |
537 */ | |
538 xl = (*par & 0x80) > 0; | |
539 | |
540 /* | |
541 * Store (data) length, and set data to point to the beginning | |
542 * of the XID parameter data. | |
543 */ | |
544 if (xl) | |
545 { | |
546 /* | |
547 * XL == 1: length is given in 8 bits. | |
548 */ | |
549 length = (*par & 0x03) << 6; | |
550 length += (*(par+1) & 0xFC) >> 2; | |
551 | |
552 data = par + 2; | |
553 } | |
554 else | |
555 { | |
556 /* | |
557 * XL == 0: length is given in 2 bits. | |
558 */ | |
559 length = *par & 0x03; | |
560 | |
561 data = par + 1; | |
562 } | |
563 | |
564 | |
565 if (data + length > &(sdu->buf[sdu->o_buf/8]) + sdu->l_buf/8) | |
566 { | |
567 /* | |
568 * The XID parameter field violates the LLC frame format (exceeds given | |
569 * SDU size). | |
570 * <R.LLC.XID_INVA.A.001> | |
571 */ | |
572 return FALSE; | |
573 } | |
574 | |
575 | |
576 /* | |
577 * Store type field. | |
578 */ | |
579 type = (*par & 0x7C) >> 2; | |
580 | |
581 | |
582 /* | |
583 * Check type and store parameter data, if any. | |
584 */ | |
585 switch (type) | |
586 { | |
587 case XID_VERSION: | |
588 CHECK_INSTANCE (version); | |
589 | |
590 /* | |
591 * XID response must not contain an XID parameter with a value that | |
592 * violates the sense of negotiation. | |
593 * <R.LLC.XID_INVA.A.008> | |
594 */ | |
595 if (cr_bit EQ SGSN_RESPONSE) | |
596 { | |
597 /* | |
598 * First compare the value with the requested value, if there is any | |
599 */ | |
600 if ( (llc_data->u->requested_xid.version.valid) AND | |
601 (llc_data->u->requested_xid.version.value XID_SENSE_DOWN (*data & 0x0F)) ) | |
602 { | |
603 return FALSE; | |
604 } | |
605 else if( !(llc_data->u->requested_xid.version.valid) AND | |
606 llc_data->version XID_SENSE_DOWN (*data & 0x0F) ) | |
607 { | |
608 /* | |
609 * If the value was not requested but included in response, compare | |
610 * it with the current value | |
611 */ | |
612 return FALSE; | |
613 } | |
614 } | |
615 /*lint -e685 Relational operator always evaluates to false*/ | |
616 CHECK_LENGTH_VALUE (XID_VERSION_LEN, | |
617 ((*data & 0x0F) > XID_VERSION_MAX), | |
618 version, llc_data->version); | |
619 /*lint +e685 Relational operator always evaluates to false*/ | |
620 /* | |
621 * Set version as valid and store value. | |
622 */ | |
623 llc_data->decoded_xid.version.valid = TRUE; | |
624 llc_data->decoded_xid.version.value = *data & 0x0F; | |
625 TRACE_1_INFO("XID Version:%d", llc_data->decoded_xid.version.value); | |
626 break; | |
627 case XID_IOV_UI: | |
628 CHECK_INSTANCE (iov_ui); | |
629 | |
630 value = ((ULONG)*data) << 24; | |
631 value += ((ULONG)*(data+1)) << 16; | |
632 value += ((ULONG)*(data+2)) << 8; | |
633 value += *(data+3); | |
634 /*lint -e685 Relational operator always evaluates to false*/ | |
635 CHECK_LENGTH_VALUE (XID_IOV_UI_LEN, | |
636 (value > XID_IOV_UI_MAX), | |
637 iov_ui, llc_data->iov_ui); | |
638 /*lint +e685 Relational operator always evaluates to false*/ | |
639 /* | |
640 * Set iov_ui as valid and store value. | |
641 */ | |
642 llc_data->decoded_xid.iov_ui.valid = TRUE; | |
643 llc_data->decoded_xid.iov_ui.value = value; | |
644 TRACE_1_INFO("XID IOV-UI:0x%.8X", value); | |
645 break; | |
646 case XID_IOV_I: | |
647 if (command EQ U_XID) | |
648 { | |
649 /* | |
650 * IOV-I must not be contained in an XID command/response. | |
651 * <R.LLC.XID_INVA.A.010>, <R.LLC.XID_PAR.A.003> | |
652 */ | |
653 TRACE_0_INFO("IOV-I must not be contained in an XID command/response"); | |
654 return FALSE; | |
655 } | |
656 | |
657 CHECK_INSTANCE (iov_i); | |
658 | |
659 value = ((ULONG)*data) << 24; | |
660 value += ((ULONG)*(data+1)) << 16; | |
661 value += ((ULONG)*(data+2)) << 8; | |
662 value += *(data+3); | |
663 /*lint -e685 Relational operator always evaluates to false*/ | |
664 CHECK_LENGTH_VALUE (XID_IOV_I_LEN, | |
665 (value > XID_IOV_I_MAX), | |
666 iov_i, *(llc_data->iov_i)); | |
667 /*lint +e685 Relational operator always evaluates to false*/ | |
668 /* | |
669 * Set iov_i as valid and store value. | |
670 */ | |
671 llc_data->decoded_xid.iov_i.valid = TRUE; | |
672 llc_data->decoded_xid.iov_i.value = value; | |
673 TRACE_1_INFO("XID IOV-I:0x%.8X", value); | |
674 break; | |
675 case XID_T200: | |
676 CHECK_INSTANCE (t200); | |
677 | |
678 value = ((ULONG)*data) << 8; | |
679 value += *(data+1); | |
680 value &= 0x00000FFFL; | |
681 | |
682 /* | |
683 * XID response must not contain an XID parameter with a value that | |
684 * violates the sense of negotiation. | |
685 * <R.LLC.XID_INVA.A.008> | |
686 */ | |
687 if (cr_bit EQ SGSN_RESPONSE) | |
688 { | |
689 /* | |
690 * First compare the value with the requested value, if there is any | |
691 */ | |
692 if ( (llc_data->u->requested_xid.t200.valid) AND | |
693 (llc_data->u->requested_xid.t200.value XID_SENSE_UP value) ) | |
694 { | |
695 TRACE_1_INFO("Value of T200:%d illegal", value); | |
696 return FALSE; | |
697 } | |
698 else if( !(llc_data->u->requested_xid.t200.valid) AND | |
699 (USHORT)INT2XID(llc_data->t200->length) XID_SENSE_UP value ) | |
700 { | |
701 /* | |
702 * If the value was not requested but included in response, compare | |
703 * it with the current value | |
704 */ | |
705 TRACE_1_INFO("Requested value of T200:%d illegal", value); | |
706 return FALSE; | |
707 } | |
708 } | |
709 | |
710 CHECK_LENGTH_VALUE (XID_T200_LEN, | |
711 ((value < XID_T200_MIN) OR (value > XID_T200_MAX)), | |
712 t200, (USHORT)INT2XID(llc_data->t200->length)); | |
713 | |
714 /* | |
715 * Set t200 as valid and store value. | |
716 */ | |
717 llc_data->decoded_xid.t200.valid = TRUE; | |
718 llc_data->decoded_xid.t200.value = (USHORT)value; | |
719 TRACE_1_INFO("XID T200:%d", llc_data->decoded_xid.t200.value); | |
720 break; | |
721 case XID_N200: | |
722 CHECK_INSTANCE (n200); | |
723 | |
724 CHECK_SENSE_OF_NEGOTIATION ((*data & 0x0F), n200, XID_SENSE_UP); | |
725 /*lint -e685 Relational operator always evaluates to false*/ | |
726 CHECK_LENGTH_VALUE (XID_N200_LEN, | |
727 (((*data & 0x0F) < XID_N200_MIN) OR ((*data & 0x0F) > XID_N200_MAX)), | |
728 n200, *(llc_data->n200)); | |
729 /*lint +e685 Relational operator always evaluates to false*/ | |
730 /* | |
731 * Set n200 as valid and store value. | |
732 */ | |
733 llc_data->decoded_xid.n200.valid = TRUE; | |
734 llc_data->decoded_xid.n200.value = *data & 0x0F; | |
735 TRACE_1_INFO("XID N200:%d", llc_data->decoded_xid.n200.value); | |
736 break; | |
737 case XID_N201_U: | |
738 CHECK_INSTANCE (n201_u); | |
739 | |
740 value = ((ULONG)*data) << 8; | |
741 value += *(data+1); | |
742 value &= 0x000007FFL; | |
743 | |
744 CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, n201_u, XID_SENSE_DOWN); | |
745 | |
746 CHECK_LENGTH_VALUE (XID_N201_U_LEN, | |
747 (((USHORT)value < XID_N201_U_MIN) OR (value > XID_N201_U_MAX)), | |
748 n201_u, *(llc_data->n201_u)); | |
749 | |
750 /* | |
751 * Set n201_u as valid and store value. | |
752 */ | |
753 llc_data->decoded_xid.n201_u.valid = TRUE; | |
754 llc_data->decoded_xid.n201_u.value = (USHORT)value; | |
755 TRACE_1_INFO("XID N201-U:%d", llc_data->decoded_xid.n201_u.value); | |
756 break; | |
757 case XID_N201_I: | |
758 CHECK_INSTANCE (n201_i); | |
759 | |
760 value = ((ULONG)*data) << 8; | |
761 value += *(data+1); | |
762 value &= 0x000007FFL; | |
763 | |
764 CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, n201_i, XID_SENSE_DOWN); | |
765 | |
766 CHECK_LENGTH_VALUE (XID_N201_I_LEN, | |
767 ((value < XID_N201_I_MIN) OR (value > XID_N201_I_MAX)), | |
768 n201_i, *(llc_data->n201_i)); | |
769 | |
770 /* | |
771 * Set n201_i as valid and store value. | |
772 */ | |
773 llc_data->decoded_xid.n201_i.valid = TRUE; | |
774 llc_data->decoded_xid.n201_i.value = (USHORT)value; | |
775 TRACE_1_INFO("XID N201-I:%d", llc_data->decoded_xid.n201_i.value); | |
776 break; | |
777 case XID_MD: | |
778 CHECK_INSTANCE (md); | |
779 | |
780 value = ((ULONG)*data) << 8; | |
781 value += *(data+1); | |
782 value &= 0x00007FFFL; | |
783 | |
784 CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, md, XID_SENSE_DOWN); | |
785 | |
786 CHECK_LENGTH_VALUE (XID_MD_LEN, | |
787 ((value != XID_MD_OFF) AND ((value < XID_MD_MIN) OR (value > XID_MD_MAX))), | |
788 md, *(llc_data->md)); | |
789 | |
790 /* | |
791 * Set md as valid and store value. | |
792 */ | |
793 llc_data->decoded_xid.md.valid = TRUE; | |
794 llc_data->decoded_xid.md.value = (USHORT)value; | |
795 TRACE_1_INFO("XID MD:%d", llc_data->decoded_xid.md.value); | |
796 break; | |
797 case XID_MU: | |
798 CHECK_INSTANCE (mu); | |
799 | |
800 value = ((ULONG)*data) << 8; | |
801 value += *(data+1); | |
802 value &= 0x00007FFFL; | |
803 | |
804 CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, mu, XID_SENSE_DOWN); | |
805 | |
806 CHECK_LENGTH_VALUE (XID_MU_LEN, | |
807 ((value != XID_MU_OFF) AND ((value < XID_MU_MIN) OR (value > XID_MU_MAX))), | |
808 mu, *(llc_data->mu)); | |
809 | |
810 /* | |
811 * Set mu as valid and store value. | |
812 */ | |
813 llc_data->decoded_xid.mu.valid = TRUE; | |
814 llc_data->decoded_xid.mu.value = (USHORT)value; | |
815 TRACE_1_INFO("XID MU:%d", llc_data->decoded_xid.mu.value); | |
816 break; | |
817 case XID_KD: | |
818 CHECK_INSTANCE (kd); | |
819 | |
820 CHECK_SENSE_OF_NEGOTIATION (*data, kd, XID_SENSE_DOWN); | |
821 /*lint -e685 Relational operator always evaluates to false*/ | |
822 CHECK_LENGTH_VALUE (XID_KD_LEN, | |
823 ((*data < XID_KD_MIN) OR (*data > XID_KD_MAX)), | |
824 kd, *(llc_data->kd)); | |
825 /*lint +e685 Relational operator always evaluates to false*/ | |
826 /* | |
827 * Set kd as valid and store value. | |
828 */ | |
829 llc_data->decoded_xid.kd.valid = TRUE; | |
830 llc_data->decoded_xid.kd.value = *data; | |
831 TRACE_1_INFO("XID KD:%d", llc_data->decoded_xid.kd.value); | |
832 break; | |
833 case XID_KU: | |
834 CHECK_INSTANCE (ku); | |
835 | |
836 CHECK_SENSE_OF_NEGOTIATION (*data, ku, XID_SENSE_DOWN); | |
837 /*lint -e685 Relational operator always evaluates to false*/ | |
838 CHECK_LENGTH_VALUE (XID_KU_LEN, | |
839 ((*data < XID_KU_MIN) OR (*data > XID_KU_MAX)), | |
840 ku, *(llc_data->ku)); | |
841 /*lint +e685 Relational operator always evaluates to false*/ | |
842 /* | |
843 * Set ku as valid and store value. | |
844 */ | |
845 llc_data->decoded_xid.ku.valid = TRUE; | |
846 llc_data->decoded_xid.ku.value = *data; | |
847 TRACE_1_INFO("XID KU:%d", llc_data->decoded_xid.ku.value); | |
848 break; | |
849 case XID_LAYER_3: | |
850 if (llc_data->decoded_l3_xid.valid) | |
851 { | |
852 /* | |
853 * More than one instance of the same XID parameter type is included. | |
854 */ | |
855 if (cr_bit EQ SGSN_COMMAND) | |
856 { | |
857 /* | |
858 * XID command: Ignore all instances except the first. | |
859 * <R.LLC.XIDNEG_R.A.014> | |
860 */ | |
861 continue; | |
862 } | |
863 else /* SGSN_RESPONSE */ | |
864 { | |
865 /* | |
866 * XID response: The XID information field is regarded as invalid. | |
867 * <R.LLC.XID_INVA.A.012> | |
868 */ | |
869 TRACE_0_INFO("More than one L3 parameters are included in XID response."); | |
870 return FALSE; | |
871 } | |
872 } | |
873 | |
874 if ((llc_data->current_sapi NEQ LL_SAPI_3) AND | |
875 (llc_data->current_sapi NEQ LL_SAPI_5) AND | |
876 (llc_data->current_sapi NEQ LL_SAPI_9) AND | |
877 (llc_data->current_sapi NEQ LL_SAPI_11)) | |
878 { | |
879 /* | |
880 * Layer-3 parameters on a SAPI different from 3, 5, 9, and 11. | |
881 * <R.LLC.XID_INVA.A.011> | |
882 */ | |
883 TRACE_0_INFO("L3 parameters on a SAPI different from 3, 5, 9, and 11."); | |
884 return FALSE; | |
885 } | |
886 | |
887 /* | |
888 * Set layer_3 as valid and store Layer-3 XID parameters. | |
889 */ | |
890 llc_data->decoded_l3_xid.valid = TRUE; | |
891 llc_data->decoded_l3_xid.length = length; | |
892 memcpy (llc_data->decoded_l3_xid.value, data, length); | |
893 TRACE_1_INFO("XID L3:%d bytes", length); | |
894 break; | |
895 case XID_RESET: | |
896 if (par NEQ &(sdu->buf[sdu->o_buf/8])) | |
897 { | |
898 /* | |
899 * Reset must be the first parameter in the XID information field. | |
900 * <R.LLC.XID_INVA.A.004> | |
901 */ | |
902 TRACE_0_INFO("Reset must be the first XID parameter."); | |
903 return FALSE; | |
904 } | |
905 | |
906 if (cr_bit EQ SGSN_COMMAND) | |
907 { | |
908 if (command EQ U_SABM) | |
909 { | |
910 /* | |
911 * SABM command: Reset is not allowed. | |
912 * <R.LLC.XID_INVA.A.003> | |
913 */ | |
914 TRACE_0_INFO("Reset is not allowed in SABM command"); | |
915 return FALSE; | |
916 } | |
917 } | |
918 else /* SGSN_RESPONSE */ | |
919 { | |
920 /* | |
921 * UA/XID response: Reset is not allowed. | |
922 * <R.LLC.XID_INVA.A.005> | |
923 */ | |
924 TRACE_0_INFO("Reset is not allowed in UA/XID response"); | |
925 return FALSE; | |
926 } | |
927 | |
928 /* | |
929 * Set reset as valid. | |
930 */ | |
931 llc_data->decoded_xid.reset.valid = TRUE; | |
932 TRACE_0_INFO("XID Reset"); | |
933 break; | |
934 default: | |
935 /* | |
936 * Unrecognised type field. | |
937 */ | |
938 if (cr_bit EQ SGSN_COMMAND) | |
939 { | |
940 /* | |
941 * XID command: Skip XID parameter. | |
942 * <R.LLC.XIDNEG_R.A.002> | |
943 */ | |
944 continue; | |
945 } | |
946 else /* SGSN_RESPONSE */ | |
947 { | |
948 /* | |
949 * XID response: The XID information field is regarded as invalid. | |
950 * <R.LLC.XID_INVA.A.006> | |
951 */ | |
952 TRACE_0_INFO("Unrecognised type field in XID response."); | |
953 return FALSE; | |
954 } | |
955 } | |
956 } | |
957 | |
958 /* | |
959 * All XID parameters have been processed, XID information field seems | |
960 * to be correct. | |
961 */ | |
962 return TRUE; | |
963 } /* u_check_xid() */ | |
964 | |
965 | |
966 | |
967 /* | |
968 +------------------------------------------------------------------------------ | |
969 | Function : u_eval_xid | |
970 +------------------------------------------------------------------------------ | |
971 | Description : This procedure evaluates the decoded XID information field in | |
972 | llc_decoded_xid (global variable). If Reset is present, the | |
973 | state of every incarnation in ABM is set to ADM (including | |
974 | the current incarnation!), all LLC layer parameters are set | |
975 | to their default values, the OCs for unack. transfer are set | |
976 | to 0, and the parameter reset_received is set to TRUE. If a | |
977 | command has been received (cr_bit is set to SGSN_COMMAND), | |
978 | all XID parameters are evaluated and stored as global values, | |
979 | if acceptable. Each XID parameter is tagged in llc_xid_tag | |
980 | for the next response. Otherwise (a response has been | |
981 | received), store the received parameters as global values | |
982 | and reset their valid flags in llc_requested_xid. In each | |
983 | case, if N201-I or N201-U have been changed, or if Layer-3 | |
984 | XID parameters have been received, set xid_ind to TRUE, | |
985 | otherwise to FALSE. Additionally remove any received parameter | |
986 | in llc_xid_negotiate, because it has been explicitly | |
987 | negotiated by the peer. | |
988 | | |
989 | Parameters : cr_bit - SGSN_COMMAND/_RESPONSE has been received | |
990 | reset_received - TRUE indicates received Reset parameter, | |
991 | else FALSE | |
992 | xid_ind - TRUE indicates changed N201-U and/or N201-I, | |
993 | so that LL_XID_IND must be sent to layer 3 | |
994 | | |
995 +------------------------------------------------------------------------------ | |
996 */ | |
997 GLOBAL void u_eval_xid (T_BIT cr_bit, | |
998 BOOL *reset_received, | |
999 BOOL *xid_ind) | |
1000 { | |
1001 UBYTE incarnation; | |
1002 | |
1003 | |
1004 TRACE_FUNCTION ("u_eval_xid"); | |
1005 | |
1006 /* | |
1007 * Preset both indicators with default values. | |
1008 */ | |
1009 *reset_received = FALSE; | |
1010 *xid_ind = FALSE; | |
1011 | |
1012 /* | |
1013 * Preset global XID indicator for next response. | |
1014 */ | |
1015 llc_data->u->xid_tag = 0L; | |
1016 | |
1017 | |
1018 /************************************************************************** | |
1019 * Reset: | |
1020 * Has to be processed first in order to take effect! | |
1021 */ | |
1022 if (llc_data->decoded_xid.reset.valid) | |
1023 { | |
1024 /* | |
1025 * Initialise all LLC layer parameters for all SAPIs. | |
1026 */ | |
1027 llc_init_parameters(); | |
1028 llc_init_requested_xid(); | |
1029 | |
1030 /* | |
1031 * Reset all incarnations of service U that are in state 'ABM' to 'ADM'. | |
1032 */ | |
1033 for (incarnation = 0; incarnation < U_NUM_INC; incarnation++) | |
1034 { | |
1035 llc_data->u_base[incarnation].state = U_ADM; | |
1036 } | |
1037 | |
1038 /* | |
1039 * LLC has to be reset. Send SIG_U_LLME_RESET_IND. | |
1040 */ | |
1041 *reset_received = TRUE; | |
1042 } | |
1043 | |
1044 | |
1045 /************************************************************************** | |
1046 * Version: | |
1047 * Shall not be negotiated while in state 'ABM'. | |
1048 * <R.LLC.XID_PAR.A.001> | |
1049 */ | |
1050 if ((llc_data->decoded_xid.version.valid) AND (GET_STATE(U) NEQ U_ABM)) | |
1051 { | |
1052 if (cr_bit EQ SGSN_COMMAND) | |
1053 { | |
1054 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_VERSION, | |
1055 llc_data->decoded_xid.version.value)) | |
1056 { | |
1057 llc_data->version = llc_data->decoded_xid.version.value; | |
1058 } | |
1059 else /* value is not acceptable */ | |
1060 { | |
1061 /* | |
1062 * Sense of negotiation down: offer lower value; sense of | |
1063 * negotiation up: offer higher value. | |
1064 * This happens automatically by just responding with our current | |
1065 * global value. | |
1066 */ | |
1067 } | |
1068 | |
1069 /* | |
1070 * Tag parameter for next response. | |
1071 */ | |
1072 llc_data->u->xid_tag |= 0x00000001L << XID_VERSION; | |
1073 } | |
1074 else /* SGSN_RESPONSE */ | |
1075 { | |
1076 /* | |
1077 * Sense of negotiation-correctness of response has already been checked | |
1078 * in u_check_xid(). | |
1079 */ | |
1080 llc_data->version = llc_data->decoded_xid.version.value; | |
1081 } | |
1082 | |
1083 /* | |
1084 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1085 * explicitly negotiated by the peer. | |
1086 * <R.LLC.XIDNEG_R.A.015> | |
1087 */ | |
1088 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_VERSION); | |
1089 } | |
1090 | |
1091 | |
1092 /************************************************************************** | |
1093 * IOV-UI: | |
1094 * Shall only be negotiated in state 'ADM'. <R.LLC.XID_PAR.A.002> | |
1095 */ | |
1096 if ((llc_data->decoded_xid.iov_ui.valid) AND (GET_STATE(U) NEQ U_ABM) ) | |
1097 { | |
1098 /* | |
1099 * Do not tag iov_ui for the XID response, because it shall only be | |
1100 * transmitted in downlink direction. | |
1101 * <R.LLC.XID_PAR.A.004> | |
1102 */ | |
1103 | |
1104 /* | |
1105 * Copy value to global variable (no sense of negotiation). | |
1106 */ | |
1107 llc_data->iov_ui = llc_data->decoded_xid.iov_ui.value; | |
1108 } | |
1109 | |
1110 | |
1111 /************************************************************************** | |
1112 * IOV-I: | |
1113 * Shall only be negotiated with SABM and UA frames. This is already | |
1114 * checked in u_check_xid(). | |
1115 * <R.LLC.XID_PAR.A.003>, <R.LLC.XID_INVA.A.010> | |
1116 */ | |
1117 if (llc_data->decoded_xid.iov_i.valid) | |
1118 { | |
1119 /* | |
1120 * Do not tag iov_i for the XID response, because it shall only be | |
1121 * transmitted in downlink direction. | |
1122 * <R.LLC.XID_PAR.A.004> | |
1123 */ | |
1124 | |
1125 /* | |
1126 * Copy value to global variable (no sense of negotiation). | |
1127 */ | |
1128 *(llc_data->iov_i) = llc_data->decoded_xid.iov_i.value; | |
1129 } | |
1130 | |
1131 | |
1132 /************************************************************************** | |
1133 * T200 (and T201): | |
1134 * Can be negotiated in state 'ADM' and 'ABM'. New values shall only apply | |
1135 * to timers set after the negotiation has been completed (which is | |
1136 * accomplished automatically). | |
1137 * <R.LLC.XID_PAR.A.006>, <R.LLC.XID_PAR.A.007> | |
1138 */ | |
1139 if (llc_data->decoded_xid.t200.valid) | |
1140 { | |
1141 if (cr_bit EQ SGSN_COMMAND) | |
1142 { | |
1143 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_T200, | |
1144 llc_data->decoded_xid.t200.value)) | |
1145 { | |
1146 llc_data->t200->length = XID2INT (llc_data->decoded_xid.t200.value); | |
1147 } | |
1148 else /* value is not acceptable */ | |
1149 { | |
1150 /* | |
1151 * Sense of negotiation down: offer lower value; sense of | |
1152 * negotiation up: offer higher value. | |
1153 * This happens automatically by just responding with our current | |
1154 * global value. | |
1155 */ | |
1156 } | |
1157 | |
1158 /* | |
1159 * In case we also want to negotiate this value, but to a lower! | |
1160 * value, delete this parameter from the requested XID structure | |
1161 */ | |
1162 if (llc_data->u->requested_xid.t200.valid AND | |
1163 llc_data->u->requested_xid.t200.value <= llc_data->decoded_xid.t200.value) | |
1164 { | |
1165 llc_data->u->requested_xid.t200.valid = FALSE; | |
1166 } | |
1167 | |
1168 /* | |
1169 * Tag parameter for next response. | |
1170 */ | |
1171 llc_data->u->xid_tag |= 0x00000001L << XID_T200; | |
1172 } | |
1173 else /* SGSN_RESPONSE */ | |
1174 { | |
1175 /* | |
1176 * Sense of negotiation-correctness of response has already been checked | |
1177 * in u_check_xid(). | |
1178 */ | |
1179 llc_data->t200->length = XID2INT (llc_data->decoded_xid.t200.value); | |
1180 } | |
1181 | |
1182 /* | |
1183 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1184 * explicitly negotiated by the peer. | |
1185 * <R.LLC.XIDNEG_R.A.015> | |
1186 */ | |
1187 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_T200); | |
1188 } | |
1189 | |
1190 | |
1191 /************************************************************************** | |
1192 * N200: | |
1193 * Can be negotiated in state 'ADM' and 'ABM'. | |
1194 * <R.LLC.XID_PAR.A.006> | |
1195 */ | |
1196 if (llc_data->decoded_xid.n200.valid) | |
1197 { | |
1198 if (cr_bit EQ SGSN_COMMAND) | |
1199 { | |
1200 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_N200, | |
1201 llc_data->decoded_xid.n200.value)) | |
1202 { | |
1203 *(llc_data->n200) = llc_data->decoded_xid.n200.value; | |
1204 } | |
1205 else /* value is not acceptable */ | |
1206 { | |
1207 /* | |
1208 * Sense of negotiation down: offer lower value; sense of | |
1209 * negotiation up: offer higher value. | |
1210 * This happens automatically by just responding with our current | |
1211 * global value. | |
1212 */ | |
1213 } | |
1214 | |
1215 /* | |
1216 * In case we also want to negotiate this value, but to a lower! | |
1217 * value, delete this parameter from the requested XID structure | |
1218 */ | |
1219 if (llc_data->u->requested_xid.n200.valid AND | |
1220 llc_data->u->requested_xid.n200.value <= llc_data->decoded_xid.n200.value) | |
1221 { | |
1222 llc_data->u->requested_xid.n200.valid = FALSE; | |
1223 } | |
1224 | |
1225 /* | |
1226 * Tag parameter for next response. | |
1227 */ | |
1228 llc_data->u->xid_tag |= 0x00000001L << XID_N200; | |
1229 } | |
1230 else /* SGSN_RESPONSE */ | |
1231 { | |
1232 /* | |
1233 * Sense of negotiation-correctness of response has already been checked | |
1234 * in u_check_xid(). | |
1235 */ | |
1236 *(llc_data->n200) = llc_data->decoded_xid.n200.value; | |
1237 } | |
1238 | |
1239 /* | |
1240 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1241 * explicitly negotiated by the peer. | |
1242 * <R.LLC.XIDNEG_R.A.015> | |
1243 */ | |
1244 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_N200); | |
1245 } | |
1246 | |
1247 | |
1248 /************************************************************************** | |
1249 * N201-U: | |
1250 * Can be negotiated in state 'ADM' and 'ABM'. If N201-U is negotiated to a | |
1251 * lower value than previously used, then any queued or new U and UI frames | |
1252 * that violate the new value of N201-U should be discarded and not | |
1253 * transmitted. | |
1254 * <R.LLC.XID_PAR.A.006>, <R.LLC.XID_PAR.A.010> | |
1255 */ | |
1256 if (llc_data->decoded_xid.n201_u.valid) | |
1257 { | |
1258 if (cr_bit EQ SGSN_COMMAND) | |
1259 { | |
1260 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U, | |
1261 llc_data->decoded_xid.n201_u.value)) | |
1262 { | |
1263 if (llc_data->decoded_xid.n201_u.value NEQ *(llc_data->n201_u)) | |
1264 { | |
1265 *(llc_data->n201_u) = llc_data->decoded_xid.n201_u.value; | |
1266 | |
1267 /* | |
1268 * LL_XID_IND has to be sent to layer 3. | |
1269 */ | |
1270 *xid_ind = TRUE; | |
1271 } | |
1272 } | |
1273 else /* value is not acceptable */ | |
1274 { | |
1275 /* | |
1276 * Sense of negotiation down: offer lower value; sense of | |
1277 * negotiation up: offer higher value. | |
1278 * This happens automatically by just responding with our current | |
1279 * global value. | |
1280 */ | |
1281 } | |
1282 | |
1283 /* | |
1284 * In case we also want to negotiate this value, but to a higher | |
1285 * value, delete this parameter from the requested XID structure | |
1286 */ | |
1287 if (llc_data->u->requested_xid.n201_u.valid AND | |
1288 llc_data->u->requested_xid.n201_u.value >= llc_data->decoded_xid.n201_u.value) | |
1289 { | |
1290 llc_data->u->requested_xid.n201_u.valid = FALSE; | |
1291 } | |
1292 | |
1293 /* | |
1294 * Tag parameter for next response. | |
1295 */ | |
1296 llc_data->u->xid_tag |= 0x00000001L << XID_N201_U; | |
1297 } | |
1298 else /* SGSN_RESPONSE */ | |
1299 { | |
1300 if (llc_data->decoded_xid.n201_u.value NEQ *(llc_data->n201_u)) | |
1301 { | |
1302 /* | |
1303 * Sense of negotiation-correctness of response has already been checked | |
1304 * in u_check_xid(). | |
1305 */ | |
1306 *(llc_data->n201_u) = llc_data->decoded_xid.n201_u.value; | |
1307 | |
1308 /* | |
1309 * LL_XID_IND has to be sent to layer 3. | |
1310 */ | |
1311 *xid_ind = TRUE; | |
1312 } | |
1313 } | |
1314 | |
1315 /* | |
1316 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1317 * explicitly negotiated by the peer. | |
1318 * <R.LLC.XIDNEG_R.A.015> | |
1319 */ | |
1320 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_N201_U); | |
1321 } | |
1322 | |
1323 | |
1324 /************************************************************************** | |
1325 * N201-I: | |
1326 * N201-I can be negotiated to any value in state 'ADM'. It can only be | |
1327 * negotiated to the same or higher value as previously used in state 'ABM'. | |
1328 * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009> | |
1329 */ | |
1330 if (llc_data->decoded_xid.n201_i.valid) | |
1331 { | |
1332 if (cr_bit EQ SGSN_COMMAND) | |
1333 { | |
1334 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I, | |
1335 llc_data->decoded_xid.n201_i.value)) | |
1336 { | |
1337 if (((GET_STATE (U) EQ U_ABM) AND | |
1338 (llc_data->decoded_xid.n201_i.value > *(llc_data->n201_i))) | |
1339 OR /* state 'ADM' */ | |
1340 (llc_data->decoded_xid.n201_i.value NEQ *(llc_data->n201_i))) | |
1341 { | |
1342 *(llc_data->n201_i) = llc_data->decoded_xid.n201_i.value; | |
1343 | |
1344 /* | |
1345 * LL_XID_IND has to be sent to layer 3. | |
1346 */ | |
1347 *xid_ind = TRUE; | |
1348 } | |
1349 } | |
1350 else /* value is not acceptable */ | |
1351 { | |
1352 /* | |
1353 * Sense of negotiation down: offer lower value; sense of | |
1354 * negotiation up: offer higher value. | |
1355 * This happens automatically by just responding with our current | |
1356 * global value. | |
1357 */ | |
1358 } | |
1359 | |
1360 /* | |
1361 * In case we also want to negotiate this value, but to a higher | |
1362 * value, delete this parameter from the requested XID structure | |
1363 */ | |
1364 | |
1365 if (llc_data->u->requested_xid.n201_i.valid AND | |
1366 llc_data->u->requested_xid.n201_i.value >= llc_data->decoded_xid.n201_i.value) | |
1367 { | |
1368 llc_data->u->requested_xid.n201_i.valid = FALSE; | |
1369 } | |
1370 | |
1371 /* | |
1372 * Tag parameter for next response. | |
1373 */ | |
1374 llc_data->u->xid_tag |= 0x00000001L << XID_N201_I; | |
1375 } | |
1376 else /* SGSN_RESPONSE */ | |
1377 { | |
1378 /* | |
1379 * Sense of negotiation-correctness of response has already been checked | |
1380 * in u_check_xid(). | |
1381 */ | |
1382 if (((GET_STATE (U) EQ U_ABM) AND | |
1383 (llc_data->decoded_xid.n201_i.value > *(llc_data->n201_i))) | |
1384 OR /* state 'ADM' */ | |
1385 (llc_data->decoded_xid.n201_i.value NEQ *(llc_data->n201_i))) | |
1386 { | |
1387 *(llc_data->n201_i) = llc_data->decoded_xid.n201_i.value; | |
1388 | |
1389 /* | |
1390 * LL_XID_IND has to be sent to layer 3. | |
1391 */ | |
1392 *xid_ind = TRUE; | |
1393 } | |
1394 } | |
1395 | |
1396 /* | |
1397 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1398 * explicitly negotiated by the peer. | |
1399 * <R.LLC.XIDNEG_R.A.015> | |
1400 */ | |
1401 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_N201_I); | |
1402 } | |
1403 | |
1404 | |
1405 /************************************************************************** | |
1406 * mD: | |
1407 * mD can be negotiated to any value in state 'ADM'. It can only be | |
1408 * negotiated to the same or higher value as previously used in state 'ABM'. | |
1409 * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009> | |
1410 */ | |
1411 if (llc_data->decoded_xid.md.valid) | |
1412 { | |
1413 if (cr_bit EQ SGSN_COMMAND) | |
1414 { | |
1415 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_MD, | |
1416 llc_data->decoded_xid.md.value)) | |
1417 { | |
1418 if (((GET_STATE (U) EQ U_ABM) AND | |
1419 (llc_data->decoded_xid.md.value > *(llc_data->md))) | |
1420 OR /* state 'ADM' */ | |
1421 (llc_data->decoded_xid.md.value NEQ *(llc_data->md))) | |
1422 { | |
1423 *(llc_data->md) = llc_data->decoded_xid.md.value; | |
1424 } | |
1425 } | |
1426 else /* value is not acceptable */ | |
1427 { | |
1428 /* | |
1429 * Sense of negotiation down: offer lower value; sense of | |
1430 * negotiation up: offer higher value. | |
1431 * This happens automatically by just responding with our current | |
1432 * global value. | |
1433 */ | |
1434 } | |
1435 | |
1436 /* | |
1437 * In case we also want to negotiate this value, but to a higher | |
1438 * value, delete this parameter from the requested XID structure | |
1439 */ | |
1440 if (llc_data->u->requested_xid.md.valid AND | |
1441 llc_data->u->requested_xid.md.value >= llc_data->decoded_xid.md.value) | |
1442 { | |
1443 llc_data->u->requested_xid.md.valid = FALSE; | |
1444 } | |
1445 | |
1446 /* | |
1447 * Tag parameter for next response. | |
1448 */ | |
1449 llc_data->u->xid_tag |= 0x00000001L << XID_MD; | |
1450 } | |
1451 else /* SGSN_RESPONSE */ | |
1452 { | |
1453 /* | |
1454 * Sense of negotiation-correctness of response has already been checked | |
1455 * in u_check_xid(). | |
1456 */ | |
1457 if (((GET_STATE (U) EQ U_ABM) AND | |
1458 (llc_data->decoded_xid.md.value > *(llc_data->md))) | |
1459 OR /* state 'ADM' */ | |
1460 (llc_data->decoded_xid.md.value NEQ *(llc_data->md))) | |
1461 { | |
1462 *(llc_data->md) = llc_data->decoded_xid.md.value; | |
1463 } | |
1464 } | |
1465 | |
1466 /* | |
1467 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1468 * explicitly negotiated by the peer. | |
1469 * <R.LLC.XIDNEG_R.A.015> | |
1470 */ | |
1471 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_MD); | |
1472 } | |
1473 | |
1474 | |
1475 /************************************************************************** | |
1476 * mU: | |
1477 * mU can be negotiated to any value in state 'ADM'. It can only be | |
1478 * negotiated to the same or higher value as previously used in state 'ABM'. | |
1479 * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009> | |
1480 */ | |
1481 if (llc_data->decoded_xid.mu.valid) | |
1482 { | |
1483 if (cr_bit EQ SGSN_COMMAND) | |
1484 { | |
1485 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_MU, | |
1486 llc_data->decoded_xid.mu.value)) | |
1487 { | |
1488 if (((GET_STATE (U) EQ U_ABM) AND | |
1489 (llc_data->decoded_xid.mu.value > *(llc_data->mu))) | |
1490 OR /* state 'ADM' */ | |
1491 (llc_data->decoded_xid.mu.value NEQ *(llc_data->mu))) | |
1492 { | |
1493 *(llc_data->mu) = llc_data->decoded_xid.mu.value; | |
1494 } | |
1495 } | |
1496 else /* value is not acceptable */ | |
1497 { | |
1498 /* | |
1499 * Sense of negotiation down: offer lower value; sense of | |
1500 * negotiation up: offer higher value. | |
1501 * This happens automatically by just responding with our current | |
1502 * global value. | |
1503 */ | |
1504 } | |
1505 | |
1506 /* | |
1507 * In case we also want to negotiate this value, but to a higher | |
1508 * value, delete this parameter from the requested XID structure | |
1509 */ | |
1510 if (llc_data->u->requested_xid.mu.valid AND | |
1511 llc_data->u->requested_xid.mu.value >= llc_data->decoded_xid.mu.value) | |
1512 { | |
1513 llc_data->u->requested_xid.mu.valid = FALSE; | |
1514 } | |
1515 | |
1516 /* | |
1517 * Tag parameter for next response. | |
1518 */ | |
1519 llc_data->u->xid_tag |= 0x00000001L << XID_MU; | |
1520 } | |
1521 else /* SGSN_RESPONSE */ | |
1522 { | |
1523 /* | |
1524 * Sense of negotiation-correctness of response has already been checked | |
1525 * in u_check_xid(). | |
1526 */ | |
1527 if (((GET_STATE (U) EQ U_ABM) AND | |
1528 (llc_data->decoded_xid.mu.value > *(llc_data->mu))) | |
1529 OR /* state 'ADM' */ | |
1530 (llc_data->decoded_xid.mu.value NEQ *(llc_data->mu))) | |
1531 { | |
1532 *(llc_data->mu) = llc_data->decoded_xid.mu.value; | |
1533 } | |
1534 } | |
1535 | |
1536 /* | |
1537 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1538 * explicitly negotiated by the peer. | |
1539 * <R.LLC.XIDNEG_R.A.015> | |
1540 */ | |
1541 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_MU); | |
1542 } | |
1543 | |
1544 | |
1545 /************************************************************************** | |
1546 * kD: | |
1547 * kD can be negotiated to any value in state 'ADM'. It can only be | |
1548 * negotiated to the same or higher value as previously used in state 'ABM'. | |
1549 * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009> | |
1550 */ | |
1551 if (llc_data->decoded_xid.kd.valid) | |
1552 { | |
1553 if (cr_bit EQ SGSN_COMMAND) | |
1554 { | |
1555 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_KD, | |
1556 llc_data->decoded_xid.kd.value)) | |
1557 { | |
1558 if (((GET_STATE (U) EQ U_ABM) AND | |
1559 (llc_data->decoded_xid.kd.value > *(llc_data->kd))) | |
1560 OR /* state 'ADM' */ | |
1561 (llc_data->decoded_xid.kd.value NEQ *(llc_data->kd))) | |
1562 { | |
1563 *(llc_data->kd) = llc_data->decoded_xid.kd.value; | |
1564 } | |
1565 } | |
1566 else /* value is not acceptable */ | |
1567 { | |
1568 /* | |
1569 * Sense of negotiation down: offer lower value; sense of | |
1570 * negotiation up: offer higher value. | |
1571 * This happens automatically by just responding with our current | |
1572 * global value. | |
1573 */ | |
1574 } | |
1575 | |
1576 /* | |
1577 * In case we also want to negotiate this value, but to a higher | |
1578 * value, delete this parameter from the requested XID structure | |
1579 */ | |
1580 if (llc_data->u->requested_xid.kd.valid AND | |
1581 llc_data->u->requested_xid.kd.value >= llc_data->decoded_xid.kd.value) | |
1582 { | |
1583 llc_data->u->requested_xid.kd.valid = FALSE; | |
1584 } | |
1585 | |
1586 /* | |
1587 * Tag parameter for next response. | |
1588 */ | |
1589 llc_data->u->xid_tag |= 0x00000001L << XID_KD; | |
1590 } | |
1591 else /* SGSN_RESPONSE */ | |
1592 { | |
1593 /* | |
1594 * Sense of negotiation-correctness of response has already been checked | |
1595 * in u_check_xid(). | |
1596 */ | |
1597 if (((GET_STATE (U) EQ U_ABM) AND | |
1598 (llc_data->decoded_xid.kd.value > *(llc_data->kd))) | |
1599 OR /* state 'ADM' */ | |
1600 (llc_data->decoded_xid.kd.value NEQ *(llc_data->kd))) | |
1601 { | |
1602 *(llc_data->kd) = llc_data->decoded_xid.kd.value; | |
1603 } | |
1604 } | |
1605 | |
1606 /* | |
1607 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1608 * explicitly negotiated by the peer. | |
1609 * <R.LLC.XIDNEG_R.A.015> | |
1610 */ | |
1611 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_KD); | |
1612 } | |
1613 | |
1614 | |
1615 /************************************************************************** | |
1616 * kU: | |
1617 * kU can be negotiated to any value in state 'ADM'. It can only be | |
1618 * negotiated to the same or higher value as previously used in state 'ABM'. | |
1619 * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009> | |
1620 */ | |
1621 if (llc_data->decoded_xid.ku.valid) | |
1622 { | |
1623 if (cr_bit EQ SGSN_COMMAND) | |
1624 { | |
1625 if (llc_xid_value_acceptable (llc_data->current_sapi, XID_KU, | |
1626 llc_data->decoded_xid.ku.value)) | |
1627 { | |
1628 if (((GET_STATE (U) EQ U_ABM) AND | |
1629 (llc_data->decoded_xid.ku.value > *(llc_data->ku))) | |
1630 OR /* state 'ADM' */ | |
1631 (llc_data->decoded_xid.ku.value NEQ *(llc_data->ku))) | |
1632 { | |
1633 *(llc_data->ku) = llc_data->decoded_xid.ku.value; | |
1634 } | |
1635 } | |
1636 else /* value is not acceptable */ | |
1637 { | |
1638 /* | |
1639 * Sense of negotiation down: offer lower value; sense of | |
1640 * negotiation up: offer higher value. | |
1641 * This happens automatically by just responding with our current | |
1642 * global value. | |
1643 */ | |
1644 } | |
1645 | |
1646 /* | |
1647 * In case we also want to negotiate this value, but to a higher | |
1648 * value, delete this parameter from the requested XID structure | |
1649 */ | |
1650 if (llc_data->u->requested_xid.ku.valid AND | |
1651 llc_data->u->requested_xid.ku.value >= llc_data->decoded_xid.ku.value) | |
1652 { | |
1653 llc_data->u->requested_xid.ku.valid = FALSE; | |
1654 } | |
1655 | |
1656 /* | |
1657 * Tag parameter for next response. | |
1658 */ | |
1659 llc_data->u->xid_tag |= 0x00000001L << XID_KU; | |
1660 } | |
1661 else /* SGSN_RESPONSE */ | |
1662 { | |
1663 /* | |
1664 * Sense of negotiation-correctness of response has already been checked | |
1665 * in u_check_xid(). | |
1666 */ | |
1667 if (((GET_STATE (U) EQ U_ABM) AND | |
1668 (llc_data->decoded_xid.ku.value > *(llc_data->ku))) | |
1669 OR /* state 'ADM' */ | |
1670 (llc_data->decoded_xid.ku.value NEQ *(llc_data->ku))) | |
1671 { | |
1672 *(llc_data->ku) = llc_data->decoded_xid.ku.value; | |
1673 } | |
1674 } | |
1675 | |
1676 /* | |
1677 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1678 * explicitly negotiated by the peer. | |
1679 * <R.LLC.XIDNEG_R.A.015> | |
1680 */ | |
1681 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_KU); | |
1682 } | |
1683 | |
1684 | |
1685 /************************************************************************** | |
1686 * Layer 3 stuff | |
1687 */ | |
1688 if (llc_data->decoded_l3_xid.valid) | |
1689 { | |
1690 /* | |
1691 * LL_XID_IND has to be sent to layer 3. | |
1692 */ | |
1693 *xid_ind = TRUE; | |
1694 | |
1695 if (cr_bit EQ SGSN_COMMAND) | |
1696 { | |
1697 /* | |
1698 * Tag parameter for next response. | |
1699 */ | |
1700 llc_data->u->xid_tag |= 0x00000001L << XID_LAYER_3; | |
1701 } | |
1702 else /* SGSN_RESPONSE */ | |
1703 { | |
1704 /* | |
1705 * Reset valid flag of parameter in requested_xid because it has been | |
1706 * included in the response. | |
1707 */ | |
1708 llc_data->requested_l3_xid->valid = FALSE; | |
1709 } | |
1710 | |
1711 /* | |
1712 * Remove tag in xid_tag_negotiate, because this parameter has been | |
1713 * explicitly negotiated by the peer. | |
1714 * <R.LLC.XIDNEG_R.A.015> | |
1715 */ | |
1716 llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_LAYER_3); | |
1717 } | |
1718 | |
1719 return; /* u_eval_xid */ | |
1720 } | |
1721 | |
1722 | |
1723 /* | |
1724 +------------------------------------------------------------------------------ | |
1725 | Function : u_insert_xid | |
1726 +------------------------------------------------------------------------------ | |
1727 | Description : This procedure inserts (i.e. appends) the XID parameters that | |
1728 | are tagged in llc_xid_tag. This variable is normally set in | |
1729 | u_eval_xid(). The parameter cr_bit indicates if the XID | |
1730 | information field is written in a command or a response frame. | |
1731 | The values of the parameters are taken from llc_requested_xid | |
1732 | if marked as valid (normally the cause when a command frame is | |
1733 | to be sent), otherwise from global variables (the normal cause | |
1734 | for a response frame). If a response frame is to be sent, and | |
1735 | the parameter is tagged in llc_xid_tag, but has not been | |
1736 | received in the command frame (as indicated by | |
1737 | llc_decoded_xid), the parameter is tagged in llc_xid_negotiate. | |
1738 | Each parameter is tagged in llc_xid_tag_sent for collision | |
1739 | checks and the like | |
1740 | | |
1741 | Parameters : sdu - a valid pointer to an SDU, containing enough octets | |
1742 | for the tagged number of XID parameters | |
1743 | cr_bit - MS_COMMAND/_RESPONSE is to be sent | |
1744 | | |
1745 +------------------------------------------------------------------------------ | |
1746 */ | |
1747 GLOBAL void u_insert_xid | |
1748 ( | |
1749 #ifdef LL_DESC | |
1750 T_desc_list3 *desc_list3, | |
1751 #else | |
1752 T_sdu *sdu, | |
1753 #endif | |
1754 T_BIT cr_bit | |
1755 ) | |
1756 { | |
1757 UBYTE *data; | |
1758 ULONG value; | |
1759 #ifdef LL_DESC | |
1760 UBYTE *desc_buf; | |
1761 T_desc3 *desc3; | |
1762 #endif | |
1763 TRACE_FUNCTION( "u_insert_xid" ); | |
1764 | |
1765 /* | |
1766 * Set data to point to the first free data octet in sdu. data has to | |
1767 * be incremented with each octet that is written in sdu to ensure that | |
1768 * it always points to the first free data octet. | |
1769 */ | |
1770 #ifdef LL_DESC | |
1771 desc3 = (T_desc3*) desc_list3->first; | |
1772 desc_buf = (UBYTE*)desc3->buffer; | |
1773 data = &desc_buf[(desc3->offset)+(desc3->len)]; | |
1774 #else | |
1775 data = &sdu->buf[(sdu->o_buf/8)+(sdu->l_buf/8)]; | |
1776 #endif | |
1777 /* | |
1778 * Preset global XID sent indicator for next response. | |
1779 */ | |
1780 llc_data->u->xid_tag_sent = 0L; | |
1781 | |
1782 | |
1783 /************************************************************************* | |
1784 * Version: | |
1785 * Shall not be negotiated while in state 'ABM'. | |
1786 * <R.LLC.XID_PAR.A.001> | |
1787 */ | |
1788 if (llc_data->u->xid_tag & (0x00000001L << XID_VERSION) AND | |
1789 (GET_STATE (U) NEQ U_ABM)) | |
1790 { | |
1791 if (cr_bit EQ MS_COMMAND) | |
1792 { | |
1793 value = llc_data->u->requested_xid.version.value; | |
1794 } | |
1795 else | |
1796 { | |
1797 if (llc_data->u->requested_xid.version.valid) | |
1798 { | |
1799 llc_data->version = llc_data->u->requested_xid.version.value; | |
1800 } | |
1801 | |
1802 value = llc_data->version; | |
1803 | |
1804 /* | |
1805 * Tag a parameter for further negotiation that was not included in | |
1806 * the XID command in every XID response until the parameter has been | |
1807 * explicitly negotiated, either by responding to an XID command that | |
1808 * included the parameter, or by explicitly including the parameter | |
1809 * the next time an XID command is transmitted. | |
1810 * <R.LLC.XIDNEG_R.A.015> | |
1811 */ | |
1812 if (!llc_data->decoded_xid.version.valid) | |
1813 { | |
1814 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_VERSION; | |
1815 } | |
1816 } | |
1817 | |
1818 /* | |
1819 * Append determined value to SDU data, increment SDU data pointer to | |
1820 * point to the first free data octet again. | |
1821 */ | |
1822 *data++ = (UBYTE)0x00 | ((UBYTE)XID_VERSION << 2) | (UBYTE)XID_VERSION_LEN; | |
1823 *data++ = (UBYTE)value; | |
1824 | |
1825 #ifdef LL_DESC | |
1826 desc3->len += (XID_VERSION_LEN + 1); | |
1827 #else | |
1828 sdu->l_buf += (XID_VERSION_LEN + 1) * 8; | |
1829 #endif | |
1830 /* | |
1831 * Tag parameter for collision checks and the like. | |
1832 */ | |
1833 llc_data->u->xid_tag_sent |= 0x00000001L << XID_VERSION; | |
1834 } | |
1835 | |
1836 /************************************************************************* | |
1837 * T200: | |
1838 * Can be negotiated in state 'ADM' and 'ABM'. | |
1839 * <R.LLC.XID_PAR.A.006> | |
1840 */ | |
1841 if (llc_data->u->xid_tag & (0x00000001L << XID_T200)) | |
1842 { | |
1843 if (cr_bit EQ MS_COMMAND) | |
1844 { | |
1845 value = llc_data->u->requested_xid.t200.value; | |
1846 } | |
1847 else | |
1848 { | |
1849 if (llc_data->u->requested_xid.t200.valid) | |
1850 { | |
1851 llc_data->t200->length = XID2INT(llc_data->u->requested_xid.t200.value); | |
1852 } | |
1853 | |
1854 value = INT2XID(llc_data->t200->length); | |
1855 | |
1856 /* | |
1857 * Tag a parameter for further negotiation that was not included in | |
1858 * the XID command in every XID response until the parameter has been | |
1859 * explicitly negotiated, either by responding to an XID command that | |
1860 * included the parameter, or by explicitly including the parameter | |
1861 * the next time an XID command is transmitted. | |
1862 * <R.LLC.XIDNEG_R.A.015> | |
1863 */ | |
1864 if (!llc_data->decoded_xid.t200.valid) | |
1865 { | |
1866 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_T200; | |
1867 } | |
1868 } | |
1869 | |
1870 /* | |
1871 * Append determined value to SDU data, increment SDU data pointer to | |
1872 * point to the first free data octet again. | |
1873 */ | |
1874 *data++ = (UBYTE)0x00 | ((UBYTE)XID_T200 << 2) | (UBYTE)XID_T200_LEN; | |
1875 *data++ = (UBYTE)(value >> 8); | |
1876 *data++ = (UBYTE)value; | |
1877 | |
1878 #ifdef LL_DESC | |
1879 desc3->len += (XID_T200_LEN + 1); | |
1880 #else | |
1881 sdu->l_buf += (XID_T200_LEN + 1) * 8; | |
1882 #endif | |
1883 | |
1884 /* | |
1885 * Tag parameter for collision checks and the like. | |
1886 */ | |
1887 llc_data->u->xid_tag_sent |= 0x00000001L << XID_T200; | |
1888 } | |
1889 | |
1890 /************************************************************************* | |
1891 * N200: | |
1892 * Can be negotiated in state 'ADM' and 'ABM'. | |
1893 * <R.LLC.XID_PAR.A.006> | |
1894 */ | |
1895 if (llc_data->u->xid_tag & (0x00000001L << XID_N200)) | |
1896 { | |
1897 if (cr_bit EQ MS_COMMAND) | |
1898 { | |
1899 value = llc_data->u->requested_xid.n200.value; | |
1900 } | |
1901 else | |
1902 { | |
1903 if (llc_data->u->requested_xid.n200.valid) | |
1904 { | |
1905 *(llc_data->n200) = llc_data->u->requested_xid.n200.value; | |
1906 } | |
1907 | |
1908 value = *(llc_data->n200); | |
1909 | |
1910 /* | |
1911 * Tag a parameter for further negotiation that was not included in | |
1912 * the XID command in every XID response until the parameter has been | |
1913 * explicitly negotiated, either by responding to an XID command that | |
1914 * included the parameter, or by explicitly including the parameter | |
1915 * the next time an XID command is transmitted. | |
1916 * <R.LLC.XIDNEG_R.A.015> | |
1917 */ | |
1918 if (!llc_data->decoded_xid.n200.valid) | |
1919 { | |
1920 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_N200; | |
1921 } | |
1922 } | |
1923 | |
1924 /* | |
1925 * Append determined value to SDU data, increment SDU data pointer to | |
1926 * point to the first free data octet again. | |
1927 */ | |
1928 *data++ = (UBYTE)0x00 | ((UBYTE)XID_N200 << 2) | (UBYTE)XID_N200_LEN; | |
1929 *data++ = (UBYTE)value; | |
1930 | |
1931 #ifdef LL_DESC | |
1932 desc3->len += (XID_N200_LEN + 1); | |
1933 #else | |
1934 sdu->l_buf += (XID_N200_LEN + 1) * 8; | |
1935 #endif | |
1936 | |
1937 /* | |
1938 * Tag parameter for collision checks and the like. | |
1939 */ | |
1940 llc_data->u->xid_tag_sent |= 0x00000001L << XID_N200; | |
1941 } | |
1942 | |
1943 /************************************************************************* | |
1944 * N201-U: | |
1945 * Can be negotiated in state 'ADM' and 'ABM'. | |
1946 * <R.LLC.XID_PAR.A.006> | |
1947 */ | |
1948 if (llc_data->u->xid_tag & (0x00000001L << XID_N201_U)) | |
1949 { | |
1950 if (cr_bit EQ MS_COMMAND) | |
1951 { | |
1952 value = llc_data->u->requested_xid.n201_u.value; | |
1953 } | |
1954 else | |
1955 { | |
1956 if (llc_data->u->requested_xid.n201_u.valid) | |
1957 { | |
1958 *(llc_data->n201_u) = llc_data->u->requested_xid.n201_u.value; | |
1959 } | |
1960 | |
1961 value = *(llc_data->n201_u); | |
1962 | |
1963 /* | |
1964 * Tag a parameter for further negotiation that was not included in | |
1965 * the XID command in every XID response until the parameter has been | |
1966 * explicitly negotiated, either by responding to an XID command that | |
1967 * included the parameter, or by explicitly including the parameter | |
1968 * the next time an XID command is transmitted. | |
1969 * <R.LLC.XIDNEG_R.A.015> | |
1970 */ | |
1971 if (!llc_data->decoded_xid.n201_u.valid) | |
1972 { | |
1973 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_N201_U; | |
1974 } | |
1975 } | |
1976 | |
1977 /* | |
1978 * Append determined value to SDU data, increment SDU data pointer to | |
1979 * point to the first free data octet again. | |
1980 */ | |
1981 *data++ = (UBYTE)0x00 | ((UBYTE)XID_N201_U << 2) | (UBYTE)XID_N201_U_LEN; | |
1982 *data++ = (UBYTE)(value >> 8); | |
1983 *data++ = (UBYTE)value; | |
1984 | |
1985 #ifdef LL_DESC | |
1986 desc3->len += (XID_N201_U_LEN + 1); | |
1987 #else | |
1988 sdu->l_buf += (XID_N201_U_LEN + 1) * 8; | |
1989 #endif | |
1990 | |
1991 /* | |
1992 * Tag parameter for collision checks and the like. | |
1993 */ | |
1994 llc_data->u->xid_tag_sent |= 0x00000001L << XID_N201_U; | |
1995 } | |
1996 | |
1997 /************************************************************************* | |
1998 * N201-I: | |
1999 * Can be negotiated in state 'ADM' and 'ABM'. | |
2000 * <R.LLC.XID_PAR.A.006> | |
2001 */ | |
2002 if (llc_data->u->xid_tag & (0x00000001L << XID_N201_I)) | |
2003 { | |
2004 if (cr_bit EQ MS_COMMAND) | |
2005 { | |
2006 value = llc_data->u->requested_xid.n201_i.value; | |
2007 } | |
2008 else | |
2009 { | |
2010 if (llc_data->u->requested_xid.n201_i.valid) | |
2011 { | |
2012 *(llc_data->n201_i) = llc_data->u->requested_xid.n201_i.value; | |
2013 } | |
2014 | |
2015 value = *(llc_data->n201_i); | |
2016 | |
2017 /* | |
2018 * Tag a parameter for further negotiation that was not included in | |
2019 * the XID command in every XID response until the parameter has been | |
2020 * explicitly negotiated, either by responding to an XID command that | |
2021 * included the parameter, or by explicitly including the parameter | |
2022 * the next time an XID command is transmitted. | |
2023 * <R.LLC.XIDNEG_R.A.015> | |
2024 */ | |
2025 if (!llc_data->decoded_xid.n201_i.valid) | |
2026 { | |
2027 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_N201_I; | |
2028 } | |
2029 } | |
2030 | |
2031 /* | |
2032 * Append determined value to SDU data, increment SDU data pointer to | |
2033 * point to the first free data octet again. | |
2034 */ | |
2035 *data++ = (UBYTE)0x00 | ((UBYTE)XID_N201_I << 2) | (UBYTE)XID_N201_I_LEN; | |
2036 *data++ = (UBYTE)(value >> 8); | |
2037 *data++ = (UBYTE)value; | |
2038 | |
2039 #ifdef LL_DESC | |
2040 desc3->len += (XID_N201_I_LEN + 1); | |
2041 #else | |
2042 sdu->l_buf += (XID_N201_I_LEN + 1) * 8; | |
2043 #endif | |
2044 | |
2045 /* | |
2046 * Tag parameter for collision checks and the like. | |
2047 */ | |
2048 llc_data->u->xid_tag_sent |= 0x00000001L << XID_N201_I; | |
2049 } | |
2050 | |
2051 /************************************************************************* | |
2052 * md: | |
2053 * Can be negotiated in state 'ADM' and 'ABM'. | |
2054 * <R.LLC.XID_PAR.A.006> | |
2055 */ | |
2056 if (llc_data->u->xid_tag & (0x00000001L << XID_MD)) | |
2057 { | |
2058 if (cr_bit EQ MS_COMMAND) | |
2059 { | |
2060 value = llc_data->u->requested_xid.md.value; | |
2061 } | |
2062 else | |
2063 { | |
2064 if (llc_data->u->requested_xid.md.valid) | |
2065 { | |
2066 *(llc_data->md) = llc_data->u->requested_xid.md.value; | |
2067 } | |
2068 | |
2069 value = *(llc_data->md); | |
2070 | |
2071 /* | |
2072 * Tag a parameter for further negotiation that was not included in | |
2073 * the XID command in every XID response until the parameter has been | |
2074 * explicitly negotiated, either by responding to an XID command that | |
2075 * included the parameter, or by explicitly including the parameter | |
2076 * the next time an XID command is transmitted. | |
2077 * <R.LLC.XIDNEG_R.A.015> | |
2078 */ | |
2079 if (!llc_data->decoded_xid.md.valid) | |
2080 { | |
2081 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_MD; | |
2082 } | |
2083 } | |
2084 | |
2085 /* | |
2086 * Append determined value to SDU data, increment SDU data pointer to | |
2087 * point to the first free data octet again. | |
2088 */ | |
2089 *data++ = (UBYTE)0x00 | ((UBYTE)XID_MD << 2) | (UBYTE)XID_MD_LEN; | |
2090 *data++ = (UBYTE)(value >> 8); | |
2091 *data++ = (UBYTE)value; | |
2092 | |
2093 #ifdef LL_DESC | |
2094 desc3->len += (XID_MD_LEN + 1); | |
2095 #else | |
2096 sdu->l_buf += (XID_MD_LEN + 1) * 8; | |
2097 #endif | |
2098 | |
2099 /* | |
2100 * Tag parameter for collision checks and the like. | |
2101 */ | |
2102 llc_data->u->xid_tag_sent |= 0x00000001L << XID_MD; | |
2103 } | |
2104 | |
2105 /************************************************************************* | |
2106 * mu: | |
2107 * Can be negotiated in state 'ADM' and 'ABM'. | |
2108 * <R.LLC.XID_PAR.A.006> | |
2109 */ | |
2110 if (llc_data->u->xid_tag & (0x00000001L << XID_MU)) | |
2111 { | |
2112 if (cr_bit EQ MS_COMMAND) | |
2113 { | |
2114 value = llc_data->u->requested_xid.mu.value; | |
2115 } | |
2116 else | |
2117 { | |
2118 if (llc_data->u->requested_xid.mu.valid) | |
2119 { | |
2120 *(llc_data->mu) = llc_data->u->requested_xid.mu.value; | |
2121 } | |
2122 | |
2123 value = *(llc_data->mu); | |
2124 | |
2125 /* | |
2126 * Tag a parameter for further negotiation that was not included in | |
2127 * the XID command in every XID response until the parameter has been | |
2128 * explicitly negotiated, either by responding to an XID command that | |
2129 * included the parameter, or by explicitly including the parameter | |
2130 * the next time an XID command is transmitted. | |
2131 * <R.LLC.XIDNEG_R.A.015> | |
2132 */ | |
2133 if (!llc_data->decoded_xid.mu.valid) | |
2134 { | |
2135 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_MU; | |
2136 } | |
2137 } | |
2138 | |
2139 /* | |
2140 * Append determined value to SDU data, increment SDU data pointer to | |
2141 * point to the first free data octet again. | |
2142 */ | |
2143 *data++ = (UBYTE)0x00 | ((UBYTE)XID_MU << 2) | (UBYTE)XID_MU_LEN; | |
2144 *data++ = (UBYTE)(value >> 8); | |
2145 *data++ = (UBYTE)value; | |
2146 | |
2147 #ifdef LL_DESC | |
2148 desc3->len += (XID_MU_LEN + 1); | |
2149 #else | |
2150 sdu->l_buf += (XID_MU_LEN + 1) * 8; | |
2151 #endif | |
2152 | |
2153 /* | |
2154 * Tag parameter for collision checks and the like. | |
2155 */ | |
2156 llc_data->u->xid_tag_sent |= 0x00000001L << XID_MU; | |
2157 } | |
2158 | |
2159 /************************************************************************* | |
2160 * kd: | |
2161 * Can be negotiated in state 'ADM' and 'ABM'. | |
2162 * <R.LLC.XID_PAR.A.006> | |
2163 */ | |
2164 if (llc_data->u->xid_tag & (0x00000001L << XID_KD)) | |
2165 { | |
2166 if (cr_bit EQ MS_COMMAND) | |
2167 { | |
2168 value = llc_data->u->requested_xid.kd.value; | |
2169 } | |
2170 else | |
2171 { | |
2172 if (llc_data->u->requested_xid.kd.valid) | |
2173 { | |
2174 *(llc_data->kd) = llc_data->u->requested_xid.kd.value; | |
2175 } | |
2176 | |
2177 value = *(llc_data->kd); | |
2178 | |
2179 /* | |
2180 * Tag a parameter for further negotiation that was not included in | |
2181 * the XID command in every XID response until the parameter has been | |
2182 * explicitly negotiated, either by responding to an XID command that | |
2183 * included the parameter, or by explicitly including the parameter | |
2184 * the next time an XID command is transmitted. | |
2185 * <R.LLC.XIDNEG_R.A.015> | |
2186 */ | |
2187 if (!llc_data->decoded_xid.kd.valid) | |
2188 { | |
2189 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_KD; | |
2190 } | |
2191 } | |
2192 | |
2193 /* | |
2194 * Append determined value to SDU data, increment SDU data pointer to | |
2195 * point to the first free data octet again. | |
2196 */ | |
2197 *data++ = (UBYTE)0x00 | ((UBYTE)XID_KD << 2) | (UBYTE)XID_KD_LEN; | |
2198 *data++ = (UBYTE)value; | |
2199 | |
2200 #ifdef LL_DESC | |
2201 desc3->len += (XID_KD_LEN + 1); | |
2202 #else | |
2203 sdu->l_buf += (XID_KD_LEN + 1) * 8; | |
2204 #endif | |
2205 | |
2206 /* | |
2207 * Tag parameter for collision checks and the like. | |
2208 */ | |
2209 llc_data->u->xid_tag_sent |= 0x00000001L << XID_KD; | |
2210 } | |
2211 | |
2212 /************************************************************************* | |
2213 * ku: | |
2214 * Can be negotiated in state 'ADM' and 'ABM'. | |
2215 * <R.LLC.XID_PAR.A.006> | |
2216 */ | |
2217 if (llc_data->u->xid_tag & (0x00000001L << XID_KU)) | |
2218 { | |
2219 if (cr_bit EQ MS_COMMAND) | |
2220 { | |
2221 value = llc_data->u->requested_xid.ku.value; | |
2222 } | |
2223 else | |
2224 { | |
2225 if (llc_data->u->requested_xid.ku.valid) | |
2226 { | |
2227 *(llc_data->ku) = llc_data->u->requested_xid.ku.value; | |
2228 } | |
2229 | |
2230 value = *(llc_data->ku); | |
2231 | |
2232 /* | |
2233 * Tag a parameter for further negotiation that was not included in | |
2234 * the XID command in every XID response until the parameter has been | |
2235 * explicitly negotiated, either by responding to an XID command that | |
2236 * included the parameter, or by explicitly including the parameter | |
2237 * the next time an XID command is transmitted. | |
2238 * <R.LLC.XIDNEG_R.A.015> | |
2239 */ | |
2240 if (!llc_data->decoded_xid.ku.valid) | |
2241 { | |
2242 llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_KU; | |
2243 } | |
2244 } | |
2245 | |
2246 /* | |
2247 * Append determined value to SDU data, increment SDU data pointer to | |
2248 * point to the first free data octet again. | |
2249 */ | |
2250 *data++ = (UBYTE)0x00 | ((UBYTE)XID_KU << 2) | (UBYTE)XID_KU_LEN; | |
2251 *data++ = (UBYTE)value; | |
2252 | |
2253 #ifdef LL_DESC | |
2254 desc3->len += (XID_KU_LEN + 1); | |
2255 #else | |
2256 sdu->l_buf += (XID_KU_LEN + 1) * 8; | |
2257 #endif | |
2258 | |
2259 /* | |
2260 * Tag parameter for collision checks and the like. | |
2261 */ | |
2262 llc_data->u->xid_tag_sent |= 0x00000001L << XID_KU; | |
2263 } | |
2264 | |
2265 /************************************************************************* | |
2266 * Insert Layer 3 (sense of negotiation: both) | |
2267 */ | |
2268 if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3)) | |
2269 { | |
2270 if (llc_data->requested_l3_xid->valid) | |
2271 { | |
2272 /* | |
2273 * Write two bytes header | |
2274 */ | |
2275 *data++ = (UBYTE)0x80 /* = set length to 8 bit */ | ((UBYTE)XID_LAYER_3 << 2) | |
2276 | ((UBYTE)((llc_data->requested_l3_xid->length >> 6) & 0x03)); | |
2277 *data++ = (UBYTE)(llc_data->requested_l3_xid->length << 2); | |
2278 | |
2279 /* | |
2280 * Copy data | |
2281 */ | |
2282 memcpy (data, llc_data->requested_l3_xid->value, | |
2283 llc_data->requested_l3_xid->length); | |
2284 | |
2285 /* | |
2286 * Increase DESC/SDU size | |
2287 */ | |
2288 #ifdef LL_DESC | |
2289 desc3->len += (llc_data->requested_l3_xid->length + 2); | |
2290 #else | |
2291 sdu->l_buf += (llc_data->requested_l3_xid->length + 2) * 8; | |
2292 #endif | |
2293 /* | |
2294 * Tag parameter for collision checks and the like. | |
2295 */ | |
2296 llc_data->u->xid_tag_sent |= 0x00000001L << XID_LAYER_3; | |
2297 } | |
2298 } | |
2299 | |
2300 #ifdef LL_DESC | |
2301 desc_list3->list_len = desc3->len; | |
2302 #endif /* LL_DESC */ | |
2303 | |
2304 #ifdef TRACE_EVE | |
2305 #ifdef LL_DESC | |
2306 { | |
2307 int i; | |
2308 int l = desc3->len; | |
2309 int o = desc3->offset; | |
2310 | |
2311 vsi_o_ttrace(VSI_CALLER TC_EVENT, "ul XID sdu dump len:%d bytes", l); | |
2312 | |
2313 for (i=0; i<l; i+=10) | |
2314 { | |
2315 vsi_o_ttrace(VSI_CALLER TC_EVENT, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x", | |
2316 desc_buf[o+i+0], desc_buf[o+i+1], | |
2317 desc_buf[o+i+2], desc_buf[o+i+3], desc_buf[o+i+4], | |
2318 | |
2319 desc_buf[o+i+5], desc_buf[o+i+6], | |
2320 desc_buf[o+i+7], desc_buf[o+i+8], desc_buf[o+i+9]); | |
2321 } | |
2322 } | |
2323 | |
2324 #else | |
2325 { | |
2326 int i; | |
2327 int l = sdu->l_buf/8; | |
2328 int o = sdu->o_buf/8; | |
2329 | |
2330 vsi_o_ttrace(VSI_CALLER TC_EVENT, "ul XID sdu dump len:%d bytes", l); | |
2331 | |
2332 for (i=0; i<l; i+=10) | |
2333 { | |
2334 vsi_o_ttrace(VSI_CALLER TC_EVENT, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x", | |
2335 sdu->buf[o+i+0], sdu->buf[o+i+1], | |
2336 sdu->buf[o+i+2], sdu->buf[o+i+3], sdu->buf[o+i+4], | |
2337 | |
2338 sdu->buf[o+i+5], sdu->buf[o+i+6], | |
2339 sdu->buf[o+i+7], sdu->buf[o+i+8], sdu->buf[o+i+9]); | |
2340 } | |
2341 } | |
2342 | |
2343 #endif /* LL_DESC */ | |
2344 #endif /* TRACE_EVE */ | |
2345 /* | |
2346 * If we have build an response including all XID parameters, | |
2347 * we can clean all the xid_tags and layer 3 parameters. | |
2348 */ | |
2349 if (cr_bit EQ MS_RESPONSE) | |
2350 { | |
2351 llc_data->u->xid_tag = 0; | |
2352 llc_data->requested_l3_xid->valid = FALSE; | |
2353 } | |
2354 | |
2355 return; | |
2356 } /* u_insert_xid() */ | |
2357 | |
2358 | |
2359 /* | |
2360 +------------------------------------------------------------------------------ | |
2361 | Function : u_insert_frmr_information | |
2362 +------------------------------------------------------------------------------ | |
2363 | Description : This procedure inserts (i.e. appends) an FRMR information | |
2364 | field into the given sdu. frame is the rejected frame of which | |
2365 | the control field is included (ctrl_length is truncated to a | |
2366 | maximum of six octets; if it is not known, length is | |
2367 | determinated from pdu_type), v_s and v_r are the current | |
2368 | send and receive state numbers of ITX/IRX, cr_bit indicates | |
2369 | if the frame was a command or response (SGSN_COMMAND/RESPONSE), | |
2370 | and reason indicates the reason of the frame rejection | |
2371 | condition (the lower nibble of reason is equivalent to W4-W1). | |
2372 | | |
2373 | Parameters : sdu - a valid pointer to an SDU, containing enough | |
2374 | octets for the FRMR information field | |
2375 | (U_FRMR_INFO_SIZE) | |
2376 | frame - frame that caused the frame rejection condition | |
2377 | pdu_type - frame type | |
2378 | ctrl_length - control field length, if known | |
2379 | v_s - current V(S) | |
2380 | v_r - current V(R) | |
2381 | cr_bit - setting of C/R bit in frame | |
2382 | reason - reason of the frame rejection condition (lower | |
2383 | nibble conforms to W4-W1 in FRMR response) | |
2384 | | |
2385 +------------------------------------------------------------------------------ | |
2386 */ | |
2387 GLOBAL void u_insert_frmr_information | |
2388 ( | |
2389 #ifndef LL_DESC | |
2390 T_sdu *sdu, | |
2391 #else | |
2392 T_desc_list3 *desc_list3, | |
2393 #endif | |
2394 T_LL_UNITDATA_IND *frame, | |
2395 T_PDU_TYPE pdu_type, | |
2396 USHORT ctrl_length, | |
2397 T_FRAME_NUM v_s, | |
2398 T_FRAME_NUM v_r, | |
2399 T_BIT cr_bit, | |
2400 UBYTE reason | |
2401 ) | |
2402 { | |
2403 | |
2404 #ifndef LL_DESC | |
2405 UBYTE *sdu_data; | |
2406 #else | |
2407 UBYTE *help, *desc_data; | |
2408 T_desc3 *desc3; | |
2409 #endif | |
2410 UBYTE *ctrl; | |
2411 USHORT octet; | |
2412 | |
2413 | |
2414 TRACE_FUNCTION( "u_insert_frmr_information" ); | |
2415 | |
2416 #ifndef LL_DESC | |
2417 /* | |
2418 * Set sdu_data to point to the first free data octet in sdu. sdu_data | |
2419 * has to be incremented with each octet that is written in sdu to ensure | |
2420 * that it always points to the first free data octet. | |
2421 */ | |
2422 sdu_data = &sdu->buf[(sdu->o_buf/8)+(sdu->l_buf/8)]; | |
2423 | |
2424 /* | |
2425 * Adjust length of SDU to include fixed sized FRMR information field. | |
2426 */ | |
2427 sdu->l_buf += U_FRMR_INFO_SIZE * 8; | |
2428 | |
2429 /* | |
2430 * Set ctrl to point to the first octet of the faulty frame control field. | |
2431 */ | |
2432 ctrl = &frame->sdu.buf[(frame->sdu.o_buf/8)+1]; | |
2433 | |
2434 /* | |
2435 * If ctrl_length is unknown, the frame type is known, therefore the length | |
2436 * of the control field can be easily determined. | |
2437 */ | |
2438 if (ctrl_length EQ FRMR_CTRL_LENGTH_UNKNOWN) | |
2439 { | |
2440 if (pdu_type EQ I_FRAME) | |
2441 { | |
2442 ctrl_length = I_CTRL_OCTETS; | |
2443 } | |
2444 else if (pdu_type EQ S_FRAME) | |
2445 { | |
2446 ctrl_length = S_CTRL_OCTETS; | |
2447 } | |
2448 else if (pdu_type EQ UI_FRAME) | |
2449 { | |
2450 ctrl_length = UI_CTRL_OCTETS; | |
2451 } | |
2452 else if (pdu_type EQ U_FRAME) | |
2453 { | |
2454 ctrl_length = U_CTRL_OCTETS; | |
2455 } | |
2456 else | |
2457 { | |
2458 /* | |
2459 * Undefined control field type, set control field length to SDU length | |
2460 * minus address field, limited to six octets. | |
2461 */ | |
2462 TRACE_ERROR ("undefined control field type"); | |
2463 ctrl_length = (sdu->l_buf/8 - 1) < 6 ? (sdu->l_buf/8 - 1) : 6; | |
2464 } | |
2465 } | |
2466 else /* ctrl_length is already known */ | |
2467 { | |
2468 /* | |
2469 * Limit control field length to six octets, according to 04.64. | |
2470 */ | |
2471 ctrl_length = ctrl_length < 6 ? ctrl_length : 6; | |
2472 } | |
2473 | |
2474 | |
2475 /* | |
2476 * Copy the first six octets of faulty control field. If the control field | |
2477 * is smaller that six octets, the unused octets are set to 0. | |
2478 */ | |
2479 for (octet = 0; octet < 6; octet++) | |
2480 { | |
2481 if (octet < ctrl_length) | |
2482 { | |
2483 sdu_data[octet] = ctrl[octet]; | |
2484 } | |
2485 else | |
2486 { | |
2487 sdu_data[octet] = 0x00; | |
2488 } | |
2489 } | |
2490 | |
2491 | |
2492 /* | |
2493 * Insert remaining four octets of FRMR information field: | |
2494 * +---+---+---+---+---+---+---+---+ | |
2495 * | X | X | X | X | V(S) | | |
2496 * +---+---+---+---+---+---+---+---+ | |
2497 * | V(S) | X | V(R) | | |
2498 * +---+---+---+---+---+---+---+---+ | |
2499 * | V(R) |C/R| | |
2500 * +---+---+---+---+---+---+---+---+ | |
2501 * | X | X | X | X | W4| W3| W2| W1| | |
2502 * +---+---+---+---+---+---+---+---+ | |
2503 */ | |
2504 sdu_data[octet++] = (UBYTE)(v_s >> 5) & 0x0F; | |
2505 sdu_data[octet++] = (UBYTE)(v_s << 3) | ((UBYTE)(v_r >> 7) & 0x0003); | |
2506 sdu_data[octet++] = (UBYTE)(v_r << 1) | (cr_bit EQ SGSN_COMMAND ? | |
2507 0x00 : 0x01); | |
2508 sdu_data[octet++] = reason & 0x0F; | |
2509 | |
2510 return; | |
2511 #else | |
2512 /* | |
2513 * Set sdu_data to point to the first free data octet in sdu. sdu_data | |
2514 * has to be incremented with each octet that is written in sdu to ensure | |
2515 * that it always points to the first free data octet. | |
2516 */ | |
2517 desc3 = (T_desc3*)desc_list3->first; | |
2518 | |
2519 help = (U8*)desc3->buffer; | |
2520 desc_data = &help[desc3->offset + desc3->len]; | |
2521 | |
2522 /* | |
2523 * Adjust length of SDU to include fixed sized FRMR information field. | |
2524 */ | |
2525 desc3->len += U_FRMR_INFO_SIZE; | |
2526 desc_list3->list_len += U_FRMR_INFO_SIZE; | |
2527 | |
2528 /* | |
2529 * Set ctrl to point to the first octet of the faulty frame control field. | |
2530 */ | |
2531 ctrl = &frame->sdu.buf[(frame->sdu.o_buf/8)+1]; | |
2532 | |
2533 /* | |
2534 * If ctrl_length is unknown, the frame type is known, therefore the length | |
2535 * of the control field can be easily determined. | |
2536 */ | |
2537 if (ctrl_length EQ FRMR_CTRL_LENGTH_UNKNOWN) | |
2538 { | |
2539 if (pdu_type EQ I_FRAME) | |
2540 { | |
2541 ctrl_length = I_CTRL_OCTETS; | |
2542 } | |
2543 else if (pdu_type EQ S_FRAME) | |
2544 { | |
2545 ctrl_length = S_CTRL_OCTETS; | |
2546 } | |
2547 else if (pdu_type EQ UI_FRAME) | |
2548 { | |
2549 ctrl_length = UI_CTRL_OCTETS; | |
2550 } | |
2551 else if (pdu_type EQ U_FRAME) | |
2552 { | |
2553 ctrl_length = U_CTRL_OCTETS; | |
2554 } | |
2555 else | |
2556 { | |
2557 /* | |
2558 * Undefined control field type, set control field length to SDU length | |
2559 * minus address field, limited to six octets. | |
2560 */ | |
2561 TRACE_ERROR ("undefined control field type"); | |
2562 ctrl_length = desc3->len - 1 < 6 ? (desc3->len - 1) : 6; | |
2563 } | |
2564 } | |
2565 else /* ctrl_length is already known */ | |
2566 { | |
2567 /* | |
2568 * Limit control field length to six octets, according to 04.64. | |
2569 */ | |
2570 ctrl_length = ctrl_length < 6 ? ctrl_length : 6; | |
2571 } | |
2572 | |
2573 | |
2574 /* | |
2575 * Copy the first six octets of faulty control field. If the control field | |
2576 * is smaller that six octets, the unused octets are set to 0. | |
2577 */ | |
2578 for (octet = 0; octet < 6; octet++) | |
2579 { | |
2580 if (octet < ctrl_length) | |
2581 { | |
2582 desc_data[octet] = ctrl[octet]; | |
2583 } | |
2584 else | |
2585 { | |
2586 desc_data[octet] = 0x00; | |
2587 } | |
2588 } | |
2589 | |
2590 | |
2591 /* | |
2592 * Insert remaining four octets of FRMR information field: | |
2593 * +---+---+---+---+---+---+---+---+ | |
2594 * | X | X | X | X | V(S) | | |
2595 * +---+---+---+---+---+---+---+---+ | |
2596 * | V(S) | X | V(R) | | |
2597 * +---+---+---+---+---+---+---+---+ | |
2598 * | V(R) |C/R| | |
2599 * +---+---+---+---+---+---+---+---+ | |
2600 * | X | X | X | X | W4| W3| W2| W1| | |
2601 * +---+---+---+---+---+---+---+---+ | |
2602 */ | |
2603 desc_data[octet++] = (UBYTE)(v_s >> 5) & 0x0F; | |
2604 desc_data[octet++] = (UBYTE)(v_s << 3) | ((UBYTE)(v_r >> 7) & 0x0003); | |
2605 desc_data[octet++] = (UBYTE)(v_r << 1) | (cr_bit EQ SGSN_COMMAND ? | |
2606 0x00 : 0x01); | |
2607 desc_data[octet++] = reason & 0x0F; | |
2608 | |
2609 return; | |
2610 #endif | |
2611 } /* u_insert_frmr_information() */ | |
2612 | |
2613 | |
2614 /* | |
2615 +------------------------------------------------------------------------------ | |
2616 | Function : u_send_sabm | |
2617 +------------------------------------------------------------------------------ | |
2618 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
2619 | the required parameters, builds an U frame header containing | |
2620 | an SABM command, and sends this primitive to TX. _Before_ it is | |
2621 | sent to TX, T200 has to be started, because otherwise the | |
2622 | primitive may not be valid anymore. | |
2623 | | |
2624 | Parameters : | |
2625 | | |
2626 +------------------------------------------------------------------------------ | |
2627 */ | |
2628 GLOBAL void u_send_sabm (void) | |
2629 { | |
2630 USHORT sdu_byte_len = 0; | |
2631 #ifdef LL_DESC | |
2632 T_desc3 *desc3; | |
2633 #endif | |
2634 | |
2635 TRACE_FUNCTION( "u_send_sabm" ); | |
2636 | |
2637 u_tag_xid_parameters(0, TRUE); | |
2638 | |
2639 /* | |
2640 * Calculate bit length of tagged XID parameters. First, add | |
2641 * the size of each tagged parameter. The size of layer-3 | |
2642 * parameters is variable, so add the given length in octets. | |
2643 */ | |
2644 ADD_IF_TAGGED (sdu_byte_len, XID_VERSION); | |
2645 ADD_IF_TAGGED (sdu_byte_len, XID_T200); | |
2646 ADD_IF_TAGGED (sdu_byte_len, XID_N200); | |
2647 ADD_IF_TAGGED (sdu_byte_len, XID_N201_U); | |
2648 ADD_IF_TAGGED (sdu_byte_len, XID_N201_I); | |
2649 ADD_IF_TAGGED (sdu_byte_len, XID_MD); | |
2650 ADD_IF_TAGGED (sdu_byte_len, XID_MU); | |
2651 ADD_IF_TAGGED (sdu_byte_len, XID_KD); | |
2652 ADD_IF_TAGGED (sdu_byte_len, XID_KU); | |
2653 if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3)) | |
2654 { | |
2655 sdu_byte_len += llc_data->requested_l3_xid->length + 2; | |
2656 } | |
2657 | |
2658 /* | |
2659 * Add SDU header and FCS field to the XID response size to get | |
2660 * the overall SDU size. | |
2661 */ | |
2662 sdu_byte_len += U_HDR_SIZE + FCS_SIZE; | |
2663 | |
2664 #ifdef LL_DESC | |
2665 { | |
2666 PALLOC(ll_unitdesc_req, LL_UNITDESC_REQ); | |
2667 | |
2668 desc3 = llc_palloc_desc((USHORT)sdu_byte_len, 0); /* One desc3 descriptor and buffer allocated */ | |
2669 | |
2670 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
2671 ll_unitdesc_req->tlli = llc_data->u->current_tlli; | |
2672 /* | |
2673 * No attach to primitive necessary. For retransmission prim | |
2674 * data is copied in T200. | |
2675 */ | |
2676 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
2677 /* | |
2678 * LLC does not know the QoS profile. | |
2679 */ | |
2680 ll_unitdesc_req->ll_qos = llc_data->cur_qos; | |
2681 | |
2682 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak); | |
2683 | |
2684 /* | |
2685 * LLC signalling frames are always sent with highest priority. | |
2686 */ | |
2687 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio; | |
2688 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio); | |
2689 #ifdef REL99 | |
2690 /* | |
2691 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
2692 * predefined PFI LL_PFI_SIGNALING shall be used. | |
2693 */ | |
2694 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi; | |
2695 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi); | |
2696 #endif /* REL99 */ | |
2697 /* | |
2698 * Set parameter of descriptor list3 | |
2699 */ | |
2700 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
2701 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
2702 | |
2703 u_build_u_frame (&ll_unitdesc_req->desc_list3, MS_COMMAND, | |
2704 llc_data->current_sapi, 1, U_SABM); | |
2705 | |
2706 u_insert_xid (&ll_unitdesc_req->desc_list3, MS_COMMAND); | |
2707 | |
2708 /* | |
2709 * T200 has to be started _before_ the primitive is sent to TX, because | |
2710 * the primitive is copied by t200_start() and it may not be valid | |
2711 * anymore after sending to TX. | |
2712 */ | |
2713 sig_u_t200_start_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
2714 | |
2715 sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
2716 } | |
2717 | |
2718 #else | |
2719 { | |
2720 PALLOC_SDU (ll_unitdata_req, LL_UNITDATA_REQ, (USHORT)(sdu_byte_len*8)); | |
2721 | |
2722 ll_unitdata_req->sapi = llc_data->current_sapi; | |
2723 ll_unitdata_req->tlli = llc_data->u->current_tlli; | |
2724 /* | |
2725 * No attach to primitive necessary. For retransmission prim | |
2726 * data is copied in T200. | |
2727 */ | |
2728 ll_unitdata_req->attached_counter = CCI_NO_ATTACHE; | |
2729 /* | |
2730 * LLC does not know the QoS profile. | |
2731 */ | |
2732 ll_unitdata_req->ll_qos.peak = LL_PEAK_SUB; | |
2733 /* | |
2734 * LLC signalling frames are always sent with highest priority. | |
2735 */ | |
2736 ll_unitdata_req->radio_prio = LL_RADIO_PRIO_1; | |
2737 #ifdef REL99 | |
2738 /* | |
2739 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
2740 * predefined PFI LL_PFI_SIGNALING shall be used. | |
2741 */ | |
2742 ll_unitdata_req->pkt_flow_id = LL_PFI_SIGNALING; | |
2743 #endif /* REL99 */ | |
2744 | |
2745 u_build_u_frame (&ll_unitdata_req->sdu, MS_COMMAND, | |
2746 llc_data->current_sapi, 1, U_SABM); | |
2747 | |
2748 u_insert_xid (&ll_unitdata_req->sdu, MS_COMMAND); | |
2749 | |
2750 /* | |
2751 * T200 has to be started _before_ the primitive is sent to TX, because | |
2752 * the primitive is copied by t200_start() and it may not be valid | |
2753 * anymore after sending to TX. | |
2754 */ | |
2755 sig_u_t200_start_req (ll_unitdata_req, GRLC_DTACS_DEF); | |
2756 | |
2757 sig_u_tx_data_req (ll_unitdata_req, GRLC_DTACS_DEF); | |
2758 } | |
2759 #endif | |
2760 return; | |
2761 } /* u_send_sabm() */ | |
2762 | |
2763 | |
2764 /* | |
2765 +------------------------------------------------------------------------------ | |
2766 | Function : u_send_disc | |
2767 +------------------------------------------------------------------------------ | |
2768 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
2769 | the required parameters, builds an U frame header containing | |
2770 | an DISC command, and sends this primitive to TX. _Before_ it is | |
2771 | sent to TX, T200 has to be started, because otherwise the | |
2772 | primitive may not be valid anymore. | |
2773 | | |
2774 | Parameters : | |
2775 | | |
2776 +------------------------------------------------------------------------------ | |
2777 */ | |
2778 GLOBAL void u_send_disc (void) | |
2779 { | |
2780 #ifdef LL_DESC | |
2781 T_desc3* desc3; | |
2782 #endif | |
2783 TRACE_FUNCTION( "u_send_disc" ); | |
2784 | |
2785 { | |
2786 #ifndef LL_DESC | |
2787 PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, | |
2788 U_HDR_SIZE_BITS + FCS_SIZE_BITS); | |
2789 #else | |
2790 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ); | |
2791 | |
2792 desc3 = llc_palloc_desc((U_HDR_SIZE_BITS + FCS_SIZE_BITS)/8, 0); | |
2793 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
2794 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
2795 #endif | |
2796 | |
2797 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
2798 ll_unitdesc_req->tlli = llc_data->u->current_tlli; | |
2799 /* | |
2800 * No attach to primitive necessary. For retransmission prim | |
2801 * data is copied in T200. | |
2802 */ | |
2803 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
2804 /* | |
2805 * LLC does not know the QoS profile. | |
2806 */ | |
2807 ll_unitdesc_req->ll_qos = llc_data->cur_qos; | |
2808 | |
2809 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak); | |
2810 | |
2811 /* | |
2812 * LLC signalling frames are always sent with highest priority. | |
2813 */ | |
2814 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio; | |
2815 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio); | |
2816 | |
2817 #ifdef REL99 | |
2818 /* | |
2819 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
2820 * predefined PFI LL_PFI_SIGNALING shall be used. | |
2821 */ | |
2822 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi; | |
2823 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi); | |
2824 | |
2825 #endif /* REL99 */ | |
2826 | |
2827 | |
2828 u_build_u_frame | |
2829 ( | |
2830 #ifndef LL_DESC | |
2831 &ll_unitdesc_req->sdu, | |
2832 #else | |
2833 &ll_unitdesc_req->desc_list3, | |
2834 #endif | |
2835 MS_COMMAND, | |
2836 llc_data->current_sapi, 1, U_DISC | |
2837 ); | |
2838 | |
2839 /* | |
2840 * T200 has to be started _before_ the primitive is sent to TX, because | |
2841 * the primitive is copied by t200_start() and it may not be valid | |
2842 * anymore after sending to TX. | |
2843 */ | |
2844 sig_u_t200_start_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
2845 | |
2846 sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
2847 } | |
2848 | |
2849 return; | |
2850 } /* u_send_disc() */ | |
2851 | |
2852 #ifdef REL99 | |
2853 /* | |
2854 +------------------------------------------------------------------------------ | |
2855 | Function : sig_tx_u_send_null | |
2856 +------------------------------------------------------------------------------ | |
2857 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
2858 | the required parameters, builds an U frame header containing | |
2859 | an NULL command, and sends this primitive to TX. | |
2860 | | |
2861 | Parameters : cause - frame cause indicates grr about cell notification | |
2862 | | |
2863 +------------------------------------------------------------------------------ | |
2864 */ | |
2865 GLOBAL void sig_tx_u_send_null (UBYTE cause) | |
2866 { | |
2867 #ifdef LL_DESC | |
2868 T_desc3* desc3; | |
2869 #endif | |
2870 TRACE_FUNCTION( "sig_tx_u_send_null" ); | |
2871 | |
2872 { | |
2873 #ifndef LL_DESC | |
2874 PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, | |
2875 U_HDR_SIZE_BITS + FCS_SIZE_BITS); | |
2876 #else | |
2877 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ); | |
2878 desc3 = llc_palloc_desc((U_HDR_SIZE_BITS + FCS_SIZE_BITS)/8, 0); | |
2879 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
2880 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
2881 #endif | |
2882 /* | |
2883 * Set TLLI for current transaction. | |
2884 */ | |
2885 llc_data->u->current_tlli = llc_data->tlli_new; | |
2886 | |
2887 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
2888 ll_unitdesc_req->tlli = llc_data->u->current_tlli; | |
2889 /* | |
2890 * No attach to primitive necessary. For retransmission prim | |
2891 * data is copied in T200. | |
2892 */ | |
2893 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
2894 /* | |
2895 * LLC does not know the QoS profile. | |
2896 */ | |
2897 ll_unitdesc_req->ll_qos.peak = GRLC_PEAK_SUB; | |
2898 /* | |
2899 * LLC signalling frames are always sent with highest priority. | |
2900 */ | |
2901 ll_unitdesc_req->radio_prio = GRLC_RADIO_PRIO_1; | |
2902 | |
2903 u_build_u_frame | |
2904 ( | |
2905 #ifndef LL_DESC | |
2906 &ll_unitdesc_req->sdu, | |
2907 #else | |
2908 &ll_unitdesc_req->desc_list3, | |
2909 #endif | |
2910 MS_COMMAND, | |
2911 llc_data->current_sapi, 0, U_NULL | |
2912 ); | |
2913 | |
2914 sig_u_tx_data_req (ll_unitdesc_req, cause); | |
2915 } | |
2916 return; | |
2917 } /* sig_tx_u_send_null() */ | |
2918 | |
2919 #endif /* REL99 */ | |
2920 /* | |
2921 +------------------------------------------------------------------------------ | |
2922 | Function : u_send_ua | |
2923 +------------------------------------------------------------------------------ | |
2924 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
2925 | the required parameters, builds an U frame header containing | |
2926 | an UA response with the given pf_bit setting, and sends this | |
2927 | primitive to TX. The parameter include_xid indicates if an | |
2928 | XID information field (according to llc_xid_tag) shall be | |
2929 | included (=TRUE) or not. | |
2930 | | |
2931 | Parameters : pf_bit - setting of the P/F bit in the received command | |
2932 | include_xid - include XID information field in frame, or not | |
2933 | | |
2934 +------------------------------------------------------------------------------ | |
2935 */ | |
2936 GLOBAL void u_send_ua (T_BIT pf_bit, | |
2937 BOOL include_xid) | |
2938 { | |
2939 #ifdef LL_DESC | |
2940 T_desc3* desc3; | |
2941 #endif | |
2942 USHORT byte_len = 0; | |
2943 | |
2944 | |
2945 TRACE_FUNCTION( "u_send_ua" ); | |
2946 | |
2947 if (include_xid EQ TRUE) | |
2948 { | |
2949 | |
2950 u_tag_xid_parameters(1, TRUE); | |
2951 | |
2952 /* | |
2953 * Calculate bit length of tagged XID parameters. First, add | |
2954 * the size of each tagged parameter. The size of layer-3 | |
2955 * parameters is variable, so add the given length in octets. | |
2956 */ | |
2957 ADD_IF_TAGGED (byte_len, XID_VERSION); | |
2958 ADD_IF_TAGGED (byte_len, XID_T200); | |
2959 ADD_IF_TAGGED (byte_len, XID_N200); | |
2960 ADD_IF_TAGGED (byte_len, XID_N201_U); | |
2961 ADD_IF_TAGGED (byte_len, XID_N201_I); | |
2962 ADD_IF_TAGGED (byte_len, XID_MD); | |
2963 ADD_IF_TAGGED (byte_len, XID_MU); | |
2964 ADD_IF_TAGGED (byte_len, XID_KD); | |
2965 ADD_IF_TAGGED (byte_len, XID_KU); | |
2966 if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3)) | |
2967 { | |
2968 byte_len += llc_data->requested_l3_xid->length + 2; | |
2969 } | |
2970 } | |
2971 | |
2972 /* | |
2973 * Add data header and FCS field to the XID response size to get | |
2974 * the overall data size. | |
2975 */ | |
2976 byte_len += U_HDR_SIZE + FCS_SIZE; | |
2977 | |
2978 { | |
2979 #ifndef LL_DESC | |
2980 PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, (USHORT)(byte_len*8)); | |
2981 #else | |
2982 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ); | |
2983 | |
2984 desc3 = llc_palloc_desc((USHORT)(byte_len), 0); | |
2985 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
2986 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
2987 | |
2988 #endif | |
2989 | |
2990 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
2991 ll_unitdesc_req->tlli = llc_data->u->current_tlli; | |
2992 /* | |
2993 * No attach to primitive necessary. There is no retransmission. | |
2994 */ | |
2995 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
2996 /* | |
2997 * LLC does not know the QoS profile. | |
2998 */ | |
2999 ll_unitdesc_req->ll_qos = llc_data->cur_qos; | |
3000 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak); | |
3001 | |
3002 /* | |
3003 * LLC signalling frames are always sent with highest priority. | |
3004 */ | |
3005 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio; | |
3006 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio); | |
3007 | |
3008 #ifdef REL99 | |
3009 /* | |
3010 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
3011 * predefined PFI LL_PFI_SIGNALING shall be used. | |
3012 */ | |
3013 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi; | |
3014 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi); | |
3015 #endif /* REL99 */ | |
3016 | |
3017 u_build_u_frame | |
3018 ( | |
3019 #ifndef LL_DESC | |
3020 &ll_unitdesc_req->sdu, | |
3021 #else | |
3022 &ll_unitdesc_req->desc_list3, | |
3023 #endif | |
3024 MS_RESPONSE, llc_data->current_sapi, pf_bit, U_UA | |
3025 ); | |
3026 | |
3027 if (include_xid EQ TRUE) | |
3028 { | |
3029 u_insert_xid | |
3030 ( | |
3031 #ifndef LL_DESC | |
3032 &ll_unitdesc_req->sdu, | |
3033 #else | |
3034 &ll_unitdesc_req->desc_list3, | |
3035 #endif | |
3036 MS_RESPONSE | |
3037 ); | |
3038 } | |
3039 | |
3040 sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
3041 } | |
3042 | |
3043 llc_init_requested_xid_sapi(llc_data->current_sapi); | |
3044 return; | |
3045 } /* u_send_ua() */ | |
3046 | |
3047 | |
3048 /* | |
3049 +------------------------------------------------------------------------------ | |
3050 | Function : u_send_dm | |
3051 +------------------------------------------------------------------------------ | |
3052 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
3053 | all required parameters, builds an U frame header containing a | |
3054 | DM response with the given pf_bit setting, and sends this | |
3055 | primitive to TX. | |
3056 | | |
3057 | Parameters : pf_bit - setting of the P/F bit in the received command | |
3058 | | |
3059 +------------------------------------------------------------------------------ | |
3060 */ | |
3061 GLOBAL void u_send_dm (T_BIT pf_bit) | |
3062 { | |
3063 #ifdef LL_DESC | |
3064 T_desc3* desc3; | |
3065 #endif | |
3066 | |
3067 TRACE_FUNCTION( "u_send_dm" ); | |
3068 | |
3069 { | |
3070 #ifndef LL_DESC | |
3071 PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, | |
3072 U_DM_SIZE_BITS + FCS_SIZE_BITS); | |
3073 #else | |
3074 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ); | |
3075 | |
3076 desc3 = llc_palloc_desc((U_DM_SIZE_BITS + FCS_SIZE_BITS)/8, 0); | |
3077 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
3078 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
3079 #endif | |
3080 | |
3081 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
3082 ll_unitdesc_req->tlli = llc_data->u->current_tlli; | |
3083 /* | |
3084 * No attach to primitive necessary. There is no retransmission. | |
3085 */ | |
3086 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
3087 /* | |
3088 * LLC does not know the QoS profile. | |
3089 */ | |
3090 ll_unitdesc_req->ll_qos = llc_data->cur_qos; | |
3091 | |
3092 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak); | |
3093 | |
3094 | |
3095 /* | |
3096 * LLC signalling frames are always sent with highest priority. | |
3097 */ | |
3098 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio; | |
3099 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio); | |
3100 | |
3101 #ifdef REL99 | |
3102 /* | |
3103 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
3104 * predefined PFI LL_PFI_SIGNALING shall be used. | |
3105 */ | |
3106 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi; | |
3107 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi); | |
3108 | |
3109 #endif /* REL99 */ | |
3110 | |
3111 u_build_u_frame | |
3112 ( | |
3113 #ifndef LL_DESC | |
3114 &ll_unitdesc_req->sdu, | |
3115 #else | |
3116 &ll_unitdesc_req->desc_list3, | |
3117 #endif | |
3118 MS_RESPONSE, | |
3119 llc_data->current_sapi, pf_bit, U_DM | |
3120 ); | |
3121 | |
3122 sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
3123 } | |
3124 | |
3125 return; | |
3126 } /* u_send_dm() */ | |
3127 | |
3128 | |
3129 /* | |
3130 +------------------------------------------------------------------------------ | |
3131 | Function : u_send_frmr | |
3132 +------------------------------------------------------------------------------ | |
3133 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
3134 | the required parameters, builds an U frame header containing | |
3135 | an FRMR response, fills in the FRMR information field based on | |
3136 | the given frame, vs, vr, the cr_bit setting of frame | |
3137 | (SGSN_COMMAND/REPONSE), and the reason of the frame rejection | |
3138 | condition (lower nibble conforms to W4-W1 in FRMR response). | |
3139 | This primitive is then sent to TX. | |
3140 | | |
3141 | Parameters : frame - frame that caused the frame rejection condition | |
3142 | pdu_type - frame type | |
3143 | ctrl_length - control field length, if known | |
3144 | vs - current V(S) | |
3145 | vr - current V(R) | |
3146 | cr_bit - setting of C/R bit in frame | |
3147 | reason - reason of the frame rejection condition (lower | |
3148 | nibble conforms to W4-W1 in FRMR response) | |
3149 | | |
3150 +------------------------------------------------------------------------------ | |
3151 */ | |
3152 GLOBAL void u_send_frmr (T_LL_UNITDATA_IND *frame, | |
3153 T_PDU_TYPE pdu_type, | |
3154 USHORT ctrl_length, | |
3155 T_FRAME_NUM vs, | |
3156 T_FRAME_NUM vr, | |
3157 T_BIT cr_bit, | |
3158 UBYTE reason) | |
3159 { | |
3160 #ifdef LL_DESC | |
3161 T_desc3* desc3; | |
3162 #endif | |
3163 | |
3164 TRACE_FUNCTION( "u_send_frmr" ); | |
3165 | |
3166 { | |
3167 #ifndef LL_DESC | |
3168 PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, | |
3169 U_FRMR_SIZE_BITS + FCS_SIZE_BITS); | |
3170 #else | |
3171 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ); | |
3172 | |
3173 desc3 = llc_palloc_desc((U_FRMR_SIZE_BITS + FCS_SIZE_BITS)/8, 0); | |
3174 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
3175 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
3176 #endif | |
3177 | |
3178 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
3179 ll_unitdesc_req->tlli = llc_data->u->current_tlli; | |
3180 /* | |
3181 * No attach to primitive necessary. There is no retransmission. | |
3182 */ | |
3183 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
3184 /* | |
3185 * LLC does not know the QoS profile. | |
3186 */ | |
3187 ll_unitdesc_req->ll_qos = llc_data->cur_qos; | |
3188 | |
3189 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak); | |
3190 | |
3191 | |
3192 /* | |
3193 * LLC signalling frames are always sent with highest priority. | |
3194 */ | |
3195 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio; | |
3196 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio); | |
3197 | |
3198 #ifdef REL99 | |
3199 /* | |
3200 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
3201 * predefined PFI LL_PFI_SIGNALING shall be used. | |
3202 */ | |
3203 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi; | |
3204 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi); | |
3205 | |
3206 #endif /* REL99 */ | |
3207 | |
3208 u_build_u_frame | |
3209 ( | |
3210 #ifndef LL_DESC | |
3211 &ll_unitdesc_req->sdu, | |
3212 #else | |
3213 &ll_unitdesc_req->desc_list3, | |
3214 #endif | |
3215 MS_RESPONSE, | |
3216 llc_data->current_sapi, 1, U_FRMR | |
3217 ); | |
3218 | |
3219 u_insert_frmr_information | |
3220 ( | |
3221 #ifndef LL_DESC | |
3222 &ll_unitdesc_req->sdu, | |
3223 #else | |
3224 &ll_unitdesc_req->desc_list3, | |
3225 #endif | |
3226 frame, pdu_type, | |
3227 ctrl_length, vs, vr, cr_bit, reason | |
3228 ); | |
3229 | |
3230 sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
3231 } | |
3232 | |
3233 return; | |
3234 } /* u_send_frmr() */ | |
3235 | |
3236 | |
3237 /* | |
3238 +------------------------------------------------------------------------------ | |
3239 | Function : u_send_llgmm_status_ind | |
3240 +------------------------------------------------------------------------------ | |
3241 | Description : This procedure allocates an LLGMM_STATUS_IND primitive, fills | |
3242 | in the error_cause parameter, and sends this primitive to GMM. | |
3243 | | |
3244 | Parameters : error_cause - LLGMM error cause | |
3245 | | |
3246 +------------------------------------------------------------------------------ | |
3247 */ | |
3248 #ifdef CC_CONCEPT | |
3249 GLOBAL void u_send_llgmm_status_ind (USHORT error_cause) | |
3250 #else | |
3251 GLOBAL void u_send_llgmm_status_ind (UBYTE error_cause) | |
3252 #endif | |
3253 { | |
3254 TRACE_FUNCTION( "u_send_llgmm_status_ind" ); | |
3255 | |
3256 { | |
3257 PALLOC (llgmm_status_ind, LLGMM_STATUS_IND); /* T_LLGMM_STATUS_IND */ | |
3258 | |
3259 #ifdef LL_2to1 | |
3260 llgmm_status_ind->ps_cause.ctrl_value = CAUSE_is_from_llc; | |
3261 llgmm_status_ind->ps_cause.value.llc_cause = error_cause; | |
3262 #else | |
3263 llgmm_status_ind->error_cause = error_cause; | |
3264 #endif | |
3265 | |
3266 PSEND (hCommGMM, llgmm_status_ind); | |
3267 } | |
3268 | |
3269 return; | |
3270 } /* u_send_llgmm_status_ind() */ | |
3271 | |
3272 | |
3273 /* | |
3274 +------------------------------------------------------------------------------ | |
3275 | Function : u_send_ll_release_cnf | |
3276 +------------------------------------------------------------------------------ | |
3277 | Description : This procedure allocates an LL_RELEASE_CNF primitive, fills in | |
3278 | tlli and sapi parameters, and sends this primitive to SNDCP. | |
3279 | | |
3280 | Parameters : | |
3281 | | |
3282 +------------------------------------------------------------------------------ | |
3283 */ | |
3284 GLOBAL void u_send_ll_release_cnf (void) | |
3285 { | |
3286 TRACE_FUNCTION( "u_send_ll_release_cnf" ); | |
3287 | |
3288 { | |
3289 PALLOC (ll_release_cnf, LL_RELEASE_CNF); | |
3290 | |
3291 ll_release_cnf->sapi = llc_data->current_sapi; | |
3292 TRACE_1_OUT_PARA("s:%d", llc_data->current_sapi ); | |
3293 PSEND (hCommSNDCP, ll_release_cnf); | |
3294 } | |
3295 | |
3296 llc_data->u->release_requested = FALSE; | |
3297 | |
3298 return; | |
3299 } /* u_send_ll_release_cnf() */ | |
3300 | |
3301 | |
3302 | |
3303 /* | |
3304 +------------------------------------------------------------------------------ | |
3305 | Function : u_send_ll_status_ind | |
3306 +------------------------------------------------------------------------------ | |
3307 | Description : This procedure allocates an LL_STATUS_IND primitive, fills in | |
3308 | tlli, sapi and cause parameters and sends this proimitive to L3 | |
3309 | | |
3310 | Parameters : cause - LL error cause | |
3311 | | |
3312 +------------------------------------------------------------------------------ | |
3313 */ | |
3314 #ifdef CC_CONCEPT | |
3315 GLOBAL void u_send_ll_status_ind (USHORT cause) | |
3316 #else | |
3317 GLOBAL void u_send_ll_status_ind (UBYTE cause) | |
3318 #endif | |
3319 { | |
3320 TRACE_FUNCTION( "u_send_ll_status_ind" ); | |
3321 | |
3322 { | |
3323 PALLOC (ll_status_ind, LL_STATUS_IND); | |
3324 | |
3325 ll_status_ind->sapi = llc_data->current_sapi; | |
3326 #ifdef LL_2to1 | |
3327 ll_status_ind->ps_cause.ctrl_value = CAUSE_is_from_llc; | |
3328 ll_status_ind->ps_cause.value.llc_cause = cause; | |
3329 #else | |
3330 ll_status_ind->error_cause = cause; | |
3331 #endif | |
3332 | |
3333 TRACE_1_OUT_PARA("s:%d", llc_data->current_sapi ); | |
3334 PSEND (hCommSNDCP, ll_status_ind); | |
3335 } | |
3336 | |
3337 return; | |
3338 } /* u_send_ll_status_ind() */ | |
3339 | |
3340 | |
3341 | |
3342 /* | |
3343 +------------------------------------------------------------------------------ | |
3344 | Function : u_send_ll_xid_cnf | |
3345 +------------------------------------------------------------------------------ | |
3346 | Description : This procedure allocates an LL_XID_CNF primitive, fills in | |
3347 | tlli, sapi and L3 parameter (if being negotiated), and sends | |
3348 | this primitive to SNDCP | |
3349 | | |
3350 | Parameters : | |
3351 | | |
3352 +------------------------------------------------------------------------------ | |
3353 */ | |
3354 GLOBAL void u_send_ll_xid_cnf (void) | |
3355 { | |
3356 TRACE_FUNCTION( "u_send_ll_xid_cnf" ); | |
3357 | |
3358 if (llc_data->decoded_l3_xid.valid EQ TRUE) | |
3359 { | |
3360 PALLOC_SDU (ll_xid_cnf, LL_XID_CNF, (USHORT)(llc_data->decoded_l3_xid.length * 8)); | |
3361 | |
3362 ll_xid_cnf->sdu.l_buf = llc_data->decoded_l3_xid.length * 8; | |
3363 ll_xid_cnf->sdu.o_buf = 0; | |
3364 | |
3365 memcpy (ll_xid_cnf->sdu.buf, | |
3366 llc_data->decoded_l3_xid.value, | |
3367 llc_data->decoded_l3_xid.length); | |
3368 | |
3369 ll_xid_cnf->sapi = llc_data->current_sapi; | |
3370 | |
3371 ll_xid_cnf->n201_u = *(llc_data->n201_u); | |
3372 ll_xid_cnf->n201_i = *(llc_data->n201_i); | |
3373 | |
3374 TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, llc_data->decoded_l3_xid.length ); | |
3375 PSEND (hCommSNDCP, ll_xid_cnf); | |
3376 } | |
3377 else | |
3378 { | |
3379 PALLOC_SDU (ll_xid_cnf, LL_XID_CNF, 0); | |
3380 | |
3381 ll_xid_cnf->sdu.l_buf = 0; | |
3382 ll_xid_cnf->sdu.o_buf = 0; | |
3383 | |
3384 ll_xid_cnf->sapi = llc_data->current_sapi; | |
3385 | |
3386 ll_xid_cnf->n201_u = *(llc_data->n201_u); | |
3387 ll_xid_cnf->n201_i = *(llc_data->n201_i); | |
3388 | |
3389 TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, 0 ); | |
3390 PSEND (hCommSNDCP, ll_xid_cnf); | |
3391 } | |
3392 | |
3393 return; | |
3394 } /* u_send_ll_xid_cnf() */ | |
3395 | |
3396 | |
3397 /* | |
3398 +------------------------------------------------------------------------------ | |
3399 | Function : u_send_ll_establish_ind | |
3400 +------------------------------------------------------------------------------ | |
3401 | Description : This procedure allocates an LL_ESTABLISH_IND primitive, fills | |
3402 | in all necessary parameters using global LLC values (or in case | |
3403 | of L-3 XID parameters, using the parameters of received XID | |
3404 | cmd/res), and sends this primitive to SNDCP | |
3405 | | |
3406 | Parameters : | |
3407 | | |
3408 +------------------------------------------------------------------------------ | |
3409 */ | |
3410 GLOBAL void u_send_ll_establish_ind (void) | |
3411 { | |
3412 USHORT len; | |
3413 | |
3414 TRACE_FUNCTION( "u_send_ll_establish_ind" ); | |
3415 | |
3416 if (llc_data->decoded_l3_xid.valid EQ TRUE) | |
3417 { | |
3418 len = (llc_data->decoded_l3_xid.length * 8); | |
3419 } | |
3420 else | |
3421 { | |
3422 len = 0; | |
3423 } | |
3424 | |
3425 { | |
3426 PALLOC_SDU (ll_establish_ind, LL_ESTABLISH_IND, len); | |
3427 | |
3428 if (llc_data->decoded_l3_xid.valid EQ TRUE) | |
3429 { | |
3430 ll_establish_ind->xid_valid = LL_XID_VALID; | |
3431 | |
3432 ll_establish_ind->sdu.o_buf = 0; | |
3433 ll_establish_ind->sdu.l_buf = llc_data->decoded_l3_xid.length * 8; | |
3434 | |
3435 memcpy (ll_establish_ind->sdu.buf, | |
3436 llc_data->decoded_l3_xid.value, | |
3437 llc_data->decoded_l3_xid.length); | |
3438 } | |
3439 else | |
3440 { | |
3441 ll_establish_ind->xid_valid = LL_XID_INVALID; | |
3442 } | |
3443 | |
3444 ll_establish_ind->sapi = llc_data->current_sapi; | |
3445 | |
3446 /* | |
3447 * evaluate N201_U | |
3448 */ | |
3449 if (llc_data->u->requested_xid.n201_u.valid AND | |
3450 llc_data->decoded_xid.n201_u.valid AND | |
3451 !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U, | |
3452 llc_data->decoded_xid.n201_u.value)) | |
3453 { | |
3454 ll_establish_ind->n201_u = llc_data->u->requested_xid.n201_u.value; | |
3455 } | |
3456 else if (llc_data->u->requested_xid.n201_u.valid AND | |
3457 !llc_data->decoded_xid.n201_u.valid AND | |
3458 !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U, | |
3459 *(llc_data->n201_u))) | |
3460 { | |
3461 ll_establish_ind->n201_u = llc_data->u->requested_xid.n201_u.value; | |
3462 } | |
3463 else | |
3464 { | |
3465 ll_establish_ind->n201_u = *(llc_data->n201_u); | |
3466 } | |
3467 | |
3468 /* | |
3469 * evaluate N201_I | |
3470 */ | |
3471 if (llc_data->u->requested_xid.n201_i.valid AND | |
3472 llc_data->decoded_xid.n201_i.valid AND | |
3473 !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I, | |
3474 llc_data->decoded_xid.n201_i.value)) | |
3475 { | |
3476 ll_establish_ind->n201_i = llc_data->u->requested_xid.n201_i.value; | |
3477 } | |
3478 else if (llc_data->u->requested_xid.n201_i.valid AND | |
3479 !llc_data->decoded_xid.n201_i.valid AND | |
3480 !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I, | |
3481 *(llc_data->n201_i))) | |
3482 { | |
3483 ll_establish_ind->n201_i = llc_data->u->requested_xid.n201_i.value; | |
3484 } | |
3485 else | |
3486 { | |
3487 ll_establish_ind->n201_i = *(llc_data->n201_i); | |
3488 } | |
3489 | |
3490 | |
3491 TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_establish_ind->sapi, len/8); | |
3492 PSEND (hCommSNDCP, ll_establish_ind); | |
3493 | |
3494 return; | |
3495 } | |
3496 } /* u_send_ll_establish_ind() */ | |
3497 | |
3498 | |
3499 | |
3500 /* | |
3501 +------------------------------------------------------------------------------ | |
3502 | Function : u_send_ll_establish_cnf | |
3503 +------------------------------------------------------------------------------ | |
3504 | Description : This procedure allocates an LL_ESTABLISH_CNF primitive, fills | |
3505 | in all necessary parameters using global LLC values (or in case | |
3506 | of L-3 XID parameters, using the parameters of received XID | |
3507 | cmd/res), and sends this primitive to SNDCP | |
3508 | | |
3509 | Parameters : | |
3510 | | |
3511 +------------------------------------------------------------------------------ | |
3512 */ | |
3513 GLOBAL void u_send_ll_establish_cnf (void) | |
3514 { | |
3515 TRACE_FUNCTION( "u_send_ll_establish_cnf" ); | |
3516 | |
3517 if (llc_data->decoded_l3_xid.valid EQ TRUE) | |
3518 { | |
3519 PALLOC_SDU (ll_establish_cnf, LL_ESTABLISH_CNF, | |
3520 (USHORT)(llc_data->decoded_l3_xid.length * 8)); | |
3521 | |
3522 ll_establish_cnf->xid_valid = LL_XID_VALID; | |
3523 | |
3524 ll_establish_cnf->sdu.o_buf = 0; | |
3525 ll_establish_cnf->sdu.l_buf = llc_data->decoded_l3_xid.length * 8; | |
3526 | |
3527 memcpy (ll_establish_cnf->sdu.buf, | |
3528 llc_data->decoded_l3_xid.value, | |
3529 llc_data->decoded_l3_xid.length); | |
3530 | |
3531 ll_establish_cnf->sapi = llc_data->current_sapi; | |
3532 | |
3533 ll_establish_cnf->n201_u = *(llc_data->n201_u); | |
3534 ll_establish_cnf->n201_i = *(llc_data->n201_i); | |
3535 | |
3536 TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, llc_data->decoded_l3_xid.length ); | |
3537 PSEND (hCommSNDCP, ll_establish_cnf); | |
3538 } | |
3539 else | |
3540 { | |
3541 PALLOC_SDU (ll_establish_cnf, LL_ESTABLISH_CNF, 0); | |
3542 | |
3543 ll_establish_cnf->xid_valid = LL_XID_INVALID; | |
3544 | |
3545 ll_establish_cnf->sapi = llc_data->current_sapi; | |
3546 | |
3547 ll_establish_cnf->n201_u = *(llc_data->n201_u); | |
3548 ll_establish_cnf->n201_i = *(llc_data->n201_i); | |
3549 | |
3550 TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, 0 ); | |
3551 PSEND (hCommSNDCP, ll_establish_cnf); | |
3552 } | |
3553 | |
3554 return; | |
3555 } /* u_send_ll_establish_cnf() */ | |
3556 | |
3557 | |
3558 /* | |
3559 +------------------------------------------------------------------------------ | |
3560 | Function : u_send_ll_release_ind | |
3561 +------------------------------------------------------------------------------ | |
3562 | Description : This procedure allocates an LL_RELEASE_IND primitive, fills | |
3563 | in tlli, sapi and cause parameters, and sends this primitive | |
3564 | to SNDCP | |
3565 | | |
3566 | Parameters : cause - LL error cause | |
3567 | | |
3568 +------------------------------------------------------------------------------ | |
3569 */ | |
3570 #ifdef CC_CONCEPT | |
3571 GLOBAL void u_send_ll_release_ind (USHORT cause) | |
3572 #else | |
3573 GLOBAL void u_send_ll_release_ind (UBYTE cause) | |
3574 #endif | |
3575 { | |
3576 TRACE_FUNCTION( "u_send_ll_release_ind" ); | |
3577 | |
3578 { | |
3579 PALLOC (ll_release_ind, LL_RELEASE_IND); | |
3580 | |
3581 ll_release_ind->sapi = llc_data->current_sapi; | |
3582 #ifdef LL_2to1 | |
3583 ll_release_ind->ps_cause.ctrl_value = CAUSE_is_from_llc; | |
3584 ll_release_ind->ps_cause.value.llc_cause = cause; | |
3585 #else | |
3586 ll_release_ind->cause = cause; | |
3587 #endif | |
3588 | |
3589 TRACE_1_OUT_PARA("s:%d", llc_data->current_sapi ); | |
3590 PSEND (hCommSNDCP, ll_release_ind); | |
3591 } | |
3592 | |
3593 llc_data->u->release_requested = FALSE; | |
3594 | |
3595 return; | |
3596 } /* u_send_ll_release_ind() */ | |
3597 | |
3598 | |
3599 | |
3600 /* | |
3601 +------------------------------------------------------------------------------ | |
3602 | Function : u_send_ll_xid_ind | |
3603 +------------------------------------------------------------------------------ | |
3604 | Description : This procedure allocates an LL_XID_IND primitive, fills | |
3605 | in all necessary parameters using global LLC values (or in case | |
3606 | of L-3 XID parameters, using the parameters of received XID | |
3607 | cmd/res), and sends this primitive to SNDCP | |
3608 | | |
3609 | Parameters : | |
3610 | | |
3611 +------------------------------------------------------------------------------ | |
3612 */ | |
3613 GLOBAL void u_send_ll_xid_ind (void) | |
3614 { | |
3615 TRACE_FUNCTION( "u_send_ll_xid_ind" ); | |
3616 | |
3617 | |
3618 | |
3619 if (llc_data->decoded_l3_xid.valid EQ TRUE) | |
3620 { | |
3621 PALLOC_SDU (ll_xid_ind, LL_XID_IND, (USHORT)(llc_data->decoded_l3_xid.length * 8)); | |
3622 | |
3623 llc_data->u->ll_xid_resp_pending = TRUE; | |
3624 ll_xid_ind->xid_valid = LL_XID_VALID; | |
3625 | |
3626 ll_xid_ind->sdu.o_buf = 0; | |
3627 ll_xid_ind->sdu.l_buf = llc_data->decoded_l3_xid.length * 8; | |
3628 | |
3629 memcpy (ll_xid_ind->sdu.buf, | |
3630 llc_data->decoded_l3_xid.value, | |
3631 llc_data->decoded_l3_xid.length); | |
3632 | |
3633 ll_xid_ind->sapi = llc_data->current_sapi; | |
3634 | |
3635 if (llc_data->u->requested_xid.n201_u.valid AND | |
3636 !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U, | |
3637 llc_data->decoded_xid.n201_u.value)) | |
3638 { | |
3639 ll_xid_ind->n201_u = llc_data->u->requested_xid.n201_u.value; | |
3640 } | |
3641 else | |
3642 { | |
3643 ll_xid_ind->n201_u = *(llc_data->n201_u); | |
3644 } | |
3645 | |
3646 switch (ll_xid_ind->sapi) | |
3647 { | |
3648 case LL_SAPI_3: | |
3649 case LL_SAPI_5: | |
3650 case LL_SAPI_9: | |
3651 case LL_SAPI_11: | |
3652 if (llc_data->u->requested_xid.n201_i.valid AND | |
3653 !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I, | |
3654 llc_data->decoded_xid.n201_i.value)) | |
3655 { | |
3656 ll_xid_ind->n201_i = llc_data->u->requested_xid.n201_i.value; | |
3657 } | |
3658 else | |
3659 { | |
3660 ll_xid_ind->n201_i = *(llc_data->n201_i); | |
3661 } | |
3662 break; | |
3663 | |
3664 default: | |
3665 ll_xid_ind->n201_i = 0; | |
3666 break; | |
3667 } | |
3668 | |
3669 /* | |
3670 * Send primitive LL_XID_IND to either GMM, SNDCP, or GSMS, | |
3671 * depending on SAPI. | |
3672 */ | |
3673 switch (ll_xid_ind->sapi) | |
3674 { | |
3675 case LL_SAPI_1: | |
3676 TRACE_PRIM_TO("GMM"); | |
3677 TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length); | |
3678 PSEND (hCommGMM, ll_xid_ind); | |
3679 break; | |
3680 case LL_SAPI_3: | |
3681 case LL_SAPI_5: | |
3682 case LL_SAPI_9: | |
3683 case LL_SAPI_11: | |
3684 TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length); | |
3685 PSEND (hCommSNDCP, ll_xid_ind); | |
3686 break; | |
3687 case LL_SAPI_7: | |
3688 #ifdef LL_2to1 | |
3689 TRACE_PRIM_TO("MM"); | |
3690 TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length); | |
3691 PSEND (hCommMM, ll_xid_ind); | |
3692 #else | |
3693 TRACE_PRIM_TO("GSMS"); | |
3694 TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length); | |
3695 PSEND (hCommGSMS, ll_xid_ind); | |
3696 #endif | |
3697 break; | |
3698 default: | |
3699 PFREE (ll_xid_ind); | |
3700 TRACE_ERROR ("Invalid global SAPI value"); | |
3701 break; | |
3702 } | |
3703 } | |
3704 else | |
3705 { | |
3706 PALLOC_SDU (ll_xid_ind, LL_XID_IND, 0); | |
3707 | |
3708 llc_data->u->ll_xid_resp_pending = FALSE; | |
3709 | |
3710 ll_xid_ind->xid_valid = LL_XID_INVALID; | |
3711 | |
3712 ll_xid_ind->sapi = llc_data->current_sapi; | |
3713 | |
3714 ll_xid_ind->n201_u = *(llc_data->n201_u); | |
3715 | |
3716 switch (ll_xid_ind->sapi) | |
3717 { | |
3718 case LL_SAPI_3: | |
3719 case LL_SAPI_5: | |
3720 case LL_SAPI_9: | |
3721 case LL_SAPI_11: | |
3722 ll_xid_ind->n201_i = *(llc_data->n201_i); | |
3723 break; | |
3724 | |
3725 default: | |
3726 ll_xid_ind->n201_i = 0; | |
3727 break; | |
3728 } | |
3729 | |
3730 /* | |
3731 * Send primitive LL_XID_IND to either GMM, SNDCP, or GSMS, | |
3732 * depending on SAPI. | |
3733 */ | |
3734 switch (ll_xid_ind->sapi) | |
3735 { | |
3736 case LL_SAPI_1: | |
3737 TRACE_PRIM_TO("GMM"); | |
3738 TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi); | |
3739 PSEND (hCommGMM, ll_xid_ind); | |
3740 break; | |
3741 case LL_SAPI_3: | |
3742 case LL_SAPI_5: | |
3743 case LL_SAPI_9: | |
3744 case LL_SAPI_11: | |
3745 TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi); | |
3746 PSEND (hCommSNDCP, ll_xid_ind); | |
3747 break; | |
3748 case LL_SAPI_7: | |
3749 #ifdef LL_2to1 | |
3750 TRACE_PRIM_TO("MM"); | |
3751 TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi); | |
3752 PSEND (hCommMM, ll_xid_ind); | |
3753 #else | |
3754 TRACE_PRIM_TO("GSMS"); | |
3755 TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi); | |
3756 PSEND (hCommGSMS, ll_xid_ind); | |
3757 #endif | |
3758 break; | |
3759 default: | |
3760 PFREE (ll_xid_ind); | |
3761 TRACE_ERROR ("invalid global SAPI value"); | |
3762 break; | |
3763 } | |
3764 } | |
3765 | |
3766 return; | |
3767 } /* u_send_ll_xid_ind() */ | |
3768 | |
3769 | |
3770 /* | |
3771 +------------------------------------------------------------------------------ | |
3772 | Function : u_tag_xid_parameters | |
3773 +------------------------------------------------------------------------------ | |
3774 | Description : This procedure tags requested parameters | |
3775 | | |
3776 | | |
3777 | Parameters : | |
3778 | - send_ack_para- used to include/ignore the ack para in XID-FRAME | |
3779 | | |
3780 +------------------------------------------------------------------------------ | |
3781 */ | |
3782 GLOBAL void u_tag_xid_parameters (T_BIT cr_bit, BOOL send_ack_para) | |
3783 { | |
3784 TRACE_FUNCTION( "u_tag_xid_parameters" ); | |
3785 | |
3786 if (cr_bit EQ MS_RESPONSE) | |
3787 { | |
3788 /* | |
3789 * Do some special handling in case we want to set mD or mU to zero | |
3790 * (= disable buffered bytes counting) and the peer does not. | |
3791 */ | |
3792 if (llc_data->decoded_xid.mu.valid) | |
3793 { | |
3794 u_handle_mX_zero_rsp ( llc_data->decoded_xid.mu.value, | |
3795 llc_data->n201_i, | |
3796 *(llc_data->mu), XID_MU_MAX, | |
3797 llc_data->ku, XID_KU_MIN, XID_KU ); | |
3798 } | |
3799 | |
3800 if (llc_data->decoded_xid.md.valid) | |
3801 { | |
3802 u_handle_mX_zero_rsp ( llc_data->decoded_xid.md.value, | |
3803 llc_data->n201_i, | |
3804 *(llc_data->md), XID_MD_MAX, | |
3805 llc_data->kd, XID_KD_MIN, XID_KD ); | |
3806 } | |
3807 } | |
3808 | |
3809 /* | |
3810 * Tag all possible requested XID parameter | |
3811 */ | |
3812 if (cr_bit EQ MS_COMMAND) | |
3813 { | |
3814 /* | |
3815 * In case we are sending a command, we can include all | |
3816 * parameters, as long they are valid. | |
3817 */ | |
3818 TAG_IF_REQUESTED (u->requested_xid.version. , XID_VERSION); | |
3819 TAG_IF_REQUESTED (u->requested_xid.t200. , XID_T200); | |
3820 TAG_IF_REQUESTED (u->requested_xid.n200. , XID_N200); | |
3821 TAG_IF_REQUESTED (u->requested_xid.n201_u. , XID_N201_U); | |
3822 TAG_IF_REQUESTED (requested_l3_xid-> , XID_LAYER_3); | |
3823 if(send_ack_para) | |
3824 { | |
3825 TRACE_EVENT("COMMAND: ACK MODE PARAMETERS INCLUDED"); | |
3826 TAG_IF_REQUESTED (u->requested_xid.n201_i. , XID_N201_I); | |
3827 TAG_IF_REQUESTED (u->requested_xid.md. , XID_MD); | |
3828 TAG_IF_REQUESTED (u->requested_xid.mu. , XID_MU); | |
3829 TAG_IF_REQUESTED (u->requested_xid.kd. , XID_KD); | |
3830 TAG_IF_REQUESTED (u->requested_xid.ku. , XID_KU); | |
3831 } | |
3832 else | |
3833 { | |
3834 llc_data->u->requested_xid.n201_i.valid = FALSE; | |
3835 llc_data->u->requested_xid.md.valid = FALSE; | |
3836 llc_data->u->requested_xid.mu.valid = FALSE; | |
3837 llc_data->u->requested_xid.kd.valid = FALSE; | |
3838 llc_data->u->requested_xid.ku.valid = FALSE; | |
3839 } | |
3840 | |
3841 } | |
3842 else | |
3843 { | |
3844 /* | |
3845 * In case we are sending a response, we can include all valid | |
3846 * parameters which are in line with the sense of negotiation. | |
3847 */ | |
3848 TAG_IF_REQUESTED_RSP (XID_SENSE_UP, n200, XID_N200); | |
3849 TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, n201_u, XID_N201_U); | |
3850 | |
3851 if(send_ack_para) | |
3852 { | |
3853 TRACE_EVENT("RESPONSE: ACK MODE PARAMETERS INCLUDED"); | |
3854 TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, n201_i, XID_N201_I); | |
3855 TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, md, XID_MD); | |
3856 TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, mu, XID_MU); | |
3857 TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, kd, XID_KD); | |
3858 TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, ku, XID_KU); | |
3859 } | |
3860 | |
3861 if (llc_data->u->requested_xid.t200.valid) | |
3862 { | |
3863 if (llc_data->decoded_xid.t200.valid) | |
3864 { | |
3865 /* simple add parameter. Sense of negotiation is already checked */ | |
3866 llc_data->u->xid_tag |= (0x00000001L << XID_T200); | |
3867 } | |
3868 else | |
3869 { | |
3870 /* Sense of negotiation compared with current values */ | |
3871 if (llc_data->u->requested_xid.t200.value XID_SENSE_UP INT2XID(llc_data->t200->length)) | |
3872 { | |
3873 llc_data->u->xid_tag |= (0x00000001L << XID_T200); | |
3874 } | |
3875 } | |
3876 } | |
3877 /* | |
3878 * L3 parameter cannot be included in response, if not included in | |
3879 * request | |
3880 */ | |
3881 | |
3882 /* | |
3883 * If an XID parameter which was not included in the SGSN command, | |
3884 * but included in the MS Response, must be included in every Response | |
3885 * until the parameter is explicitly negotiated by the SGSN | |
3886 */ | |
3887 | |
3888 if(llc_data->u->xid_tag_negotiate) | |
3889 { | |
3890 llc_data->u->xid_tag |= llc_data->u->xid_tag_negotiate; | |
3891 } | |
3892 } | |
3893 } /* u_tag_xid_parameters() */ | |
3894 | |
3895 /* | |
3896 +------------------------------------------------------------------------------ | |
3897 | Function : u_send_xid | |
3898 +------------------------------------------------------------------------------ | |
3899 | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in | |
3900 | the required parameters, builds an U frame header containing an | |
3901 | XID command/response (depending on the cr_bit setting), inserts | |
3902 | all XID parmameters that are to be negotiated, and sends this | |
3903 | primitive to TX. If a command frame is being sent (see cr_bit), | |
3904 | T200 has to be started _before_ the primitive is sent to TX, | |
3905 | because otherwise the primitive may not be valid anymore. | |
3906 | | |
3907 | NOTE: T200 must not be running, when an XID command is to be | |
3908 | sent. This must be ensured by the caller of u_send_xid(). | |
3909 | | |
3910 | Parameters : | |
3911 | | |
3912 +------------------------------------------------------------------------------ | |
3913 */ | |
3914 GLOBAL void u_send_xid (T_BIT cr_bit) | |
3915 { | |
3916 #ifdef LL_DESC | |
3917 T_desc3* desc3; | |
3918 #endif | |
3919 USHORT byte_len = 0; | |
3920 | |
3921 TRACE_FUNCTION( "u_send_xid" ); | |
3922 | |
3923 /* | |
3924 * Calculate bit length of tagged XID parameters. First, add | |
3925 * the size of each tagged parameter. The size of layer-3 | |
3926 * parameters is variable, so add the given length in octets. | |
3927 */ | |
3928 ADD_IF_TAGGED (byte_len, XID_VERSION); | |
3929 ADD_IF_TAGGED (byte_len, XID_T200); | |
3930 ADD_IF_TAGGED (byte_len, XID_N200); | |
3931 ADD_IF_TAGGED (byte_len, XID_N201_U); | |
3932 /*Acknowledge Mode Parameters will be ignored in XID FRAME: | |
3933 ADD_IF_TAGGED (byte_len, XID_N201_I); | |
3934 ADD_IF_TAGGED (byte_len, XID_MD); | |
3935 ADD_IF_TAGGED (byte_len, XID_MU); | |
3936 ADD_IF_TAGGED (byte_len, XID_KD); | |
3937 ADD_IF_TAGGED (byte_len, XID_KU); | |
3938 */ | |
3939 if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3)) | |
3940 { | |
3941 byte_len += llc_data->requested_l3_xid->length + 2; | |
3942 } | |
3943 | |
3944 /* | |
3945 * Add data header and FCS field to the XID response size to get | |
3946 * the overall data size. | |
3947 */ | |
3948 byte_len += U_HDR_SIZE + FCS_SIZE; | |
3949 | |
3950 { | |
3951 #ifndef LL_DESC | |
3952 PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, (USHORT)(byte_len*8)); | |
3953 #else | |
3954 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ); | |
3955 | |
3956 desc3 = llc_palloc_desc(byte_len, 0); | |
3957 | |
3958 ll_unitdesc_req->desc_list3.first = (ULONG)desc3; | |
3959 ll_unitdesc_req->desc_list3.list_len = desc3->len; | |
3960 #endif | |
3961 ll_unitdesc_req->sapi = llc_data->current_sapi; | |
3962 ll_unitdesc_req->tlli = llc_data->tlli_new; | |
3963 /* | |
3964 * LLC does not know the QoS profile. | |
3965 */ | |
3966 ll_unitdesc_req->ll_qos = llc_data->cur_qos; | |
3967 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak); | |
3968 | |
3969 /* | |
3970 * LLC signalling frames are always sent with highest priority. | |
3971 */ | |
3972 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio; | |
3973 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio); | |
3974 | |
3975 #ifdef REL99 | |
3976 /* | |
3977 * From 24.008 & 23.060 it is interpreted that for all signalling data, a | |
3978 * predefined PFI LL_PFI_SIGNALING shall be used. | |
3979 */ | |
3980 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi; | |
3981 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi); | |
3982 | |
3983 #endif /* REL99 */ | |
3984 /* | |
3985 * No attach to primitive necessary. For retransmission prim | |
3986 * data is copied in T200 (if requested). | |
3987 */ | |
3988 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE; | |
3989 | |
3990 /* | |
3991 * Label U_SEND_XID_CONT | |
3992 */ | |
3993 | |
3994 /* | |
3995 * pf_bit must always be 1 when XID cmd/res are being sent | |
3996 */ | |
3997 u_build_u_frame | |
3998 ( | |
3999 #ifndef LL_DESC | |
4000 &ll_unitdesc_req->sdu, | |
4001 #else | |
4002 &ll_unitdesc_req->desc_list3, | |
4003 #endif | |
4004 cr_bit, llc_data->current_sapi, 1, U_XID | |
4005 ); | |
4006 | |
4007 u_insert_xid | |
4008 ( | |
4009 #ifndef LL_DESC | |
4010 &ll_unitdesc_req->sdu, | |
4011 #else | |
4012 &ll_unitdesc_req->desc_list3, | |
4013 #endif | |
4014 cr_bit | |
4015 ); | |
4016 | |
4017 if (cr_bit EQ MS_COMMAND) | |
4018 { | |
4019 /* | |
4020 * remember that an XID command is currently being sent | |
4021 */ | |
4022 llc_data->u->xid_pending = TRUE; | |
4023 | |
4024 /* | |
4025 * T200 has to be started !before! the primitive is sent to TX. | |
4026 */ | |
4027 sig_u_t200_start_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
4028 } | |
4029 | |
4030 /* | |
4031 * U frames are always sent with default cause | |
4032 */ | |
4033 sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF); | |
4034 } | |
4035 | |
4036 if (cr_bit EQ MS_RESPONSE) | |
4037 { | |
4038 llc_init_requested_xid_sapi(llc_data->current_sapi); | |
4039 } | |
4040 | |
4041 return; | |
4042 } /* u_send_xid() */ | |
4043 | |
4044 | |
4045 | |
4046 /* | |
4047 +------------------------------------------------------------------------------ | |
4048 | Function : u_handle_optimization | |
4049 +------------------------------------------------------------------------------ | |
4050 | Description : This procedure adds the values of the requested XID parameter | |
4051 | to the decoded XID structure, if they are not included (as an | |
4052 | optimization issue). | |
4053 | | |
4054 | Parameters : | |
4055 | | |
4056 +------------------------------------------------------------------------------ | |
4057 */ | |
4058 GLOBAL void u_handle_optimization (void) | |
4059 { | |
4060 | |
4061 TRACE_FUNCTION ("u_handle_optimization"); | |
4062 | |
4063 | |
4064 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_VERSION) AND | |
4065 llc_data->decoded_xid.version.valid == FALSE ) | |
4066 { | |
4067 llc_data->decoded_xid.version.valid = TRUE; | |
4068 llc_data->decoded_xid.version.value = llc_data->u->requested_xid.version.valid | |
4069 ? llc_data->u->requested_xid.version.value | |
4070 : llc_data->version; | |
4071 } | |
4072 | |
4073 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_T200) AND | |
4074 llc_data->decoded_xid.t200.valid == FALSE ) | |
4075 { | |
4076 llc_data->decoded_xid.t200.valid = TRUE; | |
4077 llc_data->decoded_xid.t200.value = llc_data->u->requested_xid.t200.valid | |
4078 ? llc_data->u->requested_xid.t200.value | |
4079 : ((USHORT)INT2XID (llc_data->t200->length)); | |
4080 } | |
4081 | |
4082 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_N200) AND | |
4083 llc_data->decoded_xid.n200.valid == FALSE ) | |
4084 { | |
4085 llc_data->decoded_xid.n200.valid = TRUE; | |
4086 llc_data->decoded_xid.n200.value = llc_data->u->requested_xid.n200.valid | |
4087 ? llc_data->u->requested_xid.n200.value | |
4088 : *(llc_data->n200); | |
4089 } | |
4090 | |
4091 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_N201_U) AND | |
4092 llc_data->decoded_xid.n201_u.valid == FALSE ) | |
4093 { | |
4094 llc_data->decoded_xid.n201_u.valid = TRUE; | |
4095 llc_data->decoded_xid.n201_u.value = llc_data->u->requested_xid.n201_u.valid | |
4096 ? llc_data->u->requested_xid.n201_u.value | |
4097 : *(llc_data->n201_u); | |
4098 } | |
4099 | |
4100 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_N201_I) AND | |
4101 llc_data->decoded_xid.n201_i.valid == FALSE ) | |
4102 { | |
4103 llc_data->decoded_xid.n201_i.valid = TRUE; | |
4104 llc_data->decoded_xid.n201_i.value = llc_data->u->requested_xid.n201_i.valid | |
4105 ? llc_data->u->requested_xid.n201_i.value | |
4106 : *(llc_data->n201_i); | |
4107 } | |
4108 | |
4109 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_MD) AND | |
4110 llc_data->decoded_xid.md.valid == FALSE ) | |
4111 { | |
4112 llc_data->decoded_xid.md.valid = TRUE; | |
4113 llc_data->decoded_xid.md.value = llc_data->u->requested_xid.md.valid | |
4114 ? llc_data->u->requested_xid.md.value | |
4115 : *(llc_data->md); | |
4116 } | |
4117 | |
4118 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_MU) AND | |
4119 llc_data->decoded_xid.mu.valid == FALSE ) | |
4120 { | |
4121 llc_data->decoded_xid.mu.valid = TRUE; | |
4122 llc_data->decoded_xid.mu.value = llc_data->u->requested_xid.mu.valid | |
4123 ? llc_data->u->requested_xid.mu.value | |
4124 : *(llc_data->mu); | |
4125 } | |
4126 | |
4127 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_KD) AND | |
4128 llc_data->decoded_xid.kd.valid == FALSE ) | |
4129 { | |
4130 llc_data->decoded_xid.kd.valid = TRUE; | |
4131 llc_data->decoded_xid.kd.value = llc_data->u->requested_xid.kd.valid | |
4132 ? llc_data->u->requested_xid.kd.value | |
4133 : *(llc_data->kd); | |
4134 } | |
4135 | |
4136 if (llc_data->u->xid_tag_sent & (0x00000001L << XID_KU) AND | |
4137 llc_data->decoded_xid.ku.valid == FALSE ) | |
4138 { | |
4139 llc_data->decoded_xid.ku.valid = TRUE; | |
4140 llc_data->decoded_xid.ku.value = llc_data->u->requested_xid.ku.valid | |
4141 ? llc_data->u->requested_xid.ku.value | |
4142 : *(llc_data->ku); | |
4143 } | |
4144 | |
4145 | |
4146 /* | |
4147 * Layer 3 XID must be included in resonse, if it was included in request | |
4148 */ | |
4149 | |
4150 } /* u_handle_optimization() */ | |
4151 | |
4152 |