Annotation of Gnu-Mach/chips/tca100_if.c, revision 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.