📄 adi_ether_bf537.c
字号:
/*********************************************************************************
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 + -