⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amd79c970.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  COPYRIGHT (c) 1998 by Radstone Technology * * * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. * * You are hereby granted permission to use, copy, modify, and distribute * this file, provided that this notice, plus the above copyright notice * and disclaimer, appears in all copies. Radstone Technology will provide * no support for this code. * *//* * RTEMS/KA9Q driver for PC-NET */#include <bsp.h>#include <rtems/error.h>#include <ka9q/rtems_ka9q.h>#include <ka9q/global.h>#include <ka9q/enet.h>#include <ka9q/iface.h>#include <ka9q/netuser.h>#include <ka9q/trace.h>#include <ka9q/commands.h>#include <pci.h>#include "amd79c970.h"/* * Number of PC-NETs supported by this driver */#define NPCNETDRIVER	1/* * Default number of buffer descriptors set aside for this driver. * The number of transmit buffer descriptors has to be quite large * since a single frame often uses four or more buffer descriptors. * * Set the number of Tx and Rx buffers, using Log_2(# buffers).  */#define LANCE_LOG2_TX_BUFFERS 4#define LANCE_LOG2_RX_BUFFERS 4#define TX_RING_SIZE			(1 << (LANCE_LOG2_TX_BUFFERS))#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)#define TX_RING_LEN_BITS		((LANCE_LOG2_TX_BUFFERS) << 4)#define RX_RING_SIZE			(1 << (LANCE_LOG2_RX_BUFFERS))#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)#define RX_RING_LEN_BITS		((LANCE_LOG2_RX_BUFFERS) << 4)/* * RTEMS event used by interrupt handler to signal daemons. * This must *not* be the same event used by the KA9Q task synchronization. */#define INTERRUPT_EVENT	RTEMS_EVENT_1/* * Receive buffer size -- Allow for a full ethernet packet plus a pointer */#define ETHPKT_SIZE	1520#define RBUF_SIZE	(ETHPKT_SIZE + sizeof (struct iface *))/* * LANCE Register Access Macros */#define PCNET_IO_RD32(dp, reg, value)	\	inport_32(&dp->pPCNet->u.dwio.##reg, value)#define PCNET_IO_WR32(dp, reg, value)	\	outport_32(&dp->pPCNet->u.dwio.##reg, value)/* * LANCE Register Access Macros */#define RD_CSR32(dp, index, value) \	PCNET_IO_WR32(dp, rap, index); \	PCNET_IO_RD32(dp, rdp, value)	#define WR_CSR32(dp, index, value) \	PCNET_IO_WR32(dp, rap, index); \	PCNET_IO_WR32(dp, rdp, value)	#define RD_BCR32(dp, index, value) \	PCNET_IO_WR32(dp, rap, index); \	PCNET_IO_RD32(dp, bdp, value)#define WR_BCR32(dp, index, value) \	PCNET_IO_WR32(dp, rap, index); \	PCNET_IO_WR32(dp, bdp, value)/* * Hardware-specific storage * * Note that the enetInitBlk field must be aligned to a 16 byte * boundary */typedef struct amd79c970Context {	rmde_t		rxBdBase[RX_RING_SIZE];	tmde_t		txBdBase[TX_RING_SIZE];	initblk_t		initBlk;	pc_net_t		*pPCNet;	unsigned32		ulIntVector;	struct mbuf		**rxMbuf;	struct mbuf		**txMbuf;	int			rxBdCount;	int			txBdCount;	int			txBdHead;	int			txBdTail;	int			txBdActiveCount;	struct iface		*iface;	rtems_id		txWaitTid;	/*	 * Statistics	 */	unsigned long	rxInterrupts;	unsigned long	rxNotFirst;	unsigned long	rxNotLast;	unsigned long	rxGiant;	unsigned long	rxNonOctet;	unsigned long	rxRunt;	unsigned long	rxBadCRC;	unsigned long	rxOverrun;	unsigned long	rxCollision;	unsigned long	rxDiscarded;	unsigned long	txInterrupts;	unsigned long	txDeferred;	unsigned long	txHeartbeat;	unsigned long	txLateCollision;	unsigned long	txRetryLimit;	unsigned long	txUnderrun;	unsigned long	txLostCarrier;	unsigned long	txRawWait;} amd79c970Context_t;static amd79c970Context_t *pAmd79c970Context[NPCNETDRIVER];/* * PC-NET interrupt handler */static rtems_isramd79c970_isr (rtems_vector_number v){	unsigned32 ulCSR0, ulCSR4, ulCSR5;	amd79c970Context_t *dp;	int i;	for(i=0; i<NPCNETDRIVER; i++)	{		dp=pAmd79c970Context[i];		if(dp->ulIntVector==v)		{			RD_CSR32(dp, CSR0, ulCSR0);			if(ulCSR0 & CSR0_RINT)			{				/*				 * We have recieve data				 */				dp->rxInterrupts++;				rtems_event_send(					dp->iface->rxproc,					INTERRUPT_EVENT);			}			if(ulCSR0 & CSR0_TINT)			{				/*				 * Data tranmitted or error				 */				dp->txInterrupts++;				if(dp->txWaitTid)				{					rtems_event_send(						dp->txWaitTid,						INTERRUPT_EVENT);				}			}			if((ulCSR0 & CSR0_INTR) &&			   !(ulCSR0 & (CSR0_RINT | CSR0_TINT)))			{				/*				 * Many possible sources				 */				RD_CSR32(dp, CSR4, ulCSR4);				RD_CSR32(dp, CSR5, ulCSR5);				DEBUG_puts("CSR0=");				DEBUG_puth(ulCSR0);				DEBUG_puts(", CSR4=");				DEBUG_puth(ulCSR4);				DEBUG_puts(", CSR5=");				DEBUG_puth(ulCSR5);				DEBUG_puts("\n\r");				/*				 * Clear it				 */				WR_CSR32(dp, CSR4, ulCSR4);				WR_CSR32(dp, CSR5, ulCSR5);			}			/*			 * Clear interrupts			 */			ulCSR0&=CSR0_BABL | CSR0_CERR | CSR0_MISS |				CSR0_MERR | CSR0_RINT | CSR0_TINT | CSR0_IENA;			WR_CSR32(dp, CSR0, ulCSR0);			RD_CSR32(dp, CSR0, ulCSR0);		}	}}/* * Initialize the ethernet hardware */static booleanamd79c970_initialize_hardware (int instance, int broadcastFlag){	amd79c970Context_t *dp;	struct mbuf 	*bp;	int		i;	unsigned8	ucPCIBusCount;	unsigned8	ucBusNumber;	unsigned8	ucSlotNumber;	unsigned32	ulDeviceID;	unsigned32	ulBAR0;	unsigned8	ucIntVector;	unsigned32	ulInitClkPCIAddr;	unsigned32	ulAPROM;	unsigned32	ulCSR0;	ucPCIBusCount=BusCountPCI();	/*	 * Scan the available busses for instance of hardware	 */	i=0;	dp=pAmd79c970Context[instance];	dp->pPCNet=(pc_net_t *)NULL;	for(ucBusNumber=0;	    (ucBusNumber<ucPCIBusCount) && (dp->pPCNet==(pc_net_t *)NULL);	    ucBusNumber++)	{		for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++)		{			PCIConfigRead32(ucBusNumber,					ucSlotNumber,					0,					PCI_CONFIG_VENDOR_LOW,					&ulDeviceID);			if(ulDeviceID!=PCI_ID(0x1022, 0x2000))			{				continue;			}			/*			 * We've found a PC-NET controller			 */			if(i++<instance)			{				continue;			}			/*			 * Read base address			 */			PCIConfigRead32(ucBusNumber,					ucSlotNumber,					0,					PCI_CONFIG_BAR_0,					&ulBAR0);			dp->pPCNet=(pc_net_t *)(ulBAR0&~PCI_ADDRESS_IO_SPACE);			/*			 * Read interrupt vector			 */			PCIConfigRead8(ucBusNumber,				       ucSlotNumber,				       0,				       PCI_CONFIG_INTERRUPTLINE,				       &ucIntVector);			dp->ulIntVector=PPCN_60X_IRQ_PCI(ucIntVector);			/*			 * Ensure that device is enabled			 */			PCIConfigWrite16(ucBusNumber,					 ucSlotNumber,					 0,					 PCI_CONFIG_COMMAND,					 PCI_ENABLE_IO_SPACE |					 PCI_ENABLE_BUS_MASTER);			break;		}	}	if(dp->pPCNet==(pc_net_t *)NULL)	{		return(FALSE);	}	/*	 * Read the ethernet number	 */	if(!dp->iface->hwaddr)	{		dp->iface->hwaddr=mallocw (EADDR_LEN);		PCNET_IO_RD32(dp, aprom[0], ulAPROM);		for(i=0;i<4;i++)		{			dp->iface->hwaddr[i]=(ulAPROM>>(i*8))&0xff;		}		PCNET_IO_RD32(dp, aprom[1], ulAPROM);		for(i=0;i<2;i++)		{			dp->iface->hwaddr[i+4]=(ulAPROM>>(i*8))&0xff;		}	}	/*	 * Allocate mbuf pointers	 */	dp->rxMbuf=mallocw (dp->rxBdCount * sizeof(*dp->rxMbuf));	dp->txMbuf=mallocw (dp->txBdCount * sizeof(*dp->txMbuf));	/*	 * Allocate space for incoming packets	 */	for(i=0; i<dp->rxBdCount; i++)	{		dp->rxMbuf[i]=bp=ambufw (RBUF_SIZE);		bp->data += sizeof (struct iface *);                dp->rxBdBase[i].rmde_addr=			Swap32((unsigned32)bp->data+PCI_SYS_MEM_BASE);                dp->rxBdBase[i].rmde_bcnt=			Swap16(-(bp->size-sizeof (struct iface *)));                dp->rxBdBase[i].rmde_flags=Swap16(RFLG_OWN);	}	/*	 * Set up transmit buffer descriptors	 */	for(i=0; i<dp->txBdCount; i++)	{                dp->txBdBase[i].tmde_status=Swap16(TST_STP | TST_ENP);                dp->txBdBase[i].tmde_error=0;		dp->txMbuf[i]=NULL;	}	/*	 * Initialise initblk	 */	if(broadcastFlag)	{		dp->initBlk.ib_mode=0;	}	else	{		dp->initBlk.ib_mode=Swap16(CSR15_DRCVBC);	}	/*	 * Set the receive descriptor ring length 	 */	dp->initBlk.ib_rlen=RX_RING_LEN_BITS;	/*	 * Set the receive descriptor ring address 	 */	dp->initBlk.ib_rdra=Swap32((unsigned32)&dp->rxBdBase[0]+				     PCI_SYS_MEM_BASE);	/*	 * Set the transmit descriptor ring length 	 */	dp->initBlk.ib_tlen=TX_RING_LEN_BITS;	/*	 * Set the tranmit descriptor ring address 	 */	dp->initBlk.ib_tdra=Swap32((unsigned32)&dp->txBdBase[0]+				     PCI_SYS_MEM_BASE);	for(i=0;i<6;i++)	{		dp->initBlk.ib_padr[i]=dp->iface->hwaddr[i];	}		/*	 * Ensure that we are in DWIO mode	 */	PCNET_IO_WR32(dp, rdp, 0);	WR_CSR32(dp, 58,CSR58_PCISTYLE);	WR_CSR32(dp, CSR3,		 CSR3_BABLM | CSR3_MERRM | CSR3_IDONM | CSR3_DXSUFLO);	WR_CSR32(dp, CSR4,		 CSR4_APADXMIT | CSR4_MFCOM | CSR4_RCVCCOM |		 CSR4_TXSTRTM | CSR4_JABM);	WR_CSR32(dp, CSR5, 0);	ulInitClkPCIAddr=(unsigned32)&dp->initBlk+PCI_SYS_MEM_BASE;	/*	 * CSR2 must contain the high order 16 bits of the first word in 	 * the initialization block 	 */	WR_CSR32(dp, CSR2, (ulInitClkPCIAddr >> 16) & 0xffff);	/*	 * CSR1 must contain the low order 16 bits of the first word in 	 * the initialization block 	 */	WR_CSR32(dp, CSR1, (ulInitClkPCIAddr & 0xffff));	/*	 * Set up interrupts	 */	set_vector(amd79c970_isr,		   dp->ulIntVector,		   instance);	/*	 * Start the device	 */	WR_CSR32(dp, CSR0, CSR0_INIT | CSR0_STRT);	/*	 * Wait for 100mS for the device to initialise	 */	for(i=0; i<100; i++)	{		RD_CSR32(dp, CSR0, ulCSR0);		if(ulCSR0 & CSR0_IDON)		{			break;		}		rtems_ka9q_ppause(1); /* 1mS */	}	if(i >= 100)	{		return(FALSE);	}	/*	 * Enable interrupts	 */	WR_CSR32(dp, CSR0, CSR0_IENA);	dp->txBdHead=dp->txBdTail=0;	dp->txBdActiveCount=0;	return(TRUE);}/* * Soak up buffer descriptors that have been sent */static voidamd79c970_retire_tx_bd (amd79c970Context_t *dp){	unsigned16 status;	unsigned32 error;	int i;	int nRetired;	i = dp->txBdTail;	nRetired = 0;	while((dp->txBdActiveCount != 0) &&	      (((status=Swap16(dp->txBdBase[i].tmde_status)) & TST_OWN)==0))	{		/*		 * See if anything went wrong		 */		if(status & TST_ERR)		{			/*			 * Check for errors			 */			error=Swap16(dp->txBdBase[i].tmde_error);			if (error & TERR_LCOL)				dp->txLateCollision++;			if (error & TERR_RTRY)				dp->txRetryLimit++;			if (error & TERR_UFLO)				dp->txUnderrun++;			if (error & TERR_EXDEF)				dp->txDeferred++;			if (error & TERR_LCAR)				dp->txLostCarrier++;		}		nRetired++;		if (status & TST_ENP)		{			/*			 * A full frame has been transmitted.			 * Free all the associated buffer descriptors.			 */			dp->txBdActiveCount -= nRetired;			while (nRetired) {				nRetired--;				free_mbuf (&dp->txMbuf[dp->txBdTail]);				if (++dp->txBdTail == dp->txBdCount)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -