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

📄 adi_ether_bf537.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
📖 第 1 页 / 共 4 页
字号:
/*********************************************************************************

Copyright(c) 2004 Analog Devices, Inc. All Rights Reserved. 

This software is proprietary and confidential.  By using this software you agree
to the terms of the associated Analog Devices License Agreement.  


*********************************************************************************/


/*********************************************************************

Include files

*********************************************************************/


#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <services/services.h>			// system service includes
#include <services/adi_int.h>
#include <drivers/adi_dev.h>			// device manager includes
#include <ADI_ETHER_BF537.h>			// BF537 ether driver includes
#include <cdefbf537.h>
#include <time.h>


/*********************************************************************

Enumerations and defines

*********************************************************************/

#define MAX_RCVE_FRAME 1560



//#define USE_SYNC


#ifdef ADI_ETHER_BF537_DEBUG
#define CHECK_QUEUES 0
#else
#define CHECK_QUEUES 0
#endif


// PHY-related constants
#define NO_PHY_REGS     0x20


// -----------------------------------------------------------------------
//                     PHY REGISTER NAMES				//
// -----------------------------------------------------------------------
#define PHYREG_MODECTL		0x0000
#define PHYREG_MODESTAT		0x0001
#define PHYREG_PHYID1		0x0002
#define PHYREG_PHYID2		0x0003
#define PHYREG_ANAR			0x0004
#define PHYREG_ANLPAR		0x0005
#define PHYREG_ANER			0x0006
#define PHYREG_NSR			0x0010
#define PHYREG_LBREMR		0x0011
#define PHYREG_REC			0x0012
#define PHYREG_10CFG		0x0013
#define PHYREG_PHY1_1		0x0014
#define PHYREG_PHY1_2		0x0015
#define PHYREG_PHY2			0x0016
#define PHYREG_TW_1			0x0017
#define PHYREG_TW_2			0x0018
#define PHYREG_TEST			0x0019


#define	EMAC2_STAOP_RD	( 0<< 1 )	// Station Management Operation=Read
#define	EMAC2_STAOP_WR	( 1<< 1 )	// Station Management Operation=Write

/*********************************************************************

Data Structures 

*********************************************************************/


typedef struct dma_descriptor {
	struct dma_descriptor	*NEXT_DESC_PTR;
	unsigned long int		START_ADDR;
	u16						CONFIG;
	u16						X_COUNT;
} DMA_DESCRIPTOR;


typedef volatile struct  DMA_REGISTERS {
	DMA_DESCRIPTOR			*NEXT_DESC_PTR;
	u32						START_ADDR;
	u16						CONFIG;
	u16						pad0;
	u32						pad1;
	u16						X_COUNT;
	u16						pad2;
	s16						X_MODIFY;
	u16						pad3;
	u16						Y_COUNT;
	u16						pad4;
	s16						Y_MODIFY;
	u16						pad5;
	u32						CURR_DESC;
	u32						CURR_ADDR;
	u16						IRQ_STATUS;
	u16						pad6;
	u16						PERIPHERAL_MAP;
	u16						pad7;
	u16						CURR_X_COUNT;
	u16						pad8;
	u32						pad9;
	u16						CURR_Y_COUNT;
	u16						pad10;
} DMA_REGISTERS;

typedef volatile struct status_area {
	u16	IPHdrChksum;		// the IP header checksum
	u16	IPPayloadChksum;	// the IP header and payload checksum
	u32	StatusWord;			// the frame status word
	volatile struct status_area		*Next;	// next status area
} STATUS_AREA;

typedef struct buffer_info {
	// this structure is overlaid on the start of the ADI_ETHER_BUFFER structure on the area reserved for the physical dev. driver
	DMA_DESCRIPTOR			*First;			// first descriptor associated with buffer
	DMA_DESCRIPTOR			*Last;			// last descriptor associated with buffer
	int						NoDesc;			// no. of descriptors associated with buffer
	STATUS_AREA				*Status;		// address of the status word area
} BUFFER_INFO;	

typedef struct frame_info {
	u16						IPHdrChksum;		// the IP header checksum
	u16						IPPayloadChksum;	// the IP header and payload checksum
	u32						StatusWord;			// the frame status word
} FRAME_INFO;
typedef struct frame_queue {
	DMA_REGISTERS		*Dma;			// base address of DMA channel registers
	
	ADI_ETHER_BUFFER		*Active;		// list of curently active frames
	ADI_ETHER_BUFFER		*Pending;		// list of pending frames
	ADI_ETHER_BUFFER		*Completed;		// list of completed frames
	ADI_ETHER_BUFFER		*Queued;		// list of buffers awaiting descriptors
	DMA_DESCRIPTOR			*Avail;			// available dma registers structures
	STATUS_AREA				*AvailStatus;	// available status areas
	int						NoAvail;		// no. of available dma register structures
	int						Channel;		// DMA channel
	int						NoCompletions;
	int						UnProcessed;	// no. of unprocessed buffers
	u32						EnableMac;		// command to enable the MAC, reset to zero one enabled
	bool					Rcve;			// if controlling receiving
	bool					Enabled;		// set once the DMA has been enabled once
	u16						CompletedStatus;// mask to determine if frame has completed
	
} FRAME_QUEUE;


typedef struct adi_ether_bf537_data {
	void					*CriticalData;
	ADI_DEV_DEVICE_HANDLE	DeviceHandle;	// device handle
	ADI_DMA_MANAGER_HANDLE	DMAHandle;		// handle to the DMA manager
	ADI_DCB_HANDLE			DCBHandle;		// callback handle
	ADI_DCB_CALLBACK_FN		DMCallback;		// client callback function
	ADI_DEV_DIRECTION 		Direction;		// data direction
	bool 					Open;			// device open
	bool					Started;		// device started
	bool					Closing;		// refuse new requests
	
	//
	FRAME_QUEUE				Rx;				// receive queues
	FRAME_QUEUE				Tx;				// transmit quueues
	ADI_ETHER_BF537_TRACE_DATA Trc;			// trace support data	
	int						MaxTraceEntries;// maximum number of trace entries
	int						TraceMaxBytes;	// maximum no. of bytes to be traced
	int						TraceSequence;
	int						TraceFirstByte;
	int						CLKIN;			// clock in value in MHZ
	
	
	int						FlowEnabled;	// record if data flow is active
	int						EtherIntIVG;	// IVG for the ethernet interrupt
	int						RXIVG;			// IVG for the RX completion
	int						TXIVG;			// IVG for the TX completion
	int						PhyAddr;		// PHY address
	int						OpMode;			// set these bits n the OPMODE regs
	bool					Port10;			// set port speed to 10 Mbit/s
	bool					GenChksums;		// IP checksums to be calculated
	bool					NoRcveLnth;		// dont insert recv length at start of buffer
	bool					StripPads;		// remove trailing pad bytes
	bool					FullDuplex;		// set full duplex mode
	bool					Negotiate;		// enable auto negotiation
	bool					Loopback;		// loopback at the PHY
	bool					Cache;			// Buffers may be cached
	bool					FlowControl;	// flow control active
	unsigned short			IntMask;		// interrupt mask
	unsigned char			Mac[6];			// MAC address of the board
	ADI_ETHER_STATISTICS_COUNTS	*Stats;
	
	
} ADI_ETHER_BF537_DATA;



/*********************************************************************

Static data and processor specific macros

*********************************************************************/


static ADI_ETHER_BF537_DATA EtherDev;				// control data pointer

static int NoTxInts=0,NoRxInts=0;
static int NoTxPosts=0,NoRxPosts=0;
static int NoTxStarts,NoRxStarts;
static int FailedPosts;
static int TxErr;



#define FLUSH(P)  asm volatile("SSYNC;FLUSH[%0++];SSYNC;":"+p"(P));
//###define FLUSH(P)  asm volatile("NOP;":"+p"(P));
#define FLUSHINV(P)  asm volatile("SSYNC;FLUSHINV[%0++];SSYNC;":"+p"(P));
#define SIMPLEFLUSHINV(P)  asm volatile("SSYNC;FLUSHINV[%0++];SSYNC;"::"#p"(P));

/*********************************************************************

Static functions

*********************************************************************/
static void SetupPinMux(void);

static void ExitCriticalRegion(void *xit)
{
	sti((unsigned int)xit);
}

static void* EnterCriticalRegion(void *xit)
{
	unsigned int im = cli();
	sti(EtherDev.IntMask & im); // disable our interrupts 
	return (void *)im;
}


#if CHECK_QUEUES
static int CheckQueues(FRAME_QUEUE *q);
#endif

#if 1
static void FlushArea(void *start, void *nd)
{
	start = (void *)(((unsigned int)start)&(~31));
	while (start<nd) 
		FLUSH(start);
}


static void FlushInvArea(void *start, void *nd)
{
	start = (void *)(((unsigned int)start)&(~31));
	while (start<nd) FLUSHINV(start);
}
#else
#define FlushArea(s,n)
#define FlushInvArea(s,n)
#endif

static int GetTcpSeqNo(ADI_ETHER_BUFFER *pBuffer)
{
		unsigned short *p,v;
		char *l;
		int u;

		
		// get protocol
		l = ((char*)(pBuffer->Data) + 23 + 2);
		// tcp protocol
		if(*l == 6)
		{
			v=0;
			l = ((char*)((pBuffer)->Data) + 40 + 2);
			// p points to the seq-num we are not getting only short
			// good enough for testing.
			p = ((unsigned short*)l);
			
			// change byte-order
			v = ( ((*p & 0xFF) << 8) | (*p >> 8));
		
				
		} else v = 0xffff;
		return v;
}

static DumpTraceBuffer(void)
{
	if (EtherDev.MaxTraceEntries>0) {
		ADI_ETHER_BF537_DATA *dev = &EtherDev;
		int i,j;
		ADI_ETHER_BF537_TRACE_ENTRY *te;
		
		te = (dev->Trc.NoOfEntries<=dev->MaxTraceEntries?dev->Trc.BaseEntry:dev->Trc.OldestEntry);
		
		for (i=0;i<dev->Trc.NoOfEntries;i++) {
			te = (ADI_ETHER_BF537_TRACE_ENTRY *)(((char *)te) + dev->Trc.EntryLnth);
			switch (te->Dirn) {
			case 'T':
			case 'R':
				printf("%c %4.4x %4.4x ",te->Dirn,te->Seqn,te->NoBytes);
				for (j=0;j<te->NoBytes;j++) {
					printf("%2.2x ",te->Data[j]);
				}
				printf("\n");
				break;
			}
			if (te>=dev->Trc.EndOfData) te = dev->Trc.BaseEntry;
		}
		
	}
}


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			// device manager callback function
);

static u32 adi_pdd_Close(		// Closes a device
	ADI_DEV_PDD_HANDLE PDDHandle	// PDD handle
);

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
);
	
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
);
	
static u32 adi_pdd_Control(		// Sets or senses a device specific parameter
	ADI_DEV_PDD_HANDLE PDDHandle,	// PDD handle
	u32 Command,					// command ID
	void *pArg						// pointer to argument
);



static ADI_INT_HANDLER(DmaErrorInterruptHandler);
static ADI_INT_HANDLER(EtherInterruptHandler);
static ADI_INT_HANDLER(RxInterruptHandler);
static ADI_INT_HANDLER(TxInterruptHandler);
static void QueueFrames(ADI_ETHER_BF537_DATA *dev, FRAME_QUEUE *q);


	
#if defined(ADI_ETHER_DEBUG)

static int ValidatePDDHandle(ADI_DEV_PDD_HANDLE PDDHandle);

#endif

#if defined(ADI_ETHER_DEBUG)
#define CHECK_RES if (res == 0) res 
#else
#define CHECK_RES res 
#endif

/*********************************************************************

Global data

*********************************************************************/


ADI_DEV_PDD_ENTRY_POINT ADI_ETHER_BF537_Entrypoint = {
	adi_pdd_Open,
	adi_pdd_Close,
	adi_pdd_Read,
	adi_pdd_Write,
	adi_pdd_Control
};


#ifdef ADI_ETHER_BF537_DEBUG
#define CheckBuffers() ADI_ETHER_BF537_CheckBuffers()
void ADI_ETHER_BF537_CheckBuffers(void);
#else 
#define CheckBuffers() 0
#endif

//
//  checkbuffers
//
typedef struct buffer {
	struct buffer			*next;
} XBUFFER;

XBUFFER *ADI_ETHER_BF537_FreeBuf;
int ADI_ETHER_BF537_NoOfBuffers;
int ADI_ETHER_BF537_NoOfFreeBuffers;
int ADI_ETHER_BF537_NoPosted;
void *ADI_ETHER_BF537_PostedBuffer;
int ADI_ETHER_BF537_OutstandingPosts;

#if CHECK_QUEUES


static void breakpoint(int noq)
{
	if (noq>2) {
		int hh=noq;
	}
}
//
//
//		CheckQueuesForBuffer
static void CheckQueuesForBuffer(FRAME_QUEUE *q, ADI_ETHER_BUFFER *buf)
{
	int noq = 0;
	ADI_ETHER_BUFFER *nxt;
	int inact=0,inpend=0,incomp=0,inqu=0;
	
	nxt = q->Active;
	while (nxt != NULL) {
		if (nxt == buf) {
			inact = 1;
			breakpoint(++noq);
		}
		nxt = nxt->pNext;
	}
	nxt = q->Pending;
	while (nxt != NULL) {
		if (nxt == buf) {
			inpend = 1;
			breakpoint(++noq);
		}
		nxt = nxt->pNext;
	}
	nxt = q->Completed;
	while (nxt != NULL) {
		if (nxt == buf) {
			incomp = 1;
			breakpoint(++noq);
		}
		nxt = nxt->pNext;
	}
	nxt = q->Queued;
	while (nxt != NULL) {
		if (nxt == buf) {
			inqu = 1;
			breakpoint(++noq);
		}
		nxt = nxt->pNext;
	}
	
}

static int CheckQueues(FRAME_QUEUE *q)
{
	ADI_ETHER_BUFFER *nxt;
	int na =0;
	DMA_DESCRIPTOR *dmr;
	int nb=0;
	extern int CurRcve,CurXmit;
	
	nxt = q->Active;
	while (nxt != NULL) {
		nb++;
		CheckQueuesForBuffer(q,nxt);
		nxt = nxt->pNext;
	}
	nxt = q->Pending;
	while (nxt != NULL) {
		nb++;
		CheckQueuesForBuffer(q,nxt);
		nxt = nxt->pNext;
	}
	nxt = q->Completed;
	while (nxt != NULL) {
		nb++;
		CheckQueuesForBuffer(q,nxt);
		nxt = nxt->pNext;
	}
	nxt = q->Queued;
	while (nxt != NULL) {
		nb++;
		CheckQueuesForBuffer(q,nxt);
		nxt = nxt->pNext;
	}
	// next we check the Avail queue
	dmr = q->Avail;
	while (dmr != NULL ) {
		na++;
		dmr = dmr->NEXT_DESC_PTR;
	}
	if (na != q->NoAvail) breakpoint(2);
	
	CheckBuffers();
	return nb;
	
}


static int CountQueue(FRAME_QUEUE *q)
{
	ADI_ETHER_BUFFER *nxt;
	int nb=0;
	
	nxt = q->Active;
	while (nxt != NULL) {
		nb++;
		nxt = nxt->pNext;
	}
	nxt = q->Pending;
	while (nxt != NULL) {
		nb++;
		nxt = nxt->pNext;
	}
	nxt = q->Completed;
	while (nxt != NULL) {
		nb++;
		nxt = nxt->pNext;
	}
	nxt = q->Queued;
	while (nxt != NULL) {
		nb++;
		nxt = nxt->pNext;
	}
	
	return nb;
	
}

void ADI_ETHER_BF537_CheckBuffers()
{
	int nr,nt,nf,nx;
	XBUFFER *xb;
	
	nr = CountQueue(&EtherDev.Rx);
	nt = CountQueue(&EtherDev.Tx);
	nf = ADI_ETHER_BF537_NoOfFreeBuffers;
	if (nt+nr+nf+ADI_ETHER_BF537_NoPosted < ADI_ETHER_BF537_NoOfBuffers-1) breakpoint(4);
}


#else
#define CheckQueues(q)
#define breakpoint(p)
void ADI_ETHER_BF537_CheckBuffers()
{
}

#endif


//
//		Set FER regs to MUX in Ethernet pins
//

static void SetupPinMux(void)
{
	unsigned int fer_val;
	unsigned int *p = &fer_val;
	
	// FER reg bug work-around
	// read it once
	fer_val = *pPORTH_FER;
	
	fer_val = 0xffff;
	
	// write it twice to the same value
	
	*pPORTH_FER = fer_val;
	*pPORTH_FER = fer_val;

}


//
//		Wait until the previous MDC/MDIO transaction has completed
//

static void PollMdcDone(void)
{

⌨️ 快捷键说明

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