📄 cs8900.c.svn-base
字号:
/*******************************************************************************
* 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 (ðerStatistic, 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(ðerSendQueue);
#if ETHER_TEST
q_init(ðerRecvQueue);
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(ðerSendQueue) >= SEND_Q_MAX)
{
etherStatistic.dwSendQueueFull++;
/* drop and free this packet. */
dsm_free_packet(&dsm);
return;
}
if (q_cnt(ðerSendQueue))
{
packet_enqueue:
/* confirm it. */
q_link(dsm, (q_link_type *)dsm);
q_put(ðerSendQueue, (q_link_type *)dsm);
if ((LC_DWORD)q_cnt(ðerSendQueue) > etherStatistic.dwSendQueueMax)
{
etherStatistic.dwSendQueueMax = q_cnt(ðerSendQueue);
}
/* 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 + -