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

📄 adi_ether_bf537.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
📖 第 1 页 / 共 4 页
字号:
	// poll the STABUSY bit
	while((*pEMAC_STAADD) & STABUSY) {};
}


//
//		Read an off-chip register in a PHY through the MDC/MDIO port
//

static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr)
{
	PollMdcDone();

	*pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
		EMAC2_STAOP_RD | STABUSY;
	
	PollMdcDone();
	
	return (u16)*pEMAC_STADAT;
}

//
//		Write an off-chip register in a PHY through the MDC/MDIO port
//

static void RawWrPHYReg(u16 PHYAddr, u16 RegAddr, u32 Data)
{
	
	*pEMAC_STADAT = Data;

	*pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
		EMAC2_STAOP_WR | STABUSY;

	PollMdcDone();
}

static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u32 Data)
{
	PollMdcDone();
	RawWrPHYReg(PHYAddr,RegAddr,Data);
}

//
//		set up the phy
//
static SetPhy(ADI_ETHER_BF537_DATA *dev)
{
	u16 phydat,phydat1;
	clock_t ndtime;
	clock_t period = ((clock_t)CLOCKS_PER_SEC)/2;
	
	//		Program PHY registers
	phydat = 0;
	int pha;
	
	
	// issue a reset
	RawWrPHYReg(dev->PhyAddr, PHYREG_MODECTL, 0x8000);	
	
	// wait half a second
	period = 30000000; // assume 600 MHZ
	ndtime = clock()+period;
	while (clock()<ndtime);

	phydat = RdPHYReg(dev->PhyAddr, PHYREG_MODECTL);
	
	
	// advertise flow control supported
	phydat = RdPHYReg(dev->PhyAddr, PHYREG_ANAR);
	phydat |= (1 << 10);
	WrPHYReg(dev->PhyAddr, PHYREG_ANAR, phydat);
	
	
	phydat = 0;
	if (dev->Negotiate) {
		phydat |= 0x1000;		// enable auto negotiation
	} else {
		if (dev->FullDuplex) {
			phydat |= (1 << 8);		// full duplex
		} else {
			phydat &= (~(1 << 8));	// half duplex
		}
		if (!dev->Port10) {
			phydat |= (1 << 13);	// 100 Mbps
		} else {
			phydat &= (~(1 << 13));	// 10 Mbps
		}
	}
	if (dev->Loopback) {
		phydat |= (1 << 14);	// enable TX->RX loopback
		//WrPHYReg(dev->PhyAddr, PHYREG_MODECTL, phydat);
	}
	WrPHYReg(dev->PhyAddr, PHYREG_MODECTL, phydat);
	period = 100000000; // assume 600 MHZ
	ndtime = clock()+period;
	while (clock()<ndtime);
	phydat = RdPHYReg(dev->PhyAddr, PHYREG_MODECTL);

	// check for SMSC PHY
	if ((RdPHYReg(dev->PhyAddr, PHYREG_PHYID1) == 0x7) && ((RdPHYReg(dev->PhyAddr, PHYREG_PHYID2)&0xfff0 ) == 0xC0A0)) {
		// we have SMSC PHY so reqest interrupt on link down condition
		
		WrPHYReg(dev->PhyAddr, 30, 0x0ff); // enable interrupts	
		// enable PHY_INT
		u32 sysctl = *pEMAC_SYSCTL;
		
		sysctl |= 0x1;
		*pEMAC_SYSCTL = sysctl;	
	}

}

#if 1
static void DumpQueue(char *str1, char *str2, ADI_ETHER_BUFFER *buf)
{
	BUFFER_INFO *bi = (BUFFER_INFO *)buf;
	DMA_DESCRIPTOR *dmr;
	
	printf("%s %s\n",str1,str2);
	
	if (bi != NULL) {
		dmr = bi->First;
	
		while (dmr != NULL) {
			printf("   NEXT_DESC_PTR:%8.8x\n",dmr->NEXT_DESC_PTR);
			printf("   CONFIG:%4.4x\n",dmr->CONFIG);
			printf("   COUNT:%4.4x\n",dmr->X_COUNT);
			printf("\n");
			dmr = dmr->NEXT_DESC_PTR;
		}
	}
}
static void DumpDesc(char *str, FRAME_QUEUE *q)
{
	
	DumpQueue(str,"Active",q->Active);
	DumpQueue(str,"Pending",q->Pending);
	DumpQueue(str,"Queued",q->Queued);
		
}

static int  DumpAllQueues;
#endif

static void GetPhyRegs(u16 addr, u16 *regs)
{
	int pha;
	
	for (pha = 0; pha < NO_PHY_REGS; pha++) {
		regs[pha] = RdPHYReg(addr, pha);
	}
#if 1
	{
		FRAME_QUEUE *q;

		if (DumpAllQueues) {		
			DumpDesc("TX",&EtherDev.Tx);
			DumpDesc("RX",&EtherDev.Rx);
		}
	}
#endif	
}

/*********************************************************************
*
*	Function:		adi_pdd_Open
*
*	Description:	Opens the BF537 EMAC for use
*
*********************************************************************/


static u32 adi_pdd_Open(				// Open a device
	ADI_DEV_MANAGER_HANDLE	ManagerHandle,	// device manager handle
	u32 					DeviceNumber,	// device number
	ADI_DEV_DEVICE_HANDLE	DeviceHandle,	// device handle
	ADI_DEV_PDD_HANDLE 		*pPDDHandle,	// pointer to PDD handle location 
	ADI_DEV_DIRECTION 		Direction,		// data direction
	void					*pEnterCriticalArg,		// enter critical region parameter
	ADI_DMA_MANAGER_HANDLE	DMAHandle,		// handle to the DMA manager
	ADI_DCB_HANDLE			DCBHandle,		// callback handle
	ADI_DCB_CALLBACK_FN		DMCallback		// client callback function
) 
{

	u32 			Result;		// return value
	void 			*CriticalResult;
	ADI_ETHER_BF537_DATA *dev= &EtherDev;	


	// check for errors if required
#ifdef ADI_ETHER_ERROR_CHECKING_ENABLED
	if (DeviceNumber > 0) {		// check the device number
		return (ADI_DEV_RESULT_BAD_DEVICE_NUMBER);
	}
#endif

	EtherDev.IntMask = 0;	// disable all interrupts
	// insure the device the client wants is available
	Result = ADI_DEV_RESULT_DEVICE_IN_USE;
	CriticalResult = EnterCriticalRegion(pEnterCriticalArg);
	if (!dev->Open) {
		// initialize the device settings
		memset(dev,0,sizeof(ADI_ETHER_BF537_DATA));
		dev->CriticalData = pEnterCriticalArg;
		dev->DeviceHandle = DeviceHandle;
		dev->DCBHandle = DCBHandle;
		dev->DMCallback = DMCallback;
		dev->Direction = Direction;
		dev->Started = false;
		dev->PhyAddr = 0x01;  // 0x01 1.1 EZ kit and BUB
		dev->CLKIN = 25;  //Ezkit
		dev->FullDuplex=false;
		dev->Negotiate = true;
		dev->FlowControl = false;
		
		dev->EtherIntIVG = 7;
		
		dev->RXIVG = 11;
		dev->Rx.Channel = 1;
		dev->Rx.Rcve = true;
		dev->Rx.CompletedStatus = 0x01000;
		dev->Rx.EnableMac = 0x0001;
		
		dev->TXIVG = 11;
		dev->Tx.Channel = 2;
		dev->Tx.CompletedStatus = 0x0001;
		dev->Tx.EnableMac = 0x010000;
		
		dev->Trc.BaseEntry = NULL;
		dev->MaxTraceEntries = 0;
		dev->TraceSequence = 0;
		
		
		dev->Open = true;
		
		// we set the GPIO pins to Ethernet mode
		SetupPinMux();
		
		*pEMAC_OPMODE = 0;
		
		Result = ADI_DEV_RESULT_SUCCESS;
		
	}
	ExitCriticalRegion(CriticalResult);
	if (Result != ADI_DEV_RESULT_SUCCESS) return (Result);
	
	
	
	// save the physical device handle in the client supplied location
	*pPDDHandle = (ADI_DEV_PDD_HANDLE *)dev;
	
	
	
	// return
	return(ADI_DEV_RESULT_SUCCESS);
}
		
		



/*********************************************************************
*
*	Function:		adi_pdd_Close
*
*	Description:	Closes down EMAC
*
*********************************************************************/


static u32 adi_pdd_Close(		// Closes a device
	ADI_DEV_PDD_HANDLE PDDHandle			// PDD handle
) 
{
	ADI_ETHER_BF537_DATA *dev = (ADI_ETHER_BF537_DATA *)PDDHandle;	
	u32 		Result = ADI_DEV_RESULT_SUCCESS;				// return value
	bool active=true;
	FRAME_QUEUE *q;
	
	// check for errors if required
#if defined(ADI_ETHER_DEBUG)
	if ((Result = ValidatePDDHandle(PDDHandle)) != ADI_DEV_RESULT_SUCCESS) return (Result);
#endif

	dev->Closing = true;
	dev->Open = false;
	if (dev->Started) {
		dev->Started = false;
		// wait for the current frames to complete
		while (active) {
			active = false;
			q = &dev->Tx;
			if ((q->Active!=NULL) || (q->Pending!=NULL) || (q->Completed !=NULL) || (q->Queued!=NULL)) active = true;
			q = &dev->Rx;
			if ((q->Active!=NULL) || (q->Pending!=NULL) || (q->Completed !=NULL) || (q->Queued!=NULL)) active = true;			
		}
		// unhook interrupts
		adi_int_CECUnhook(dev->RXIVG,RxInterruptHandler);
		adi_int_CECUnhook(dev->TXIVG,TxInterruptHandler);
		adi_int_CECUnhook(dev->EtherIntIVG,EtherInterruptHandler);
		adi_int_CECUnhook(7,DmaErrorInterruptHandler);
	}
		
	// return
	return(Result);
}
	

//
//		Queue new frames
//
static void QueueNewFrames(ADI_ETHER_BF537_DATA *dev, FRAME_QUEUE *q,ADI_ETHER_BUFFER *bfs)
{
	ADI_ETHER_BUFFER *lstq,*buf;
	void *CriticalResult;
	int no_frames=0;
	
	
	
	// mark all the buffers as unprocessed
	buf = bfs;
	while (buf != NULL) {
		no_frames++;
		buf->StatusWord = 0;
		buf->ProcessedFlag = 0;
		buf->ProcessedElementCount = 0;
		buf = buf->pNext;
	}

	CriticalResult = EnterCriticalRegion(dev->CriticalData);

	lstq = NULL;
	buf = q->Queued;
	while (buf != NULL) {
		lstq = buf;
		buf = buf->pNext;
	}
	
	// now append on the Queued queue
	if (lstq == NULL) {
		q->Queued = bfs;
	} else {
		lstq->pNext = bfs;
	}
#ifdef ADI_ETHER_BF537_DEBUG	
	bfs->usage = Queued;
	bfs->rxusage = q->Rcve;
#endif	
	if (dev->Started) QueueFrames(dev,q);
	q->UnProcessed += no_frames;
	
	ExitCriticalRegion(CriticalResult);

	

}




/*********************************************************************
*
*	Function:		adi_pdd_Read
*
*	Description:	Provides buffers to store data when data is received
*					from the EMAC
*
*********************************************************************/


static u32 adi_pdd_Read(			// Reads data or queues an inbound buffer to a device
	ADI_DEV_PDD_HANDLE 	PDDHandle,		// PDD handle
	ADI_DEV_BUFFER_TYPE	BufferType,		// buffer type
	ADI_DEV_BUFFER 		*pBuffer		// pointer to buffer
)
{
	
	u32 		Result;				// return value
	ADI_ETHER_BF537_DATA *dev = (ADI_ETHER_BF537_DATA *)PDDHandle;
	
	// check for errors if required
#if defined(ADI_ETHER_DEBUG)
	if ((Result = ValidatePDDHandle(PDDHandle)) != ADI_DEV_RESULT_SUCCESS) return (Result);
	if (BufferType != DEV_1D) {
		return (ADI_DEV_BUFFER_TYPE_INCOMPATIBLE);
	}
	if (((ADI_ETHER_BUFFER *)pBuffer->Data & 0x03) || ((ADI_ETHER_BUFFER *)pBuffer->Payload & 0x03) ) {
		return ADI_ETHER_RESULT_MEMORY_NOT_ALIGNED;
	}
#endif

	QueueNewFrames(dev,&dev->Rx,(ADI_ETHER_BUFFER *)pBuffer);
	
	return(ADI_DEV_RESULT_SUCCESS);
}





/*********************************************************************
*
*	Function:		adi_pdd_Write
*
*	Description:	Provides buffers containing data to be transmitted
*					out through the EMAC
*
*********************************************************************/


static u32 adi_pdd_Write(		// Writes data or queues an outbound buffer to a device
	ADI_DEV_PDD_HANDLE 	PDDHandle,			// PDD handle
	ADI_DEV_BUFFER_TYPE	BufferType,			// buffer type
	ADI_DEV_BUFFER 		*pBuffer			// pointer to buffer
)

{
	
	u32 		Result;				// return value
	ADI_ETHER_BF537_DATA *dev = (ADI_ETHER_BF537_DATA *)PDDHandle;	
	char *src;
	ADI_ETHER_BUFFER *act = (ADI_ETHER_BUFFER *)pBuffer;
	
	// check for errors if required
#if defined(ADI_ETHER_DEBUG)
	if ((Result = ValidatePDDHandle(PDDHandle)) != ADI_DEV_RESULT_SUCCESS) return (Result);
	if (BufferType != DEV_1D) {
		return (ADI_DEV_BUFFER_TYPE_INCOMPATIBLE);
	}
	if (((ADI_ETHER_BUFFER *)pBuffer->Data & 0x03) || ((ADI_ETHER_BUFFER *)pBuffer->Payload & 0x03) ) {
		return ADI_ETHER_RESULT_MEMORY_NOT_ALIGNED;
	}
	if (((ADI_ETHER_BUFFER *)pBuffer->ElementCount*(ADI_ETHER_BUFFER *)pBuffer->ElementWidth) & 0x03) {
		return ADI_ETHER_RESULT_MEMORY_LENGTH_INVALID;
	}
#endif


	while (act !=  NULL) {
		// Plant the source MAC address
		src = 8+(char *)(act->Data);
		memcpy(src,dev->Mac,6);
		FlushArea(src,src+6);
		act = act->pNext;
	}


	QueueNewFrames(dev,&dev->Tx,(ADI_ETHER_BUFFER *)pBuffer);
	
	return(ADI_DEV_RESULT_SUCCESS);
}



//
//		Set MAC address
//

static void SetupMacAddr(unsigned char *mac)
{
	unsigned int lo;
	int i;
	
	lo = 0;
	for (i=3;i>=0; i--) {
		lo = (lo<<8) | mac[i];		
	}
	*pEMAC_ADDRLO = lo;
	
	lo = 0;
	for (i=5;i>=4; i--) {
		lo = (lo<<8) | mac[i];		
	}
	*pEMAC_ADDRHI = lo;
}

//
//		Get MAC address
//

static void GetMacAddr(unsigned char *mac)
{
	unsigned int lo;
	int i;
	
	lo = *pEMAC_ADDRLO;
	for (i=0;i<4; i++) {
		mac[i] = lo&0xff;
		lo = lo >> 8;		
	}
	
	lo = *pEMAC_ADDRHI;
	for (i=4;i<6; i++) {
		mac[i] = lo&0xff;
		lo = lo >> 8;		
	}
}

//
//		Update statistics
//

static void UpdateStatistics(u64 *stats)
{
	volatile unsigned long *cnts = pEMAC_RXC_OK;
	int ncnts = sizeof(ADI_ETHER_STATISTICS_COUNTS)/sizeof(u64);
	int rxcnts = offsetof(ADI_ETHER_STATISTICS_COUNTS,cEMAC_TX_CNT_OK)/sizeof(u64);

	ncnts -= rxcnts;	// no. of TX counts
		
	while (rxcnts>0) {
		*stats++ += *cnts++;
		rxcnts--;
	}
	cnts = pEMAC_TXC_OK;
	while (ncnts>0) {
		*stats++ += *cnts++;
		ncnts--;
	}
	
}


//
//		Configure and start the MAC
//
static int StartMac(ADI_ETHER_BF537_DATA *dev)
{
	int res;
	u32 opmode;
	u16 sysctl;
	void *CriticalResult;
	static DMA_DESCRIPTOR txfirst,txlast;
	u16 vrctl;
	unsigned int vco,cmsel,msk;
	u16 fer_val;
	
	
	memset(dev->Stats,0,sizeof(ADI_ETHER_STATISTICS_COUNTS));
	UpdateStatistics((u64*)dev->Stats);
	
	vrctl = *pVR_CTL;
	if ((vrctl&0x4000)==0) {
		*pVR_CTL = 0x4000|vrctl; //enable CLKBFOE to enable clock for the PHY
		msk = cli();
		ssync();
		idle();
		sti(msk);
	}
		
		
	//		Set FER regs to MUX in Ethernet pins
	// FER reg bug work-around
	// read it once
	fer_val = *pPORTH_FER;
	// MUX all of these pins to Ethernet
	fer_val = 0xFFFF;

	// write it twice to the same value
	*pPORTH_FER = fer_val;
	*pPORTH_FER = fer_val;
	
		
	
	// enable the interrupts in the SIC
	res       = adi_int_SICSetIVG(ADI_INT_DMA1_ETHERNET_RX_PORTH_A,dev->RXIVG);
	CHECK_RES = adi_int_SICEnable(ADI_INT_DMA1_ETHERNET_RX_PORTH_A);
	
	CHECK_RES = adi_int_SICSetIVG(ADI_INT_DMA2_ETHERNET_TX_PORTH_B,dev->TXIVG);
	CHECK_RES = adi_int_SICEnable(ADI_INT_DMA2_ETHERNET_TX_PORTH_B);
	
	CHECK_RES = adi_int_SICSetIVG(ADI_INT_PERIPHERAL_ERROR,dev->EtherIntIVG);
	CHECK_RES = adi_int_SICEnable(ADI_INT_PERIPHERAL_ERROR);
	
	CHECK_RES = adi_int_SICSetIVG(ADI_INT_DMA_ERROR,7);
	CHECK_RES = adi_int_SICEnable(ADI_INT_DMA_ERROR);

	// hook the DMA error interrupt
	CHECK_RES = adi_int_CECHook(7,DmaErrorInterruptHandler,dev,true);
	// hook the ether interrupt
	CHECK_RES = adi_int_CECHook(dev->EtherIntIVG,EtherInterruptHandler,dev,true);
	
	if (res == 0) {
		
		if (dev->Rx.Dma == NULL ) {
			dev->Rx.Dma = (DMA_REGISTERS *)(DMA0_NEXT_DESC_PTR+0x40*dev->Rx.Channel);
			//dev->Rx.Dma->CONFIG = 0;
			dev->Rx.Dma->X_COUNT = 0;
			dev->Rx.Dma->X_MODIFY = 4;
			dev->Rx.Dma->Y_COUNT = 0;
		}

		if (dev->Tx.Dma == NULL) {
			dev->Tx.Dma = (DMA_REGISTERS *)(DMA0_NEXT_DESC_PTR+0x40*dev->Tx.Channel);
			//dev->Tx.Dma->CONFIG = 0;
			dev->Tx.Dma->X_COUNT = 0;
			dev->Tx.Dma->X_MODIFY = 4;
			dev->Tx.Dma->Y_COUNT = 0;
		}
		// set the imask

⌨️ 快捷键说明

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