Annotation of driverkit/notes/enetPseudocode, revision 1.1.1.1

1.1       root        1: {\rtf0\ansi{\fonttbl\f0\fmodern Ohlfs;\f1\fmodern Courier;}
                      2: \paperw13040
                      3: \paperh10200
                      4: \margl120
                      5: \margr120
                      6: {\colortbl\red0\green0\blue0;}
                      7: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\f0\b0\i0\ul0\fs24                        enet Pseudocode\
                      8:                \
                      9: 
                     10: \f1\b\fs28 /* \
                     11:  * instance variables\
                     12:  */
                     13: \f0\b0\fs24 \
                     14: \{\
                     15:        enetBuf_t       *
                     16: \fc0 TxBufList;        // Free buffers. Maybe one global \
                     17:                                        //   list?\
                     18:        enetBuf_t       *RxBufList;\
                     19:        id              txBufLock;      // NXSpinLock; protects TxBufList\
                     20:        id              rxBufLock;\
                     21:        id              rpcLock;        // NXSleepLock; I/O thread and netOutput\
                     22:                                        //   must grab this to do kernel RPCs\
                     23:        int             numTxBufsQd;    // # of TX DMA buffers enqueued\
                     24:        int             numRxBufsQd;\
                     25:        port_t          IOPort;         // I/O thread gets all of its work \
                     26:                                        //   thru here\
                     27:        int             jamRetryCount;
                     28: \
                     29: \}\
                     30: \
                     31: 
                     32: \f1\b\fs28 /* \
                     33:  * Exported Methods    \
                     34:  */
                     35: \f0\b0\fs24 \
                     36: 
                     37: \
                     38: + probe:(dev_num_t)devNumber deviceMaster:(port_t)deviceMaster\
                     39: \{\
                     40:        alloc an instance of self;\
                     41:        return [newInst enetInit:devNumber deviceMaster:deviceMaster];\
                     42: \}\
                     43: \
                     44: /*\
                     45:  * I think this is only called once...\
                     46:  */\
                     47: - (int)netInit\
                     48: \{\
                     49:        init instance variables;\
                     50:        init hardware to a good state;\
                     51:        for(some initial # of free enetBufs) \{\
                     52:                kalloc or vm_allocate a page;\
                     53:                break up page into enetBuf's;\
                     54:                for each enetBuf_t \{\
                     55:                        init it;\
                     56:                        enqueue on Rx or TXBufList;\
                     57:                        numFreeBufs++;\
                     58:                \}\
                     59:        \}\
                     60:        [self enqueueRxBufs];\
                     61: \}\
                     62: \
                     63: - (int)netOutput : (netbuf_t)buf\
                     64:                   addrs : (void *)addrs\
                     65: \{\
                     66:        /*\
                     67:         * Assuming that this is NOT called at interrupt level...\
                     68:         */\
                     69:        [rpcLock lock];\
                     70:        dma_enqueue(data = nb_map(netbuf), \
                     71:                dma_id = netbuf, \
                     72:                length = nb_size(netbuf));\
                     73:        if(!running) \{\
                     74:                [self dmaStart];\
                     75:                arrange for NetJamTimer() callout in 10 seconds;\
                     76:        \}\
                     77:        [rpcLock unlock];\
                     78: \}\
                     79:                   \
                     80: - (netbuf_t)netGetBuf\
                     81: \{\
                     82:        if no bufs in TxBufList \{\
                     83:                return NULL;\
                     84:        \}\
                     85:        return(nb_alloc_wrapper(&enetBuf->dmaData,\
                     86:                size of DMA Data,\
                     87:                &enetBufFree(),\
                     88:                &enetBuf));\
                     89: \}\
                     90: \
                     91: - (int)netControl : (const char *)command\
                     92:                    data : (void *)data\
                     93: \{\
                     94:        /* crufty crap */\
                     95: \}\
                     96: \
                     97: 
                     98: \f1\b\fs28 /* \
                     99:  * Private Methods\
                    100:  */
                    101: \f0\b0\fs24 \
                    102: - (void)enqueueRxBufs\
                    103: \{\
                    104:        /*\
                    105:         * Enqueue all free bufs in RxBufList on hardware DMA queue\
                    106:         */\
                    107:        [rpcLock lock];\
                    108:        do \{\
                    109:                get an enetBuf from RxBufList;\
                    110:                netbuf = nb_alloc_wrapper(&enetBuf->dmaData,\
                    111:                        size of DMA Data,\
                    112:                        &enetBufFree(),\
                    113:                        &enetBuf);\
                    114:                dma_enqueue(data = &enetBuf.dmaData,\
                    115:                        dma_id = netbuf, \
                    116:                        length = sizeof DMA data);\
                    117:                rxDmaQCount++;\
                    118:        \
                    119:        \} while RxBufList not empty;\
                    120:        [rpcLock unlock]; \
                    121: \}\
                    122: \
                    123: - enetInit:(dev_num_t)devNumber deviceMaster:(port_t)deviceMaster\
                    124: \{\
                    125:        get ethernet address from monitor or somewhere;\
                    126:        if_attach(a zillion args);\
                    127:        return self;\
                    128: \}\
                    129: \
                    130: - enetInt\
                    131: \{\
                    132:        if device interrupt \{\
                    133:                log this bogality;\
                    134:        \}\
                    135: 
                    136: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0      if chan[rcv] interrupt \{\
                    137:                [self enetRxInt];\
                    138:        \}\
                    139:        if chan[xmit] interrupt \{\
                    140:                [self enetTxInt];\
                    141:        \}\
                    142: 
                    143: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \}\
                    144: \
                    145: /*\
                    146:  * Note should not be any device errors, only channel errors.\
                    147:  */\
                    148: 
                    149: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 - enetRxInt\
                    150: \{\
                    151:        if any DMA errors (errorInterrupt, busError) \{\
                    152:                dmaAort;\
                    153:                log it and clear it;\
                    154:        \}\
                    155:        if overrun \{\
                    156:                log it and clear it;\
                    157:        \}\
                    158:        do \{\
                    159:                [rpcLock lock];\
                    160:                chan_dma_dequeue(completed only, enable interrupts \
                    161:                                if no more);\
                    162:                [rpcLock unlock];\
                    163:                if(dma_id == NULL)\
                    164:                        break - done;\
                    165:                if(any errors in chan_status) \{\
                    166:                        /* drop it on the floor */\
                    167:                        nb_free((netbuf_t)dma_id);\
                    168:                \}\
                    169:                else \{\
                    170:                        filter out unwanted multicast packets;\
                    171:                        if_handle_input((netbuf_t)dma_id);\
                    172:                \}\
                    173:        \} for all completed descriptors;\
                    174:        [self enqueueRxBufs];\
                    175: \}\
                    176: \
                    177: - enetTxInt\
                    178: \{\
                    179:        abort = 0;\
                    180:        \
                    181:        untimeout(NetJamTimer callout);\
                    182:        if any DMA errors (errorInterrupt, busError) \{\
                    183:                log it and clear it;\
                    184:                dmaDisable;\
                    185:                abort++;\
                    186:        \}\
                    187:        if late collision or underrun \{\
                    188:                log it and clear it;\
                    189:                abort++;\
                    190:        \}\
                    191:        if No heart beat or >15 retries error \{\
                    192:                abort++;\
                    193:                [self enJam];\
                    194:        \}\
                    195:        do \{\
                    196:                [rpcLock lock];\
                    197:                if(abort) \{\
                    198: 
                    199: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0                      chan_dma_dequeue(ALL descriptors, enable ints);\
                    200:                \}\
                    201:                else \{
                    202: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 \
                    203:                        chan_dma_dequeue(
                    204: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 completed only, enable
                    205: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0  
                    206: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 interrupts 
                    207: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 \
                    208:                                
                    209: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 if no more
                    210: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 );\
                    211:                \}\
                    212:                [rpcLock unlock];\
                    213:                if(dma_id == NULL)\
                    214:                        break - done;\
                    215:                nb_free((netbuf_t)dma_id);\
                    216: 
                    217: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0      \} for all completed descriptors;
                    218: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 \
                    219: \}\
                    220: 
                    221: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 \
                    222: - (jam_t)enJam\
                    223: \{\
                    224: \
                    225:        if (++jamRetryCount < max) \
                    226:                return JAM_GOOD;\
                    227: \
                    228:        remember current I/F mode (TPE or thin);\
                    229:        select TPE;\
                    230:        wait some h/w delay for Link Integrity to settle down;\
                    231:        if link integrity good \{\
                    232:                return JAM_GOOD;\
                    233:        \}\
                    234:        else if (mode was TPE on entry) \{\
                    235:                select Thin wire;\
                    236:                return JAM_GOOD;\
                    237:        \}\
                    238:        \
                    239:        /* \
                    240:         * Net down.\
                    241:         */\
                    242:        dequeue and free all frames;\
                    243:        set net_down flag; set timeout to clear it in 10 seconds;\
                    244:        if_down();\
                    245:        return JAM_BAD;\
                    246: \}\
                    247: \
                    248: - (enetBuf_t)enetBufGet(which queue)\
                    249: \{\
                    250:        safely get an enetBuf from appropriate queue;\
                    251: \}\
                    252: \
                    253: - (void)enetBufPut\
                    254: \{\
                    255:        safely put an enetBuf on its free queue;\
                    256: \}\
                    257: \
                    258: 
                    259: \f1\b\fs28 /*\
                    260:  * Threads and Functions\
                    261:  */
                    262: \f0\b0\fs24 \
                    263: \
                    264: /*\
                    265:  * enetThread() does the following:\
                    266:  * -- handles all interrupts (normally DMA; others are errors)\
                    267:  * -- Dispatches received packets; keeps RX DMA queue as full as possible\
                    268:  * -- detects Net Jammed conditions, reconfigures I/F (TPE or Thin).\
                    269:  */\
                    270: enetThread(id enetObj)\
                    271: \{\
                    272:        msg_receive(IOPort);\
                    273:        switch msg_id \{\
                    274:            case INT_MSG_DEVICE:\
                    275:            case INT_MSG_DMA:\
                    276:                [enetObj enetInt];\
                    277:            case ENET_JAMMED_MSG_ID:\
                    278:                [enetObj enJam];\
                    279:        \}\
                    280: \}\
                    281: \
                    282: /*\
                    283:  * Called out from nb_free(), as freefunc(freefunc_arg).\
                    284:  */\
                    285: enetBufFree(enetBuf_t *enetBuf) \{\
                    286:        enqueue this on enetBufList;\
                    287: \}\
                    288: \
                    289: /*\
                    290:  * Called out via IOTimeout(); we arrange for one of these to happen 10\
                    291:  * seconds after we start a DMA out. This handles the "net jammed so bad that\
                    292:  * we don't even see collisions" error, caused by continuous carrier sense.\
                    293:  */\
                    294: 
                    295: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 NetJamTimer
                    296: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 (
                    297: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0 port_t enetIOPort
                    298: \pard\tx1152\tx2304\tx3456\tx4608\tx5760\tx6912\tx8064\tx9216\tx10368\tx11520\fc0 )
                    299: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\fc0  \{\
                    300:        send ENET_JAMMED_MSG message to the I/O thread;\
                    301: \}\
                    302: 
                    303: }

unix.superglobalmegacorp.com

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