FreeCalypso > hg > fc-magnetite
comparison src/g23m-gprs/llc/llc_irxf.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 (IRX-statemachine) | |
20 +----------------------------------------------------------------------------- | |
21 */ | |
22 | |
23 #ifndef LLC_IRXF_C | |
24 #define LLC_IRXF_C | |
25 #endif | |
26 | |
27 #define ENTITY_LLC | |
28 | |
29 /*==== INCLUDES =============================================================*/ | |
30 | |
31 #include <string.h> | |
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 | |
43 #include "llc_itxs.h" /* to get ITX signal definitions */ | |
44 #include "llc_irxf.h" /* to get IRX local functions */ | |
45 | |
46 | |
47 /*==== CONST ================================================================*/ | |
48 | |
49 /*==== LOCAL VARS ===========================================================*/ | |
50 | |
51 /*==== PRIVATE FUNCTIONS ====================================================*/ | |
52 | |
53 /*==== PUBLIC FUNCTIONS =====================================================*/ | |
54 | |
55 | |
56 | |
57 /* | |
58 +------------------------------------------------------------------------------ | |
59 | Function : irx_init | |
60 +------------------------------------------------------------------------------ | |
61 | Description : This procedure initialises all necessary variables of | |
62 | i_frames_rx for all SAPIs. | |
63 | | |
64 | Parameters : | |
65 | | |
66 +------------------------------------------------------------------------------ | |
67 */ | |
68 GLOBAL void irx_init (void) | |
69 { | |
70 UBYTE inc; | |
71 | |
72 TRACE_FUNCTION( "irx_init" ); | |
73 | |
74 /* | |
75 * Initialise all 4 SAPIs | |
76 */ | |
77 SWITCH_SERVICE (llc, irx, 0); | |
78 INIT_STATE (IRX_0, IRX_TLLI_UNASSIGNED); | |
79 | |
80 SWITCH_SERVICE (llc, irx, 1); | |
81 INIT_STATE (IRX_1, IRX_TLLI_UNASSIGNED); | |
82 | |
83 SWITCH_SERVICE (llc, irx, 2); | |
84 INIT_STATE (IRX_2, IRX_TLLI_UNASSIGNED); | |
85 | |
86 SWITCH_SERVICE (llc, irx, 3); | |
87 INIT_STATE (IRX_3, IRX_TLLI_UNASSIGNED); | |
88 | |
89 /* | |
90 * Initialise the IRX data structure | |
91 */ | |
92 for (inc = 0; inc < IRX_NUM_INC; inc++) | |
93 { | |
94 SWITCH_SERVICE (llc, irx, inc); | |
95 | |
96 /* | |
97 * Free old used resources (in case of an LLC restart): | |
98 * memory, stored primitives, running timer. | |
99 */ | |
100 irx_queue_clean (); | |
101 | |
102 llc_data->irx->ll_send_ready = FALSE; | |
103 llc_data->irx->last_ns = NS_EQUAL_VR; | |
104 | |
105 llc_data->irx->queue = NULL; | |
106 } | |
107 | |
108 return; | |
109 } /* irx_init() */ | |
110 | |
111 | |
112 /* | |
113 +------------------------------------------------------------------------------ | |
114 | Function : irx_init_sapi | |
115 +------------------------------------------------------------------------------ | |
116 | Description : This procedure initialises all necessary variables of | |
117 | i_frames_rx for the given SAPI. | |
118 | | |
119 | Parameters : | |
120 | | |
121 +------------------------------------------------------------------------------ | |
122 */ | |
123 GLOBAL void irx_init_sapi (void) | |
124 { | |
125 TRACE_FUNCTION( "irx_init_sapi" ); | |
126 | |
127 llc_data->sapi->va = 0; | |
128 llc_data->sapi->vs = 0; | |
129 llc_data->sapi->vr = 0; | |
130 | |
131 llc_data->irx->vf = 0; | |
132 llc_data->irx->last_ns = NS_EQUAL_VR; | |
133 llc_data->irx->B_rx = 0; | |
134 | |
135 return; | |
136 } /* irx_init_sapi() */ | |
137 | |
138 | |
139 /* | |
140 +------------------------------------------------------------------------------ | |
141 | Function : irx_init_abm | |
142 +------------------------------------------------------------------------------ | |
143 | Description : This procedure initialises all necessary variables of | |
144 | i_frames_rx for the given SAPI when switching into ABM. | |
145 | | |
146 | Parameters : | |
147 | | |
148 +------------------------------------------------------------------------------ | |
149 */ | |
150 GLOBAL void irx_init_abm (void) | |
151 { | |
152 TRACE_FUNCTION( "irx_init_abm" ); | |
153 | |
154 llc_data->sapi->va = 0; | |
155 llc_data->sapi->vs = 0; | |
156 llc_data->sapi->vr = 0; | |
157 | |
158 llc_data->irx->vf = 0; | |
159 llc_data->irx->last_ns = NS_EQUAL_VR; | |
160 | |
161 /* | |
162 * Reset OCs for acknowledged transfer. | |
163 */ | |
164 llc_data->sapi->oc_i_tx = 0L; | |
165 llc_data->sapi->oc_i_rx = 0L; | |
166 | |
167 return; | |
168 } /* irx_init_abm() */ | |
169 | |
170 | |
171 | |
172 /* | |
173 +------------------------------------------------------------------------------ | |
174 | Function : irx_queue_store | |
175 +------------------------------------------------------------------------------ | |
176 | Description : This procedure stores the primitive into the per ns sorted | |
177 | queue. If the queue is full, is_busy set to TRUE will be | |
178 | returnd. | |
179 | | |
180 | Parameters : | |
181 | | |
182 +------------------------------------------------------------------------------ | |
183 */ | |
184 GLOBAL void irx_queue_store (T_LL_UNITDATA_IND *ll_unitdata_ind, | |
185 T_FRAME_NUM ns, | |
186 BOOL *is_busy) | |
187 { | |
188 T_IRX_QUEUE** entry = &(llc_data->irx->queue); | |
189 T_IRX_QUEUE* next; | |
190 T_FRAME_NUM n = llc_data->irx->vf; | |
191 ULONG M = *(llc_data->md) * 16; | |
192 | |
193 TRACE_FUNCTION( "irx_queue_store" ); | |
194 | |
195 /* | |
196 * First skip already for L3 ready waiting entries | |
197 */ | |
198 while (*entry && (*entry)->ns == n) | |
199 { | |
200 n++; | |
201 n %= (MAX_SEQUENCE_NUMBER+1); | |
202 | |
203 if ((*entry)->ns == ns) | |
204 { | |
205 /* | |
206 * Ignore duplicate frame | |
207 */ | |
208 *is_busy = FALSE; | |
209 | |
210 TRACE_0_INFO( "Unexpected duplicate frame number" ); | |
211 PFREE (ll_unitdata_ind); | |
212 | |
213 return; | |
214 } | |
215 | |
216 entry = &((*entry)->next); | |
217 } | |
218 | |
219 /* | |
220 * Now find the inserting position (queue sorted per ns, | |
221 * 'lower' frame numbers stored first) | |
222 */ | |
223 while (*entry) | |
224 { | |
225 if ((*entry)->ns == ns) | |
226 { | |
227 /* | |
228 * Ignore duplicate frame | |
229 */ | |
230 *is_busy = FALSE; | |
231 | |
232 TRACE_0_INFO( "Duplicate frame number received" ); | |
233 PFREE (ll_unitdata_ind); | |
234 | |
235 return; | |
236 } | |
237 | |
238 /* | |
239 * n <= ns <= (*entry)->ns - 1 | |
240 */ | |
241 if (FRAME_NUM_VALID( n, ns, (*entry)->ns - 1)) | |
242 { | |
243 /* | |
244 * Found a nice place in between | |
245 */ | |
246 break; | |
247 } | |
248 | |
249 entry = &((*entry)->next); | |
250 } | |
251 | |
252 /* | |
253 * Position found - save ptr to next entry | |
254 */ | |
255 next = *entry; | |
256 | |
257 /* | |
258 * Allocate memory | |
259 */ | |
260 MALLOC( *entry, sizeof(T_IRX_QUEUE) ); | |
261 | |
262 if( *entry ) | |
263 { | |
264 /* | |
265 * Memory successful allocated. Fill in struct entries. | |
266 */ | |
267 (*entry)->next = next; | |
268 (*entry)->ns = ns; | |
269 (*entry)->frame = ll_unitdata_ind; | |
270 | |
271 /* | |
272 * Increase amount of stored Information in rx queue | |
273 */ | |
274 llc_data->irx->B_rx += BYTELEN(ll_unitdata_ind->sdu.l_buf); | |
275 | |
276 /* | |
277 * Determine 'own receiver busy' condition | |
278 */ | |
279 if ((M == 0) || (*(llc_data->n201_i) <= M - llc_data->irx->B_rx)) | |
280 { | |
281 *is_busy = FALSE; | |
282 } | |
283 else | |
284 { | |
285 *is_busy = TRUE; | |
286 } | |
287 } | |
288 else | |
289 { | |
290 /* | |
291 * Out of memory | |
292 */ | |
293 *is_busy = TRUE; | |
294 TRACE_ERROR( "Out of memory in irx_queue_store()" ); | |
295 PFREE (ll_unitdata_ind); | |
296 } | |
297 | |
298 } /* irx_queue_store() */ | |
299 | |
300 | |
301 /* | |
302 +------------------------------------------------------------------------------ | |
303 | Function : irx_update_vr | |
304 +------------------------------------------------------------------------------ | |
305 | Description : This procedure increments V(R) if the next following frames | |
306 | are already stored in the queue. | |
307 | | |
308 | Parameters : | |
309 | | |
310 +------------------------------------------------------------------------------ | |
311 */ | |
312 GLOBAL void irx_update_vr (void) | |
313 { | |
314 T_IRX_QUEUE* entry = llc_data->irx->queue; | |
315 | |
316 TRACE_FUNCTION( "irx_update_vr" ); | |
317 | |
318 /* | |
319 * Search the queue from the beginning to entry V(R) | |
320 */ | |
321 while (entry) | |
322 { | |
323 if (entry->ns == llc_data->sapi->vr) | |
324 { | |
325 /* | |
326 * Increment V(R) and continue searching | |
327 */ | |
328 llc_data->sapi->vr++; | |
329 | |
330 if (llc_data->sapi->vr > MAX_SEQUENCE_NUMBER) | |
331 { | |
332 llc_data->sapi->oc_i_rx += (MAX_SEQUENCE_NUMBER+1); | |
333 llc_data->sapi->vr = 0; | |
334 } | |
335 } | |
336 | |
337 entry = entry->next; | |
338 } | |
339 | |
340 } /* irx_update_vr() */ | |
341 | |
342 | |
343 /* | |
344 +------------------------------------------------------------------------------ | |
345 | Function : irx_get_last_queued_ns | |
346 +------------------------------------------------------------------------------ | |
347 | Description : This procedure returns the frame number of the last queue entry | |
348 | | |
349 | Parameters : *found - set to TRUE if ns found, FALSE otherwise | |
350 | | |
351 +------------------------------------------------------------------------------ | |
352 */ | |
353 GLOBAL void irx_get_last_queued_ns (BOOL *found, T_FRAME_NUM *num) | |
354 { | |
355 T_IRX_QUEUE* entry = llc_data->irx->queue; | |
356 | |
357 TRACE_FUNCTION( "irx_get_last_queued_ns" ); | |
358 | |
359 /* | |
360 * Search the queue from the beginning to last entry | |
361 */ | |
362 while (entry AND entry->next) | |
363 entry = entry->next; | |
364 | |
365 if (entry) | |
366 { | |
367 *found = TRUE; | |
368 *num = entry->ns; | |
369 } | |
370 else | |
371 { | |
372 *found = FALSE; | |
373 *num = 0; | |
374 } | |
375 | |
376 } /* irx_get_last_queued_ns() */ | |
377 | |
378 | |
379 /* | |
380 +------------------------------------------------------------------------------ | |
381 | Function : irx_queue_retrieve | |
382 +------------------------------------------------------------------------------ | |
383 | Description : If the next frame in sequence is stored in the queue then this | |
384 | procedure will return the primitive pointer, sets found to | |
385 | TRUE and removes the frame from the queue. | |
386 | | |
387 | Parameters : | |
388 | | |
389 +------------------------------------------------------------------------------ | |
390 */ | |
391 GLOBAL void irx_queue_retrieve (T_LL_UNITDATA_IND **ll_unitdata_ind, BOOL *found) | |
392 { | |
393 T_IRX_QUEUE** entry = &(llc_data->irx->queue); | |
394 | |
395 TRACE_FUNCTION( "irx_queue_retrieve" ); | |
396 | |
397 /* | |
398 * Take the first queue entry, if this is the next one (queue is sorted per ns) | |
399 */ | |
400 if ((*entry != NULL) && ((*entry)->ns == llc_data->irx->vf)) | |
401 { | |
402 /* | |
403 * Store pointer to the entry | |
404 */ | |
405 T_IRX_QUEUE* current = *entry; | |
406 | |
407 /* | |
408 * Remove entry from the queue (make second to first) | |
409 */ | |
410 *entry = current->next; | |
411 | |
412 *ll_unitdata_ind = current->frame; | |
413 | |
414 /* | |
415 * Decrease amount of stored Information in rx queue | |
416 */ | |
417 if (llc_data->irx->B_rx >= (ULONG)(BYTELEN((*ll_unitdata_ind)->sdu.l_buf))) | |
418 { | |
419 llc_data->irx->B_rx -= BYTELEN((*ll_unitdata_ind)->sdu.l_buf); | |
420 } | |
421 else | |
422 { | |
423 llc_data->irx->B_rx = 0; | |
424 TRACE_0_INFO("Unexpected SDU lenght handled"); | |
425 } | |
426 | |
427 /* | |
428 * Free retrieved entry | |
429 */ | |
430 MFREE (current); | |
431 | |
432 *found = TRUE; | |
433 | |
434 /* | |
435 * Increment V(f) (= Next frame number to forward to L3) | |
436 */ | |
437 llc_data->irx->vf += 1; | |
438 llc_data->irx->vf %= (MAX_SEQUENCE_NUMBER+1); | |
439 | |
440 return; | |
441 } | |
442 | |
443 /* | |
444 * Set default return values | |
445 */ | |
446 *ll_unitdata_ind = NULL; | |
447 *found = FALSE; | |
448 } | |
449 | |
450 | |
451 | |
452 /* | |
453 +------------------------------------------------------------------------------ | |
454 | Function : irx_queue_clean | |
455 +------------------------------------------------------------------------------ | |
456 | Description : This procedure removes all entries from the IRX queue | |
457 | | |
458 | Parameters : | |
459 | | |
460 +------------------------------------------------------------------------------ | |
461 */ | |
462 GLOBAL void irx_queue_clean (void) | |
463 { | |
464 T_IRX_QUEUE** entry = &(llc_data->irx->queue); | |
465 | |
466 TRACE_FUNCTION( "irx_queue_clean" ); | |
467 | |
468 while (*entry) | |
469 { | |
470 /* | |
471 * get pointer to next (=first) entry | |
472 */ | |
473 T_IRX_QUEUE* current = *entry; | |
474 | |
475 /* | |
476 * Free frame, if one is attached to the entry | |
477 */ | |
478 if (current->frame != NULL) | |
479 { | |
480 PFREE (current->frame); | |
481 } | |
482 | |
483 /* | |
484 * remove next entry from the entry (make second to first) | |
485 */ | |
486 *entry = current->next; | |
487 | |
488 /* | |
489 * free the removed entry | |
490 */ | |
491 MFREE (current); | |
492 } | |
493 | |
494 /* | |
495 * Adjust amount of stored Information in rx queue | |
496 */ | |
497 llc_data->irx->B_rx = 0; | |
498 | |
499 } /* irx_queue_clean() */ | |
500 | |
501 | |
502 | |
503 /* | |
504 +------------------------------------------------------------------------------ | |
505 | Function : irx_build_sack_bitmap | |
506 +------------------------------------------------------------------------------ | |
507 | Description : This procedure builds a SACK bitmap, depending on current | |
508 | status | |
509 | | |
510 | Parameters : | |
511 | | |
512 +------------------------------------------------------------------------------ | |
513 */ | |
514 GLOBAL void irx_build_sack_bitmap ( T_SACK_BITMAP *bitmap ) | |
515 { | |
516 T_IRX_QUEUE* entry = llc_data->irx->queue; | |
517 int start_ns = (llc_data->sapi->vr + 1) % (MAX_SEQUENCE_NUMBER+1); | |
518 T_FRAME_NUM num = llc_data->irx->vf; | |
519 USHORT d; | |
520 | |
521 | |
522 TRACE_FUNCTION( "irx_build_sack_bitmap" ); | |
523 | |
524 /* | |
525 * Init bitmap to 0 (= frame not successfully received) | |
526 */ | |
527 memset (bitmap, 0, sizeof(T_SACK_BITMAP)); | |
528 | |
529 /* | |
530 * Skip already for L3 ready waiting entries | |
531 */ | |
532 while (entry && entry->ns == num) | |
533 { | |
534 num++; | |
535 num %= (MAX_SEQUENCE_NUMBER+1); | |
536 | |
537 entry = entry->next; | |
538 } | |
539 | |
540 | |
541 /* | |
542 * Check the queue for successful received entries | |
543 */ | |
544 while (entry) | |
545 { | |
546 /* | |
547 * If frame is successful received, mark it in bitmap | |
548 */ | |
549 d = FRAME_NUM_DISTANCE(start_ns, entry->ns); | |
550 | |
551 if (d < (S_FRAME_SACK_MAX_CTRL_OCTETS * 8)) | |
552 { | |
553 bitmap->data[d>>3] |= 0x80>>(d%8); | |
554 } | |
555 | |
556 entry = entry->next; | |
557 } | |
558 } /* irx_build_sack_bitmap () */ | |
559 | |
560 | |
561 /* | |
562 +------------------------------------------------------------------------------ | |
563 | Function : irx_ack_all_to | |
564 +------------------------------------------------------------------------------ | |
565 | Description : This procedure handles the acknowledgement of transmitted I- | |
566 | frames from va to n (which is equal to nr -1) | |
567 | Parameters : | |
568 | | |
569 +------------------------------------------------------------------------------ | |
570 */ | |
571 GLOBAL void irx_ack_all_to (T_FRAME_NUM n) | |
572 { | |
573 TRACE_FUNCTION( "irx_ack_all_to" ); | |
574 | |
575 n %= (MAX_SEQUENCE_NUMBER+1); | |
576 | |
577 if (FRAME_WIN_VALID(n, llc_data->sapi->va, *(llc_data->ku))) | |
578 { | |
579 while (llc_data->sapi->va != (n+1)%(MAX_SEQUENCE_NUMBER+1)) | |
580 { | |
581 sig_irx_itx_ack_ind (TRUE, llc_data->sapi->va); | |
582 | |
583 llc_data->sapi->va++; | |
584 llc_data->sapi->va %= (MAX_SEQUENCE_NUMBER+1); | |
585 } | |
586 | |
587 /* | |
588 * Sending L3 Data confirmations | |
589 */ | |
590 sig_irx_itx_cnf_l3data_req (); | |
591 } | |
592 | |
593 } /* irx_ack_all_to () */ | |
594 | |
595 | |
596 /* | |
597 +------------------------------------------------------------------------------ | |
598 | Function : irx_handle_sack | |
599 +------------------------------------------------------------------------------ | |
600 | Description : This procedure handles the acknowledge bits of a SACK | |
601 | supervisory frame and strips the SACK bitmap from the SDU | |
602 | | |
603 | Parameters : | |
604 | | |
605 +------------------------------------------------------------------------------ | |
606 */ | |
607 GLOBAL void irx_handle_sack (T_FRAME_NUM nr, | |
608 T_LL_UNITDATA_IND *ll_unitdata_ind, | |
609 T_PDU_TYPE frame_type) | |
610 { | |
611 int i, n, bytes; | |
612 T_FRAME_NUM rn = 0; | |
613 T_SACK_BITMAP *bm; | |
614 | |
615 TRACE_FUNCTION( "irx_handle_sack" ); | |
616 | |
617 /* | |
618 * Extract SACK bitmap and number of Ptr to bits from sdu: | |
619 */ | |
620 if (frame_type == I_FRAME) | |
621 { | |
622 bm = (T_SACK_BITMAP*)&(ll_unitdata_ind->sdu.buf[ | |
623 (ll_unitdata_ind->sdu.o_buf >> 3) + 1]); | |
624 bytes = ll_unitdata_ind->sdu.buf[ | |
625 (ll_unitdata_ind->sdu.o_buf >> 3)] & 0xF1; | |
626 } | |
627 else | |
628 { | |
629 bm = (T_SACK_BITMAP*)&(ll_unitdata_ind->sdu.buf[ | |
630 (ll_unitdata_ind->sdu.o_buf >> 3)]); | |
631 bytes = ll_unitdata_ind->sdu.l_buf >> 3; | |
632 } | |
633 | |
634 /* | |
635 * Little Protection | |
636 */ | |
637 if ( bytes > S_FRAME_SACK_MAX_CTRL_OCTETS ) | |
638 { | |
639 bytes = S_FRAME_SACK_MAX_CTRL_OCTETS; | |
640 TRACE_ERROR ("Illegal SACK bitmap size received"); | |
641 } | |
642 | |
643 /* | |
644 * For each bit, which is set, send an acknowledge to ITX | |
645 */ | |
646 for (i = 0; i < bytes; i++) | |
647 { | |
648 for (n = 7; n >= 0; n--) | |
649 { | |
650 /* | |
651 * first increment rn (must begin with 1) | |
652 */ | |
653 rn++; | |
654 | |
655 /* | |
656 * check if bit is set from MSB to LSB | |
657 */ | |
658 if ( bm->data[i] & (1 << n) ) | |
659 { | |
660 /* | |
661 * set frame acknowledged | |
662 */ | |
663 sig_irx_itx_ack_ind ( TRUE, (T_FRAME_NUM)(nr + rn)); | |
664 } | |
665 else | |
666 { | |
667 /* | |
668 * mark frame for retransmission | |
669 */ | |
670 sig_irx_itx_ack_ind ( FALSE, (T_FRAME_NUM)(nr + rn)); | |
671 } | |
672 } | |
673 } | |
674 | |
675 /* | |
676 * send L3 data confirmation | |
677 */ | |
678 sig_irx_itx_cnf_l3data_req (); | |
679 | |
680 /* | |
681 * Strip SACK bitmap from I frame SDUs to get clean L3 PDU | |
682 */ | |
683 if (frame_type == I_FRAME) | |
684 { | |
685 ll_unitdata_ind->sdu.o_buf += bytes << 3; | |
686 ll_unitdata_ind->sdu.l_buf -= bytes << 3; | |
687 } | |
688 | |
689 } /* irx_handle_sack () */ | |
690 | |
691 | |
692 /* | |
693 +------------------------------------------------------------------------------ | |
694 | Function : irx_send_ack | |
695 +------------------------------------------------------------------------------ | |
696 | Description : This procedure handles the detection of sequence errors and | |
697 | the sending of appropriate acknowledgements | |
698 | | |
699 | Parameters : | |
700 | | |
701 +------------------------------------------------------------------------------ | |
702 */ | |
703 GLOBAL void irx_send_ack (T_BIT a_bit) | |
704 { | |
705 TRACE_FUNCTION( "irx_send_ack" ); | |
706 | |
707 /* | |
708 * Send S frame depending on last N(S) / V(R) condition | |
709 */ | |
710 switch (llc_data->irx->last_ns) | |
711 { | |
712 case NS_EQUAL_VR: | |
713 /* | |
714 * Send an RR only, if requested | |
715 */ | |
716 if (a_bit) | |
717 { | |
718 sig_irx_itx_send_rr_req (ABIT_NO_REQ); | |
719 } | |
720 else | |
721 { | |
722 /* | |
723 * Trigger ITX to check queue and send frames | |
724 * This is done inside the other signals, too. | |
725 */ | |
726 sig_irx_itx_trigger_ind (); | |
727 } | |
728 break; | |
729 | |
730 case NS_EQUAL_VR_PLUS_1: | |
731 /* | |
732 * Sequence error - one missing | |
733 */ | |
734 sig_irx_itx_send_ack_req (ABIT_NO_REQ); | |
735 break; | |
736 | |
737 case NS_NO_SEQUENCE_ERROR: | |
738 /* | |
739 * Send an SACK only, if requested | |
740 */ | |
741 if (a_bit) | |
742 { | |
743 T_SACK_BITMAP bitmap; | |
744 | |
745 irx_build_sack_bitmap( &bitmap ); | |
746 sig_irx_itx_send_sack_req (ABIT_NO_REQ, &bitmap); | |
747 } | |
748 else | |
749 { | |
750 /* | |
751 * Trigger ITX to check queue and send frames | |
752 * This is done inside the other signals, too. | |
753 */ | |
754 sig_irx_itx_trigger_ind (); | |
755 } | |
756 break; | |
757 | |
758 default: | |
759 /* | |
760 * Sequence error - one or more missing | |
761 */ | |
762 { | |
763 T_SACK_BITMAP bitmap; | |
764 | |
765 irx_build_sack_bitmap( &bitmap ); | |
766 sig_irx_itx_send_sack_req (ABIT_NO_REQ, &bitmap); | |
767 } | |
768 break; | |
769 } | |
770 | |
771 } /* irx_send_ack () */ | |
772 | |
773 | |
774 /* | |
775 +------------------------------------------------------------------------------ | |
776 | Function : irx_send_rnr | |
777 +------------------------------------------------------------------------------ | |
778 | Description : This procedure sends an RNR to ITX | |
779 | | |
780 | Parameters : | |
781 | | |
782 +------------------------------------------------------------------------------ | |
783 */ | |
784 GLOBAL void irx_send_rnr () | |
785 { | |
786 TRACE_FUNCTION( "irx_send_rnr" ); | |
787 | |
788 sig_irx_itx_send_rnr_req (ABIT_NO_REQ); | |
789 | |
790 } /* irx_send_rnr() */ | |
791 | |
792 |