FreeCalypso > hg > fc-magnetite
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 |