⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs8900.c.svn-base

📁 三星arm2440与cs8900的以太网驱动
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
        tcpipCb1 = func1;
        tcpipCb2 = func2;
        tcpipCb3 = func3;                      
        
        tcpipCb3(linkState);
    }
    #if ETHER_DEBUG
    else
    {
        #if (!ETHER_TEST)
        sysPrnUart("ether init NOT over!\n");            
        #endif 
    } 
    #endif 
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
void etherTask(MessageId tEvent, LC_BYTE *pbData, LC_WORD wLen)
{
    switch (tEvent)
    {
    case EV_ACTIVATE_REQ:
        etherTaskActiveMsg();
        break;

    case EV_TIMER1EVENT: /* loop timer event. */
        etherLinkCheck();
        break;

    #if MSG_WAKEUP
    case 2: /* check send queue. */
    #if ETHER_DEBUG
        if (wLen != 1)
        {
            sysPrnUart("ethernet internal msg len %d error!\n", wLen);
            break;
        }
    #endif
        etherSendQueueRetry(*pbData);
        break;
    #endif

    default:
        sysPrnUart("ether task recv unknown event[0x%08x]!\n", tEvent);
        break;        
    }

    oseFreeMem(pbData);
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherLinkCheck(void)
{
    LC_BYTE curState = UP;    

    if (etherInitOver)
    {
        if ((readReg(PP_LineSTAT) & PP_LineSTAT_LinkOK) == 0)
        {
            curState = DOWN;
        }
        
        if (curState != linkState)
        {
            linkState = curState;
            
            if (tcpipCb3)
            {
                tcpipCb3(curState);
            }                    
        }
    }    
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherInterrupt(void)
{
    LC_INT status;

    while (status = readWord(ISQ_PORT))
    {
        switch(status & ISQ_EventMask)
        {
#if ETHER_DEBUG
            /*sysPrnUart("%d\n", status);*/
#endif
        case ISQ_RxEvent:
        	#if ETHER_DEBUG
        	etherStatistic.dwRecvInt++;
        	#endif 
            triggerType |= RECV_INT_TRIGGER;
            etherRx();
            break;
            
        case ISQ_TxEvent:
            if (status & (PP_TER_TxOK | PP_TER_CRS | PP_TER_SQE | 
                        PP_TER_Late | PP_TER_16Collisions) != PP_TER_TxOK)
            {
                etherStatistic.dwSendError++;
            }
            #if ETHER_DEBUG
            etherStatistic.dwSendInt++;
            #endif 
            etherSendQueueWakeup(SEND_INT_TRIGGER);
            break;
            
        case ISQ_BufEvent:
        	#if ETHER_DEBUG
        	etherStatistic.dwBuffInt++;
        	#endif 
            if (status & PP_BER_Rdy4Tx)
            {
                etherSendQueueWakeup(BUF_INT_TRIGGER);
            }            
            break;
            
        case ISQ_RxMissEvent:
            etherStatistic.dwRxMiss += (status >> 6);
            break;
            
        case ISQ_TxColEvent:
            etherStatistic.dwTxCol += (status >> 6);
            break; 
        }       
    }    
    
    rEINTPEND |= (1 << 9);
    ClearPending(0x1 << ETHER_INT_BIT); 
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherRx(void)
{
    LC_WORD status;
    LC_INT  len;
    LC_WORD *addr;
    LC_WORD itemSize;
    LC_WORD i;

    dsm_item_type *dsm, *next;

    status = readWord(RX_FRAME_PORT);
    len = readWord(RX_FRAME_PORT); /* not include CRC */

    if (status & PP_RER_RxOK == 0)
    {
        etherStatistic.dwInvalidRecvFrame++;
        return;        
    }
    
    if (len > ETHER_PKT_MAX)
    {
        etherStatistic.dwRecvPktTooLong++;
        return;
    }
    
    if (!len)
    {
        etherStatistic.dwRecvPktTooShort++;
        return;
    }
    
    if (!tcpipCb1)
    {
        return;
    }
    
    /* use the whole buffer of the dsm item, no offset. */
    itemSize = dsm_get_item_size(DSM_DS_LARGE_ITEM_POOL);
    dsm = dsm_new_buffer_all(DSM_DS_LARGE_ITEM_POOL, len);
    if (!dsm)
    {
        etherStatistic.dwDsmMallocFailed++;
        return;
    }
    
    i = len >> 1;
    addr = (LC_WORD *)dsm->data_ptr;
    next = dsm;
    for (; i > 0; i--)
    {
        *addr = readWord(RX_FRAME_PORT); 
        next->used += 2;     

        if (next->used == itemSize)
        {        	
            next = next->pkt_ptr;
            if (!next)
            {
            #if ETHER_DEBUG
                if (i - 1) 
                {
                    etherStatistic.dwEtherDsmLogicError++;
                    sysPrnUart("etherRx! [%d %d]\n", i, len);
                }
            #endif
                
                goto recv_done;
            }

            addr = (LC_WORD *)next->data_ptr;
        }
        else
        {        	
            addr++;
        }
    }

    if (len & 1)
    {
        *addr = readWord(RX_FRAME_PORT);
        next->used += 1;        
    }

recv_done:
    etherStatistic.dwRecvFrame++;
    etherStatistic.dwRecvByte += len;
    
    #if ETHER_DEBUG
    recv_dsm = dsm;
    #endif 
  
    tcpipCb1(dsm);   
     
    oseActiveDt(ETHER_INT_BIT);    
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherSendQueueRetry(LC_BYTE type)
{
    dsm_item_type *dsm;
    LC_INT cnt;
    LC_INT result;
    LC_WORD len;    

    if ((cnt = q_cnt(&etherSendQueue)) == 0)
    {
        triggerType &= ~(SEND_INT_TRIGGER | BUF_INT_TRIGGER);
        return;
    }

    while (cnt)
    {
        dsm = (dsm_item_type *)q_get(&etherSendQueue);

        #if ETHER_DEBUG
        if (!dsm)
        {
            sysPrnUart("ether send queue error!\n");
            q_init(&etherSendQueue);
            triggerType &= ~(SEND_INT_TRIGGER | BUF_INT_TRIGGER);
            return;
        }
        #endif
        
        /* I'm sure, length is valid.*/
        len = dsm_length_packet(dsm);

        result = etherDrvTx(dsm, len);
        if (result == BUS_NOT_RDY)
        {
            #if ETHER_DEBUG
            if (type != SEND_INT_TRIGGER) /* amazing. */
            {
                sysPrnUart("etherSendQueueRetry!\n");
            }
            #endif
            
            triggerType &= ~(SEND_INT_TRIGGER | BUF_INT_TRIGGER);
            /* wait for next interrupt. */
            return; 
        }

        cnt--;
    }
    
    triggerType &= ~(SEND_INT_TRIGGER | BUF_INT_TRIGGER);
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherSendQueueWakeup(LC_BYTE type)
{
#if MSG_WAKEUP
    
    /* ONLY record when msg wakeup. */
    triggerType |= type;
    
    /* only wake up send queue once per INT. */
    if (0 == msgWakeup)
    {
        msgWakeup = 1;
        oseActiveDt(ETHER_INT_BIT);
    }
    
#else 
    etherSendQueueRetry(type);
#endif
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
void etherStatisticRestart(void)
{
    memset (&etherStatistic, 0, sizeof (struct ifStatistic));
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static LC_INT etherDrvTx(dsm_item_type *dsm, LC_WORD wPktLen)
{
    dsm_item_type *next;
    LC_WORD i, wBufLen;
    /*volatile*/ LC_WORD *addr;    

    /* initiate a transmit sequence */
    writeWord(TX_CMD_PORT, PP_TxCmd_TxStart_Full);
    writeWord(TX_LEN_PORT, wPktLen);

    /* Test to see if the chip has allocated memory for the packet */
    if ((readReg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0)
    {
        return BUS_NOT_RDY;        
    }

    /* Write the contents of the packet */
    i = wPktLen >> 1;
    wBufLen = dsm->used;
    next = dsm;
    addr = (LC_WORD *)dsm->data_ptr;
    
    for (; i > 0; i--)
    {
        writeWord(TX_FRAME_PORT, *addr); 
        wBufLen -= 2;       

        if (0 == wBufLen)
        {
            next = next->pkt_ptr;
            if (0 == next)
            {
                #if ETHER_DEBUG
                if (i - 1) 
                {
                    etherStatistic.dwTcpipDsmLogicError++;
                    sysPrnUart("etherDrvTx! [%d %d ]\n", i, wPktLen);
                }
                #endif

                goto packet_free;   
            }

            addr = (LC_WORD *)next->data_ptr;
            wBufLen = next->used;
        }
        else
        {        	
            addr++;
        }        
    }

    if (wPktLen & 1)
    {
        writeWord(TX_FRAME_PORT, *addr);
    }

packet_free:
    etherStatistic.dwSendFrame++;
    etherStatistic.dwSendByte += wPktLen;

    dsm_free_packet(&dsm);  
    return 0;
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherDt(void)
{	
    #if ETHER_DEBUG
    LC_BYTE buf[ETHER_PRN_SIZE * 3];
    LC_WORD len;
    #endif 
    
#if MSG_WAKEUP
    if (msgWakeup)
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -