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