?? lan9118.c
字號:
DWORD Lan_PopRxStatus(const DWORD dwLanBase)
{
DWORD result=0UL;
result=GetRegDW(dwLanBase,RX_FIFO_INF);
if(result&0x00FF0000UL) {
/*Rx status is available, read it */
result=GetRegDW(dwLanBase,RX_STATUS_FIFO_PORT);
} else {
result=0UL;
}
return result;
}
/*
FUNCTION: Rx_FastForward
This function skips the current packet in RX fifo.
*/
void Rx_FastForward(const DWORD dwLanBase)
{
#ifdef SMC_DEBUG
char buffer [128];
#endif
DWORD dwTemp;
DWORD dwTimeOut=100UL;
SetRegDW(dwLanBase,RX_DP_CTRL,RX_DP_CTRL_RX_FFWD_);
dwTemp = GetRegDW(dwLanBase, DUMMY_READ_REG);
dwTemp = dwTemp;
LanDelayUS(dwLanBase, 1UL);
while((dwTimeOut)&&(GetRegDW(dwLanBase,RX_DP_CTRL)& RX_DP_CTRL_RX_FFWD_))
{
LanDelayUS(dwLanBase,1UL);
dwTimeOut--;
}
if(dwTimeOut==0UL) {
#ifdef SMC_DEBUG
sprintf (buffer, "timed out waiting for RX FFWD to finish, RX_DP_CTRL=0x%08lX",
GetRegDW(dwLanBase, RX_DP_CTRL));
OS_TEXT_OUT (buffer);
#endif
}
}
/*
FUNCTION: lan9118Open
This function allocates and initializes driver private
structures, lan9118 hardware, platform specific timing.
It identifies Lan911x variation and attaches interrupt.
*/
static int lan9118Open(NGifnet *netp)
{
char buffer [128];
int ictrl;
DWORD dwIdRev;
DWORD dwLanBase;
NGbuf* bufPrivate = NULL;
PLAN9118_DATA pLan9118Data = NULL;
/*is interface already running?*/
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
if(netp->if_flags & NG_IFF_RUNNING)
{
ngOSIntrCtl(ictrl);
return NG_EALREADY;
}
ngOSIntrCtl(ictrl);
/* allocate a memory buffer to store driver private data */
ngBufAlloc(bufPrivate);
if (bufPrivate == NULL) {
return NG_EINVAL;
}
bufPrivate->buf_datap=(NGubyte*) bufPrivate;
pLan9118Data = netp->if_devptr1 = bufPrivate;
pLan9118Data->saved_buf = NULL;
OS_TEXT_OUT (driver_version);
NG_ETHIF_DATA(((void *) netp), eif_base) = (void *) LAN9118_REG_BASE;
NG_ETHIF_DATA(((void *) netp), eif_irq) = LAN9118_IRQN;
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
dwIdRev = LanDetectChipId (dwLanBase);
if (dwIdRev == 0xffffffffUL)
{
OS_TEXT_OUT ("unknown ethernet chip\n");
}
else
{
sprintf (buffer, "chip id = %04lx\n", dwIdRev);
OS_TEXT_OUT (buffer);
}
PlatformSetBusTiming (dwIdRev);
if (!Lan_Initialize (netp)) {
return NG_EINVAL;
}
Lan_InitializeInterrupts (dwLanBase, 0UL);
Lan_EnableSoftwareInterrupt (dwLanBase);
/* link configuration: default is auto-negociation */
NG_ETHIF_DATA(((void *) netp), eif_flags) =
(NGushort) NG_ETHIFF_AUTONEG;
SetLinkCfg (netp, (NGubyte) 0); /* auto-negociate */
SetLinkAdv (netp, (NGushort) ~0); /* advertise all */
SetLink (netp, (NGubyte) NG_ETHIF_LINK_DOWN);
if(!Phy_Initialize(netp, PHY_ADDR))
{
return NG_EINVAL;
}
if (!Lan_MacLoad (netp)) {
return NG_EINVAL;
}
Lan_InitializeTx (dwLanBase);
Lan_InitializeRx (dwLanBase, 0x00000200UL);
/*set the NGifnet flags*/
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
netp->if_flags|=NG_IFF_RUNNING|NG_IFF_UP;
ngOSIntrCtl(ictrl);
/*install the interupt handler */
ngOSIsrAttach9118 (LAN9118_IRQN, lan9118Isr, netp);
return NG_EOK;
}
/*
FUNCTION: lan9118Start
This function checks outbound queue for ready to transmit
packets. Then transmits packets as much as it can.
*/
static void lan9118Start(NGifnet * netp)
{
LAN9118_DATA *pLan9118Data;
DWORD dwLanBase;
int ictrl;
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
if(netp->if_flags & NG_IFF_OACTIVE)
{
/* interface running */
ngOSIntrCtl(ictrl);
return;
}
else
{
ngOSIntrCtl(ictrl);
pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
for (;;)
{
/* dequeue the packet */
if (pLan9118Data->saved_buf == NULL) {
ngBufDequeue(netp, pLan9118Data->saved_buf);
}
if(pLan9118Data->saved_buf==NULL) {
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
netp->if_flags &= ~NG_IFF_OACTIVE;
ngOSIntrCtl(ictrl);
break;
}
/* if there is enough space in TX fifo */
if (((DWORD) pLan9118Data->saved_buf->buf_datalen+16UL) <=
Lan_GetTxDataFreeSpace (dwLanBase)) {
Lan_SendPacketPIO (
dwLanBase,
(NGushort) pLan9118Data->saved_buf->buf_datalen,
(NGushort) pLan9118Data->saved_buf->buf_datalen,
pLan9118Data->saved_buf->buf_datap);
if (Lan_GetTxStatusCount (dwLanBase) >= 30UL) {
Lan_UpdateTxCounters (netp);
}
if (pLan9118Data->saved_buf->buf_flags & (NG_BUFF_BCAST|NG_BUFF_MCAST))
{
netp->if_omcasts++;
}
ngBufOutputFree(pLan9118Data->saved_buf);
pLan9118Data->saved_buf = NULL;
}
else {
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
netp->if_flags |= NG_IFF_OACTIVE;
ngOSIntrCtl(ictrl);
SetRegDW (dwLanBase, FIFO_INT, 0x32000000UL);
break;
}
}
}
return;
}
/*
FUNCTION: lan9118Close
This function cleans up driver and shutdowns the lan9118
ethernet controller.
*/
static int lan9118Close(NGifnet* netp)
{
NGbuf * bufp;
const LAN9118_DATA *pLan9118Data;
int ictrl;
/* interface is not running*/
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
if(!(netp->if_flags & NG_IFF_RUNNING))
{
ngOSIntrCtl(ictrl);
return NG_EALREADY;
}
/* clear flags*/
(netp->if_flags)&=~(NG_IFF_RUNNING|NG_IFF_UP);
ngOSIntrCtl(ictrl);
pLan9118Data = (PLAN9118_DATA) netp->if_devptr1;
Lan_UpdateTxCounters (netp);
/*uninstall the irq*/
Lan_StopGptTimer ((DWORD) NG_ETHIF_DATA(((void *) netp), eif_base));
ngOSIsrDetach9118 (LAN9118_IRQN);
/* Remove pending buffers */
for (;;)
{
ngBufDequeue(netp, bufp);
if (bufp == NULL)
{
break;
}
ngBufOutputFree(bufp);
}
if (pLan9118Data->saved_buf)
{
ngBufOutputFree(pLan9118Data->saved_buf);
}
ngBufOutputFree((NGbuf *) ((void *) pLan9118Data));
return NG_EOK;
}
/*
FUNCTION: lan9118Isr
This function handles lan9118 related interrupts.
*/
static void lan9118Isr(void *data)
{
NGbuf* bufReceiv; /*buffer to store the received packet*/
NGifnet *netp;
DWORD dwIntCfg;
DWORD dwIntSts;
DWORD dwLanBase;
netp = (NGifnet *) data;
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
dwIntCfg = GetRegDW (dwLanBase, INT_CFG);
if ((dwIntCfg & 0x00001100UL) != 0x00001100UL) {
return;
}
if (dwIntCfg & 0x00FFEEEEUL) {
return;
}
dwIntSts = Lan_GetInterruptStatus (dwLanBase);
if(dwIntSts&INT_STS_SW_INT_) {
Lan_HandleSoftwareInterrupt(dwLanBase);
}
if(dwIntSts&INT_STS_RSFL_) {
DWORD dwRxStatus;
while((dwRxStatus=Lan_PopRxStatus(dwLanBase))!=0UL)
{
const DWORD dwPacketLength=((dwRxStatus&0x3FFF0000UL)>>16);
if(dwRxStatus&RX_STS_ES) {
netp->if_ierrors++;
netp->if_iqdrops++;
/* flush RX FIFO */
Rx_FastForward(dwLanBase);
continue;
}
else {
/* check for length error & ignore packet */
if ((dwRxStatus & (RX_STS_LENGTH_ERR_ | RX_STS_FRAME_TYPE_ETH_)) == RX_STS_LENGTH_ERR_) {
netp->if_ierrors++;
netp->if_iqdrops++;
/* flush RX FIFO */
Rx_FastForward(dwLanBase);
continue;
}
/* allocate memory for the received packet*/
ngBufAlloc(bufReceiv);
if(bufReceiv==NULL)
{
netp->if_iqdrops++;
/* flush RX FIFO */
Rx_FastForward(dwLanBase);
continue;
}
else {
if (dwRxStatus & RX_STS_MCAST_PACKET)
{
netp->if_imcasts++;
}
/* prepare structure */
bufReceiv->buf_datap=((NGubyte*)bufReceiv)+ngBufDataOffset-ETHER_HDR_LEN;
bufReceiv->buf_datalen=(int) dwPacketLength - 4 /* CRC */;
Lan_ReadRxFifo (dwLanBase,
((DWORD *)((DWORD) bufReceiv->buf_datap - 2UL)),
(dwPacketLength+2UL+3UL)>>2);
netp->if_ibytes += dwPacketLength;
/* enqueue the message */
ngEtherInput(netp, bufReceiv,1);
/* update stat */
netp->if_ipackets++;
}
}
}
netp->if_iqdrops += GetRegDW(dwLanBase,RX_DROP);
Lan_ClearInterruptStatus(dwLanBase,INT_STS_RSFL_);
}
if(dwIntSts&INT_STS_TDFA_) {
SetRegDW(dwLanBase,FIFO_INT,0xFF000000UL);
Lan_ClearInterruptStatus(dwLanBase,INT_STS_TDFA_);
netp->if_flags &= ~NG_IFF_OACTIVE;
lan9118Start (netp);
}
if(dwIntSts&INT_STS_GPT_INT_) {
Lan_ClearInterruptStatus(dwLanBase,INT_STS_GPT_INT_);
Phy_CheckLink (netp);
}
}
/*
FUNCTION: lan9118SetMulti
This function set the lan9118 hash table to filter out
unwanted multicast packets.
*/
#ifdef _lint
static void lan9118SetMulti(const NGifnet * const netp)
#else
static void lan9118SetMulti(NGifnet * netp)
#endif
{
NGubyte ht[8]; /* hash table */
NGuint crc; /* crc of the dest adr*/
int i;
int ictrl; /* save previous interrupt state */
DWORD dwMacCr;
DWORD dwLanBase;
/* disable int */
ictrl = ngOSIntrCtl(NG_INTRCTL_DISABLE);
dwLanBase = (DWORD) NG_ETHIF_DATA(((void *) netp), eif_base);
if(netp->if_flags & NG_IFF_PROMISC)
{
/* get all promiscuous */
dwMacCr = Lan_GetMacRegDW (dwLanBase, MAC_CR);
dwMacCr |= MAC_CR_PRMS_;
dwMacCr &= ~MAC_CR_MCPAS_;
dwMacCr &= ~MAC_CR_HPFILT_;
Lan_SetMacRegDW (dwLanBase, MAC_CR, dwMacCr);
ngOSIntrCtl(ictrl); /* re-enable inetrrupt */
return;
}
if(netp->if_flags & NG_IFF_ALLMULTI || NG_ETHIF_DATA(((void *) netp), eif_allmultis))
{
/* get all multicasts */
dwMacCr = Lan_GetMacRegDW (dwLanBase, MAC_CR);
dwMacCr &= ~MAC_CR_PRMS_;
dwMacCr |= MAC_CR_MCPAS_;
dwMacCr &= ~MAC_CR_HPFILT_;
Lan_SetMacRegDW (dwLanBase, MAC_CR, dwMacCr);
ngOSIntrCtl(ictrl); /* re-enable inetrrupt */
return;
}
#if (NG_ETHIF_MULTIADDRS_MAX==0)
dwMacCr = Lan_GetMacRegDW (dwLanBase, MAC_CR);
dwMacCr &= ~MAC_CR_PRMS_;
dwMacCr &= ~MAC_CR_MCPAS_;
dwMacCr &= ~MAC_CR_HPFILT_;
Lan_SetMacRegDW (dwLanBase, HASHH, 0);
Lan_SetMacRegDW (dwLanBase, HASHL, 0);
Lan_SetMacRegDW (dwLanBase, MAC_CR, dwMacCr);
ngOSIntrCtl(ictrl); /* re-enable inetrrupt */
#else
dwMacCr = Lan_GetMacRegDW (dwLanBase, MAC_CR);
dwMacCr &= ~MAC_CR_PRMS_;
dwMacCr &= ~MAC_CR_MCPAS_;
dwMacCr |= MAC_CR_HPFILT_;
/* clear table */
for(i = 0; i < 8; i++)
ht [i] = (NGubyte) 0;
/* parse list of groups */
for (i = 0; i < NG_ETHIF_MULTIADDRS_MAX; i++)
{
if (NG_ETHIF_DATA(((void *) netp), eif_multiaddrs)[i].eifm_refcount)
{
crc = ngEtherCRC32( NG_ETHIF_DATA(((void *) netp), eif_multiaddrs)[i].eifm_addr, 6);
crc >>= 26;
ht[crc>>3] = (NGubyte) (ht[crc>>3] | (1 << (crc & 0x7U)));
}
}
/* set filter */
Lan_SetMacRegDW (dwLanBase, HASHL, ((DWORD) ht [3] << 24) | ((DWORD) ht [2] << 16) | ((DWORD) ht [1] << 8) | (DWORD) ht [0]);
Lan_SetMacRegDW (dwLanBase, HASHH, ((DWORD) ht [7] << 24) | ((DWORD) ht [6] << 16) | ((DWORD) ht [5] << 8) | (DWORD) ht [4]);
Lan_SetMacRegDW (dwLanBase, MAC_CR, dwMacCr);
ngOSIntrCtl(ictrl); /* re-enable inetrrupt */
#endif
}
/* Driver entry point */
#define LAN9118_MACROCAT_(a, b) a ## b
#define LAN9118_MACROCAT(a, b) LAN9118_MACROCAT_(a, b)
#define LAN9118_MACROQUOTE_(a) #a
#define LAN9118_MACROQUOTE(a) LAN9118_MACROQUOTE_(a)
const NGnetdrv LAN9118_MACROCAT(ngNetDrv_, LAN9118_DRVNAME) = {
LAN9118_MACROQUOTE(LAN9118_DRVNAME),
NG_IFT_ETHER, /* adaptator type */
NG_IFF_BROADCAST|NG_IFF_MULTICAST, /* interface at startup*/
//lint -e{834}
ETHERMTU, /* maximum transmission unit*/
100000000UL, /* link speed (b/s)*/
ngEtherInit, /* initialise the NGethifnet*/
lan9118Open,
lan9118Close,
ngEtherOutput,
lan9118Start,
ngEtherCntl,
lan9118SetMulti
};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -