comparison src/g23m-gprs/llc/llc_itxf.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 (ITX-statemachine)
20 +-----------------------------------------------------------------------------
21 */
22
23 #ifndef LLC_ITXF_C
24 #define LLC_ITXF_C
25 #endif
26
27 #define ENTITY_LLC
28
29 /*==== INCLUDES =============================================================*/
30
31 #include <string.h> /* to get memcpy() */
32
33 #include "typedefs.h" /* to get Condat data types */
34 #include "vsi.h" /* to get a lot of macros */
35 #include "macdef.h"
36 #include "gprs.h"
37 #include "gsm.h" /* to get a lot of macros */
38 #include "cnf_llc.h" /* to get cnf-definitions */
39 #include "mon_llc.h" /* to get mon-definitions */
40 #include "prim.h" /* to get the definitions of used SAP and directions */
41 #include "llc.h" /* to get the global entity definitions */
42 #include "llc_f.h" /* to get the global entity definitions */
43 #include "llc_txs.h" /* to get signal interface to TX */
44 #include "llc_itxt.h" /* to get signal interface to TX */
45 #include "llc_llmes.h" /* to get signal interface to LLME */
46 #include "llc_itxf.h" /* to get ITX local functions */
47
48 /*==== CONST ================================================================*/
49
50 /*==== LOCAL VARS ===========================================================*/
51
52 /*==== PRIVATE FUNCTIONS ====================================================*/
53 LOCAL void itx_send_i_frame (T_ITX_I_QUEUE_ENTRY* entry,
54 T_ABIT_REQ_TYPE tr);
55
56 LOCAL void itx_i_queue_get_next (T_IQ_STATUS* status,
57 T_ITX_I_QUEUE_ENTRY** entry,
58 T_ABIT_REQ_TYPE* rt);
59
60 LOCAL void itx_i_queue_get_retr (T_IQ_STATUS* status,
61 T_ITX_I_QUEUE_ENTRY** entry,
62 T_ABIT_REQ_TYPE* rt);
63
64 LOCAL void itx_s_queue_retrieve (BOOL* found,
65 T_COMMAND* sx,
66 T_ABIT_REQ_TYPE* rt,
67 T_FRAME_NUM* nr,
68 T_SACK_BITMAP* bm,
69 USHORT* bm_byte_size);
70
71 LOCAL void itx_send_s_frame (T_COMMAND sx,
72 T_ABIT_REQ_TYPE rt,
73 T_FRAME_NUM nr,
74 T_SACK_BITMAP* bm,
75 USHORT bm_byte_size);
76
77
78 /*==== PUBLIC FUNCTIONS =====================================================*/
79
80
81
82 /*
83 +------------------------------------------------------------------------------
84 | Function : itx_init
85 +------------------------------------------------------------------------------
86 | Description : This procedure initialises all necessary variables of
87 | i_frames_tx for all SAPIs.
88 |
89 | Parameters :
90 |
91 +------------------------------------------------------------------------------
92 */
93 GLOBAL void itx_init (void)
94 {
95 UBYTE inc;
96
97 TRACE_FUNCTION( "itx_init" );
98
99 /*
100 * Initialise all 4 SAPIs with state TLLI_UNASSIGNED.
101 */
102 SWITCH_SERVICE (llc, itx, 0);
103 INIT_STATE (ITX_0, ITX_TLLI_UNASSIGNED);
104
105 SWITCH_SERVICE (llc, itx, 1);
106 INIT_STATE (ITX_1, ITX_TLLI_UNASSIGNED);
107
108 SWITCH_SERVICE (llc, itx, 2);
109 INIT_STATE (ITX_2, ITX_TLLI_UNASSIGNED);
110
111 SWITCH_SERVICE (llc, itx, 3);
112 INIT_STATE (ITX_3, ITX_TLLI_UNASSIGNED);
113
114 /*
115 * Initialise the ITX data structure
116 */
117 for (inc = 0; inc < ITX_NUM_INC; inc++)
118 {
119 SWITCH_SERVICE (llc, itx, inc);
120
121 /*
122 * Free old used resources (in case of an LLC restart):
123 * memory, stored primitives, running timer.
124 */
125 itx_i_queue_clean();
126 itx_s_queue_clean();
127
128 /*
129 * Init data area
130 */
131 llc_data->itx->tx_waiting = FALSE;
132 llc_data->itx->buffer_was_full = FALSE;
133
134 llc_data->itx->i_queue.first = NULL;
135 llc_data->itx->s_queue = NULL;
136
137 llc_data->itx->n_pb_retr = 0;
138 }
139
140 return;
141 } /* itx_init() */
142
143
144 /*
145 +------------------------------------------------------------------------------
146 | Function : itx_init_sapi
147 +------------------------------------------------------------------------------
148 | Description : This procedure initialises all necessary variables of
149 | i_frames_tx for the current SAPI.
150 |
151 | Parameters :
152 |
153 +------------------------------------------------------------------------------
154 */
155 GLOBAL void itx_init_sapi (void)
156 {
157 TRACE_FUNCTION( "itx_init_sapi" );
158
159 llc_data->itx->buffer_was_full = FALSE;
160
161 llc_data->itx->t201_entry = NULL;
162 llc_data->itx->n_pb_retr = 0;
163 llc_data->itx->B_tx = 0;
164
165 return;
166 } /* itx_init_sapi() */
167
168
169 /*
170 +------------------------------------------------------------------------------
171 | Function : itx_queue_sequence_check
172 +------------------------------------------------------------------------------
173 | Description : This procedure checks for the A bit request conditions "end of
174 | a sequence of transmitted I frames"
175 |
176 | Parameters :
177 |
178 +------------------------------------------------------------------------------
179 */
180 GLOBAL void itx_queue_sequence_check (T_IQ_STATUS status,
181 T_ITX_I_QUEUE_ENTRY* entry,
182 T_ABIT_REQ_TYPE* rt)
183 {
184 TRACE_FUNCTION( "itx_queue_sequence_check" );
185
186 /*
187 * Do not overwrite rt, if it is already set
188 */
189 if (*rt == ABIT_SET_REQ )
190 {
191 return;
192 }
193
194 /*
195 * Handle rt depending on status
196 */
197 switch (status)
198 {
199 case IQ_NEW_FRAME:
200 /*
201 * If a next frame is not available, the sequence ends
202 */
203 if (entry == NULL)
204 {
205 *rt = ABIT_SET_REQ;
206 }
207 break;
208
209 case IQ_RETR_FRAME:
210 /*
211 * If no frame to retransmit is following, the sequence ends
212 */
213 while (entry)
214 {
215 if (entry->status == IQ_RETR_FRAME)
216 {
217 /*
218 * Another one is following
219 */
220 return;
221 }
222 entry = entry->next;
223 }
224 *rt = ABIT_SET_REQ;
225 break;
226
227 default:
228 TRACE_ERROR("Status unexpected");
229 break;
230 }
231 }
232
233
234
235 /*
236 +------------------------------------------------------------------------------
237 | Function : itx_i_queue_get_next
238 +------------------------------------------------------------------------------
239 | Description : This procedure gets the next new frame from the I frame queue.
240 |
241 | Parameters :
242 |
243 +------------------------------------------------------------------------------
244 */
245 LOCAL void itx_i_queue_get_next (T_IQ_STATUS* status,
246 T_ITX_I_QUEUE_ENTRY** entry,
247 T_ABIT_REQ_TYPE* rt )
248 {
249 T_ITX_I_QUEUE_ENTRY* iq_ptr;
250
251 TRACE_FUNCTION( "itx_i_queue_get_next" );
252
253 /*
254 * Search for a frame with type equal status
255 */
256 iq_ptr = llc_data->itx->i_queue.first;
257 while (iq_ptr)
258 {
259 /*
260 * check if we have found the entry
261 */
262 if (iq_ptr->status == IQ_NEW_FRAME)
263 {
264 *entry = iq_ptr;
265 *status = IQ_NEW_FRAME;
266
267 /*
268 * check for A bit set condition
269 */
270 itx_queue_sequence_check (IQ_NEW_FRAME, iq_ptr->next, rt);
271
272 /*
273 * next one found
274 */
275 return;
276 }
277
278 iq_ptr = iq_ptr->next;
279 }
280
281 /*
282 * We have nothing found to transmit
283 */
284 *entry = NULL;
285 *status = IQ_NO_FRAME;
286 *rt = ABIT_NO_REQ;
287
288 } /* itx_i_queue_get_next() */
289
290 /*
291 +------------------------------------------------------------------------------
292 | Function : itx_i_queue_get_retr
293 +------------------------------------------------------------------------------
294 | Description : This procedure gets the next frame maked for retransmission
295 | from the I frame queue.
296 |
297 | Parameters :
298 |
299 +------------------------------------------------------------------------------
300 */
301 LOCAL void itx_i_queue_get_retr (T_IQ_STATUS* status,
302 T_ITX_I_QUEUE_ENTRY** entry,
303 T_ABIT_REQ_TYPE* rt )
304 {
305 T_ITX_I_QUEUE_ENTRY* iq_ptr;
306
307 TRACE_FUNCTION( "itx_i_queue_get_retr" );
308
309 /*
310 * Search for a frame makred for retransmission
311 * Retransmissions can't be stored after new frames
312 */
313 iq_ptr = llc_data->itx->i_queue.first;
314 while (iq_ptr && iq_ptr->status != IQ_NEW_FRAME)
315 {
316 /*
317 * check if we have found the entry
318 */
319 if (iq_ptr->status == IQ_RETR_FRAME)
320 {
321 *entry = iq_ptr;
322 *status = IQ_RETR_FRAME;
323
324 /*
325 * check for A bit set condition
326 */
327 itx_queue_sequence_check (IQ_RETR_FRAME, iq_ptr->next, rt);
328
329 /*
330 * next one found
331 */
332 return;
333 }
334
335 iq_ptr = iq_ptr->next;
336 }
337
338 /*
339 * We have nothing found to transmit
340 */
341 *entry = NULL;
342 *status = IQ_NO_FRAME;
343 *rt = ABIT_NO_REQ;
344
345 } /* itx_i_queue_get_retr () */
346
347
348 /*
349 +------------------------------------------------------------------------------
350 | Function : itx_send_next_frame
351 +------------------------------------------------------------------------------
352 | Description : If LLC is not suspended and TX is ready to receive a frame,
353 | this procedure handles the sending of the next I/S or S frame,
354 | if one is availabel in the I or S queue.
355 |
356 | Parameters :
357 |
358 +------------------------------------------------------------------------------
359 */
360 GLOBAL void itx_send_next_frame (T_ABIT_REQ_TYPE req)
361 {
362 T_ITX_I_QUEUE_ENTRY* entry;
363 T_IQ_STATUS status;
364 T_ABIT_REQ_TYPE rt = ABIT_NO_REQ;
365 T_SACK_BITMAP bm;
366 T_COMMAND sx;
367 T_FRAME_NUM nr;
368 USHORT bm_byte_size;
369 BOOL found;
370
371 TRACE_FUNCTION( "itx_send_next_frame" );
372
373 /*
374 * First check, if TX is ready to receive a frame
375 */
376 if ((llc_data->itx->tx_waiting == FALSE) || (llc_data->suspended == TRUE))
377 {
378 /*
379 * Label ITX_SEND_1
380 */
381
382 return;
383 }
384
385 /*
386 * Try to get a frame marked for retransmission from the I queue
387 */
388 itx_i_queue_get_retr (&status, &entry, &rt);
389
390 /*
391 * If we found none, try to get a new frame
392 */
393 if (status == IQ_NO_FRAME )
394 {
395 /*
396 * Try it only, if the transmit window is not full => V(S) < V(A) + k
397 */
398 if ( FRAME_WIN_VALID(llc_data->sapi->vs, llc_data->sapi->va, *(llc_data->ku)) )
399 {
400 itx_i_queue_get_next (&status, &entry, &rt);
401 }
402 }
403
404 switch (status)
405 {
406 case IQ_NO_FRAME:
407 /*
408 * Label ITX_SEND_2
409 */
410
411 /*
412 * No I frame to send, look for a S frame
413 */
414 itx_s_queue_retrieve (&found, &sx, &rt, &nr, &bm, &bm_byte_size);
415 /*
416 * If an command was found, send it, else leave
417 */
418 if (found)
419 {
420 itx_send_s_frame (sx, rt, nr, &bm, bm_byte_size);
421 }
422 break;
423
424 case IQ_NEW_FRAME:
425 /*
426 * Set A-bit flag in case of V(S) = V(A) + k after sending
427 */
428 if( llc_data->sapi->vs == (llc_data->sapi->va +
429 *(llc_data->ku) - 1) % (MAX_SEQUENCE_NUMBER+1) )
430 {
431 rt = ABIT_SET_REQ;
432 }
433
434 /*
435 * Set current value of V(S) and OC to the next frame and
436 * increment it. Must be done before calling send_i_frame
437 * because of possible recursion!
438 */
439 entry->ns = llc_data->sapi->vs++;
440 entry->oc_i_tx = llc_data->sapi->oc_i_tx;
441
442 /*
443 * Handle OC(tx) and MAX_SEQUENCE_NUMBER for acknowledged transfer.
444 */
445 if (llc_data->sapi->vs > MAX_SEQUENCE_NUMBER)
446 {
447 llc_data->sapi->vs = 0;
448 llc_data->sapi->oc_i_tx += (MAX_SEQUENCE_NUMBER+1);
449 }
450
451 /*
452 * Transmit I frame and set waiting for acknowlege
453 */
454 itx_send_i_frame (entry, rt);
455 break;
456
457 case IQ_RETR_FRAME:
458 /*
459 * Increment retransmission counter and check if
460 * another transmission of this frame is allowed.
461 */
462 entry->n_retr++;
463 if (entry->n_retr <= *(llc_data->n200) )
464 {
465 /*
466 * Retransmit frame and set waiting for acknowlege
467 */
468 itx_send_i_frame (entry, rt);
469 }
470 else
471 {
472 /*
473 * Initiate re-establish
474 */
475 sig_itx_llme_reest_ind (LLGMM_ERRCS_ACK_NO_PEER_RES_REEST);
476 }
477 break;
478
479 default:
480 TRACE_ERROR ("UNEXPECTED RETURN CODE");
481 break;
482 }
483
484 } /* itx_send_next_frame() */
485
486
487 /*
488 +------------------------------------------------------------------------------
489 | Function : itx_s_queue_clean
490 +------------------------------------------------------------------------------
491 | Description : This procedure removes all entries from the S frame queue
492 |
493 | Parameters :
494 |
495 +------------------------------------------------------------------------------
496 */
497 GLOBAL void itx_s_queue_clean (void)
498 {
499 T_ITX_S_QUEUE_ENTRY** entry = &(llc_data->itx->s_queue);
500
501 TRACE_FUNCTION( "itx_s_queue_clean" );
502
503 while (*entry)
504 {
505 /*
506 * get pointer to next (=first) entry
507 */
508 T_ITX_S_QUEUE_ENTRY* current = *entry;
509
510 /*
511 * remove next entry from the entry (make second to first)
512 */
513 *entry = current->next;
514
515 /*
516 * free the removed entry
517 */
518 MFREE (current);
519 }
520 } /* itx_s_queue_clean() */
521
522
523 /*
524 +------------------------------------------------------------------------------
525 | Function : itx_i_queue_clean
526 +------------------------------------------------------------------------------
527 | Description : This procedure removes all entries including the attached L3
528 | data from the I-frame queue.
529 |
530 | Parameters :
531 |
532 +------------------------------------------------------------------------------
533 */
534 GLOBAL void itx_i_queue_clean (void)
535 {
536 T_ITX_I_QUEUE_ENTRY** entry = &(llc_data->itx->i_queue.first);
537
538 TRACE_FUNCTION( "itx_i_queue_clean" );
539
540 while( *entry )
541 {
542 /*
543 * get pointer to next (=first) entry
544 */
545 T_ITX_I_QUEUE_ENTRY* current = *entry;
546
547 /*
548 * remove next entry from the entry (make second to first)
549 */
550 *entry = current->next;
551
552 /*
553 * free L3 primitive data, if attached to the removed entry
554 */
555 if (current->frame)
556 {
557
558 /*
559 * Decrease attached counter. If no one is still attached
560 * free the primitive memory
561 */
562 if (current->frame->attached_counter > CCI_NO_ATTACHE)
563 {
564 current->frame->attached_counter --;
565
566 if (current->frame->attached_counter == CCI_NO_ATTACHE)
567 {
568 #ifdef LL_DESC
569 /*
570 * The descriptor contents of the primitive structure
571 * must be freed as well.
572 */
573 llc_cl_desc3_free((T_desc3*)current->frame->desc_list3.first);
574 #endif /* LL_DESC */
575 PFREE (current->frame);
576 }
577 else
578 {
579 TRACE_0_INFO("LL_DATA_REQ still attached");
580 }
581 }
582 }
583
584 /*
585 * free next entry
586 */
587 MFREE (current);
588 }
589
590 /*
591 * Adjust number of stored entries in I frame queue
592 */
593 llc_data->itx->i_queue.entries = 0;
594
595 /*
596 * Adjust I frame queue size
597 */
598 llc_data->itx->B_tx = 0;
599
600 /*
601 * If a I frame is associated with T201, also reset this
602 */
603 TIMERSTOP (T201);
604 llc_data->itx->t201_entry = NULL;
605
606 } /* itx_i_queue_clean() */
607
608
609 /*
610 +------------------------------------------------------------------------------
611 | Function : itx_handle_ll_ready_ind
612 +------------------------------------------------------------------------------
613 | Description : This procedure checks if further storing of L3 data is allowed.
614 | If possible, a LL_READY_IND is send.
615 |
616 | Parameters : data_send - TRUE if data sent was the reason to call
617 |
618 +------------------------------------------------------------------------------
619 */
620 GLOBAL void itx_handle_ll_ready_ind (BOOL data_send)
621 {
622 ULONG M = *(llc_data->mu) * 16;
623
624 TRACE_FUNCTION( "itx_handle_ll_ready_ind" );
625
626 /*
627 * If data_send was the reason to call this function,
628 * only send ready, if buffer was full last call.
629 */
630 if ((data_send == TRUE) && (llc_data->itx->buffer_was_full == FALSE))
631 {
632 /*
633 * Nothing to do
634 */
635 return;
636 }
637
638 /*
639 * Check if we already have stored more frames than current ku or if
640 * M - if relevant - would exceed if we would add an N201 size frame.
641 * If this is true set buffer_was_full to TRUE. Otherwise send out an
642 * LL_READY_IND.
643 */
644 if ((llc_data->itx->i_queue.entries < *(llc_data->ku) + ITX_ADD_QUEUE_SIZE) AND
645 ( (M == 0) OR (*(llc_data->n201_i) <= M - llc_data->itx->B_tx) ) )
646 {
647 PALLOC (ll_ready_ind, LL_READY_IND);
648
649 ll_ready_ind->sapi = llc_data->current_sapi;
650
651 TRACE_1_OUT_PARA("s:%d", ll_ready_ind->sapi);
652 PSEND (hCommSNDCP, ll_ready_ind);
653
654 llc_data->itx->buffer_was_full = FALSE;
655 }
656 else
657 {
658 llc_data->itx->buffer_was_full = TRUE;
659
660 TRACE_0_INFO("ITX buffer full");
661 }
662 } /* itx_handle_ll_ready_ind() */
663
664 /*
665 +------------------------------------------------------------------------------
666 | Function : itx_i_queue_store
667 +------------------------------------------------------------------------------
668 | Description : This procedure tries to store the L3 data request.
669 |
670 | Parameters :
671 |
672 +------------------------------------------------------------------------------
673 */
674 GLOBAL void itx_i_queue_store
675 (
676 #ifdef LL_DESC
677 T_LL_DESC_REQ* ll_desc_req, BOOL *result
678 #else
679 T_LL_DATA_REQ* ll_desc_req, BOOL *result
680 #endif
681 )
682 {
683 #ifdef LL_DESC
684 T_desc3* desc3;
685 #endif
686 ULONG M = *(llc_data->mu) * 16;
687
688 TRACE_FUNCTION( "itx_i_queue_store" );
689
690 /*
691 * Check, if M would exceed if we transmit this frame.
692 */
693 #ifdef LL_DESC
694 if ( M == 0 ||
695 (ULONG)(ll_desc_req->desc_list3.list_len) <= M - llc_data->itx->B_tx )
696 #else
697 if ( M == 0 ||
698 (ULONG)(BYTELEN(ll_desc_req->sdu.l_buf)) <= M - llc_data->itx->B_tx )
699 #endif
700 {
701 /*
702 * Store data to the end of the queue (queue type: oldies first)
703 */
704 T_ITX_I_QUEUE_ENTRY** entry = &(llc_data->itx->i_queue.first);
705
706 while( *entry )
707 entry = &((*entry)->next);
708
709 MALLOC( *entry, sizeof(T_ITX_I_QUEUE_ENTRY) );
710
711 if( *entry )
712 {
713 /*
714 * Memory successful allocated. Fill in struct entries.
715 */
716 (*entry)->next = NULL;
717 (*entry)->status = IQ_NEW_FRAME;
718 (*entry)->n_retr = 0;
719 (*entry)->ns = 0;
720 (*entry)->frame = ll_desc_req;
721
722 /*
723 * Store primitive header parameter
724 */
725 (*entry)->ll_qos = ll_desc_req->ll_qos;
726 (*entry)->radio_prio = ll_desc_req->radio_prio;
727 (*entry)->reference = ll_desc_req->reference1;
728 (*entry)->seg_pos = ll_desc_req->seg_pos;
729
730 #ifdef REL99
731 /*
732 * Fill packet flow identifier with corrrect values if it is from one of the SNDCP SAP.
733 * If data request is from GMM fill PFI = LL_PFI_SIGNALING,
734 * If data request is from GSMS fill PFI = LL_PFI_SMS
735 * for all other SAPs(if sapi 2 & 8 are supported in future) set pkt_flow_id is to LL_PKT_FLOW_ID_NOT_PRES,
736 * until specification are clarified.
737 */
738 switch(ll_desc_req->sapi)
739 {
740 case LL_SAPI_1:
741 /*
742 * From 24.008 & 23.060 it is interpreted that for all signalling data, a
743 * predefined PFI LL_PFI_SIGNALING shall be used.
744 */
745 (*entry)->pkt_flow_id = LL_PFI_SIGNALING;
746 break;
747
748 case LL_SAPI_3:
749 case LL_SAPI_5:
750 case LL_SAPI_9:
751 case LL_SAPI_11:
752 (*entry)->pkt_flow_id = (UBYTE)ll_desc_req->pkt_flow_id;
753 break;
754
755 case LL_SAPI_7:
756 /*
757 * From 24.008 & 23.060 it is interpreted that for all SMS data, a
758 * predefined PFI LL_PFI_SMS shall be used.
759 */
760 (*entry)->pkt_flow_id = LL_PFI_SMS;
761 break;
762
763 default:
764 /*
765 * It is possible when we support llc sapi 2 and 8 are supported.
766 * Fill PFI valuse it LL_PKT_FLOW_ID_NOT_PRES
767 */
768 (*entry)->pkt_flow_id = LL_PKT_FLOW_ID_NOT_PRES;
769 break;
770 }
771 #endif /*REL99 */
772
773 #ifdef LL_DESC
774 desc3 = (T_desc3*)ll_desc_req->desc_list3.first;
775
776 (*entry)->offset = desc3->offset;
777 (*entry)->len = desc3->len;
778
779 /*
780 * Increase attached counter
781 */
782 ll_desc_req->attached_counter ++;
783
784 /*
785 * Increase number of stored entries in I frame queue
786 */
787 llc_data->itx->i_queue.entries++;
788
789 /*
790 * Increase amount of stored Information in I frame queue
791 */
792
793 llc_data->itx->B_tx += (ll_desc_req->desc_list3.list_len);
794
795 #else
796 (*entry)->sdu_o_buf = ll_desc_req->sdu.o_buf;
797 (*entry)->sdu_l_buf = ll_desc_req->sdu.l_buf;
798
799 /*
800 * Increase attached counter
801 */
802 ll_desc_req->attached_counter ++;
803
804 /*
805 * Increase number of stored entries in I frame queue
806 */
807 llc_data->itx->i_queue.entries++;
808
809 /*
810 * Increase amount of stored Information in I frame queue
811 */
812 llc_data->itx->B_tx += BYTELEN(ll_desc_req->sdu.l_buf);
813
814 #endif /*LL_DESC */
815 /*
816 * Store data succeded
817 */
818 *result = TRUE;
819 return;
820 }
821 else
822 {
823 /*
824 * Out of memory
825 */
826 TRACE_ERROR( "Out of memory in itx_i_queue_store()" );
827 }
828 }
829
830 *result = FALSE;
831 return;
832 } /* itx_i_queue_store() */
833
834
835
836 /*
837 +------------------------------------------------------------------------------
838 | Function : itx_i_queue_get_ready
839 +------------------------------------------------------------------------------
840 | Description : This procedure checks, if the next entry in the queue is
841 | already acknowledged. If this is true, the entry will be
842 | removed and the frame reference will be returned.
843 |
844 | Parameters :
845 |
846 +------------------------------------------------------------------------------
847 */
848 GLOBAL void itx_i_queue_get_ready (BOOL* found,
849 #ifdef LL_2to1
850 T_LL_reference1* reference,
851 #else
852 T_reference1* reference,
853 #endif
854 UBYTE state)
855 {
856 T_ITX_I_QUEUE_ENTRY** entry = &(llc_data->itx->i_queue.first);
857
858 TRACE_FUNCTION( "itx_i_queue_get_ready" );
859
860 /*
861 * The first entry is the oldest. Only this must be observed.
862 */
863 if ((*entry) != NULL && (*entry)->status == IQ_IS_ACK_FRAME)
864 {
865 /*
866 * store pointer to the entry
867 */
868 T_ITX_I_QUEUE_ENTRY* current = *entry;
869
870 /*
871 * remove entry from the queue (make second to first)
872 */
873 *entry = current->next;
874
875 /*
876 * Decrease number of stored entries in I frame queue
877 */
878 llc_data->itx->i_queue.entries--;
879
880 if (current->frame)
881 {
882
883 /*
884 * return original data request reference number
885 */
886 *reference = current->reference;
887
888 /*
889 * decrease amount of stored Information in I frame queue.
890 * Take the original value of sdu_len as it was send by L3
891 */
892 #ifdef LL_DESC
893 if (llc_data->itx->B_tx >= (ULONG)(current->len))
894 {
895 llc_data->itx->B_tx -= (ULONG)(current->len);
896 #else
897 if (llc_data->itx->B_tx >= (ULONG)(BYTELEN(current->sdu_l_buf)))
898 {
899 llc_data->itx->B_tx -= (ULONG)(BYTELEN(current->sdu_l_buf));
900 #endif
901 }
902 else
903 {
904 llc_data->itx->B_tx = 0;
905 TRACE_0_INFO("Unexpected SDU bytelen handled");
906 }
907
908 /*
909 * decrease attached counter. If no one is still attached
910 * free the primitive memory
911 */
912 if (current->frame->attached_counter > CCI_NO_ATTACHE)
913 {
914 current->frame->attached_counter --;
915
916 if (current->frame->attached_counter == CCI_NO_ATTACHE)
917 {
918 #ifdef LL_DESC
919 llc_cl_desc3_free((T_desc3*)current->frame->desc_list3.first);
920 #endif /* LL_DESC */
921 PFREE (current->frame);
922 }
923 else
924 {
925 TRACE_0_INFO("LL_DATA_REQ still attached");
926 }
927 }
928 }
929 else
930 {
931 *found = FALSE;
932 TRACE_0_INFO("No LL_DATA_REQ attached to queue entry");
933 return;
934 }
935
936 /*
937 * if the retrieved I frame is associated with T201, reset this
938 */
939 if (current == llc_data->itx->t201_entry)
940 {
941 if (state != ITX_ABM_PEER_BUSY)
942 {
943 /*
944 * In this state the timer handles other stuff
945 */
946 TIMERSTOP (T201);
947 }
948
949 llc_data->itx->t201_entry = NULL;
950 }
951
952 /*
953 * free retrieved entry
954 */
955 MFREE (current);
956
957 *found = TRUE;
958 }
959 else
960 {
961 *found = FALSE;
962 }
963 } /* itx_i_queue_get_ready() */
964
965
966
967 /*
968 +------------------------------------------------------------------------------
969 | Function : itx_i_queue_set_status
970 +------------------------------------------------------------------------------
971 | Description : This procedure sets the acknowledge flag to the frame send with
972 | N equal to num.
973 |
974 | Parameters :
975 |
976 +------------------------------------------------------------------------------
977 */
978 GLOBAL void itx_i_queue_set_status (T_IQ_STATUS status, T_FRAME_NUM num)
979 {
980 T_ITX_I_QUEUE_ENTRY* entry = llc_data->itx->i_queue.first;
981
982 TRACE_FUNCTION( "itx_i_queue_set_status" );
983
984 while (entry)
985 {
986 /*
987 * check if we have found the entry
988 */
989 if (entry->ns == num )
990 {
991 /*
992 * found it - set ack and leave
993 */
994 entry->status = status;
995 return;
996 }
997
998 /*
999 * goto next entry
1000 */
1001 entry = entry->next;
1002 }
1003 } /* itx_i_queue_set_status() */
1004
1005
1006 /*
1007 +-----------------------------------------------------------------------------
1008 | Function : itx_s_queue_store
1009 +------------------------------------------------------------------------------
1010 | Description : This procedure stores the command to the end of the S queue
1011 |
1012 | Parameters :
1013 |
1014 +------------------------------------------------------------------------------
1015 */
1016 GLOBAL void itx_s_queue_store (T_COMMAND command,
1017 T_ABIT_REQ_TYPE req_type,
1018 T_FRAME_NUM nr,
1019 T_SACK_BITMAP* bitmap)
1020 {
1021 T_ITX_S_QUEUE_ENTRY** entry = &(llc_data->itx->s_queue);
1022
1023 TRACE_FUNCTION( "itx_s_queue_store" );
1024
1025 /*
1026 * find the end
1027 */
1028 while( *entry )
1029 entry = &((*entry)->next);
1030
1031 /*
1032 * allocate memory
1033 */
1034 MALLOC( *entry, sizeof(T_ITX_S_QUEUE_ENTRY) );
1035
1036 if( *entry )
1037 {
1038 /*
1039 * Memory successful allocated. Fill in struct entries.
1040 */
1041 (*entry)->next = NULL;
1042 (*entry)->sx = command;
1043 (*entry)->rt = req_type;
1044 (*entry)->nr = nr;
1045
1046 /*
1047 * Copy SACK bitmap
1048 */
1049 if (bitmap)
1050 {
1051 (*entry)->bitmap = *bitmap;
1052 }
1053 }
1054 else
1055 {
1056 /*
1057 * Out of memory
1058 */
1059 TRACE_ERROR( "Out of memory in itx_i_queue_store()" );
1060 }
1061 } /* itx_s_queue_store() */
1062
1063
1064 /*
1065 +------------------------------------------------------------------------------
1066 | Function : itx_s_queue_retrieve
1067 +------------------------------------------------------------------------------
1068 | Description : This procedure returns the first entry and removes it from the
1069 | the queue or, if not available returns a RR command with found
1070 | set to false.
1071 |
1072 | Parameters :
1073 |
1074 +------------------------------------------------------------------------------
1075 */
1076 LOCAL void itx_s_queue_retrieve (BOOL* found,
1077 T_COMMAND* sx,
1078 T_ABIT_REQ_TYPE* rt,
1079 T_FRAME_NUM* nr,
1080 T_SACK_BITMAP* bm,
1081 USHORT* bm_byte_size)
1082 {
1083 int i;
1084
1085 T_ITX_S_QUEUE_ENTRY** entry = &(llc_data->itx->s_queue);
1086
1087 TRACE_FUNCTION( "itx_s_queue_retrieve" );
1088
1089 /*
1090 * Take the next entry, if available
1091 */
1092 if (*entry != NULL)
1093 {
1094 /*
1095 * Store pointer to the entry
1096 */
1097 T_ITX_S_QUEUE_ENTRY* current = *entry;
1098
1099 /*
1100 * Remove entry from the queue (make second to first)
1101 */
1102 *entry = current->next;
1103
1104 *sx = current->sx;
1105 *rt = current->rt;
1106 *nr = current->nr;
1107 *bm = current->bitmap;
1108
1109 /*
1110 * Free retrieved entry
1111 */
1112 MFREE (current);
1113
1114 *found = TRUE;
1115
1116 /*
1117 * Special handling for SACK command
1118 */
1119 if(*sx == I_SACK)
1120 {
1121 /*
1122 * Calculate bitmap size
1123 */
1124 for(i = S_FRAME_SACK_MAX_CTRL_OCTETS-1; i >= 0; i--)
1125 {
1126 if( bm->data[i] != 0)
1127 {
1128 /*
1129 * Return bm size in bits
1130 */
1131 *bm_byte_size = i+1;
1132 return;
1133 }
1134 }
1135 }
1136
1137 /*
1138 * No valid bitmap found, return
1139 */
1140 *bm_byte_size = 0;
1141 return;
1142 }
1143 else
1144 {
1145 /*
1146 * Set default return values
1147 */
1148 *found = FALSE;
1149 *sx = I_RR;
1150 *nr = llc_data->sapi->vr;
1151 *rt = ABIT_NO_REQ;
1152 *bm_byte_size = 0;
1153 }
1154 } /* itx_s_queue_retrieve () */
1155
1156
1157 /*
1158 +------------------------------------------------------------------------------
1159 | Function : itx_send_i_frame
1160 +------------------------------------------------------------------------------
1161 | Description : This procedure gets the next supervisor information to send
1162 | and build together with the I frame to transmit the final
1163 | (expect ciphering and FSC, which will be done by TX) LLC frame.
1164 |
1165 | Parameters :
1166 |
1167 +------------------------------------------------------------------------------
1168 */
1169 LOCAL void itx_send_i_frame (T_ITX_I_QUEUE_ENTRY* entry,
1170 T_ABIT_REQ_TYPE a_req)
1171 {
1172 #ifdef LL_DESC
1173 T_desc_list3* desc_list3;
1174 T_desc3* desc3;
1175 U8* desc_buf;
1176 #else
1177 T_sdu* sdu;
1178 #endif
1179 T_COMMAND sx;
1180 T_ABIT_REQ_TYPE rt;
1181 T_SACK_BITMAP bm;
1182 T_FRAME_NUM nr;
1183 USHORT bm_byte_size;
1184 USHORT header_size;
1185 USHORT offset;
1186 BOOL found;
1187
1188 TRACE_FUNCTION( "itx_send_i_frame" );
1189
1190 #ifdef LL_DESC
1191 if (entry && entry->frame)
1192 {
1193 PALLOC(ll_unitdesc_req, LL_UNITDESC_REQ);
1194
1195 ll_unitdesc_req->attached_counter = entry->frame->attached_counter;
1196 ll_unitdesc_req->desc_list3 = entry->frame->desc_list3;
1197
1198 /*
1199 * Restore original primitive header parameter of the frame.
1200 */
1201 ll_unitdesc_req->sapi = llc_data->current_sapi;
1202 ll_unitdesc_req->tlli = llc_data->tlli_new;
1203 ll_unitdesc_req->ll_qos = entry->ll_qos;
1204 ll_unitdesc_req->cipher = LL_CIPHER_ON;
1205 ll_unitdesc_req->radio_prio = entry->radio_prio;
1206 ll_unitdesc_req->seg_pos = entry->seg_pos;
1207 #ifdef REL99
1208 ll_unitdesc_req->pkt_flow_id = entry->pkt_flow_id;
1209 #endif /* REL99 */
1210
1211 desc_list3 = &(ll_unitdesc_req->desc_list3);
1212
1213 desc3 = (T_desc3*)(desc_list3->first);
1214
1215 /*
1216 * Restore original desc3 offset and length
1217 */
1218 desc3->offset = entry->offset;
1219 desc3->len = entry->len;
1220
1221 #else
1222 if (entry && entry->frame)
1223 {
1224 PPASS (entry->frame, ll_unitdesc_req, LL_UNITDATA_REQ);
1225
1226 /*
1227 * Restore original primitive header parameter of the frame.
1228 */
1229 ll_unitdesc_req->sapi = llc_data->current_sapi;
1230 ll_unitdesc_req->tlli = llc_data->tlli_new;
1231 ll_unitdesc_req->ll_qos = entry->ll_qos;
1232 ll_unitdesc_req->cipher = LL_CIPHER_ON;
1233 ll_unitdesc_req->radio_prio = entry->radio_prio;
1234 ll_unitdesc_req->seg_pos = entry->seg_pos;
1235 #ifdef REL99
1236 ll_unitdesc_req->pkt_flow_id = entry->pkt_flow_id;
1237 #endif /* REL99 */
1238
1239 sdu = &(ll_unitdesc_req->sdu);
1240
1241 /*
1242 * Restore original SDU offset and length
1243 */
1244 sdu->o_buf = entry->sdu_o_buf;
1245 sdu->l_buf = entry->sdu_l_buf;
1246 #endif
1247
1248
1249 /*
1250 * Get next S-frame. Take the returned RR if not found = FALSE.
1251 */
1252 itx_s_queue_retrieve (&found, &sx, &rt, &nr, &bm, &bm_byte_size);
1253
1254 /*
1255 * Overwrite A-bit flag request, if neccessary
1256 */
1257 if (a_req == ABIT_SET_REQ)
1258 {
1259 rt = ABIT_SET_REQ;
1260 }
1261
1262 #ifndef LL_DESC
1263 /*
1264 * header_size is 4 octets + 1 byte SACK header and the size of
1265 * SACK bitmap. The SDU length equal bytes more than the original values.
1266 */
1267 if (bm_byte_size > 0)
1268 {
1269 header_size = I_CTRL_MIN_OCTETS + 1 + bm_byte_size;
1270 sdu->o_buf -= header_size * 8;
1271 sdu->l_buf += header_size * 8;
1272 }
1273 else
1274 {
1275 header_size = I_CTRL_MIN_OCTETS;
1276 sdu->o_buf -= header_size * 8;
1277 sdu->l_buf += header_size * 8;
1278 }
1279
1280 if (entry->sdu_o_buf < header_size * 8)
1281 {
1282 TRACE_ERROR ("ERROR: SDU offset not big enough");
1283 /*
1284 * Now try to give stack a chance to continue
1285 */
1286 sdu->o_buf = 0;
1287 }
1288
1289 offset = sdu->o_buf/8;
1290
1291 /*
1292 * Build LLC Header:
1293 * First insert address field (PD and C/R bit are always 0)
1294 */
1295 sdu->buf[offset++] = llc_data->current_sapi;
1296
1297 /*
1298 * Insert 1st octet of control field:
1299 * Set A bit and 5 most significant bits of N(S)
1300 */
1301 if (rt == ABIT_SET_REQ)
1302 {
1303 sdu->buf[offset++] = 0x40 | (UBYTE)(entry->ns >> 4);
1304 }
1305 else
1306 {
1307 sdu->buf[offset++] = (UBYTE)(entry->ns >> 4);
1308 }
1309
1310 /*
1311 * Insert 2nd octet of control field:
1312 * 4 least significant bits of N(S) and 3 most significant bits of N(R)
1313 */
1314 sdu->buf[offset++] = (UBYTE)(((entry->ns << 4) & 0xF0) | (nr >> 6));
1315
1316 /*
1317 * Insert 3nd octet of control field:
1318 * 6 least significant bits of N(R) and the supervisory function bits
1319 */
1320 sdu->buf[offset++] = (UBYTE)(((nr << 2) & 0xFC) | sx);
1321
1322 /*
1323 * Special SACK handling
1324 */
1325 if (sx == I_SACK && bm_byte_size != 0)
1326 {
1327 USHORT i;
1328
1329 /*
1330 * Insert 1 SACK octet: k - number of SACK bytes
1331 */
1332 sdu->buf[offset++] = (UBYTE)bm_byte_size;
1333
1334 /*
1335 * Insert SACK bitmap
1336 */
1337 for (i = 0; i < bm_byte_size; i++)
1338 {
1339 sdu->buf[offset++] = bm.data[i];
1340 }
1341 }
1342
1343 /*
1344 * Set frame to waiting for ack
1345 */
1346 entry->status = IQ_W4ACK_FRAME;
1347 #else /* LL_DESC*/
1348
1349 /*
1350 * header_size is 4 octets + 1 byte SACK header and the size of
1351 * SACK bitmap. The SDU length equal bytes more than the original values.
1352 */
1353 if (bm_byte_size > 0)
1354 {
1355 header_size = I_CTRL_MIN_OCTETS + 1 + bm_byte_size;
1356 desc3->offset -= header_size;
1357 desc3->len += header_size;
1358 desc_list3->list_len += header_size;
1359 }
1360 else
1361 {
1362 header_size = I_CTRL_MIN_OCTETS;
1363 desc3->offset -= header_size;
1364 desc3->len += header_size;
1365 desc_list3->list_len += header_size;
1366 }
1367
1368 if (entry->offset < header_size)
1369 {
1370 TRACE_ERROR ("ERROR: SDU offset not big enough");
1371 /*
1372 * Now try to give stack a chance to continue
1373 */
1374 desc3->offset = 0;
1375 }
1376
1377 offset = desc3->offset;
1378 desc_buf = (UBYTE*)desc3->buffer;
1379
1380 if(!desc_buf)
1381 {
1382 TRACE_ERROR("desc_buf is NULLPTR !!!");
1383 return;
1384 }
1385
1386 /*
1387 * Build LLC Header:
1388 * First insert address field (PD and C/R bit are always 0)
1389 */
1390 desc_buf[offset++] = llc_data->current_sapi;
1391
1392 /*
1393 * Insert 1st octet of control field:
1394 * Set A bit and 5 most significant bits of N(S)
1395 */
1396 if (rt == ABIT_SET_REQ)
1397 {
1398 desc_buf[offset++] = 0x40 | (UBYTE)(entry->ns >> 4);
1399 }
1400 else
1401 {
1402 desc_buf[offset++] = (UBYTE)(entry->ns >> 4);
1403 }
1404
1405 /*
1406 * Insert 2nd octet of control field:
1407 * 4 least significant bits of N(S) and 3 most significant bits of N(R)
1408 */
1409 desc_buf[offset++] = (UBYTE)(((entry->ns << 4) & 0xF0) | (nr >> 6));
1410
1411 /*
1412 * Insert 3nd octet of control field:
1413 * 6 least significant bits of N(R) and the supervisory function bits
1414 */
1415 desc_buf[offset++] = (UBYTE)(((nr << 2) & 0xFC) | sx);
1416
1417 /*
1418 * Special SACK handling
1419 */
1420 if (sx == I_SACK && bm_byte_size != 0)
1421 {
1422 USHORT i;
1423
1424 /*
1425 * Insert 1 SACK octet: k - number of SACK bytes
1426 */
1427 desc_buf[offset++] = (UBYTE)bm_byte_size;
1428
1429 /*
1430 * Insert SACK bitmap
1431 */
1432 for (i = 0; i < bm_byte_size; i++)
1433 {
1434 desc_buf[offset++] = bm.data[i];
1435 }
1436 }
1437
1438 /*
1439 * Set frame to waiting for ack
1440 */
1441 entry->status = IQ_W4ACK_FRAME;
1442
1443 #endif /* LL_DESC */
1444 #ifdef TRACE_EVE
1445 {
1446 static char* sf[] = { "RR", "ACK", "RNR", "SACK" };
1447
1448 if(sx <= 3)
1449 {
1450 TRACE_4_INFO("Next I-Frame %s NS:%d NR:%d A:%d", sf[sx], entry->ns, nr, rt);
1451 }
1452 }
1453 #endif
1454
1455 /*
1456 * reset TX ready flag
1457 */
1458 llc_data->itx->tx_waiting = FALSE;
1459
1460 /*
1461 * If A bit was set, associate T201 with the transmitted I frame
1462 * and start T201
1463 */
1464 if (rt == ABIT_SET_REQ)
1465 {
1466 llc_data->itx->t201_entry = entry;
1467 TIMERSTART(T201, llc_data->t200->length);
1468 }
1469
1470 /*
1471 * Now send the frame to TX ( do this as last statement - recursion possible)
1472 */
1473 sig_itx_tx_data_req( ll_unitdesc_req, I_FRAME, entry->ns, GRLC_DTACS_DEF, header_size,
1474 entry->oc_i_tx);
1475 }
1476 } /* itx_send_i_frame() */
1477
1478
1479 /*
1480 +------------------------------------------------------------------------------
1481 | Function : itx_send_s_frame
1482 +------------------------------------------------------------------------------
1483 | Description : This procedure sends the supervisor command to TX
1484 |
1485 | Parameters :
1486 |
1487 +------------------------------------------------------------------------------
1488 */
1489 LOCAL void itx_send_s_frame (T_COMMAND sx,
1490 T_ABIT_REQ_TYPE rt,
1491 T_FRAME_NUM nr,
1492 T_SACK_BITMAP* bm,
1493 USHORT bm_byte_size)
1494 {
1495 USHORT offset;
1496
1497 #ifndef LL_DESC
1498 T_sdu* sdu;
1499 USHORT sdu_bitsize;
1500 #else
1501 T_desc3* desc3;
1502 USHORT desc_bytesize;
1503 U8* buf;
1504 #endif
1505
1506 TRACE_FUNCTION( "itx_send_s_frame" );
1507
1508 #ifndef LL_DESC
1509 /*
1510 * Calculate SDU size
1511 */
1512 sdu_bitsize = (S_FRAME_MIN_OCTETS_WITHOUT_FCS * 8) + (bm_byte_size * 8);
1513
1514 /*
1515 * Build primitive and include supervisory command
1516 */
1517 {
1518 PALLOC_SDU (ll_unitdata_req, LL_UNITDATA_REQ, sdu_bitsize);
1519
1520 ll_unitdata_req->sapi = llc_data->current_sapi;
1521 ll_unitdata_req->tlli = llc_data->tlli_new;
1522
1523 ll_unitdata_req->attached_counter = CCI_NO_ATTACHE;
1524 /*
1525 * LLC does not know the QoS profile. S frames should use
1526 * LL_NO_REL
1527 */
1528 ll_unitdesc_req->ll_qos = llc_data->cur_qos;
1529 TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
1530
1531 /*
1532 * LLC signalling frames are always sent with highest priority.
1533 */
1534 ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
1535 TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
1536
1537
1538 #ifdef REL99
1539 /*
1540 * From 24.008 & 23.060 it is interpreted that for all signalling data, a
1541 * predefined PFI LL_PFI_SIGNALING shall be used.
1542 */
1543 ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
1544 TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
1545
1546 #endif /* REL99 */
1547
1548 /*
1549 * Don't worry about L3 reference - TX will ignore it
1550 */
1551
1552 /*
1553 * SDU offset is 0. The SDU length is sdu_bitsize
1554 */
1555 sdu = &(ll_unitdata_req->sdu);
1556 sdu->o_buf = 0;
1557 sdu->l_buf = sdu_bitsize;
1558
1559 offset = 0;
1560
1561 /*
1562 * Build LLC Header:
1563 * First insert address field (PD and C/R bit are always 0)
1564 */
1565 sdu->buf[offset++] = llc_data->current_sapi;
1566
1567 /*
1568 * Set A bit and 3 most significant bits of N(R)
1569 */
1570 if (rt == ABIT_SET_REQ)
1571 {
1572 /* LINTED [following sdu index fits into sdu] */
1573 sdu->buf[offset++] = 0xA0 | (UBYTE)(nr >> 6);
1574 }
1575 else
1576 {
1577 /* LINTED [following sdu index fits into sdu] */
1578 sdu->buf[offset++] = 0x80 | (UBYTE)(nr >> 6);
1579 }
1580
1581 /*
1582 * 6 least significant bits of N(R) and the supervisory function bits
1583 */
1584 {
1585 /* LINTED [following sdu index fits into sdu] */
1586 sdu->buf[offset++] = (UBYTE)(((nr << 2) & 0xFC) | sx);
1587 }
1588
1589 /*
1590 * Special SACK bitmap handling
1591 */
1592 if (sx == I_SACK && bm_byte_size != 0 && bm != NULL)
1593 {
1594 USHORT i;
1595
1596 /*
1597 * Insert SACK bitmap
1598 */
1599 for (i = 0; i < bm_byte_size; i++)
1600 {
1601 /* LINTED [following sdu indexes are fitting into sdu] */
1602 sdu->buf[offset++] = bm->data[i];
1603 }
1604 }
1605
1606 #ifdef TRACE_EVE
1607 {
1608 static char* sf[] = { "RR", "ACK", "RNR", "SACK" };
1609
1610 if(sx <= 3)
1611 {
1612 TRACE_3_INFO("Next S-Frame %s NR:%d A:%d", sf[sx], nr, rt);
1613 }
1614 }
1615 #endif
1616
1617 /*
1618 * Reset TX ready flag (before sending because of possible recursion)
1619 */
1620 llc_data->itx->tx_waiting = FALSE;
1621
1622 /*
1623 * Now send the frame to TX. header_size and oc are not used and set to zero.
1624 */
1625 sig_itx_tx_data_req( ll_unitdata_req, S_FRAME, nr, GRLC_DTACS_DEF, 0, 0);
1626 }
1627 #else /* LL_DESC */
1628
1629 /*
1630 * Calculate DESC size
1631 */
1632 desc_bytesize = (S_FRAME_MIN_OCTETS_WITHOUT_FCS) + (bm_byte_size);
1633
1634 /*
1635 * Build primitive and include supervisory command
1636 */
1637 {
1638 PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
1639
1640 desc3 = llc_palloc_desc(desc_bytesize, 0);
1641
1642 ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
1643 ll_unitdesc_req->desc_list3.list_len = desc3->len;
1644
1645 ll_unitdesc_req->sapi = llc_data->current_sapi;
1646 ll_unitdesc_req->tlli = llc_data->tlli_new;
1647
1648 ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
1649 /*
1650 * LLC does not know the QoS profile. S frames should use
1651 * LL_NO_REL
1652 */
1653 ll_unitdesc_req->ll_qos.peak = GRLC_PEAK_SUB;
1654 #ifdef LL_2to1
1655 ll_unitdesc_req->ll_qos.relclass = PS_NO_REL;
1656 #else
1657 ll_unitdesc_req->ll_qos.relclass = LL_NO_REL;
1658 #endif
1659
1660 /*
1661 * LLC signalling frames are always sent with highest priority.
1662 */
1663 ll_unitdesc_req->radio_prio = GRLC_RADIO_PRIO_1;
1664 #ifdef REL99
1665 /*
1666 * From 24.008 & 23.060 it is interpreted that for all signalling data, a
1667 * predefined PFI LL_PFI_SIGNALING shall be used.
1668 */
1669 ll_unitdesc_req->pkt_flow_id = LL_PFI_SIGNALING;
1670 #endif /* REL99 */
1671 /*
1672 * Don't worry about L3 reference - TX will ignore it
1673 */
1674
1675 /*
1676 * SDU offset is 0. The SDU length is sdu_bitsize
1677 */
1678 desc3->offset = 0;
1679 desc3->len = desc_bytesize;
1680
1681 offset = 0;
1682 buf = (U8*)desc3->buffer;
1683 /*
1684 * Build LLC Header:
1685 * First insert address field (PD and C/R bit are always 0)
1686 */
1687 buf[offset++] = llc_data->current_sapi;
1688
1689 /*
1690 * Set A bit and 3 most significant bits of N(R)
1691 */
1692 if (rt == ABIT_SET_REQ)
1693 {
1694 /* LINTED [following sdu index fits into sdu] */
1695 buf[offset++] = 0xA0 | (UBYTE)(nr >> 6);
1696 }
1697 else
1698 {
1699 /* LINTED [following sdu index fits into sdu] */
1700 buf[offset++] = 0x80 | (UBYTE)(nr >> 6);
1701 }
1702
1703 /*
1704 * 6 least significant bits of N(R) and the supervisory function bits
1705 */
1706 {
1707 /* LINTED [following sdu index fits into sdu] */
1708 buf[offset++] = (UBYTE)(((nr << 2) & 0xFC) | sx);
1709 }
1710
1711 /*
1712 * Special SACK bitmap handling
1713 */
1714 if (sx == I_SACK && bm_byte_size != 0 && bm != NULL)
1715 {
1716 USHORT i;
1717
1718 /*
1719 * Insert SACK bitmap
1720 */
1721 for (i = 0; i < bm_byte_size; i++)
1722 {
1723 /* LINTED [following sdu indexes are fitting into sdu] */
1724 buf[offset++] = bm->data[i];
1725 }
1726 }
1727
1728 #ifdef TRACE_EVE
1729 {
1730 static char* sf[] = { "RR", "ACK", "RNR", "SACK" };
1731
1732 if(sx <= 3)
1733 {
1734 TRACE_3_INFO("Next S-Frame %s NR:%d A:%d", sf[sx], nr, rt);
1735 }
1736 }
1737 #endif
1738
1739 /*
1740 * Reset TX ready flag (before sending because of possible recursion)
1741 */
1742 llc_data->itx->tx_waiting = FALSE;
1743
1744 /*
1745 * Now send the frame to TX. header_size and oc are not used and set to zero.
1746 */
1747 sig_itx_tx_data_req( ll_unitdesc_req, S_FRAME, nr, GRLC_DTACS_DEF, 0, 0);
1748 }
1749 #endif /* LL_DESC */
1750 } /* itx_send_s_frame() */
1751
1752