www.pudn.com > 440B0-LwIP.zip > MacUtil.c
#include#include "std.h" #include "sysconf.h" #include "snds.h" #include "isr.h" #include "mac.h" //下面是为协议栈的存在而添加的 #include "netif.h" #include "eth4510if.h" #include "OS_CPU.h" /* #include #include #include #include "uart.h" #include "pollio.h" #include "timer.h" #include "memory.h" #include "iic.h" */ sFrameDescriptor RxFDBaseAddr[MaxRxFrameDescriptors]; // Tx Frame Descriptor sMACFrame RxFBABaseAddr[MaxRxFrameData]; // Tx Frame Buffer sFrameDescriptor TxFDBaseAddr[MaxTxFrameDescriptors]; // Rx Frame Descriptor sMACFrame TxFBABaseAddr[MaxTxFrameData]; // Rx Frame Buffer // Global variables used for MAC driver volatile U32 gMacCon = FullDup ; volatile U32 gMacTxCon = EnComp ; volatile U32 gMacRxCon = RxEn | StripCRC ; volatile U32 gBdmaTxCon = BTxBRST | BTxMSL110 | BTxSTSKO ; volatile U32 gBdmaRxCon = BRxDIE | BRxEn | BRxLittle | BRxMAINC | BRxBRST | \ BRxNLIE | BRxNOIE | BRxSTSKO ; volatile U32 gCamCon = CompEn | BroadAcc | GroupAcc; volatile U32 gDuplexValue = 0 ; volatile U32 gCTxFDPtr, gWTxFDPtr ; volatile U32 gCRxFDPtr, gPreviousFdp=0 ; volatile U32 gCam0_Addr0 = 0 , gCam0_Addr1 = 0 ; volatile U8 MyMacSrcAddr[6] ; volatile int WatchDogTime = 0 ; volatile int gErrorPacketCnt =0 ; volatile int BdmaRxDoneFlagForLoopBackCheck = 0 ; volatile int MacTxDoneFlagForLoopBackCheck = 0 ; // Global variable structure for store status 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} ; //网络初始化 void LanInitialize(void) { //配置物理收发设备 ResetPhyChip() ; //获取MAC层网卡硬件物理地址 GetMyMacAddr() ; // Initialize MAC and BDMA controller MacInitialize() ; } /* * void MacInitialize(void) * Initialize MAC and BDMA Controller */ void MacInitialize(void) { /*-----------------------------------------------------------------* * 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) ; SysSetInterrupt(nBDMA_RX_INT, BDMA_Rx_isr) ; 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 = SwReset ; BDMARXLSZ = MaxRxFrameSize+40 ; // 1520 MACCON = gMacCon ; /*-----------------------------------------------------------------* * 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_Reg(0) = gCam0_Addr0; CAM_Reg(1) = gCam0_Addr1; // CAM Enable Register(CAMEN) CAMEN = 0x0001 ; CAMCON = gCamCon ; /*-----------------------------------------------------------------* * 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. * *-----------------------------------------------------------------*/ ReadyMacTx() ; ReadyMacRx() ; } /* * void TxFDInitialize(void) ; * Initialize Tx frame descriptor area-buffers. */ void TxFDInitialize(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. BDMATXPTR = (U32)TxFDBaseAddr + 0x4000000; gWTxFDPtr = gCTxFDPtr = BDMATXPTR; // Get Transmit buffer base address. FrameDataAddr = (U32)TxFBABaseAddr + 0x4000000; // Generate linked list. pFrameDescriptor = (sFrameDescriptor *) gCTxFDPtr; 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; } /* * void RxFDInitialize(void) ; * Initialize Rx frame descriptor area-buffers. */ 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. BDMARXPTR = (U32)RxFDBaseAddr + 0x4000000; gCRxFDPtr = BDMARXPTR; // Get Transmit buffer base address. FrameDataAddr = (U32)RxFBABaseAddr + 0x4000000; // Generate linked list. pFrameDescriptor = (sFrameDescriptor *) gCRxFDPtr; 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; } /* * Function : ReadyMacTx * Description : set Tx Registers related with BDMA & MAC to transmit * packet. */ void ReadyMacTx(void) { BDMATXCON = gBdmaTxCon ; MACTXCON = gMacTxCon ; } /* * Function : ReadyMacRx * Description : set Rx Registers related with BDMA & MAC to Receive packet. */ void ReadyMacRx(void) { BDMARXCON = gBdmaRxCon ; MACRXCON = gMacRxCon ; } /* * Function : MacTxGo * Description : MAC Transfer Start for interactive mode */ void MacTxGo(void) { // Enable MAC and BDMA Transfer if (!(BDMATXCON & BTxEn)) BDMATXCON |= BTxEn ; MACTXCON |= TxEn ; } /* * Function : GetMyMacAddr * Description : Get MAC Address From IIC EEPROM */ void GetMyMacAddr(void) { U8 MacAddr[MAC_ADDR_SIZE]; U8 TempAddr[MAC_ADDR_SIZE]; int i; gCam0_Addr0 = gCam0_Addr1 = 0 ; MacAddr[0] = 0x55 ; MacAddr[1] = 0x44 ; MacAddr[2] = 0x33 ; MacAddr[3] = 0x22 ; MacAddr[4] = 0x11 ; MacAddr[5] = 0x00 ; /* Get MAC Address */ for (i=0;i<(int)MAC_ADDR_SIZE;i++) TempAddr[i] = MacAddr[i]; /* Copy MAC Address to global variable */ 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) ; /* Set CAM0 register : 0x9100~0x9103, 0x9104, 0x9105 */ CAM_Reg(0) = gCam0_Addr0; CAM_Reg(1) = gCam0_Addr1; for (i=0;i<(int)MAC_ADDR_SIZE;i++) MyMacSrcAddr[i] = TempAddr[i]; } /* * Function : ResetPhyChip * Description : Reset The Phychip, Auto-Negotiation Enable */ void ResetPhyChip(void) { //10Mbps 半双工模式 //MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,0x0); //10Mbps 全双工模式 //MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,PHY_FULLDUPLEX); //100Mbps 半双工模式 //MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,DR_100MB); //100Mbps 全双工模式 //MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,DR_100MB|PHY_FULLDUPLEX); //自动检测配置 MiiStationWrite(PHY_CNTL_REG,PHYHWADDR,ENABLE_AN|RESTART_AN); } /* * Function : MiiStationRead, MiiStationWrite * Description : MII Interface Station Management Register Read or Write * Input : PhyInAddr(PHY internal register address) * PhyAddr(PHY unique address) * PhyWrData(When Write) * Output: PhyRdData(WhenRead) */ void MiiStationWrite(U32 PhyInAddr, U32 PhyAddr, U32 PhyWrData) { STADATA = PhyWrData ; STACON = PhyInAddr | PhyAddr | MiiBusy | PHYREGWRITE ; while( (STACON & MiiBusy) ) ; delay_physet() ; } U32 MiiStationRead(U32 PhyInAddr, U32 PhyAddr) { U32 PhyRdData ; STACON = PhyInAddr | PhyAddr | MiiBusy ; while( (STACON & MiiBusy) ) ; PhyRdData = STADATA ; return PhyRdData ; } void delay_physet(void) { int i=1000 ; while(i--) ; } /* * Function : MAC_Tx_isr * Description : Interrupt Service Routine for MAC Tx */ void MAC_Tx_isr(void) { sFrameDescriptor *pTxFDptr; U32 *pFrameDataPtr ; U32 Status ; U32 CTxPtr ; CTxPtr = BDMATXPTR ; while ( gCTxFDPtr != CTxPtr ) { pTxFDptr = (sFrameDescriptor *) gCTxFDPtr; // 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++ ; } else { // 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. ReadyMacTx() ; } // end if // Clear Framedata pointer already used. pTxFDptr->StatusAndFrameLength = (U32)0x0; gCTxFDPtr = (U32)pTxFDptr->NextFrameDescriptor ; } // end while loop } /* * Function : MAC_Rx_isr * Description : Interrupt Service Routine for MAC Rx * Not Used */ void MAC_Rx_isr(void) { } /* * Function : BDMA_Tx_isr * Description : Interrupt Service Routine for BDMA Tx * Not Used */ void BDMA_Tx_isr(void) { } /* * Function : BDMA_Rx_isr * Description : Interrupt Service Routine for BDMA Rx * Ethenet Frame is received in BDMA_Rx_isr */ void BDMA_Rx_isr(void) { sFrameDescriptor *pRxFDptr ; U32 RxStatus, FrameLength ; U32 CRxPtr; U32 sBdmaStat ; U8 *pFrameData ; // Step 1. Get current frame descriptor and status CRxPtr = BDMARXPTR ; sBdmaStat = BDMASTAT ; // Step 2. Clear BDMA status register bit by write 1 BDMASTAT |= S_BRxRDF ; gsBdmaRxStatus.BdmaRxCnt++ ; do { // Step 3. Check Null List Interrupt if ( BDMASTAT & S_BRxNL ) { BDMASTAT |= S_BRxNL ; gsBdmaRxStatus.BRxNLErr++ ; MacInitialize() ; 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 ; pFrameData = (U8 *)pRxFDptr->FrameDataPtr ; gsBdmaRxStatus.BdmaRxGood++ ; // Step 6. Get received frame to memory buffer //由丁一修改 ethernetif_input(netif_default,pFrameData ,FrameLength); } else { //put_byte('q'); // 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++ ; } // Step 8. Change ownership to BDMA for next use (pRxFDptr->FrameDataPtr) |= fOwnership_BDMA; // 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() ; } } /* * Function : SendPacket * Description : Send ethernet frame function * Input : frame data pointer, frame length * Output : transmit ok(1) or error(0) */ int SendPacket( unsigned char* Data,int Size) { sFrameDescriptor *psTxFD; U32 *pFrameDataPtr ; U8 *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 & fOwnership_BDMA) ) return 0 ; // 3. Prepare Tx Frame data to Frame buffer memcpy ((U8 *)pFrameData,(U8 *)Data,FrameLength); // 4. Set TX Frame flag & Length Field psTxFD->Reserved = (PaddingMode | CRCMode | SourceAddrIncrement | \ LittleEndian | WidgetAlign00 | MACTxIntEn); psTxFD->StatusAndFrameLength = (U32)(FrameLength & 0xffff); // 5. Cheange ownership to BDMA psTxFD->FrameDataPtr |= fOwnership_BDMA; // 6. Enable MAC and BDMA Tx control register MacTxGo(); // 7. Change the Tx frame descriptor for next use gWTxFDPtr = (U32)(psTxFD->NextFrameDescriptor); return 1 ; }