comparison src/g23m-gprs/llc/llc_uf.c @ 183:219afcfc6250

src/g23m-gprs: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 13 Oct 2016 04:24:13 +0000
parents
children
comparison
equal deleted inserted replaced
182:f02d0a0e1849 183:219afcfc6250
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