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

📄 cs8900.c.svn-base

📁 三星arm2440与cs8900的以太网驱动
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/*******************************************************************************
*   File Name: 
					cs89x0.c
*   Description:
				    cs89x0 ethernet controller.	
*   Copyright:
      Copyright (c) 2003 LONICOM, Incorporated and its licensors. All Rights 
    Reserved. LONICOM Proprietary. Export of this technology or software is 
    regulated by the P.R.C Government. Diversion contrary to P.R.C law 
    prohibited.

*   Change History:
*   Date          Author      Release     Description
	2008/03/05    wangguofeng   0.1         create
*******************************************************************************/

/*******************************************************************************
                                Include Files
*******************************************************************************/
#include "string.h"
#include "cs8900.h"
#include "srvEvent.h"
#include "2440Regs.h"


/*******************************************************************************
                                Global Variables
*******************************************************************************/
LC_BYTE linkState;
LC_BYTE etherInitOver = 0;
LC_BYTE triggerType;
LC_BYTE etherAddr[ETHER_ADDR_LEN] = {0x00, 0x1D, 0x09, 0x09, 0x1B, 0xA9};

#if MSG_WAKEUP
LC_BYTE msgWakeup;
#endif

#if ETHER_DEBUG
dsm_item_type *recv_dsm;
#endif 

q_type  etherSendQueue;
#if ETHER_TEST
q_type  etherRecvQueue;
#endif 

struct ifStatistic etherStatistic;
LC_BYTE *etherStatisticInfo[] = 
{
	"==========================ether drv statistic=============================\n"
	"SendFrame",    
	"SendByte",
	"RecvFrame",
	"RecvByte",
	"SendError",
	"SendQueueFull",
	"SendQueueMax",
	"SendPktTooLong",
	"RecvPktTooLong",
	"RecvPktTooShort",
	"InvalidRecvFrame",
	"DsmMallocFailed",		
	
	#if ETHER_DEBUG
	"EtherDsmLogicError",
	"TcpipDsmLogicError",
	"SendInt",
	"RecvInt",
	"BuffInt",
	#endif 
	
	#if ETHER_TEST
	"RecvQueueFull",
	"RecvQueueMax",
	#endif 
	
	"RxMiss",
	"TxCol",
	"===========================================================================\n"
};  
    
rxEnqueue       tcpipCb1;
rxMsgSend       tcpipCb2;
ifStateNotify   tcpipCb3;
    
#if ETHER_TEST
LC_DWORD recvCnt;
LC_DWORD sendCnt;
    
LC_BYTE *pktSend[4];
LC_WORD pktLen[4];

LC_BYTE pktSend1[64];
LC_BYTE pktSend2[68];
LC_BYTE pktSend3[72];
LC_BYTE pktSend4[76];
#endif 


/*******************************************************************************
                           global Function Declarations
*******************************************************************************/
void etherInit(void);
void etherStatisticRestart(void);
void etherStatisticGet(LC_BYTE *buf);
LC_WORD etherByteToStr(LC_BYTE *in, LC_WORD len, LC_BYTE *out);
void etherTask(MessageId tEvent, LC_BYTE *pbData, LC_WORD wLen);

#if ETHER_TEST
void etherTestTask(MessageId tEvent, LC_BYTE *pbData, LC_WORD wLen);
#endif


/*******************************************************************************
                           static Function Declarations
*******************************************************************************/
static LC_INT readReg(LC_WORD port);
static LC_INT readWord(LC_WORD port);
static void writeReg(LC_WORD port, LC_WORD value);
static void writeWord(LC_WORD port, LC_WORD value);
static void etherRx(void);
static void etherLinkCheck(void);
static void etherDt(void);
static void etherInterrupt(void);
static void etherSendQueueRetry(LC_BYTE type);
static void etherSendQueueWakeup(LC_BYTE type);
static LC_INT etherDrvTx(dsm_item_type *dsm, LC_WORD wPktLen);
static void etherChipReset(void);
static void etherSetMacAddr(LC_BYTE *addr);
static void etherTaskActiveMsg(void);

#if ETHER_NOT_YET
static void etherClose(void);
static void etherHalt(void);
#endif 

#if ETHER_TEST
static void etherTestInit(void);
static void etherTestSend(void);
static void etherTestRecv(void);
static void recvQueueAppend(dsm_item_type *dsm);
static void recvMsgSend(void);
static void linkStateUpdate(LC_BYTE state);
#endif 


/*******************************************************************************
                         Function Implementations
*******************************************************************************/
/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void etherTaskActiveMsg(void)
{
    /* link state check. */
    etherLinkCheck();
    
    /* set link check timer. */
    oseSetLoopTimer(TIMER1, 1000 * 60 * 2, NULL_PARAM);
    
    #if ETHER_TEST
    oseSendAsyncMsg(EV_ACTIVATE_REQ, 0, 0, ETHER_TEST_TASK_ID);    
    #endif    
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
void etherInit(void)
{
    LC_INT i;
    LC_DWORD addr;

    if (etherInitOver)
    {
        sysPrnUart("ethernet already init!\n");
        return;
    }

    /* global structures and variables */
    linkState = DOWN;
    triggerType = 0; 
    
    memset (&etherStatistic, 0, sizeof (struct ifStatistic));

    tcpipCb1 = 0;
    tcpipCb2 = 0;
    tcpipCb3 = 0;

    #if MSG_WAKEUP
    msgWakeup = 0;  
    #endif
    
    #if ETHER_DEBUG
    recv_dsm = 0;
    #endif 

    q_init(&etherSendQueue);
    #if ETHER_TEST
    q_init(&etherRecvQueue);
    etherRegCb(recvQueueAppend, recvMsgSend, linkStateUpdate); 
    #endif    

    /* ethernet controller. */
    rBWSCON = (rBWSCON & ~(0xf << 12)) | (0xd << 12);
    rBANKCON3 = (3 << 11) | (0x7 << 8) | (0x1 << 6) | (0x3 << 4) | (0x3 << 2);
    
    /* set GPIO */
	rGPGCON |= (2 << 2); 	
	rGPGUP |= (1 << 1);  	
	rEXTINT1 |= (4 << 4);   
	
	oseIntConnect(ETHER_INT_BIT, etherInterrupt, etherDt, 0, 1024);
	
	rEINTMASK &= ~(1 << 9); 
	rEINTPEND |= (1 << 9); 
	
	/* clear INT controller pending. */
	ClearSubPending(0x1 << ETHER_INT_BIT);
	ClearPending(0x1 << ETHER_INT_BIT);
	
	/* enable INT controller. */
    EnableIrq(0x1 << ETHER_INT_BIT);	

    /* chip id check */
    if (readReg(PP_ChipID) != CHIP_EISA_ID_SIG)
    {
        sysPrnUart("CS8900 Ethernet chip not matched!\n");
        return;        
    }

    etherChipReset();

    /* Prevent the crystal chip from generating interrupts */
    writeReg(PP_BusCTL, readReg(PP_BusCTL) & ~PP_BusCTL_EnableIRQ);

    /* try to load MAC addr from EEPROM. */
    if ((readReg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
        (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) 
    {
        for (i = 0; i < ETHER_ADDR_LEN / 2; i++)
        {
            addr = readReg(PP_IA + i * 2);
            etherAddr[i * 2] = (LC_BYTE)(addr & 0xff);
            etherAddr[i * 2 + 1] = (LC_BYTE)(addr >> 8);
        }
    }
    else
    {
        etherSetMacAddr(etherAddr);
    }     

    writeReg(PP_CS8900_ISAINT, 0); 

    writeReg(PP_RxCTL, DEF_RX_ACCEPT); 

    writeReg(PP_RxCFG, (PP_RxCFG_RxOK | PP_RxCFG_CRC));

    writeReg(PP_TxCFG,                  
                (PP_TxCFG_CRS |
                 PP_TxCFG_SQE |
                 PP_TxCFG_TxOK |
                 PP_TxCFG_Late |
                 PP_TxCFG_Jabber |
                 PP_TxCFG_Collision |
                 PP_TxCFG_Collision));
    
    writeReg(PP_BufCFG,                 
                (PP_BufCFG_TxRDY |
                 PP_BufCFG_Miss |
                 PP_BufCFG_TxCol |
                 PP_BufCFG_TxUE));    
    
    /* Turn on both receive and transmit operations */
    writeReg(PP_LineCTL, (readReg(PP_LineCTL) |
                                PP_LineCTL_Rx |
                                PP_LineCTL_Tx));
                                
    /* here. we shoule enable everything. */
    /*writeReg(PP_BusCTL, readReg(PP_BusCTL) | PP_BusCTL_IOCHRDYE);*/
    writeReg(PP_BusCTL, readReg(PP_BusCTL) | PP_BusCTL_EnableIRQ);       

    /* delay. */
    for (i = 0; i < 3000; i++);    
    
    etherInitOver = 1;    
    
    sysPrnUart("ethernet init OK! local mac[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",
				    etherAddr[0], etherAddr[1], etherAddr[2], 
				    etherAddr[3], etherAddr[4], etherAddr[5]);
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
void etherTx(dsm_item_type *dsm)
{
    LC_WORD wPktLen;
    LC_INT result;
    
    #if (ETHER_DEBUG > 1)
    LC_BYTE buf[ETHER_PRN_SIZE * 3];
    memset (buf, 0x00, sizeof (buf));
    #endif 

    #if ETHER_DEBUG
    if (!dsm)
    {
        return;
    }
    #endif

    wPktLen = dsm_length_packet(dsm);
    
    #if (ETHER_DEBUG > 1)
    etherByteToStr(dsm->data_ptr, 64, buf);
    sysPrnUart("send pkt len=%d header:\n%s\n", wPktLen, buf);
    #endif 
    
    if (wPktLen > ETHER_PKT_MAX)
    {
        etherStatistic.dwSendPktTooLong++;

        /* drop and free this packet. */
        dsm_free_packet(&dsm);
        return;       
    }

    if (q_cnt(&etherSendQueue) >= SEND_Q_MAX)
    {
        etherStatistic.dwSendQueueFull++;

        /* drop and free this packet. */
        dsm_free_packet(&dsm);
        return;
    }

    if (q_cnt(&etherSendQueue))
    {
packet_enqueue:
        /* confirm it. */
        q_link(dsm, (q_link_type *)dsm);            
        
        q_put(&etherSendQueue, (q_link_type *)dsm);
        
        if ((LC_DWORD)q_cnt(&etherSendQueue) > etherStatistic.dwSendQueueMax)
        {
            etherStatistic.dwSendQueueMax = q_cnt(&etherSendQueue);
        }        
        
        /* wait for send interrupt or buffer interrupt. */
        return;
    }
    
    result = etherDrvTx(dsm, wPktLen);
    if (result == BUS_NOT_RDY)
    {
        goto packet_enqueue;
    }    
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void writeWord(LC_WORD port, LC_WORD value)
{
    *(volatile CS8900_REG *)(CS8900_BASE + port) = value;    
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static LC_INT readWord(LC_WORD port)
{
    return (*(volatile CS8900_REG *)(CS8900_BASE + port));
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static void writeReg(LC_WORD port, LC_WORD value)
{
    *(volatile CS8900_REG *)(CS8900_BASE + ADD_PORT) = port;
    *(volatile CS8900_REG *)(CS8900_BASE + DATA_PORT) = value;
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
static LC_INT readReg(LC_WORD port)
{
    *(volatile CS8900_REG *)(CS8900_BASE + ADD_PORT) = port;
    return (*(volatile CS8900_REG *)(CS8900_BASE + DATA_PORT));    
}

/*==============================================================================
*   Function        :   
*   Description     :
*   In Parameter    :
**      Type        :
**      Description :
*   Out Parameter   :
**      Type        :
**      Description :
*   Return          :
*   Other           :
==============================================================================*/
/* ether init MUST be called before this function. */
void etherRegCb(rxEnqueue func1, rxMsgSend func2, ifStateNotify func3)
{
    if (!func1 || !func2 || !func3)
    {
        sysPrnUart("etherRegCb!\n");
        return;
    }  

    if (etherInitOver)
    {

⌨️ 快捷键说明

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