mac2510.c
来自「source code of armboot for s3c4510」· C语言 代码 · 共 962 行 · 第 1/2 页
C
962 行
/* * Cirrus Logic CS8900A Ethernet * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * Copyright (C) 1999 Ben Williamson <benw@pobox.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is loaded into SRAM in bootstrap mode, where it waits * for commands on UART1 to read and write memory, jump to code etc. * A design goal for this program is to be entirely independent of the * target board. Anything with a CL-PS7111 or EP7211 should be able to run * this code in bootstrap mode. All the board specifics can be handled on * the host. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "armboot.h"#include "command.h"#include "net.h"#include "s3c2510.h"#include "mac2510.h"#include "log.h"#ifdef CONFIG_S3C2510#if (CONFIG_COMMANDS & CFG_CMD_NET)API_DEVICE api_Mac_dev;#if 0 //hans, FIXME, below buffers are allocated in C-data structure, but should be allocated in Non-cachable areaRECEIVE_FRAME_DESC rx_buff_desc[RX_FD_NUM];TRANSMIT_FRAME_DESC tx_buff_desc[TX_FD_NUM];char rx_framebuff_addr[RX_FD_NUM][END_BUFSIZ];#else//<--hans, for DMA area(Upper 1MBytes) accesstypedef struct End_Buffer { char end_buffer[END_BUFSIZ];} END_BUFFER;RECEIVE_FRAME_DESC *rx_buff_desc;TRANSMIT_FRAME_DESC *tx_buff_desc;END_BUFFER *rx_framebuff_addr;//-->hans end#endifvoid InitEtherApi(bd_t *bd){ api_init(bd, &api_Mac_dev);}void eth_halt( void ){ api_MacIntDisable(&api_Mac_dev); api_MacHWStop(&api_Mac_dev); api_MacHWReset(&api_Mac_dev); api_MacBuffFree(&api_Mac_dev);}int eth_init( bd_t *bd ){ api_MacBuffInit(&api_Mac_dev); api_MacHWInit(&api_Mac_dev); api_MacHWStart(&api_Mac_dev); return 0;}/* Get a data block via Ethernet */extern int eth_rx(void){ api_MacRcv(&api_Mac_dev); /* Pass the packet up to the protocol layers. */ /*NetReceive(NetRxPackets[0], rxlen);*/ return 0;}/* Send a data block via Ethernet. */extern int eth_send(volatile void *packet, int length){ api_MacSend(&api_Mac_dev, (ulong)packet, length); return 0;}/***************************//* Sub Function for driver *//***************************//********************************************************************************* api_MacHWReset - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacHWReset(API_DEVICE *api_Mac_dev){ uBDMARXCON bdmaRxCon; uBDMATXCON bdmaTxCon; uMACCON macCon; ulong pEtherAddr=api_Mac_dev->EtherAddr; *(ulong *)(&bdmaRxCon) = 0; *(ulong *)(&bdmaTxCon) = 0; *(ulong *)(&macCon) = 0; /*Init mac phy */ MAC_PHY_INIT(); bdmaRxCon.rxCon_reg.bRxRS= 1; REG_OUT_LONG (pEtherAddr, BDMARXCON, bdmaRxCon.rxCon_resetval); bdmaTxCon.txCon_reg.bTxRS= 1; REG_OUT_LONG (pEtherAddr, BDMATXCON, bdmaTxCon.txCon_resetval); macCon.macCon_reg.mReset = 1; macCon.macCon_reg.mII_OFF = ETH_PHY_SELECT; /* MII ON or 7-Wire ON */ REG_OUT_LONG (pEtherAddr, MACCON, macCon.macCon_resetval); api_Mac_dev->status = HW_RESET_DONE; return OK;}/********************************************************************************* api_MacBuffInit - Initialize TX and RX FD lists* Make a circular list of Rx and TX frame descriptors and buffers.* Two global variables gpReceiveFrameDescStart and gpTransmitFrameDescStart * stores the pointer to the start of the list. BDMA TX/RX PTR registers are * also initialized with the start of the appropriate list.*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacBuffInit(API_DEVICE *api_Mac_dev){ STATUS status = OK; int count; RECEIVE_FRAME_DESC* pReceiveFrameDesc; TRANSMIT_FRAME_DESC* pTransmitFrameDesc; ulong pEtherAddr=api_Mac_dev->EtherAddr; char *pTransmitFramebuff;//<--hans, for DMA area(Upper 1MBytes) access rx_buff_desc = (RECEIVE_FRAME_DESC *)(DRAM_LIMIT - (sizeof(RECEIVE_FRAME_DESC)*RX_FD_NUM)); tx_buff_desc =(TRANSMIT_FRAME_DESC *)(((ulong)rx_buff_desc & ~(0x3)) - (sizeof(TRANSMIT_FRAME_DESC)*TX_FD_NUM)); rx_framebuff_addr =(END_BUFFER *)(((ulong)tx_buff_desc & ~(0x3)) - (sizeof(END_BUFFER)*RX_FD_NUM));//-->hans end /*Init Rx Fd */ pReceiveFrameDesc = (RECEIVE_FRAME_DESC *)&(rx_buff_desc[0]); if(pReceiveFrameDesc == NULL) return ERROR; api_Mac_dev->gpReceiveFrameDescStart = pReceiveFrameDesc; REG_OUT_LONG(pEtherAddr, BDMARXDPTR, (ulong)pReceiveFrameDesc); REG_OUT_LONG(pEtherAddr, BRXBDCNT, (ulong)NULL); api_Mac_dev->RXDONEOFFSET =0; for(count = 0; count < RX_FD_NUM; count++) {//<--hans, for DMA area(Upper 1MBytes) access pReceiveFrameDesc->rxFrameData = (ulong)&rx_framebuff_addr[count];//-->hans end *(ulong *) (&pReceiveFrameDesc->rxStatusLength) = 0; pReceiveFrameDesc->rxStatusLength.owner = 1; /* owner: BDMA */ pReceiveFrameDesc ++; }/* end of for loop*/ /*Init Tx Fd */ pTransmitFrameDesc = (TRANSMIT_FRAME_DESC *)&(tx_buff_desc[0]); if(pTransmitFrameDesc == NULL) return ERROR; api_Mac_dev->gpTransmitFrameDescStart = pTransmitFrameDesc; REG_OUT_LONG(pEtherAddr, BDMATXDPTR, (ulong)pTransmitFrameDesc); REG_OUT_LONG(pEtherAddr, BTXBDCNT, (ulong)NULL); api_Mac_dev->TXOFFSET =0; api_Mac_dev->TXDONEOFFSET =0; for(count = 0; count < TX_FD_NUM; count++) { pTransmitFrameDesc->txFrameData = (ulong)NULL; *(ulong *) (&pTransmitFrameDesc->txStatusLength) = 0; /* owner: CPU */ pTransmitFrameDesc ++; pTransmitFramebuff += END_BUFSIZ; }/* end of for loop */ api_Mac_dev->buffInitialized = INIT_DONE; api_Mac_dev->status = BUFF_INIT_DONE; return status;}/********************************************************************************* api_MacBuffFree - Free the allocated TX and RX FD lists and buffers* This function frees all the allocated TX and RX FDs and the associated* buffers** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacBuffFree(API_DEVICE *api_Mac_dev){ STATUS status = OK; api_Mac_dev->buffInitialized = NOT_INIT_YET; api_Mac_dev->status = BUFF_FREE_DONE; return status;}/********************************************************************************* initCAMReg - .** RETURNS: OK or ERROR return status why..** SEE ALSO: **/int initCAMReg ( API_DEVICE *api_Mac_dev ) { uCAMEN camEn; uCAMCON camCon; ulong count; uchar *pAddr; STATUS status = OK; ulong pEtherAddr=api_Mac_dev->EtherAddr; /* Copy our MAC address to the first location in address array */ pAddr = (uchar *)(&(api_Mac_dev->addrList[0])); *(ulong *)pAddr = htonl (*(ulong *)api_Mac_dev->enetAddr); #if BIG_ENDIAN pAddr += 4; #else /*BIG_ENDIAN*/ pAddr += 6; #endif /*BIG_ENDIAN*/ *(ushort *)pAddr = htons (*(ushort *)(api_Mac_dev->enetAddr+4)); /* Copy the address array into CAM registers */ for (count = 0; count < 32; count++) REG_OUT_LONG(pEtherAddr, (CAM_BASE + (count*4)), api_Mac_dev->addrList[count]); /* init CAMCON register */ *(ulong *) (&camCon) = 0; camCon.camCon_reg.mBroad= 1; camCon.camCon_reg.mCompEn= 1; REG_OUT_LONG(pEtherAddr, CAMCON, camCon.camCon_resetval); /* init CAMEN register. Set bits for our MAC address and all * multicast addresses */ api_Mac_dev->mcastAddrCount = 21; *(ulong *)(&camEn) = 0; for (count = 0; count <= api_Mac_dev->mcastAddrCount; count++) camEn.camen_reg.camEnable |= (0x1<<count); REG_OUT_LONG(pEtherAddr, CAMEN, camEn.camen_resetval); return status; }/********************************************************************************** RETURNS: OK or ERROR return status why..** SEE ALSO:*/int api_MacHWInit(API_DEVICE *api_Mac_dev){ STATUS status = OK; uBDMARXCON bdmaRxCon; uBDMATXCON bdmaTxCon; uBDMARXLEN bdmaRxLen; uMACCON macCon; uMACTXCON macTxCon; uMACRXCON macRxCon; ulong pEtherAddr=api_Mac_dev->EtherAddr; /* init BDMATXCON register */ *(ulong *)(&bdmaTxCon) = 0; bdmaTxCon.txCon_reg.bTxNBD =TX_FD_NUM_PWR2; bdmaTxCon.txCon_reg.bTxMSL = 100; /* BDMA transmit to MAC tx start level : 4/8 */ REG_OUT_LONG(pEtherAddr, BDMATXCON, bdmaTxCon.txCon_resetval); /* init BDMARXCON register */ *(ulong *) (&bdmaRxCon) = 0; bdmaRxCon.rxCon_reg.bRxNBD =RX_FD_NUM_PWR2; bdmaRxCon.rxCon_reg.bRxWA = 0; /* 0 bytes alignment */ REG_OUT_LONG(pEtherAddr, BDMARXCON, bdmaRxCon.rxCon_resetval); /* init BDMARXLEN */ *(ulong *)(&bdmaRxLen) = 0; bdmaRxLen.rxLen_reg.bRxMFS = END_BUFSIZ; bdmaRxLen.rxLen_reg.bRxBS = END_BUFSIZ - 16; /* Rx Buffer Size */ REG_OUT_LONG(pEtherAddr, BDMARXLEN, bdmaRxLen.rxLen_resetval); /* init MACCON register */ *(ulong *)(&macCon) = 0; macCon.macCon_reg.mII_OFF = ETH_PHY_SELECT; if(api_Mac_dev->duplexMode == FULL_DUPLEX) macCon.macCon_reg.full_duplex = 1; REG_OUT_LONG(pEtherAddr, MACCON, macCon.macCon_resetval); /* init MACTXCON register */ *(ulong *)(&macTxCon) = 0; REG_OUT_LONG(pEtherAddr, MACTXCON, macTxCon.macTxCon_resetval); /* init MACRXCON register */ *(ulong *)(&macRxCon) = 0; macRxCon.macRxCon_reg.mStripCRC = 1; REG_OUT_LONG(pEtherAddr, MACRXCON, macRxCon.macRxCon_resetval); /* Init CAM regiser and CAM Enable register */ initCAMReg(api_Mac_dev); api_Mac_dev->status = HW_INIT_DONE; return status;}/********************************************************************************* api_MacHWStart - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacHWStart(API_DEVICE *api_Mac_dev){ STATUS status = OK; uBDMARXCON bdmaRxCon; uMACRXCON macRxCon; ulong pEtherAddr=api_Mac_dev->EtherAddr; /* init BDMARXCON register */ REG_IN_LONG(pEtherAddr, BDMARXCON, *(ulong *) (&bdmaRxCon)); bdmaRxCon.rxCon_reg.bRxEn = 1; REG_OUT_LONG(pEtherAddr, BDMARXCON, bdmaRxCon.rxCon_resetval); /* init MACRXCON register */ REG_IN_LONG(pEtherAddr, MACRXCON, *(ulong *) (&macRxCon)); macRxCon.macRxCon_reg.mRxEn = 1; REG_OUT_LONG(pEtherAddr, MACRXCON, macRxCon.macRxCon_resetval); api_Mac_dev->status = HW_START_STATUS; return status;}/********************************************************************************* api_MacHWStop - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */int api_MacHWStop (API_DEVICE *api_Mac_dev){ STATUS status = OK; uBDMARXCON bdmaRxCon; uBDMATXCON bdmaTxCon; uMACCON macCon; ulong pEtherAddr=api_Mac_dev->EtherAddr; REG_IN_LONG(pEtherAddr, BDMARXCON, *(ulong *)(&bdmaRxCon)); bdmaRxCon.rxCon_reg.bRxEn = 0; REG_OUT_LONG(pEtherAddr, BDMARXCON, *(ulong *)(&bdmaRxCon)); REG_IN_LONG(pEtherAddr, BDMATXCON, *(ulong *)(&bdmaTxCon)); bdmaTxCon.txCon_reg.bTxEn= 0; REG_OUT_LONG(pEtherAddr, BDMATXCON, *(ulong *)(&bdmaTxCon)); REG_IN_LONG(pEtherAddr, MACCON, *(ulong *)(&macCon)); macCon.macCon_reg.mHaltImm = 1; REG_OUT_LONG(pEtherAddr, MACCON, *(ulong *)(&macCon)); api_Mac_dev->status = STOP_STATUS; return status;}/********************************************************************************* api_MacRcv - .*** RETURNS: OK or ERROR return status why..** SEE ALSO: */void api_MacRcv(API_DEVICE *api_Mac_dev){ RECEIVE_FRAME_DESC* pFd; ulong RXFDCNT; uBMRXSTAT bmRxStat; uBDMARXCON bmRxCon; ushort* pFrameData; ulong frameLength; ulong pEtherAddr=api_Mac_dev->EtherAddr; /* Read & Clear BDMA Status Reg and Clear interrupt pending */ REG_IN_LONG(pEtherAddr, BMRXSTAT, *(ulong *)(&bmRxStat)); REG_OUT_LONG(pEtherAddr, BMRXSTAT, 0); // Only for s3c2510 pFd = api_Mac_dev->gpReceiveFrameDescStart + api_Mac_dev->RXDONEOFFSET; if((*(ulong *)(&(pFd->rxStatusLength)) & 0xffff)==0) return; REG_IN_LONG(pEtherAddr, BRXBDCNT, RXFDCNT); /* Process all packets received. */ while (api_Mac_dev->RXDONEOFFSET != RXFDCNT) { pFd = api_Mac_dev->gpReceiveFrameDescStart + api_Mac_dev->RXDONEOFFSET; /* Check BDMA Receive Ownership */ if( ! pFd->rxStatusLength.owner ) { if(*(ulong *)(&(pFd->rxStatusLength)) & MACRXFRAMEERRMASK ){ /* Rx Error packet */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?