📄 ethernet.c
字号:
#include <zooboot.h>
#include <command.h>
#include <hardware.h>
#include <net.h>
#ifdef CFG_DRIVER_ETHER
#if (CFG_COMMANDS & CFG_CMD_NET)
#define LITTLE
int pad0[10];
sFrameDescriptor RxFDBaseAddr[MaxRxFrameDescriptors*2]; //Ethernet0 Rx Frame Descriptor
int pad1[10];
sMACFrame RxFBABaseAddr[MaxRxFrameData*2]; //Ethernet0 Rx Frame Buffer
sFrameDescriptor TxFDBaseAddr0[MaxTxFrameDescriptors*2]; //Ethernet0 Tx Frame Descriptor
sMACFrame TxFBABaseAddr0[MaxTxFrameData*2]; //Ethernet0 Tx Frame Buffer
// Global variables used for MAC driver
#if WITH_CRC
volatile U32 gMacRxCon = RxEn ;
#else
volatile U32 gMacRxCon = RxEn | StripCRC ;
#endif
volatile U32 gBdmaTxCon = BTxBRST | BTxMSL111 | BTxSTSKO ;
#ifdef LITTLE
volatile U32 gBdmaRxCon = BRxDIE | BRxEn | BRxLittle | BRxMAINC | BRxBRST | \
BRxNLIE | BRxNOIE | BRxSTSKO ;
#else
volatile U32 gBdmaRxCon = BRxDIE | BRxEn | BRxBig | BRxMAINC | BRxBRST | \
BRxNLIE | BRxNOIE | BRxSTSKO |BRxWA00;
#endif
volatile U32 gCamCon = StationAcc | BroadAcc | GroupAcc; // promiscuous mode
//volatile U32 gCamCon = BroadAcc | CompEn;
volatile U32 gCTxFDPtr0, gWTxFDPtr0 ;
volatile U32 gCRxFDPtr0, gPreviousFdp=0 ;
volatile U32 gCam0_Addr0 = 0 , gCam0_Addr1 = 0 ;
volatile int gErrorPacketCnt =0 ;
// Global variable structure for store status
//Ethernet0
pMACTxStatus gsMacTxStatus = {0,0,0,0,0,0,0,0,0,0,0} ;
pMACRxStatus gsMacRxStatus = {0,0,0,0,0,0,0,0,0} ;
pBDMATxStatus gsBdmaTxStatus = {0,0,0} ;
pBDMARxStatus gsBdmaRxStatus = {0,0,0,0,0} ;
/* Initialize Tx frame descriptor area-buffers */
static
void TxFDInitialize(void)
{
sFrameDescriptor *pFrameDescriptor;
sFrameDescriptor *pStartFrameDescriptor;
sFrameDescriptor *pLastFrameDescriptor = NULL;
U32 FrameDataAddr;
U32 i;
// Get Frame descriptor's base address.
// +0x400_0000 is for setting this area to non-cacheable area.
BDMATXPTR0 = (U32)TxFDBaseAddr0 + 0x4000000;
gWTxFDPtr0 = gCTxFDPtr0 = BDMATXPTR0;
// Get Transmit buffer base address.
FrameDataAddr = (U32)TxFBABaseAddr0 + 0x4000000;
// Generate linked list.
pFrameDescriptor = (sFrameDescriptor *) gCTxFDPtr0;
pStartFrameDescriptor = pFrameDescriptor;
for(i=0; i < MaxTxFrameDescriptors; i++) {
if(pLastFrameDescriptor == NULL)
pLastFrameDescriptor = pFrameDescriptor;
else
pLastFrameDescriptor->NextFrameDescriptor = (U32)pFrameDescriptor;
pFrameDescriptor->FrameDataPtr =
(U32)(FrameDataAddr & fOwnership_CPU);
pFrameDescriptor->Reserved = (U32)0x0;
pFrameDescriptor->StatusAndFrameLength = (U32)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;
}
/* Initialize Rx frame descriptor area-buffers */
static
void RxFDInitialize(void)
{
sFrameDescriptor *pFrameDescriptor;
sFrameDescriptor *pStartFrameDescriptor;
sFrameDescriptor *pLastFrameDescriptor = NULL;
U32 FrameDataAddr;
U32 i;
// Get Frame descriptor's base address.
// +0x4000000 is for setting this area to non-cacheable area.
BDMARXPTR0 = (U32)RxFDBaseAddr + 0x4000000;
gCRxFDPtr0 = BDMARXPTR0;
// Get Transmit buffer base address.
FrameDataAddr = (U32)RxFBABaseAddr + 0x4000000;
// Generate linked list.
pFrameDescriptor = (sFrameDescriptor *) gCRxFDPtr0;
pStartFrameDescriptor = pFrameDescriptor;
for(i=0; i < MaxRxFrameDescriptors; i++) {
if(pLastFrameDescriptor == NULL)
pLastFrameDescriptor = pFrameDescriptor;
else
pLastFrameDescriptor->NextFrameDescriptor = (U32)pFrameDescriptor;
pFrameDescriptor->FrameDataPtr =
(U32)(FrameDataAddr | fOwnership_BDMA | 0x4000000 );
pFrameDescriptor->Reserved = (U32)0x0;
pFrameDescriptor->StatusAndFrameLength = (U32)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;
}
/* set Tx Registers related with BDMA & MAC to transmit packet */
static
void ReadyMacTx(void)
{
BDMATXCON0 = gBdmaTxCon ;
MACTXCON0 = EnComp ;
}
/* set Rx Registers related with BDMA & MAC to Receive packet */
static
void ReadyMacRx(void)
{
BDMARXCON0 = gBdmaRxCon ;
MACRXCON0 = gMacRxCon ;
}
/* MAC Transfer Start for interactive mode */
static
void MacTxGo(int mac_n)
{
// Enable MAC and BDMA Transfer
if (!(MACTXCON0 & TxEn)) MACTXCON0 |= TxEn ;
if (!(BDMATXCON0 & BTxEn)) BDMATXCON0 |= BTxEn ;
}
/* Get MAC Address From IIC EEPROM */
static
void GetMyMacAddr(void)
{
U8 MacAddr[MAC_ADDR_SIZE];
U8 TempAddr[MAC_ADDR_SIZE];
int i;
gCam0_Addr0 = gCam0_Addr1 = 0 ;
/* samsung's mac */
MacAddr[0] = 0x00 ;
MacAddr[1] = 0x00 ;
MacAddr[2] = 0xf0 ;
MacAddr[3] = 0x90 ;
MacAddr[4] = 0x11 ;
MacAddr[5] = 0x11 ;
/* Get MAC Address */
for (i=0;i<(int)MAC_ADDR_SIZE;i++) TempAddr[i] = MacAddr[i];
/* Copy MAC Address to global variable */
/* big endian */
for (i=0;i<(int)MAC_ADDR_SIZE-2;i++)
gCam0_Addr0 = (gCam0_Addr0 << 8) | TempAddr[i] ;
for (i=(int)(MAC_ADDR_SIZE-2);i<(int)MAC_ADDR_SIZE;i++)
gCam0_Addr1 = (gCam0_Addr1 << 8) | TempAddr[i] ;
gCam0_Addr1 = (gCam0_Addr1 << 16) ;
}
/* Initialize MAC and BDMA Controller */
static
void MacInitialize(void)
{
int cam_n=0;
/* 1. Disable MAC and BDMA interrupts */
//Disable_Intr(nMAC0_TX_INT) ; // Disable MAC0 Tx Interrupt
//Disable_Intr(nBDMA0_RX_INT) ; // Disable BDMA0 Rx Interrupt
/* 2. BDMA and MAC interrupt vector setup */
//SysSetInterrupt(nMAC0_TX_INT, MAC0_Tx_isr) ;
//SysSetInterrupt(nBDMA0_RX_INT, BDMA0_Rx_isr) ;
/* 3. Set the initial condition of the BDMA, and MAC */
//Ethernet0
BDMARXCON0 = BRxRS ; // Reset BDMAC Receiver
BDMARXCON0 = 0x0; // Reset signal Rise.
BDMATXCON0 = BTxRS ; // Reset BDMA0 Transceiver
MACCON0 = SwReset ;
BDMARXLSZ0 = MaxRxFrameSize+20 ; // 1517=0x05EC; 1520
MACCON0 = FullDup ;
/* 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
cam_n= Cam_index+(Cam_index/2);
CAM_Reg0(cam_n) = gCam0_Addr0;
cam_n++;
CAM_Reg0(cam_n) = gCam0_Addr1;
// CAM Enable Register(CAM_index)
CAMEN0 = (1<<Cam_index);
CAMCON0 = gCamCon ;
/* 6. Enable interrupt BDMA Rx and MAC Tx interrupt */
//Enable_Intr(nBDMA0_RX_INT);
//Enable_Intr(nMAC0_TX_INT);
/* 7. Configure the BDMA and MAC control registers */
ReadyMacTx() ;
ReadyMacRx() ;
}
static
void delay_physet(void)
{
int i=1000 ;
while(i--) ;
}
/* MII Interface Station Management Register Read or Write */
static
void MiiStationWrite(U32 PhyInAddr, U32 PhyAddr, U32 PhyWrData)
{
STADATA0 = PhyWrData ;
STACON0 = PhyInAddr | PhyAddr | MiiBusy | PHYREGWRITE ;
while( (STACON0 & MiiBusy) ) ;
delay_physet() ;
}
/* Reset The Phychip, Auto-Negotiation Enable */
static
void ResetPhyChip(void)
{
// For MII I/F
//MiiStationWrite(PHY_CNTL_REG,PHYHWADDR, ENABLE_AN | RESTART_AN); // Auto-negotiation
MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,0x0) ; // 10M Half duplex
}
/* Initialize Phy and Mac */
static
void EthInitialize(void)
{
// Reset the PHY chip and start Auto-negotiat
ResetPhyChip() ;
// Read MAC address from IIC EEPROM
GetMyMacAddr() ;
// Initialize MAC and BDMA controller
MacInitialize() ;
}
/* Interrupt Service Routine for MAC0 Tx
Only check status */
void MAC0_Tx_isr(void)
{
sFrameDescriptor *pTxFDptr;
U32 *pFrameDataPtr ;
U32 Status ;
U32 CTxPtr ;
CTxPtr = BDMATXPTR0 ;
while ( gCTxFDPtr0 != CTxPtr ) {
pTxFDptr = (sFrameDescriptor *) gCTxFDPtr0;
// Check CPU ownership
// if Owner is BDMA then break
pFrameDataPtr = (U32 *)&pTxFDptr->FrameDataPtr;
if ( (*pFrameDataPtr & fOwnership_BDMA) ) break ;
Status = (pTxFDptr->StatusAndFrameLength >> 16) & 0xffff;
if (Status & Comp)
gsMacTxStatus.MacTxGood++ ;
// Save Error status
// Check each status, because, error can duplicated
if (Status & Under) gsMacTxStatus.UnderErr++ ;
if (Status & ExColl) gsMacTxStatus.ExCollErr++ ;
if (Status & TxDeffer) 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.
if (Status != 0x4080)
{
//MacDebugStatus() ;
if(!(Status & Comp))
ReadyMacTx() ;
}
// Clear Framedata pointer already used.
pTxFDptr->StatusAndFrameLength = (U32)0x0;
gCTxFDPtr0 = (U32)pTxFDptr->NextFrameDescriptor ;
} // end while loop
}
/* Interrupt Service Routine for BDMA0 Rx
Ethenet Frame is received in BDMA0_Rx_isr */
void BDMA0_Rx_isr(void)
{
sFrameDescriptor *pRxFDptr ;
U32 RxStatus, FrameLength ;
U32 CRxPtr;
U32 sBdmaStat, CheckOwnerShip ;
U8 *pFrameData ;
// Step 1. Get current frame descriptor and status
CRxPtr = BDMARXPTR0 ;
sBdmaStat = BDMASTAT0 ;
BDMASTAT0 = sBdmaStat;
// Step 2. Clear BDMA status register bit by write 1
//BDMASTAT0 |= S_BRxRDF ;
gsBdmaRxStatus.BdmaRxCnt++ ;
do {
// Step 3. Check Null List Interrupt
//if ( BDMASTAT0 & S_BRxNL ) {
// BDMASTAT0 |= S_BRxNL ;
if ( sBdmaStat & S_BRxNL ) {
gsBdmaRxStatus.BRxNLErr++ ;
MacInitialize() ;
break ;
}
// Step 4. Get Rx Frame Descriptor
pRxFDptr = (sFrameDescriptor *)gCRxFDPtr0 ;
RxStatus = (pRxFDptr->StatusAndFrameLength >> 16) & 0xffff;
//pFrameData = (U8 *)pRxFDptr->FrameDataPtr ;
/* Check BDMA Receive Ownership */
//CheckOwnerShip = *pFrameData & fOwnership_BDMA;
//if(!CheckOwnerShip)
//{
// Step 5. If Rx frame is good, then process received frame
if((RxStatus & RxGood)&&!(RxStatus & OvMax)) {
FrameLength = pRxFDptr->StatusAndFrameLength & 0xffff ;
pFrameData = (U8 *)pRxFDptr->FrameDataPtr ;
gsBdmaRxStatus.BdmaRxGood++ ;
//// Step 6. Get received frame to memory buffer
NetReceive(pFrameData, FrameLength);
}
else {
// Step 7. If Rx frame has error, then process error frame
gErrorPacketCnt++ ;
// Save Error status
// Check each status, because, error can duplicated
if (RxStatus & OvMax) {
gsMacRxStatus.OvMaxSize++ ;
}
if (RxStatus & CtlRecd) 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++ ;
}
//}
//else
//{
//break;
//}
// Step 8. Change ownership to BDMA for next use
(pRxFDptr->FrameDataPtr) |= fOwnership_BDMA;
// Save Current Status and Frame Length field, and clear
// Step 9. Get Next Frame Descriptor pointer to process
gCRxFDPtr0 = (U32)(pRxFDptr->NextFrameDescriptor) ;
} while (CRxPtr != gCRxFDPtr0);
// Step 10. Check Notowner status
if ( sBdmaStat & S_BRxNO ) {
BDMASTAT0 |= S_BRxNO ;
gsBdmaRxStatus.BRxNOErr++ ;
ReadyMacRx() ;
}
}
/* Send ethernet frame function
frame data pointer, frame length
output: transmit ok(1) or error(0) */
int SendPacket(U8 *Data,int Size)
{
sFrameDescriptor *psTxFD;
U32 *pFrameDataPtr ;
U8 *pFrameData ;
int FrameLength ;
// 1. Get Tx frame descriptor & data pointer
psTxFD = (sFrameDescriptor *)gWTxFDPtr0 ;
pFrameData = (U8 *)psTxFD->FrameDataPtr ;
pFrameDataPtr = (U32 *)&psTxFD->FrameDataPtr;
FrameLength = Size + sizeof(etheader) ;
// 2. Check BDMA ownership
if ( (*pFrameDataPtr & fOwnership_BDMA) ) return 0 ; // 1 : BDMA
// 3. Prepare Tx Frame data to Frame buffer
memcpy ((U8 *)pFrameData,(U8 *)Data,FrameLength);
// 4. Set TX Frame flag & Length Field
#ifdef LITTLE
psTxFD->Reserved = (PaddingMode | CRCMode | SourceAddrIncrement | \
LittleEndian | WidgetAlign00 | MACTxIntEn);
#else
psTxFD->Reserved = (PaddingMode | CRCMode | SourceAddrIncrement | \
BigEndian | WidgetAlign00 | MACTxIntEn);
#endif
psTxFD->StatusAndFrameLength = (U32)(FrameLength & 0xffff);
// 5. Cheange ownership to BDMA
psTxFD->FrameDataPtr |= fOwnership_BDMA;
// 6. Enable MAC and BDMA Tx control register
MacTxGo(0);
// 7. Change the Tx frame descriptor for next use
gWTxFDPtr0 = (U32)(psTxFD->NextFrameDescriptor);
return 1 ;
}
int eth_init( bd_t *bd ) {
EthInitialize() ;
return 0;
}
/* send the packet and wait for its complete */
int eth_send(volatile void *packet, int length) {
uint status;
SendPacket(packet, length);
while(1) {
status = MACTXSTAT0;
if (status & Comp) break;
}
/* check status */
MAC0_Tx_isr() ;
return 0;
}
int eth_rx(void) {
int size;
if(!(BDMASTAT0 & S_BRxRDF)) return 0;
/* handle received packets by calling NetReceive */
BDMA0_Rx_isr();
return size;
}
void eth_halt( void )
{
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -