Annotation of driverkit/notes/enetPseudocode, revision 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.