📄 drv_eth.c
字号:
/***********************************************************************
* MODULE: drv_eth.c
* Description: Ethernet Driver
* Runtime Env: ARM7TDMI - KS32C50100
* Company:
* Change History:
* 03-28-02 Create (Yadong Wang)
***********************************************************************/
#include <string.h>
#include "common_types.h"
#include "samsung4510.h"
#include "drv_eth.h"
#include "main.h"
// Ethernet address, move to EEPRM later
tU8 dev_addr[] = {0x00, 0x40, 0x95, 0x36, 0x35, 0x34};
/*****************************************************************
* Local routines
****************************************************************/
static void MAC_Tx_isr(void);
static void MAC_Rx_isr(void);
static void BDMA_Tx_isr(void);
static void BDMA_Rx_isr(void);
static void RxFDInitialize(void);
static void TxFDInitialize(void);
/*****************************************************************
* Local variables
****************************************************************/
// Rx Frame Descriptor, data buffer, and pointers
static sFrameDescriptor TxFDBaseAddr[MaxTxFrameDescriptors];
static sMACFrame TxFBABaseAddr[MaxTxFrameData];
static volatile tU32 gCTxFDPtr, gWTxFDPtr;
// Tx Frame Descriptor, data buffer, and pointers
static sFrameDescriptor RxFDBaseAddr[MaxRxFrameDescriptors];
static sMACFrame RxFBABaseAddr[MaxRxFrameData];
static volatile tU32 gCRxFDPtr;
// Rx Status and error count
static tU32 EthStatusAddr; // anchor address
static pBDMARxStatus gsBdmaRxStatus;
static pMACRxStatus gsMacRxStatus;
static pMACTxStatus gsMacTxStatus;
//static pBDMATxStatus gsBdmaTxStatus;
/*****************************************************************
* Init
****************************************************************/
tU16 DrvEthInit()
{
tU8 i;
/*-----------------------------------------------------------------*
* 1. Disable MAC and BDMA interrupts. *
*-----------------------------------------------------------------*/
Disable_Int(nMAC_RX_INT) ; // Disable MAC Rx Interrupt
Disable_Int(nMAC_TX_INT) ; // Disable MAC Tx Interrupt
Disable_Int(nBDMA_RX_INT) ; // Disable BDMA Rx Interrupt
Disable_Int(nBDMA_TX_INT) ; // Disable BDMA Tx Interrupt
/*-----------------------------------------------------------------*
* 2. BDMA and MAC interrupt vector setup. *
*-----------------------------------------------------------------*/
SysSetInterrupt(nMAC_RX_INT, MAC_Rx_isr);
SysSetInterrupt(nMAC_TX_INT, MAC_Tx_isr); // needed
SysSetInterrupt(nBDMA_RX_INT, BDMA_Rx_isr); // needed
SysSetInterrupt(nBDMA_TX_INT, BDMA_Tx_isr);
/*-----------------------------------------------------------------*
* 3. Set the initial condition of the BDMA, and MAC *
*-----------------------------------------------------------------*/
BDMARXCON = BRxRS ; // Reset BDMAC Receiver
BDMATXCON = BTxRS ; // Reset BDMAC Transceiver
MACCON = Reset ;
BDMARXLSZ = sizeof(sMACFrame); //MaxRxFrameSize+40 ; // 1520
MACCON = 0; //CompEn | BroadAcc;
/*-----------------------------------------------------------------*
* 4. Set the BDMA Tx/Rx Frame Descriptor *
*-----------------------------------------------------------------*/
TxFDInitialize();
RxFDInitialize();
/*-----------------------------------------------------------------*
* 5. Set the CAM Control register and the MAC address value *
*-----------------------------------------------------------------*/
// CAM0 register of CAM registers : 0x9100~0x9103, 0x9104, 0x9105
for(i = 0; i < 4; i++)
CAM_Reg(0) = (CAM_Reg(0) << 8) | dev_addr[i];
for(i = 4; i < 6; i++)
CAM_Reg(1) = (CAM_Reg(1) << 8) | dev_addr[i];
CAM_Reg(1) = (CAM_Reg(1) << 16);
// CAM Enable Register(CAMEN)
CAMEN = 0x0001 ;
CAMCON = CompEn | BroadAcc;
/*-----------------------------------------------------------------*
* 6. Enable interrupt BDMA Rx and MAC Tx interrupt. *
*-----------------------------------------------------------------*/
Enable_Int(nBDMA_RX_INT);
Enable_Int(nMAC_TX_INT);
//Enable_Int(nMAC_RX_INT);
/*-----------------------------------------------------------------*
* 7. Configure the BDMA and MAC control registers. *
*-----------------------------------------------------------------*/
BDMATXCON = BTxBRST | BTxMSL110 | BTxSTSKO | BTxEn;
MACTXCON = EnComp | TxEn;
BDMARXCON = BRxDIE | BRxEn | BRxLittle | BRxMAINC | BRxBRST | BRxNLIE | BRxNOIE | BRxSTSKO | BRxWA10;
MACRXCON = RxEn;
/*-----------------------------------------------------------------*
* 8. PHY init *
*-----------------------------------------------------------------*/
#if 0
printk("Reseting PHY\n");
MIIWrite(0x0, 0x0, 1<<15);
while((MIIRead(0x0, 0x0) & (1<<15)));
printk("Perform AN again\n");
MIIWrite(0x0, 0x0, MIIRead(0x0, 0x0) & ~(1<<12));
// while(!(MIIRead(0x11, 0x0) & (1<<4)));
MIIWrite(0x0, 0x0, 1<<13|1<<8);
status = MIIRead(0x11, 0x0);
if(status & 1<<15)
printk("10M/b ");
else
printk("100M/b ");
if(status & 1<<14)
printk("Full duplex\n");
else printk("Half duplex\n");
#endif
// Start the transmit queue
//netif_start_queue(dev);
EthData[ETH_STS_ADDR] = (tU32)(&EthStatusAddr);
return 0;
}
/*****************************************************************
* Write
* Description : Send ethernet frame function
* Input : frame data pointer, frame length
* Output : transmit ok(1) or error(0)
****************************************************************/
int DrvEthWrite(U8 *Data,int Size)
{
sFrameDescriptor *psTxFD;
tU32 *pFrameDataPtr ;
tU8 *pFrameData ;
int FrameLength ;
// 1. Get Tx frame descriptor & data pointer
psTxFD = (sFrameDescriptor *)gWTxFDPtr ;
pFrameData = (U8 *)psTxFD->FrameDataPtr ;
pFrameDataPtr = (U32 *)&psTxFD->FrameDataPtr;
FrameLength = Size + sizeof(etheader) ;
// 2. Check BDMA ownership
if ( (*pFrameDataPtr & BDMA_owner) )
return 0 ;
// 3. Prepare Tx Frame data to Frame buffer
memcpy ((tU8 *)pFrameData,(tU8 *)Data,FrameLength);
// 4. Set TX Frame flag & Length Field
psTxFD->Reserved = (Padding | CRCMode | FrameDataPtrInc | \
LittleEndian | WA00 | MACTxIntEn);
psTxFD->StatusAndFrameLength = (tU32)(FrameLength & 0xffff);
// 5. Cheange ownership to BDMA
psTxFD->FrameDataPtr |= BDMA_owner;
// 6. Enable MAC and BDMA Tx control register
if (!(BDMATXCON & BTxEn))
BDMATXCON |= BTxEn ;
MACTXCON |= TxEn ;
// 7. Change the Tx frame descriptor for next use
gWTxFDPtr = (tU32)(psTxFD->NextFrameDescriptor);
return 1 ;
}
/*****************************************************************
* Read, through ISR and call back
****************************************************************/
/*****************************************************************
* Local routines
****************************************************************/
// init Tx Frame Descriptor
static void TxFDInitialize(void)
{
sFrameDescriptor *pFrameDescriptor;
sFrameDescriptor *pStartFrameDescriptor;
sFrameDescriptor *pLastFrameDescriptor = NULL;
tU32 FrameDataAddr, i;
// Get Frame descriptor's base address.
// +0x4000000 is for setting this area to non-cacheable area.
BDMATXPTR = (tU32)TxFDBaseAddr + 0x4000000;
gWTxFDPtr = gCTxFDPtr = BDMATXPTR;
// Get Transmit buffer base address.
FrameDataAddr = (tU32)TxFBABaseAddr + 0x4000000;
// Generate linked list.
pFrameDescriptor = (sFrameDescriptor *) gCTxFDPtr;
pStartFrameDescriptor = pFrameDescriptor;
for(i=0; i < MaxTxFrameDescriptors; i++)
{
if(pLastFrameDescriptor == NULL)
pLastFrameDescriptor = pFrameDescriptor;
else
pLastFrameDescriptor->NextFrameDescriptor = (tU32)pFrameDescriptor;
pFrameDescriptor->FrameDataPtr = (tU32)(FrameDataAddr & CPU_owner);
pFrameDescriptor->Reserved = (tU32)0x0;
pFrameDescriptor->StatusAndFrameLength = (tU32)0x0;
pFrameDescriptor->NextFrameDescriptor = NULL;
pLastFrameDescriptor = pFrameDescriptor;
pFrameDescriptor++;
FrameDataAddr += sizeof(sMACFrame);
} // end for loop
// Make Frame descriptor to ring buffer type.
pFrameDescriptor--;
pFrameDescriptor->NextFrameDescriptor = (tU32)pStartFrameDescriptor;
}
// init Rx Frame Descriptor
static void RxFDInitialize(void)
{
sFrameDescriptor *pFrameDescriptor;
sFrameDescriptor *pStartFrameDescriptor;
sFrameDescriptor *pLastFrameDescriptor = NULL;
tU32 FrameDataAddr, i;
// Get Frame descriptor's base address.
// +0x4000000 is for setting this area to non-cacheable area.
BDMARXPTR = (tU32)RxFDBaseAddr + 0x4000000;
gCRxFDPtr = BDMARXPTR;
// Get Transmit buffer base address.
FrameDataAddr = (tU32)RxFBABaseAddr + 0x4000000;
// Generate linked list.
pFrameDescriptor = (sFrameDescriptor *) gCRxFDPtr;
pStartFrameDescriptor = pFrameDescriptor;
for(i=0; i < MaxRxFrameDescriptors; i++)
{
if(pLastFrameDescriptor == NULL)
pLastFrameDescriptor = pFrameDescriptor;
else
pLastFrameDescriptor->NextFrameDescriptor = (tU32)pFrameDescriptor;
pFrameDescriptor->FrameDataPtr =
(tU32)(FrameDataAddr | BDMA_owner | 0x4000000 );
pFrameDescriptor->Reserved = (tU32)0x0;
pFrameDescriptor->StatusAndFrameLength = (tU32)0x0;
pFrameDescriptor->NextFrameDescriptor = NULL;
pLastFrameDescriptor = pFrameDescriptor;
pFrameDescriptor++;
FrameDataAddr += sizeof(sMACFrame);
} // end for loop
// Make Frame descriptor to ring buffer type.
pFrameDescriptor--;
pFrameDescriptor->NextFrameDescriptor = (U32)pStartFrameDescriptor;
}
static void MAC_Rx_isr()
{
}
static void BDMA_Tx_isr()
{
}
// ISR for BDMA Rx (Ethenet Frame is received)
static void BDMA_Rx_isr(void)
{
sFrameDescriptor *pRxFDptr ;
tU16 error = 0;
tU32 RxStatus, FrameLength ;
tU32 CRxPtr;
tU32 sBdmaStat ;
tU8 *pFrameData ;
// Step 1. Get current frame descriptor and status
CRxPtr = BDMARXPTR ;
sBdmaStat = BDMASTAT ;
// Step 2. Clear BDMA status register bit by write 1
BDMASTAT |= sBdmaStat & 0x17001D;
gsBdmaRxStatus.BdmaRxCnt++ ;
do
{
// Step 3. Check Null List Interrupt
if ( BDMASTAT & S_BRxNL )
{
BDMASTAT |= S_BRxNL ;
gsBdmaRxStatus.BRxNLErr++ ;
// MacInitialize() ;
error = 1;
break ;
}
// Step 4. Get Rx Frame Descriptor
pRxFDptr = (sFrameDescriptor *)gCRxFDPtr ;
RxStatus = (pRxFDptr->StatusAndFrameLength >> 16) & 0xffff;
// Step 5. If Rx frame is good, then process received frame
if((RxStatus & RxGood)&&!(RxStatus & OvMax))
{
FrameLength = pRxFDptr->StatusAndFrameLength & 0xffff - 4;
pFrameData = (U8 *)pRxFDptr->FrameDataPtr + 2;
gsBdmaRxStatus.BdmaRxGood++ ;
// Step 6. Get received frame to memory buffer
ReceivePackets(pFrameData, FrameLength);
}
else
{
error = 1;
// Step 7. If Rx frame has error, then process error frame
gsMacRxStatus.gErrorPacketCnt++ ;
if (RxStatus & OvMax) gsMacRxStatus.OvMaxSize++;
if (RxStatus & CtlRcv) gsMacRxStatus.sCtlRecd++;
if (RxStatus & Rx10Stat) gsMacRxStatus.sRx10Stat++;
if (RxStatus & AlignErr) gsMacRxStatus.AllgnErr++;
if (RxStatus & CRCErr) gsMacRxStatus.sCRCErr++;
if (RxStatus & Overflow) gsMacRxStatus.OverflowErr++;
if (RxStatus & LongErr) gsMacRxStatus.sLongErr++;
if (RxStatus & RxPar) gsMacRxStatus.RxParErr++;
if (RxStatus & RxHalted) gsMacRxStatus.sRxHalted++;
}
// Step 8. Change ownership to BDMA for next use
(pRxFDptr->FrameDataPtr) |= BDMA_owner;
// Save Current Status and Frame Length field, and clear
pRxFDptr->StatusAndFrameLength = (U32)0x0;
// Step 9. Get Next Frame Descriptor pointer to process
gCRxFDPtr = (U32)(pRxFDptr->NextFrameDescriptor) ;
} while (CRxPtr != gCRxFDPtr);
// Step 10. Check Notowner status
if ( sBdmaStat & S_BRxNO )
{
BDMASTAT |= S_BRxNO ;
gsBdmaRxStatus.BRxNOErr++ ;
// ReadyMacRx() ;
}
}
// ISR for MAC Tx
static void MAC_Tx_isr(void)
{
sFrameDescriptor *pTxFDptr;
tU32 *pFrameDataPtr ;
tU32 Status ;
tU32 CTxPtr ;
CTxPtr = BDMATXPTR ;
while ( gCTxFDPtr != CTxPtr )
{
pTxFDptr = (sFrameDescriptor *) gCTxFDPtr;
// Check CPU ownership, if Owner is BDMA then break
pFrameDataPtr = (tU32 *)&pTxFDptr->FrameDataPtr;
if ( (*pFrameDataPtr & BDMA_owner) )
break ;
Status = (pTxFDptr->StatusAndFrameLength >> 16) & 0xffff;
if (Status & Comp)
{
gsMacTxStatus.MacTxGood++ ;
}
else
{
// Save Error status
// Check each status, because, error can duplicated
if (Status & Under) gsMacTxStatus.UnderErr++ ;
if (Status & ExColl) gsMacTxStatus.ExCollErr++ ;
if (Status & TxDefer) gsMacTxStatus.TxDefferedErr++ ;
if (Status & Paused) gsMacTxStatus.sPaused++ ;
if (Status & Defer) gsMacTxStatus.DeferErr++ ;
if (Status & NCarr) gsMacTxStatus.NCarrErr++ ;
if (Status & SQErr) gsMacTxStatus.sSQE++ ;
if (Status & LateColl) gsMacTxStatus.LateCollErr++ ;
if (Status & TxPar) gsMacTxStatus.TxParErr++ ;
if (Status & TxHalted) gsMacTxStatus.sTxHalted++ ;
// Set MAC/BDMA Tx control register for next use.
// MacDebugStatus() ;
// ReadyMacTx() ;
}
// Clear Framedata pointer already used.
pTxFDptr->StatusAndFrameLength = (tU32)0x0;
gCTxFDPtr = (tU32)pTxFDptr->NextFrameDescriptor ;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -