FreeBSD/Linux Kernel Cross Reference
sys/chips/tca100_if.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: tca100_if.c,v $
29 * Revision 2.2 93/08/10 15:19:11 mrt
30 * Added a switch to turn off error printf's.
31 * [93/08/02 cmaeda]
32 * Initial check-in.
33 * [93/06/09 16:01:11 jcb]
34 *
35 *
36 */
37
38 /*** TCA 100 ATM NETWORK INTERFACE ***/
39
40 #ifndef STUB
41 #include <chips/tca100_if.h>
42 # else
43 #include "tca100_if.h"
44 #endif
45
46 #define SMALL_WINDOW_SIZE (BOM_DATA_SIZE + EOM_DATA_SIZE)
47 #define INITIAL_WINDOW_SIZE BOM_DATA_SIZE
48 #define CONTINUATION_WINDOW_SIZE (71 * COM_DATA_SIZE)
49 #define FINAL_WINDOW_SIZE (70 * COM_DATA_SIZE + EOM_DATA_SIZE)
50 #define MAX_LONG_RX 2
51 #define MAX_LONG_TX 5
52 #define BASE_TIME_OUT 5
53 #define DELAYED_TIME_OUT 15
54 #define MAX_RETRY 3
55 #define POLL_LIMIT 100000
56 #define POLL_IDLE_TIME 1
57 #define POLL_CELL_TIME 8
58
59 #define TCA_SYNCH 0xfc00
60 #define TCA_ACK (NW_SUCCESS << 10)
61 #define TCA_NAK (NW_FAILURE << 10)
62 #define TCA_OVR (NW_OVERRUN << 10)
63 #define TCA_SEQ (NW_INCONSISTENCY << 10)
64
65 int tca100_verbose = 0;
66
67 int tick[MAX_DEV];
68
69 nw_control_s nw_tx_control[MAX_DEV][MAX_LONG_TX];
70 nw_control_s nw_rx_control[MAX_DEV][MAX_LONG_RX];
71
72 int long_tx_count[MAX_DEV], long_rx_count[MAX_DEV];
73
74 nw_tx_header_t delayed_tx_first[MAX_DEV], delayed_tx_last[MAX_DEV];
75 nw_rx_header_t delayed_rx_first[MAX_DEV], delayed_rx_last[MAX_DEV];
76
77 nw_tcb tct[MAX_EP];
78
79 u_int MTU[] = {9244, 65528, 65532, 65528};
80 u_int MTU_URGENT[] = {32, 28, 32, 28};
81
82 nw_dev_entry_s tca100_entry_table = {
83 tca100_initialize, tca100_status, spans_timer_sweep, tca100_timer_sweep,
84 tca100_poll, tca100_send, tca100_rpc, spans_input, spans_open, spans_accept,
85 spans_close, spans_add, spans_drop};
86
87 typedef enum {
88 ATM_HEADER,
89 SAR_HEADER,
90 SAR_TRAILER,
91 CS_HEADER,
92 CS_TRAILER,
93 FRAME_ERROR,
94 DELIVERY_ERROR,
95 SYNCH_ERROR,
96 SEQ_ERROR,
97 OVERRUN_ERROR,
98 RX_RETRANSMISSION,
99 TX_RETRANSMISSION
100 } tca_error;
101
102 int tca_ec[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
103
104 nw_result tca100_initialize(int dev) {
105 nw_result rc;
106 int i;
107
108 rc = spans_initialize(dev);
109 if (rc = NW_SUCCESS) {
110 tick[dev] = 0;
111 for (i = 0; i < MAX_LONG_TX; i++)
112 nw_tx_control[dev][i].ep = 0;
113 long_tx_count[dev] = 0;
114 delayed_tx_first[dev] = delayed_tx_last[dev] = NULL;
115 for (i = 0; i < MAX_LONG_RX; i++)
116 nw_rx_control[dev][i].ep = 0;
117 long_rx_count[dev] = 0;
118 delayed_rx_first[dev] = delayed_rx_last[dev] = NULL;
119 for (i = 0; i < MAX_EP; i++) {
120 tct[i].rx_sar_header = 0;
121 tct[i].rx_control = NULL;
122 tct[i].tx_queued_count = 0;
123 tct[i].tx_control = NULL;
124 }
125 rc = NW_SUCCESS;
126 }
127 return rc;
128 }
129
130 nw_result tca100_status(int dev) {
131 nw_result rc;
132 atm_device_t atmp;
133 u_int status;
134
135 atmp = (atm_device_t) devct[dev].addr;
136 status = atmp->sreg;
137 if (status & RX_NO_CARRIER) {
138 atmp->creg_set = CR_RX_RESET;
139 atmp->creg_clr = ~CR_RX_RESET;
140 atmp->creg_set = CR_RX_ENABLE;
141 atmp->sreg = 0;
142 rc = NW_NO_CARRIER;
143 } else if (status & RX_CELL_LOST) {
144 atmp->sreg = RX_COUNT_INTR;
145 rc = NW_OVERRUN;
146 } else {
147 rc = NW_SUCCESS;
148 }
149 return rc;
150 }
151
152
153 void tca100_synch_send(int dev, nw_tcb_t tcb, u_int reply) {
154 vol_u_int *tx_fifo = &((atm_device_t) devct[dev].addr)->txfifo[0];
155
156 #ifdef TRACING
157 printf("Synch sent %x\n", reply);
158 #endif
159
160 tx_fifo[0] = tcb->tx_atm_header;
161 tx_fifo[1] = SSM;
162 tx_fifo[2] = HTONL(8);
163 tx_fifo[3] = HTONL(NW_SYNCHRONIZATION);
164 tx_fifo[4] = htonl(reply);
165 tx_fifo[5] = HTONL(8);
166 tx_fifo[6] = 0;
167 tx_fifo[7] = 0;
168 tx_fifo[8] = 0;
169 tx_fifo[9] = 0;
170 tx_fifo[10] = 0;
171 tx_fifo[11] = 0;
172 tx_fifo[12] = 0;
173 tx_fifo[13] = SYNCH_SEGMENT_TRAILER;
174 }
175
176 #define broken_cell_mend(length) { \
177 missing = length; \
178 while (missing != 0) { \
179 if (missing > block_count) { \
180 limit = 0; \
181 missing -= block_count; \
182 } else { \
183 limit = block_count - missing; \
184 missing = 0; \
185 } \
186 while (block_count > limit) { \
187 t1 = block[0]; \
188 block++; \
189 tx_fifo[1] = t1; \
190 block_count -= 4; \
191 } \
192 if (block_count == 0) { \
193 ecb->tx_current = tx_header = ecb->tx_current->next; \
194 if (tx_header != NULL) { \
195 block_count = tx_header->block_length; \
196 block = (vol_u_int *) tx_header->block; \
197 } \
198 } \
199 } \
200 }
201
202
203 nw_result tca100_window_send(int dev, nw_ecb_t ecb, nw_tcb_t tcb,
204 boolean_t initial) {
205 nw_result rc;
206 register vol_u_int *tx_fifo = &((atm_device_t) devct[dev].addr)->txfifo[0];
207 register vol_u_int *block;
208 register u_int block_count, msg_count;
209 register int com_count;
210 int eom_count;
211 register u_int atm_header, sar_header, sar_trailer;
212 u_int cs_header, end_count;
213 int limit, missing;
214 register u_int t1, t2;
215 nw_tx_header_t tx_header;
216 nw_options options;
217
218 atm_header = tcb->tx_atm_header;
219 if (initial) {
220 sar_header = tcb->tx_sar_header & MID;
221 tx_header = ecb->tx_initial;
222 block = (vol_u_int *) tx_header->block;
223 block_count = tx_header->block_length;
224 options = tx_header->options;
225 msg_count = tx_header->msg_length;
226 if (ecb->protocol == NW_LINE)
227 msg_count += 4;
228 if (options == NW_URGENT)
229 msg_count += 4;
230 cs_header = ecb->protocol | (sar_header & 0xff) << 8 |
231 (msg_count & 0xff00) << 8 | msg_count << 24;
232 tcb->tx_cs_header = cs_header;
233
234 if (msg_count <= SSM_DATA_SIZE) { /*Single segment message*/
235 tx_fifo[0] = atm_header;
236 sar_trailer = (msg_count + 8) << 26;
237 tx_fifo[1] = SSM | sar_header; /*Sequence number 0 is implicit*/
238 end_count = msg_count + 4;
239 tx_fifo[1] = cs_header;
240 if (options == NW_URGENT) {
241 tx_fifo[1] = HTONL(NW_URGENT);
242 msg_count -= 4;
243 }
244 if (ecb->protocol == NW_LINE) {
245 tx_fifo[1] = tx_header->peer.local_ep >> 8 |
246 (tx_header->peer.local_ep & 0x00ff) << 8 |
247 (tx_header->peer.remote_ep & 0xff00) << 8 |
248 tx_header->peer.remote_ep << 24;
249 msg_count -= 4;
250 }
251 if (ecb->protocol == NW_SEQ_PACKET) {
252 tcb->tx_synch = 0;
253 } else {
254 tcb->tx_synch = -1;
255 }
256 goto EOM_payload;
257
258 } else { /*Beginning of message*/
259 tx_fifo[0] = atm_header;
260 sar_trailer = FULL_SEGMENT_TRAILER;
261 tx_fifo[1] = BOM | sar_header; /*Sequence number 0 is implicit*/
262 tx_fifo[2] = cs_header;
263 if (block_count < BOM_DATA_SIZE) {
264 if (ecb->protocol == NW_LINE) {
265 t1 = tx_header->peer.local_ep >> 8 |
266 (tx_header->peer.local_ep & 0x00ff) << 8 |
267 (tx_header->peer.remote_ep & 0xff00) << 8 |
268 tx_header->peer.remote_ep << 24;
269 missing = BOM_DATA_SIZE - 4;
270 tx_fifo[3] = t1;
271 } else {
272 missing = BOM_DATA_SIZE;
273 }
274 broken_cell_mend(missing);
275 } else {
276 if (ecb->protocol == NW_LINE) {
277 t1 = tx_header->peer.local_ep >> 8 |
278 (tx_header->peer.local_ep & 0x00ff) << 8 |
279 (tx_header->peer.remote_ep & 0xff00) << 8 |
280 tx_header->peer.remote_ep << 24;
281 } else {
282 t1 = block[0];
283 block_count -= 4;
284 block++;
285 }
286 t2 = block[0];
287 tx_fifo[3] = t1;
288 tx_fifo[4] = t2;
289 t1 = block[1];
290 t2 = block[2];
291 tx_fifo[5] = t1;
292 tx_fifo[6] = t2;
293 t1 = block[3];
294 t2 = block[4];
295 tx_fifo[7] = t1;
296 tx_fifo[8] = t2;
297 t1 = block[5];
298 t2 = block[6];
299 tx_fifo[9] = t1;
300 tx_fifo[10] = t2;
301 t1 = block[7];
302 t2 = block[8];
303 tx_fifo[11] = t1;
304 tx_fifo[12] = t2;
305 block_count -= (BOM_DATA_SIZE - 4);
306 block += 9;
307 }
308 if (ecb->protocol == NW_RAW) {
309 msg_count -= BOM_DATA_SIZE;
310 com_count = msg_count / COM_DATA_SIZE;
311 msg_count = msg_count % COM_DATA_SIZE;
312 eom_count = 1;
313 tcb->tx_synch = -1;
314 } else if (msg_count > SMALL_WINDOW_SIZE) {
315 com_count = eom_count = 0;
316 tcb->tx_synch = msg_count;
317 msg_count -= BOM_DATA_SIZE;
318 } else {
319 com_count = 0;
320 eom_count = 1;
321 if (ecb->protocol == NW_SEQ_PACKET) {
322 tcb->tx_synch = 0;
323 } else {
324 tcb->tx_synch = -1;
325 }
326 msg_count -= BOM_DATA_SIZE;
327 }
328 tx_fifo[13] = sar_trailer;
329 sar_header += SEQ_INC;
330 }
331
332 } else {
333 sar_header = tcb->tx_sar_header;
334 sar_trailer = FULL_SEGMENT_TRAILER;
335 block = (vol_u_int *) tcb->tx_p;
336 block_count = tcb->tx_block_count;
337 msg_count = tcb->tx_msg_count;
338 if (msg_count > FINAL_WINDOW_SIZE) {
339 com_count = (CONTINUATION_WINDOW_SIZE / COM_DATA_SIZE);
340 eom_count = 0;
341 tcb->tx_synch = msg_count;
342 msg_count -= CONTINUATION_WINDOW_SIZE;
343 } else {
344 com_count = msg_count / COM_DATA_SIZE;
345 msg_count = msg_count % COM_DATA_SIZE;
346 eom_count = 1;
347 if (ecb->protocol == NW_SEQ_PACKET) {
348 tcb->tx_synch = 0;
349 } else {
350 tcb->tx_synch = -1;
351 }
352 }
353 }
354
355 while (com_count-- > 0) { /*Continuation of message*/
356 tx_fifo[0] = atm_header;
357 tx_fifo[1] = sar_header; /*COM is 0 and is implicit*/
358 if (block_count >= COM_DATA_SIZE) {
359 t1 = block[0];
360 t2 = block[1];
361 tx_fifo[2] = t1;
362 tx_fifo[3] = t2;
363 t1 = block[2];
364 t2 = block[3];
365 tx_fifo[4] = t1;
366 tx_fifo[5] = t2;
367 t1 = block[4];
368 t2 = block[5];
369 tx_fifo[6] = t1;
370 tx_fifo[7] = t2;
371 t1 = block[6];
372 t2 = block[7];
373 tx_fifo[8] = t1;
374 tx_fifo[9] = t2;
375 t1 = block[8];
376 t2 = block[9];
377 tx_fifo[10] = t1;
378 tx_fifo[11] = t2;
379 t1 = block[10];
380 block_count -= COM_DATA_SIZE;
381 tx_fifo[12] = t1;
382 tx_fifo[13] = sar_trailer;
383 block += 11;
384 sar_header = (sar_header + SEQ_INC) & (SEQ_NO | MID);
385 } else {
386 broken_cell_mend(COM_DATA_SIZE);
387 tx_fifo[13] = sar_trailer;
388 sar_header = (sar_header + SEQ_INC) & (SEQ_NO | MID);
389 }
390 }
391
392 if (eom_count != 0) { /*End of message*/
393 tx_fifo[0] = atm_header;
394 tx_fifo[1] = EOM | sar_header;
395 end_count = msg_count;
396 sar_trailer = (msg_count + 4) << 26;
397
398 EOM_payload:
399 if (block_count >= msg_count) {
400 if (msg_count & 0x4) {
401 t1 = block[0];
402 tx_fifo[1] = t1;
403 }
404 block = (vol_u_int *) ((char *) block + msg_count);
405 switch (msg_count >> 3) {
406 case 5:
407 t1 = block[-10];
408 t2 = block[-9];
409 tx_fifo[1] = t1;
410 tx_fifo[1] = t2;
411 case 4:
412 t1 = block[-8];
413 t2 = block[-7];
414 tx_fifo[1] = t1;
415 tx_fifo[1] = t2;
416 case 3:
417 t1 = block[-6];
418 t2 = block[-5];
419 tx_fifo[1] = t1;
420 tx_fifo[1] = t2;
421 case 2:
422 t1 = block[-4];
423 t2 = block[-3];
424 tx_fifo[1] = t1;
425 tx_fifo[1] = t2;
426 case 1:
427 t1 = block[-2];
428 t2 = block[-1];
429 tx_fifo[1] = t1;
430 tx_fifo[1] = t2;
431 }
432 msg_count = 0;
433 } else {
434 broken_cell_mend(msg_count);
435 msg_count = 0;
436 }
437
438 EOM_cs_trailer:
439 tx_fifo[1] = tcb->tx_cs_header;
440 switch (end_count) {
441 case 0: tx_fifo[1] = 0;
442 case 4: tx_fifo[1] = 0;
443 case 8: tx_fifo[1] = 0;
444 case 12: tx_fifo[1] = 0;
445 case 16: tx_fifo[1] = 0;
446 case 20: tx_fifo[1] = 0;
447 case 24: tx_fifo[1] = 0;
448 case 28: tx_fifo[1] = 0;
449 case 32: tx_fifo[1] = 0;
450 case 36: tx_fifo[1] = 0;
451 }
452 tx_fifo[13] = sar_trailer;
453 }
454
455 if (tcb->tx_synch == -1) {
456
457 #ifdef TRACING
458 printf("Final window sent\n");
459 #endif
460
461 sar_header = (sar_header + MID_INC) & MID;
462 if (sar_header == 0)
463 sar_header = 1;
464 tcb->tx_sar_header = sar_header;
465 rc = NW_SUCCESS;
466 } else {
467
468 #ifdef TRACING
469 printf("Window synch at %x\n", msg_count);
470 #endif
471
472 tcb->tx_sar_header = sar_header;
473 tcb->tx_p = (u_int *) block;
474 tcb->tx_block_count = block_count;
475 tcb->tx_msg_count = msg_count;
476 rc = NW_SYNCH;
477 }
478 return rc;
479 }
480
481 nw_result tca100_send(nw_ep ep, nw_tx_header_t header, nw_options options) {
482 nw_result rc;
483 int i, dev;
484 nw_ecb_t ecb;
485 nw_tcb_t tcb;
486 nw_control_t control;
487 nw_tx_header_t tx_header, tx_previous;
488
489 dev = NW_DEVICE(header->peer.rem_addr_1);
490 ecb = &ect[ep];
491 tcb = &tct[ep];
492 if ((options == NW_URGENT && header->msg_length >
493 MTU_URGENT[ecb->protocol]) || header->msg_length > MTU[ecb->protocol]) {
494 rc = NW_BAD_LENGTH;
495 } else if (tcb->tx_queued_count != 0 ||
496 (ecb->protocol != NW_RAW &&
497 long_tx_count[dev] >= MAX_LONG_TX &&
498 (header->msg_length > SMALL_WINDOW_SIZE ||
499 ecb->protocol == NW_SEQ_PACKET))) {
500 if (options == NW_URGENT && tcb->tx_queued_count != 0) {
501 tx_header = delayed_tx_first[dev];
502 tx_previous = NULL;
503 while (tx_header != NULL && tx_header->sender != ep) {
504 tx_previous = tx_header;
505 tx_header = tx_header->next;
506 }
507 if (tx_previous == NULL)
508 delayed_tx_first[dev] = header;
509 else
510 tx_previous->next = header;
511 while (header->next != NULL)
512 header = header->next;
513 header->next = tx_header;
514 } else {
515 if (delayed_tx_first[dev] == NULL)
516 delayed_tx_first[dev] = header;
517 else
518 delayed_tx_last[dev]->next = header;
519 delayed_tx_last[dev] = header;
520 }
521 tcb->tx_queued_count++;
522 rc = NW_QUEUED;
523
524 #ifdef TRACING
525 printf("Send enqueued ep %d\n", ep);
526 #endif
527
528 } else {
529
530
531 #ifdef TRACING
532 printf("Send ep %d\n", ep);
533 #endif
534
535 ecb->tx_initial = ecb->tx_current = header;
536 rc = tca100_window_send(dev, ecb, tcb, TRUE);
537 if (rc == NW_SUCCESS) {
538 while (header != NULL) {
539 if (header->buffer != NULL)
540 nc_buffer_deallocate(ep, header->buffer);
541 header = header->next;
542 }
543 nc_tx_header_deallocate(ecb->tx_initial);
544 ecb->tx_initial = ecb->tx_current = NULL;
545 } else {
546 control = &nw_tx_control[dev][0];
547 while (control->ep != 0)
548 control++;
549 control->ep = ep;
550 control->time_out = tick[dev] + BASE_TIME_OUT;
551 control->retry = 0;
552 tcb->reply = TCA_SYNCH;
553 tcb->tx_control = control;
554 tcb->tx_queued_count++;
555 if (long_tx_count[dev] + long_rx_count[dev] == 0)
556 nc_fast_timer_set(dev);
557 long_tx_count[dev]++;
558 }
559 }
560 return rc;
561 }
562
563
564 nw_result tx_slot_free(int dev, nw_control_t control) {
565 nw_result rc;
566 nw_tcb_t tcb;
567 nw_ecb_t ecb;
568 nw_tx_header_t tx_header;
569 nw_ep ep;
570
571 tcb = &tct[control->ep];
572 tcb->tx_control = NULL;
573 tcb->tx_queued_count--;
574 do {
575 tx_header = delayed_tx_first[dev];
576 if (tx_header == NULL) {
577 control->ep = 0;
578 long_tx_count[dev]--;
579 rc = NW_FAILURE;
580 } else {
581 ep = tx_header->sender;
582
583 #ifdef TRACING
584 printf("Send dequeued ep %d\n", ep);
585 #endif
586
587 ecb = &ect[ep];
588 tcb = &tct[ep];
589 ecb->tx_initial = ecb->tx_current = tx_header;
590 while (tx_header->next != NULL &&
591 tx_header->next->msg_length == 0) {
592 tx_header = tx_header->next;
593 }
594 delayed_tx_first[dev] = tx_header->next;
595 if (tx_header->next == NULL)
596 delayed_tx_last[dev] = NULL;
597 tx_header->next = NULL;
598 rc = tca100_window_send(dev, ecb, tcb, TRUE);
599 if (rc == NW_SYNCH) {
600 control->ep = ep;
601 tcb->tx_control = control;
602 tcb->reply = TCA_SYNCH;
603 control->time_out = tick[dev] + BASE_TIME_OUT;
604 control->retry = 0;
605 }
606 }
607 } while (rc == NW_SUCCESS);
608 return rc;
609 }
610
611 nw_result rx_slot_free(int dev, nw_control_t control) {
612 nw_result rc;
613 nw_rx_header_t rx_header;
614 nw_ep ep;
615 nw_tcb_t tcb;
616
617 if (control == NULL) {
618 rc = NW_SUCCESS;
619 } else {
620 tct[control->ep].rx_control = NULL;
621 while ((rx_header = delayed_rx_first[dev]) != NULL &&
622 tick[dev] >= rx_header->time_stamp) {
623 delayed_rx_first[dev] = rx_header->next;
624 nc_buffer_deallocate(rx_header->buffer->peer.local_ep,
625 rx_header->buffer);
626 ep = rx_header->receiver;
627 tcb = &tct[ep];
628 tcb->rx_sar_header = SSM | (tcb->rx_sar_header & MID);
629 nc_rx_header_deallocate(rx_header);
630 }
631 if (rx_header == NULL) {
632 delayed_rx_last[dev] = NULL;
633 control->ep = 0;
634 long_rx_count[dev]--;
635 rc = NW_FAILURE;
636 } else {
637 delayed_rx_first[dev] = rx_header->next;
638 if (rx_header->next == NULL)
639 delayed_rx_last[dev] = NULL;
640 ep = rx_header->receiver;
641 tcb = &tct[ep];
642 tca100_synch_send(dev, tcb, rx_header->reply);
643 control->ep = ep;
644 control->time_out = tick[dev] + BASE_TIME_OUT;
645 tcb->rx_control = control;
646 nc_rx_header_deallocate(rx_header);
647 }
648 }
649 }
650
651
652 int tca100_poll(int dev) {
653 vol_u_int *status = &((atm_device_t) devct[dev].addr)->sreg;
654 vol_u_int *ctl_set = &((atm_device_t) devct[dev].addr)->creg_set;
655 vol_u_int *rx_counter = &((atm_device_t) devct[dev].addr)->rxcount;
656 register vol_u_int *rx_fifo = &((atm_device_t) devct[dev].addr)->rxfifo[0];
657 register u_int rx_cell_count;
658 register u_int predicted_atm_header = 0;
659 register u_int predicted_sar_header;
660 u_int atm_header, sar_header, predicted_sar_trailer,
661 cs_header, end_count, cs_pad, rx_cell_total, reply,
662 block_length, initial_offset;
663 register vol_u_int *msg;
664 register int msg_count;
665 register int next_synch;
666 register u_int t1, t2;
667 nw_ecb_t ecb, tx_ecb;
668 nw_tcb_t new_tcb, tx_tcb;
669 nw_tcb dummy_tcb_s;
670 nw_tcb_t tcb = &dummy_tcb_s;
671 nw_control_t control;
672 nw_buffer_t buffer;
673 nw_protocol protocol;
674 nw_ep lep, rep;
675 nw_delivery delivery_type = NW_RECEIVE;
676 nw_rx_header_t rx_header;
677 nw_tx_header_t tx_header;
678 int i;
679 u_int tx_seqno, rx_seqno, tx_count, rx_count;
680
681 rx_cell_total = 0;
682 while ((rx_cell_count = *rx_counter & RX_COUNTER_MASK) != 0) {
683 rx_cell_total += rx_cell_count;
684 while (rx_cell_count-- > 0) {
685 atm_header = rx_fifo[0]; /*Check ATM header and SAR header*/
686 sar_header = (rx_fifo[1] & SAR_HEADER_MASK);
687 if (atm_header != predicted_atm_header) {
688 /*Must be cell from a different connection*/
689 if (atm_header & ~(ATM_VPVC_MASK | ATM_HEADER_RSV_BITS)) {
690 atm_header_error:
691 tca_ec[ATM_HEADER]++;
692 if (tca100_verbose)
693 printf("ATM header error %x\n", atm_header);
694 discard_cell:
695 *((char *) rx_fifo) = 0;
696 delivery_type = NW_RECEIVE;
697 continue;
698 } else {
699 t1 = (atm_header & ATM_VPVC_MASK) >> ATM_VPVC_SHIFT;
700 new_tcb = &tct[t1];
701 ecb = &ect[t1];
702
703 /*Switch cached connection*/
704 if (new_tcb->rx_sar_header == 0)
705 goto atm_header_error;
706 tcb->rx_sar_header = predicted_sar_header;
707 tcb->rx_p = (u_int *) msg;
708 tcb->rx_count = msg_count;
709 tcb->rx_next_synch = next_synch;
710 predicted_atm_header = atm_header;
711 tcb = new_tcb;
712 predicted_sar_header = tcb->rx_sar_header;
713 msg = tcb->rx_p;
714 msg_count = tcb->rx_count;
715 next_synch = tcb->rx_next_synch;
716 }
717 }
718
719 if (sar_header != predicted_sar_header) {
720 if ((sar_header ^ predicted_sar_header) == EOM &&
721 ((predicted_sar_header & BOM) || msg_count <= EOM_DATA_SIZE)) {
722 /*Difference on end of message bit only*/
723 predicted_sar_header = sar_header;
724 } else if (sar_header == SSM) { /*MID 0*/
725 cs_header = rx_fifo[2];
726 t1 = rx_fifo[3];
727 if (cs_header == HTONL(8) && t1 == HTONL(NW_SYNCHRONIZATION)) {
728 reply = rx_fifo[4]; /*Synch cell*/
729 if (rx_fifo[5] != cs_header)
730 goto cs_header_error;
731 cs_pad = rx_fifo[6];
732 t1 = rx_fifo[7];
733 t2 = rx_fifo[8];
734 cs_pad |= t1;
735 cs_pad |= t2;
736 t1 = rx_fifo[9];
737 t2 = rx_fifo[10];
738 cs_pad |= t1;
739 cs_pad |= t2;
740 t1 = rx_fifo[11];
741 t2 = rx_fifo[12];
742 cs_pad |= t1;
743 cs_pad |= t2;
744 t1 = rx_fifo[13];
745 if (cs_pad)
746 goto cs_trailer_error;
747 if ((t1 & SAR_TRAILER_MASK) != SYNCH_SEGMENT_TRAILER)
748 goto sar_trailer_error;
749 if (tcb->tx_control == NULL) {
750 tca_ec[SYNCH_ERROR]++;
751 if (tca100_verbose)
752 printf("Synch error %x\n", ntohl(reply));
753 } else {
754 tcb->reply = ntohl(reply);
755
756 #ifdef TRACING
757 printf("Received synch ep %d %x\n", ecb->id, tcb->reply);
758 #endif
759
760 }
761 continue;
762 } else if (t1 == HTONL(NW_URGENT)) { /*Urgent cell*/
763 delivery_type = NW_RECEIVE_URGENT;
764 goto cs_header_check;
765 } else { /*Bad segment*/
766 goto sar_header_error;
767 }
768 } else if (!(sar_header & ATM_HEADER_CRC_SYNDROME) &&
769 (sar_header & BOM) && (sar_header & SEQ_NO) == 0) {
770 if ((sar_header & MID) == (predicted_sar_header & MID)) {
771 /*Retransmission*/
772 if (tcb->rx_control != NULL) {
773 tcb->rx_control->ep = 0;
774 long_rx_count[dev]--;
775 }
776 nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
777 tcb->rx_buffer);
778 predicted_sar_header = sar_header;
779 tca_ec[RX_RETRANSMISSION]++;
780 if (tca100_verbose)
781 printf("Receiving retransmission ep %d sar %x\n",
782 ecb->id, sar_header);
783 } else if (predicted_sar_header & BOM) {
784 /*Sequence number error*/
785 if (tca100_verbose)
786 printf("Sequence error ep %d pred %x real %x\n", ecb->id,
787 predicted_sar_header, sar_header);
788 if (ecb->protocol == NW_SEQ_PACKET) {
789 reply = 0xffff0000 | TCA_SEQ | (predicted_sar_header & MID);
790 tca100_synch_send(dev, tcb, reply);
791 tca_ec[SEQ_ERROR]++;
792 goto discard_cell;
793 } else {
794 predicted_sar_header = sar_header;
795 }
796 } else {
797 goto sar_header_error; /*Badly out of synch*/
798 }
799 } else { /*Cell loss*/
800
801 sar_header_error:
802 if (!(predicted_sar_header & BOM)) {
803 rx_slot_free(dev, tcb->rx_control);
804 nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
805 tcb->rx_buffer);
806 predicted_sar_header = SSM | (predicted_sar_header & MID);
807 }
808 tca_ec[SAR_HEADER]++;
809 if (tca100_verbose)
810 printf("SAR header error ep %d pred %x real %x\n", ecb->id,
811 predicted_sar_header, sar_header);
812 goto discard_cell;
813 }
814 }
815
816 if ((predicted_sar_header & SEG_TYPE) == COM) {
817 /*Continuation of message*/
818 if (msg_count <= next_synch) {
819 if (msg_count == next_synch &&
820 msg_count >= CONTINUATION_WINDOW_SIZE) {
821 reply = (msg_count << 16) | TCA_ACK | (predicted_sar_header & MID);
822 tca100_synch_send(dev, tcb, reply);
823 if (msg_count > (CONTINUATION_WINDOW_SIZE + FINAL_WINDOW_SIZE)) {
824 next_synch = msg_count - CONTINUATION_WINDOW_SIZE;
825 } else if (ecb->protocol == NW_SEQ_PACKET) {
826 next_synch = 0;
827 } else {
828 next_synch = -1;
829 }
830 tcb->rx_control->time_out = tick[dev] + BASE_TIME_OUT;
831 } else {
832 rx_slot_free(dev, tcb->rx_control);
833 nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
834 tcb->rx_buffer);
835 predicted_sar_header = SSM | (predicted_sar_header & MID);
836 tca_ec[FRAME_ERROR]++;
837 if (tca100_verbose)
838 printf("Frame error ep %d\n", ecb->id);
839 goto discard_cell;
840 }
841 }
842 t1 = rx_fifo[2];
843 t2 = rx_fifo[3];
844 msg[0] = t1;
845 msg[1] = t2;
846 t1 = rx_fifo[4];
847 t2 = rx_fifo[5];
848 msg[2] = t1;
849 msg[3] = t2;
850 t1 = rx_fifo[6];
851 t2 = rx_fifo[7];
852 msg[4] = t1;
853 msg[5] = t2;
854 t1 = rx_fifo[8];
855 t2 = rx_fifo[9];
856 msg[6] = t1;
857 msg[7] = t2;
858 t1 = rx_fifo[10];
859 t2 = rx_fifo[11];
860 msg[8] = t1;
861 msg[9] = t2;
862 t1 = rx_fifo[12];
863 t2 = rx_fifo[13];
864 msg[10] = t1;
865 if ((t2 & SAR_TRAILER_MASK) != FULL_SEGMENT_TRAILER) {
866 t1 = t2;
867 goto sar_trailer_error;
868 }
869 predicted_sar_header = (predicted_sar_header + SEQ_INC) &
870 (SEQ_NO | MID);
871 msg_count -= COM_DATA_SIZE;
872 msg += 11;
873
874 } else if ((predicted_sar_header & BOM) != 0) {
875 cs_header = rx_fifo[2];
876
877 cs_header_check:
878 block_length = msg_count = (((cs_header >> 8) & 0xff00) |
879 (cs_header >> 24));
880 protocol = cs_header & 0x00ff;
881 if (protocol == NW_RAW || protocol == NW_SEQ_PACKET) {
882 lep = ecb->conn->peer.local_ep;
883 rep = ecb->conn->peer.remote_ep;
884 if (delivery_type == NW_RECEIVE)
885 initial_offset = 0;
886 else
887 initial_offset = 4;
888 } else {
889 t1 = rx_fifo[3];
890 block_length -= 4;
891 lep = (t1 >> 8) & 0xff00 | t1 >> 24;
892 rep = (t1 & 0xff00) >> 8 | (t1 & 0x00ff) << 8;
893 if (delivery_type == NW_RECEIVE)
894 initial_offset = 4;
895 else
896 initial_offset = 8;
897 }
898 if (protocol != ecb->protocol || (protocol == NW_DATAGRAM) ||
899 (protocol == NW_LINE && ect[lep].protocol != NW_DATAGRAM) ||
900 ((predicted_sar_header & 0x00ff) << 8) != (cs_header & 0xff00) ||
901 ((delivery_type != NW_RECEIVE) &&
902 msg_count - initial_offset > MTU_URGENT[protocol]) ||
903 msg_count > MTU[protocol] || (msg_count & 0x3)) {
904
905 cs_header_error:
906 if ((protocol != NW_RAW && msg_count > SMALL_WINDOW_SIZE) ||
907 protocol == NW_SEQ_PACKET) {
908 reply = 0xffff0000 | TCA_NAK | (predicted_sar_header & MID);
909 tca100_synch_send(dev, tcb, reply);
910 }
911 tca_ec[CS_HEADER]++;
912 if (tca100_verbose)
913 printf("CS header error ep %d sar %x cs %x\n", ecb->id,
914 predicted_sar_header, cs_header);
915 goto discard_cell;
916 }
917 buffer = nc_buffer_allocate(lep, sizeof(nw_buffer_s) + block_length);
918 if (buffer == NULL) {
919 if ((protocol != NW_RAW && msg_count > SMALL_WINDOW_SIZE) ||
920 protocol == NW_SEQ_PACKET) {
921 reply = 0xffff0000 | TCA_OVR | (predicted_sar_header & MID);
922 tca100_synch_send(dev, tcb, reply);
923 }
924 tca_ec[OVERRUN_ERROR]++;
925 if (tca100_verbose)
926 printf("Overrun error ep %d\n", ecb->id);
927 goto discard_cell;
928 }
929 if (protocol == NW_RAW) {
930 next_synch = -1;
931 } else if (msg_count > SMALL_WINDOW_SIZE) {
932 reply = (msg_count << 16) | TCA_ACK | (predicted_sar_header & MID);
933 if (long_rx_count[dev] >= MAX_LONG_RX) {
934 rx_header = nc_rx_header_allocate();
935 if (rx_header == NULL) {
936 nc_buffer_deallocate(lep, buffer);
937 tca_ec[OVERRUN_ERROR]++;
938 goto discard_cell;
939 }
940 rx_header->buffer = buffer;
941 rx_header->receiver = ecb->id;
942 rx_header->reply = reply;
943 rx_header->time_stamp = tick[dev] + DELAYED_TIME_OUT;
944 rx_header->next = NULL;
945 if (delayed_rx_last[dev] == NULL)
946 delayed_rx_first[dev] = rx_header;
947 else
948 delayed_rx_last[dev]->next = rx_header;
949 delayed_rx_last[dev] = rx_header;
950 } else {
951 tca100_synch_send(dev, tcb, reply);
952 control = &nw_rx_control[dev][0];
953 while (control->ep != 0)
954 control++;
955 control->ep = ecb->id;
956 control->time_out = tick[dev] + BASE_TIME_OUT;
957 tcb->rx_control = control;
958 if (long_rx_count[dev] + long_tx_count[dev] == 0)
959 nc_fast_timer_set(dev);
960 long_rx_count[dev]++;
961 }
962 if (msg_count > INITIAL_WINDOW_SIZE + FINAL_WINDOW_SIZE)
963 next_synch = msg_count - INITIAL_WINDOW_SIZE;
964 else if (protocol == NW_SEQ_PACKET)
965 next_synch = 0;
966 else
967 next_synch = -1;
968 } else if (protocol == NW_SEQ_PACKET) {
969 next_synch = 0;
970 } else {
971 next_synch = -1;
972 }
973 msg = (vol_u_int *) ((char *) buffer + sizeof(nw_buffer_s));
974 tcb->rx_cs_header = cs_header;
975 tcb->rx_buffer = buffer;
976 buffer->buf_next = NULL;
977 buffer->msg_seqno = sar_header & MID;
978 buffer->block_offset = sizeof(nw_buffer_s);
979 buffer->block_length = block_length;
980 buffer->peer.rem_addr_1 = ecb->conn->peer.rem_addr_1;
981 buffer->peer.rem_addr_2 = ecb->conn->peer.rem_addr_2;
982 buffer->peer.local_ep = lep;
983 buffer->peer.remote_ep = rep;
984
985 if ((predicted_sar_header & EOM) == 0) { /*BOM*/
986 if (initial_offset == 0) {
987 t1 = rx_fifo[3];
988 t2 = rx_fifo[4];
989 msg[0] = t1;
990 msg[1] = t2;
991 msg += 2;
992 } else {
993 msg[0] = rx_fifo[4];
994 msg++;
995 }
996 t1 = rx_fifo[5];
997 t2 = rx_fifo[6];
998 msg[0] = t1;
999 msg[1] = t2;
1000 t1 = rx_fifo[7];
1001 t2 = rx_fifo[8];
1002 msg[2] = t1;
1003 msg[3] = t2;
1004 t1 = rx_fifo[9];
1005 t2 = rx_fifo[10];
1006 msg[4] = t1;
1007 msg[5] = t2;
1008 t1 = rx_fifo[11];
1009 t2 = rx_fifo[12];
1010 msg[6] = t1;
1011 t1 = rx_fifo[13];
1012 msg[7] = t2;
1013 if ((t1 & SAR_TRAILER_MASK) != FULL_SEGMENT_TRAILER)
1014 goto sar_trailer_error;
1015 msg_count -= BOM_DATA_SIZE;
1016 msg += 8;
1017 predicted_sar_header = (predicted_sar_header + SEQ_INC) &
1018 (SEQ_NO | MID);
1019
1020 } else { /*SSM*/
1021 end_count = msg_count + 4;
1022 predicted_sar_trailer = (msg_count + 8) << 26;
1023 if (delivery_type != NW_RECEIVE) {
1024 msg[0] = NW_URGENT;
1025 msg++;
1026 }
1027 msg_count -= initial_offset;
1028 goto EOM_payload;
1029 }
1030 } else { /*EOM*/
1031 end_count = msg_count;
1032 predicted_sar_trailer = (msg_count + 4) << 26;
1033
1034 EOM_payload:
1035 if (msg_count & 0x4) {
1036 msg[0] = rx_fifo[2];
1037 }
1038 msg = (vol_u_int *) ((char *) msg + msg_count);
1039 /*Fall-through the cases is intentional*/
1040 switch (msg_count >> 3) {
1041 case 5:
1042 t1 = rx_fifo[2];
1043 t2 = rx_fifo[2];
1044 msg[-10] = t1;
1045 msg[-9] = t2;
1046 case 4:
1047 t1 = rx_fifo[2];
1048 t2 = rx_fifo[2];
1049 msg[-8] = t1;
1050 msg[-7] = t2;
1051 case 3:
1052 t1 = rx_fifo[2];
1053 t2 = rx_fifo[2];
1054 msg[-6] = t1;
1055 msg[-5] = t2;
1056 case 2:
1057 t1 = rx_fifo[2];
1058 t2 = rx_fifo[2];
1059 msg[-4] = t1;
1060 msg[-3] = t2;
1061 case 1:
1062 t1 = rx_fifo[2];
1063 t2 = rx_fifo[2];
1064 msg[-2] = t1;
1065 msg[-1] = t2;
1066 }
1067
1068 /*CS trailer should be equal to the CS header, followed by
1069 padding zeros*/
1070 cs_pad = (rx_fifo[2] != tcb->rx_cs_header);
1071 /*Fall-through the cases is intentional*/
1072 t1 = t2 = 0;
1073 switch (end_count) {
1074 case 0:
1075 t1 = rx_fifo[2];
1076 case 4:
1077 t2 = rx_fifo[2];
1078 cs_pad |= t1;
1079 case 8:
1080 t1 = rx_fifo[2];
1081 cs_pad |= t2;
1082 case 12:
1083 t2 = rx_fifo[2];
1084 cs_pad |= t1;
1085 case 16:
1086 t1 = rx_fifo[2];
1087 cs_pad |= t2;
1088 case 20:
1089 t2 = rx_fifo[2];
1090 cs_pad |= t1;
1091 case 24:
1092 t1 = rx_fifo[2];
1093 cs_pad |= t2;
1094 case 28:
1095 t2 = rx_fifo[2];
1096 cs_pad |= t1;
1097 case 32:
1098 t1 = rx_fifo[2];
1099 cs_pad |= t2;
1100 case 36:
1101 t2 = rx_fifo[2];
1102 cs_pad |= t1;
1103 cs_pad |= t2;
1104 }
1105 t1 = rx_fifo[13];
1106 if (cs_pad != 0) {
1107 /*Errors in CS trailer or pad*/
1108 cs_trailer_error:
1109 tca_ec[CS_TRAILER]++;
1110 if (tca100_verbose)
1111 printf("CS trailer error ep %d hd %x pad %x\n", ecb->id,
1112 tcb->rx_cs_header, cs_pad);
1113 goto trailer_error;
1114
1115 } else if ((t1 & SAR_TRAILER_MASK) != predicted_sar_trailer) {
1116 /*Error in SAR trailer or framing*/
1117 sar_trailer_error:
1118 tca_ec[SAR_TRAILER]++;
1119 if (tca100_verbose)
1120 printf("SAR trailer error ep %d pred %x real %x\n", ecb->id,
1121 predicted_sar_trailer, t1);
1122 goto trailer_error;
1123
1124 } else if (!nc_deliver_result(tcb->rx_buffer->peer.local_ep,
1125 delivery_type, (int) tcb->rx_buffer)) {
1126 tca_ec[DELIVERY_ERROR]++;
1127 if (tca100_verbose)
1128 printf("Delivery error ep %d\n", ecb->id);
1129
1130 trailer_error:
1131 if (next_synch >= 0 && !(t1 & HEADER_CRC_ERROR)) {
1132 reply = (msg_count << 16) | TCA_NAK | (predicted_sar_header & MID);
1133 tca100_synch_send(dev, tcb, reply);
1134 }
1135 rx_slot_free(dev, tcb->rx_control);
1136 nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
1137 tcb->rx_buffer);
1138 predicted_sar_header = SSM | (predicted_sar_header & MID);
1139 delivery_type = NW_RECEIVE;
1140 } else {
1141
1142 #ifdef TRACING
1143 printf("Received correctly ep %d\n", ecb->id);
1144 #endif
1145
1146 if (next_synch == 0) {
1147 reply = TCA_ACK | (predicted_sar_header & MID);
1148 tca100_synch_send(dev, tcb, reply);
1149 }
1150 rx_slot_free(dev, tcb->rx_control);
1151 if (delivery_type != NW_RECEIVE) {
1152 delivery_type = NW_RECEIVE;
1153 predicted_sar_header = SSM | (predicted_sar_header & MID);
1154 } else {
1155 predicted_sar_header = (predicted_sar_header + MID_INC) & MID;
1156 if (predicted_sar_header == 0)
1157 predicted_sar_header = 1;
1158 predicted_sar_header |= SSM;
1159 }
1160 }
1161 }
1162 }
1163
1164 control = &nw_tx_control[dev][0];
1165 for (i = 0; i < MAX_LONG_TX; i++) {
1166 if (control->ep != 0 && tct[control->ep].reply != TCA_SYNCH) {
1167 tx_ecb = &ect[control->ep];
1168 tx_tcb = &tct[control->ep];
1169 rx_seqno = tx_tcb->reply & MID;
1170 tx_seqno = tx_tcb->tx_sar_header & MID;
1171 rx_count = tx_tcb->reply >> 16;
1172 tx_count = tx_tcb->tx_synch;
1173 reply = tx_tcb->reply & TCA_SYNCH;
1174 if (reply == TCA_ACK) {
1175 if (rx_seqno == tx_seqno && rx_count == tx_count) {
1176 if (rx_count == 0) {
1177 #ifdef TRACING
1178 printf("Received final ack ep %d\n", tx_ecb->id);
1179 #endif
1180
1181 tx_seqno = (tx_seqno + MID_INC) & MID;
1182 if (tx_seqno == 0)
1183 tx_seqno = 1;
1184 tx_tcb->tx_sar_header = tx_seqno;
1185 tx_slot_free(dev, control);
1186 tx_tcb->reply = NW_SUCCESS;
1187 nc_deliver_result(tx_ecb->id, NW_SEND, NW_SUCCESS);
1188 } else {
1189 if (tca100_window_send(dev, tx_ecb, tx_tcb,
1190 FALSE) == NW_SUCCESS) {
1191 nc_deliver_result(control->ep, NW_SEND, NW_SUCCESS);
1192 tx_tcb->reply = NW_SUCCESS;
1193 tx_slot_free(dev, control);
1194 } else {
1195 control->time_out = tick[dev] + BASE_TIME_OUT;
1196 tx_tcb->reply = TCA_SYNCH;
1197 }
1198 }
1199 } else {
1200 goto synch_error;
1201 }
1202 } else if (reply == TCA_OVR) {
1203 if (rx_seqno == tx_seqno && rx_count == 0xffff &&
1204 ((int) tx_ecb->tx_initial->msg_length -
1205 (int) tx_tcb->tx_synch) <= (int) SMALL_WINDOW_SIZE) {
1206 nc_deliver_result(control->ep, NW_SEND, NW_OVERRUN);
1207 tx_tcb->reply = NW_OVERRUN;
1208 tx_slot_free(dev, control);
1209 } else {
1210 goto synch_error;
1211 }
1212 } else if (reply == TCA_NAK) {
1213 if (rx_seqno == tx_seqno &&
1214 (rx_count == tx_count || (rx_count == 0xffff &&
1215 ((int) tx_ecb->tx_initial->msg_length -
1216 (int) tx_tcb->tx_synch) <= (int) SMALL_WINDOW_SIZE))) {
1217 if (++control->retry < MAX_RETRY) {
1218 if (tca100_verbose)
1219 printf("Sending retransmission ep %d\n", tx_ecb->id);
1220 if (tca100_window_send(dev, tx_ecb, tx_tcb,
1221 TRUE) == NW_SUCCESS) {
1222 nc_deliver_result(control->ep, NW_SEND, NW_SUCCESS);
1223 tx_tcb->reply = NW_SUCCESS;
1224 tx_slot_free(dev, control);
1225 } else {
1226 control->time_out = tick[dev] + BASE_TIME_OUT;
1227 tx_tcb->reply = TCA_SYNCH;
1228 }
1229 tca_ec[TX_RETRANSMISSION]++;
1230 } else {
1231 nc_deliver_result(control->ep, NW_SEND, NW_FAILURE);
1232 tx_tcb->reply = NW_FAILURE;
1233 tx_slot_free(dev, control);
1234 }
1235 } else {
1236 goto synch_error;
1237 }
1238 } else if (reply == TCA_SEQ) {
1239 if (rx_count == 0xffff && tx_ecb->protocol == NW_SEQ_PACKET &&
1240 ((int) tx_ecb->tx_initial->msg_length -
1241 (int) tx_tcb->tx_synch) <= (int) SMALL_WINDOW_SIZE &&
1242 rx_seqno == ((((tx_seqno + MID_INC) & MID) == 0) ?
1243 1 : tx_seqno + MID_INC)) {
1244 tx_tcb->tx_sar_header = rx_seqno;
1245 if (tca100_window_send(dev, tx_ecb, tx_tcb,
1246 TRUE) == NW_SUCCESS) {
1247 nc_deliver_result(control->ep, NW_SEND, NW_SUCCESS);
1248 tx_tcb->reply = NW_SUCCESS;
1249 tx_slot_free(dev, control);
1250 } else {
1251 control->time_out = tick[dev] + BASE_TIME_OUT;
1252 tx_tcb->reply = TCA_SYNCH;
1253 }
1254 tca_ec[TX_RETRANSMISSION]++;
1255 if (tca100_verbose)
1256 printf("Sending seq retransmission ep %d\n", tx_ecb->id);
1257 } else {
1258 goto synch_error;
1259 }
1260 } else {
1261 synch_error:
1262 tca_ec[SYNCH_ERROR]++;
1263 tx_tcb->reply = NW_FAILURE;
1264 if (tca100_verbose)
1265 printf("Synch error\n");
1266 }
1267 }
1268 control++;
1269 }
1270 }
1271 *status = ~(RX_COUNT_INTR | RX_EOM_INTR | RX_TIME_INTR);
1272 tcb->rx_sar_header = predicted_sar_header;
1273 tcb->rx_p = (u_int *) msg;
1274 tcb->rx_count = msg_count;
1275 tcb->rx_next_synch = next_synch;
1276 *ctl_set = RX_COUNT_INTR;
1277 return rx_cell_total;
1278 }
1279
1280
1281
1282 void tca100_timer_sweep(int dev) {
1283 int i, rt;
1284 u_int reply;
1285 nw_control_t control;
1286 nw_ecb_t ecb;
1287 nw_tcb_t tcb;
1288 nw_tx_header_t tx_header;
1289 nw_rx_header_t rx_header;
1290
1291 tick[dev]++;
1292 control = &nw_rx_control[dev][0];
1293 for (i = 0; i < MAX_LONG_RX; i++) {
1294 if (control->ep != 0 && control->time_out < tick[dev]) {
1295 rx_slot_free(dev, control);
1296 tcb = &tct[control->ep];
1297 nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep, tcb->rx_buffer);
1298 tcb->rx_sar_header = SSM | (tcb->rx_sar_header & MID);
1299 }
1300 control++;
1301 }
1302 control = &nw_tx_control[dev][0];
1303 for (i = 0; i < MAX_LONG_TX; i++) {
1304 if (control->ep != 0 && control->time_out < tick[dev]) {
1305 ecb = &ect[control->ep];
1306 tcb = &tct[control->ep];
1307 if (++control->retry < MAX_RETRY) {
1308 if (control->retry == 1)
1309 rt = ( /* random() */ + devct[dev].local_addr_2) & 0x000f;
1310 else
1311 rt = ( /* random() */ + devct[dev].local_addr_1
1312 + devct[dev].local_addr_2) & 0x00ff;
1313 control->time_out = tick[dev] + BASE_TIME_OUT + rt;
1314 tca100_window_send(dev, ecb, tcb, TRUE);
1315 tca_ec[TX_RETRANSMISSION]++;
1316 } else {
1317 nc_deliver_result(control->ep, NW_SEND, NW_TIME_OUT);
1318 tx_slot_free(dev, control);
1319 }
1320 }
1321 control++;
1322 }
1323 if (long_tx_count[dev] + long_rx_count[dev] > 0)
1324 nc_fast_timer_set(dev);
1325 else
1326 tick[dev] = 0;
1327 }
1328
1329 nw_buffer_t tca100_rpc(nw_ep ep, nw_tx_header_t header, nw_options options) {
1330 nw_result rc;
1331 nw_buffer_t buf;
1332 nw_ecb_t ecb;
1333 nw_tcb_t tcb;
1334 nw_rx_header_t rx_header;
1335 int dev, poll_time, ncells;
1336
1337 tcb = &tct[ep];
1338 ecb = &ect[header->peer.local_ep];
1339 dev = NW_DEVICE(header->peer.rem_addr_1);
1340 if ((rc = tca100_send(ep, header, options)) == NW_BAD_LENGTH) {
1341 buf = NW_BUFFER_ERROR;
1342 } else if (rc == NW_QUEUED) {
1343 buf = NULL;
1344 } else {
1345 poll_time = 0;
1346 if (rc == NW_SYNCH) {
1347 while (tcb->reply == TCA_SYNCH && poll_time < POLL_LIMIT) {
1348 ncells = tca100_poll(dev);
1349 if (ncells == 0)
1350 poll_time += POLL_IDLE_TIME;
1351 else
1352 poll_time += ncells * POLL_CELL_TIME;
1353 }
1354 }
1355 if (tcb->reply != NW_SUCCESS) {
1356 buf = NW_BUFFER_ERROR;
1357 } else {
1358 while (ecb->rx_first == NULL && poll_time < POLL_LIMIT) {
1359 ncells = tca100_poll(dev);
1360 if (ncells == 0)
1361 poll_time += POLL_IDLE_TIME;
1362 else
1363 poll_time += ncells * POLL_CELL_TIME;
1364 }
1365 if (ecb->rx_first == NULL) {
1366 buf = NULL;
1367 } else {
1368 rx_header = ecb->rx_first;
1369 buf = rx_header->buffer;
1370 ecb->rx_first = rx_header->next;
1371 if (ecb->rx_first == NULL)
1372 ecb->rx_last = NULL;
1373 nc_rx_header_deallocate(rx_header);
1374 }
1375 }
1376 }
1377
1378 return buf;
1379 }
1380
1381
1382
1383
1384
1385
1386
1387
1388
Cache object: 289f190ccf068828b53e39f124febb12
|