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 + -
显示快捷键?