Annotation of Gnu-Mach/chips/tca100_if.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.