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

📄 adi_ether_bf537.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
📖 第 1 页 / 共 4 页
字号:
		dev->IntMask = ~((1<<dev->RXIVG) | (1<<dev->TXIVG) | (1<<dev->EtherIntIVG) );
		
		// hook the RX,TX complete interrupts
		res = adi_int_CECHook(dev->RXIVG,RxInterruptHandler,dev,true);
		if (res == 0) {
			res = adi_int_CECHook(dev->TXIVG,TxInterruptHandler,dev,true);
			if (res != 0) {
				adi_int_CECUnhook(dev->RXIVG,RxInterruptHandler);
			}
		}
		if (res != 0)  {
			adi_int_CECUnhook(7,DmaErrorInterruptHandler);
			adi_int_CECUnhook(dev->EtherIntIVG,EtherInterruptHandler);
		}
		
		if (res == 0) {
			
			u32 fcclk,fsclk,fvco;
			u32 N,mdc;
			
			
			vco = ((*pPLL_CTL>>9)&0x3f) * dev->CLKIN;
			if (*pPLL_CTL&1) {
				vco = vco>>1; 	// divide by 2
			}
			cmsel = (*pPLL_DIV>>4)&0x3;
			fcclk = vco/(1<<cmsel);
			
			cmsel = *pPLL_DIV&0x0f;
			fsclk = vco/cmsel;
			
			N= (((fsclk+4)/5)-1)&0x3f;
					
			mdc = (fsclk*5)/(N+1);
			
			//set up the EMAC controller
	
			// reset counters, clear on read, saturate , enable counters
			*pEMAC_MMC_CTL = 0x0d;
			
			
			// dont enable RX and TX until we have a buffer to start the DMA with
			opmode = 0x00000000;
			if (dev->StripPads) {
				opmode |= 0x0002;
			}
			if (dev->FullDuplex) {
				opmode |= 0x04000000;
			}
			opmode |= dev->OpMode;
			*pEMAC_OPMODE = opmode;
			
			sysctl = 0;
			if (dev->GenChksums) {
				sysctl |= 0x0004;
			}
			if (dev->NoRcveLnth) {
				sysctl &= (~0x0002);
			} else {
				sysctl |= 0x0002;
			}
			sysctl = (N<<8) | sysctl;	// or in the SCLK:MDC divisor
			
			*pEMAC_SYSCTL = sysctl;	
			
			// set up the PHY
			SetPhy(dev);

			
			// now actually enable the interrupts
			*pEMAC_MMC_RIRQE = 0x00ffffff;		// RX counter interrupts
			*pEMAC_MMC_TIRQE = 0x00ffffff;		// RX counter interrupts
					
			dev->Started = true;
			
			CriticalResult = EnterCriticalRegion(dev->CriticalData);
			QueueFrames(dev,&dev->Tx);
			QueueFrames(dev,&dev->Rx);
			ExitCriticalRegion(CriticalResult);
		}
	}
	
	return res;
}


/*********************************************************************
*
*	Function:		adi_pdd_Control
*
*	Description:	Configures the EMAC
*
*********************************************************************/


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
) 

{
	
	u32 		Result;				// return value
	ADI_ETHER_BF537_DATA *dev = (ADI_ETHER_BF537_DATA *)PDDHandle;	
	ADI_ETHER_MEM_SIZES *msizes;
	ADI_ETHER_SUPPLY_MEM *memsup;
	int maxbuf,i;
	DMA_DESCRIPTOR *nxt,*lst;
	u32 *prefix;
	ADI_ETHER_BUFFER_COUNTS *bufcnts;
	ADI_ETHER_IVG_MAPPING *ivgs;
	ADI_ETHER_DMA_MAPPING *dmas;
	char *EndXmit;
	ADI_ETHER_BF537_TRACE_INFO *trcinfo;
	char *basemem,*obasemem;
	u32 lnthmem;
	volatile STATUS_AREA *sts,*lsts;
	
	u32 ii = ADI_DEV_CMD_GET_PERIPHERAL_DMA_SUPPORT;
	ii = ADI_ETHER_CMD_MEM_SIZES;
	
	// 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);
	}
#endif

	// avoid casts
	Result = ADI_DEV_RESULT_SUCCESS;
	

	// CASEOF (Command ID)
	switch (Command) {
		case ADI_DEV_CMD_SET_DATAFLOW:		
			// enable or disable accordingly
			dev->FlowEnabled = (int)pArg;
			break;
			
		case ADI_DEV_CMD_SET_DATAFLOW_METHOD:		
			break;
			
		case ADI_DEV_CMD_GET_PERIPHERAL_DMA_SUPPORT:		
			// no we dont want peripheral DMA support
			(*(int *)pArg) = false;
			break;
			
		case ADI_ETHER_CMD_MEM_SIZES:
			msizes = (ADI_ETHER_MEM_SIZES *)(pArg);
			msizes->BaseMemSize = sizeof(ADI_ETHER_STATISTICS_COUNTS);
			msizes->MemPerRecv = 36+sizeof(DMA_DESCRIPTOR[2]);
			msizes->MemPerXmit = 36+sizeof(DMA_DESCRIPTOR[3]);
			break;
			
		case ADI_ETHER_CMD_SUPPLY_MEM:
			memsup = (ADI_ETHER_SUPPLY_MEM *)(pArg);
			
			if (memsup->BaseMemLength < sizeof(ADI_ETHER_STATISTICS_COUNTS)) {
				Result = ADI_DEV_RESULT_NO_MEMORY;
			} else {
				dev->Stats = memsup->BaseMem;
				memset(dev->Stats,0,sizeof(ADI_ETHER_STATISTICS_COUNTS));
			}
			
#if 1			
			// layout the available RX desciptors
			lnthmem = memsup->RcveMemLength;
			obasemem = basemem = (char *)memsup->RcveMem;
			// round up base mem to be a multiple of 32
			basemem = (char *)((((u32)basemem)+31)&(~0x1F));
			// adjust the length remaining
			lnthmem = lnthmem - (basemem - obasemem);
			memsup->MaxRcveFrames = maxbuf = lnthmem/(32+sizeof(DMA_DESCRIPTOR[2]));
			if (maxbuf>=1) {
				// layout the status words
				lsts = NULL;
				dev->Rx.AvailStatus = (STATUS_AREA *)basemem;
				for (i=0;i<maxbuf;i++) {
					sts = (STATUS_AREA *)basemem;
					if (lsts!=NULL) lsts->Next = sts;
					sts->Next = NULL;
					lsts = sts;
					basemem += 32;
				}
				
				dev->Rx.Avail = (DMA_DESCRIPTOR *)basemem;
				dev->Rx.NoAvail = 2*maxbuf;
				nxt = dev->Rx.Avail;
				for (i=0;i<maxbuf;i++) {
					lst = nxt+1;
					memset(nxt,0,sizeof(DMA_DESCRIPTOR));
					nxt[0].NEXT_DESC_PTR = lst;
					lst->NEXT_DESC_PTR = nxt+2;
					nxt += 2;
				}
				lst->NEXT_DESC_PTR = NULL;
			} else {
				memsup->MaxRcveFrames = 0;
				Result = ADI_DEV_RESULT_NO_MEMORY;
			}
			
			CheckQueues(&dev->Rx);
			
			// layout the available TX desciptors			
			lnthmem = memsup->XmitMemLength;
			obasemem = basemem = (char *)memsup->XmitMem;
			// round up base mem to be a multiple of 32
			basemem = (char *)((((u32)basemem)+31)&(~0x1F));
			// adjust the length remaining
			lnthmem = lnthmem - (basemem - obasemem);
			memsup->MaxXmitFrames = maxbuf = lnthmem/(32+sizeof(DMA_DESCRIPTOR[3]));
			if (maxbuf>=1) {
				// layout the status words
				lsts = NULL;
				dev->Tx.AvailStatus = (STATUS_AREA *)basemem;
				for (i=0;i<maxbuf;i++) {
					sts = (STATUS_AREA *)basemem;
					if (lsts!=NULL) lsts->Next = sts;
					sts->Next = NULL;
					lsts = sts;
					basemem += 32;
				}
				
				dev->Tx.Avail = (DMA_DESCRIPTOR *)basemem;				
				dev->Tx.NoAvail = 3*maxbuf;
				nxt = dev->Tx.Avail;
				for (i=0;i<maxbuf;i++) {
					memset(nxt,0,sizeof(DMA_DESCRIPTOR));
					nxt[0].NEXT_DESC_PTR = nxt+1;
					nxt[1].NEXT_DESC_PTR = nxt+2;
					lst = &nxt[2];
					lst->NEXT_DESC_PTR = nxt+3;
					nxt += 3;
				}
				lst->NEXT_DESC_PTR = NULL;
			} else {
				memsup->MaxXmitFrames = 0;
				Result = ADI_DEV_RESULT_NO_MEMORY;
			}

			CheckQueues(&dev->Tx);
#else
			// layout the available RX desciptors
			dev->Rx.Avail = memsup->RcveMem;
			memsup->MaxRcveFrames = maxbuf = memsup->RcveMemLength/sizeof(DMA_DESCRIPTOR[2]);
			dev->Rx.NoAvail = 2*maxbuf;
			if (maxbuf>=1) {
				nxt = dev->Rx.Avail;
				for (i=0;i<maxbuf;i++) {
					lst = nxt+1;
					memset(nxt,0,sizeof(DMA_DESCRIPTOR));
					nxt[0].NEXT_DESC_PTR = lst;
					lst->NEXT_DESC_PTR = nxt+2;
					nxt += 2;
				}
				lst->NEXT_DESC_PTR = NULL;
			} else {
				memsup->MaxRcveFrames = 0;
				Result = ADI_DEV_RESULT_NO_MEMORY;
			}
			
			CheckQueues(&dev->Rx);
			
			// layout the available TX desciptors			
			dev->Tx.Avail = memsup->XmitMem;
			EndXmit = (char *)dev->Tx.Avail+memsup->XmitMemLength;
			memsup->MaxXmitFrames = maxbuf = memsup->XmitMemLength/sizeof(DMA_DESCRIPTOR[3]);
			dev->Tx.NoAvail = 3*maxbuf;
			if (maxbuf>=1) {
				nxt = dev->Tx.Avail;
				for (i=0;i<maxbuf;i++) {
					memset(nxt,0,sizeof(DMA_DESCRIPTOR));
					nxt[0].NEXT_DESC_PTR = nxt+1;
					nxt[1].NEXT_DESC_PTR = nxt+2;
					lst = &nxt[2];
					lst->NEXT_DESC_PTR = nxt+3;
					nxt += 3;
				}
				lst->NEXT_DESC_PTR = NULL;
			} else {
				memsup->MaxXmitFrames = 0;
				Result = ADI_DEV_RESULT_NO_MEMORY;
			}

			CheckQueues(&dev->Tx);
			
#endif

			

			break;
		case ADI_ETHER_CMD_GET_MAC_ADDR:
			GetMacAddr((unsigned char *)(pArg));
			break;
		case ADI_ETHER_CMD_SET_MAC_ADDR:
			if (*pEMAC_OPMODE&0x00010001) {
				Result = ADI_DEV_RESULT_INVALID_SEQUENCE;
			} else {
				memcpy(dev->Mac,pArg,6);
				SetupMacAddr((unsigned char *)(pArg));
			}
			break;
		case ADI_ETHER_CMD_GET_STATISTICS:
			UpdateStatistics((u64*)dev->Stats);
			memcpy((void *)(pArg),dev->Stats,sizeof(ADI_ETHER_STATISTICS_COUNTS));
			break;
		case ADI_ETHER_CMD_GET_BUFFER_PREFIX:
			prefix = (u32 *)(pArg);
			*prefix = 0;
			break;
		case ADI_ETHER_CMD_UNPROCESSED_BUFFER_COUNTS:
			bufcnts = (ADI_ETHER_BUFFER_COUNTS *)(pArg);
			bufcnts->RcvrBufferCnt = dev->Rx.UnProcessed;
			bufcnts->XmitBufferCnt = dev->Tx.UnProcessed;
			break;
		case ADI_ETHER_CMD_GET_MIN_RECV_BUFSIZE:
			prefix = (u32 *)(pArg);
			*prefix = MAX_RCVE_FRAME;
			break;
		case ADI_ETHER_CMD_SET_SPEED:
			i = (int)(pArg);
			if ((i <= 0) || (i > 2)) {
				Result = ADI_DEV_RESULT_NOT_SUPPORTED;
			} else {
				dev->Port10 = (i == 1);
				dev->Negotiate = false;
			}
			break;
		case ADI_ETHER_CMD_SET_FULL_DUPLEX:
			i = (int)(pArg);
			dev->FullDuplex = (i!=0);
			dev->Negotiate = false;
			break;
		case ADI_ETHER_CMD_SET_NEGOTIATE:
			i = (int)(pArg);
			dev->Negotiate = (i!=0);
			break;
		case ADI_ETHER_CMD_START:
			Result = StartMac(dev);
			break;
		case ADI_ETHER_CMD_GET_PHY_REGS:
			GetPhyRegs(dev->PhyAddr,(void *)(pArg));
			break;
		case ADI_ETHER_CMD_SET_LOOPBACK:
			i = (int)(pArg);
			dev->Loopback = (i!=0);
			if (dev->Started) {
				// change the phy
				u16 cur;
				
				cur = RdPHYReg(dev->PhyAddr, PHYREG_MODECTL);
				if (dev->Loopback) {
					cur |= (1 << 14);	// enable TX->RX loopback
				} else {
					cur &= (~(1 << 14));
				}
				WrPHYReg(dev->PhyAddr, PHYREG_MODECTL,cur);
			}
			break;
		case ADI_ETHER_CMD_BUFFERS_IN_CACHE:
			i = (int)(pArg);
			dev->Cache = (i!=0);
			break;
			
		case ADI_ETHER_CMD_BF537_NO_RCVE_LNTH:
			i = (int)(pArg);
			dev->NoRcveLnth = (i!=0);
			break;
		case ADI_ETHER_CMD_BF537_STRIP_PAD:
			i = (int)(pArg);
			dev->StripPads = (i!=0);
			break;
		case ADI_ETHER_CMD_BF537_CLKIN:
			i = (int)(pArg);
			dev->CLKIN = i;
			break;
		case ADI_ETHER_CMD_BF537_USE_IVG:
			ivgs = (ADI_ETHER_IVG_MAPPING *)(pArg);
			dev->EtherIntIVG = ivgs->ErrIVG;
			dev->RXIVG = ivgs->RxIVG;
			dev->TXIVG = ivgs->TxIVG;
			break;
		case ADI_ETHER_CMD_BF537_USE_DMA:
			dmas = (ADI_ETHER_DMA_MAPPING *)(pArg);
			dev->Rx.Channel = dmas->RxChannel;
			dev->Tx.Channel = dmas->TxChannel;
			break;
		case ADI_ETHER_CMD_BF537_SET_PHY_ADDR:
			i = (int)(pArg);
			dev->PhyAddr = i &0xffff;
			break;
		case ADI_ETHER_CMD_GEN_CHKSUMS:
			dev->GenChksums = true;
			break;
		case ADI_ETHER_CMD_BF537_SET_TRACE:
			trcinfo = (ADI_ETHER_BF537_TRACE_INFO *)(pArg);
			dev->Trc.BaseEntry = (ADI_ETHER_BF537_TRACE_ENTRY *)trcinfo->Mem;
			dev->Trc.EntryLnth = (sizeof(ADI_ETHER_BF537_TRACE_ENTRY)+trcinfo->MaxBytes+3)&(~0x3); // round up to multiple of 4
			dev->Trc.NoOfEntries = trcinfo->LnthMem/dev->Trc.EntryLnth;
			if (dev->Trc.NoOfEntries <=0) {
				dev->Trc.BaseEntry = NULL;
				dev->MaxTraceEntries = 0;		
				Result = ADI_DEV_RESULT_NO_MEMORY;
			} else {
				dev->Trc.EndOfData = (ADI_ETHER_BF537_TRACE_ENTRY *)(((char *)dev->Trc.BaseEntry) + dev->Trc.EntryLnth*dev->Trc.NoOfEntries);
				dev->MaxTraceEntries = dev->Trc.NoOfEntries;				
				dev->Trc.OldestEntry = dev->Trc.BaseEntry;
				dev->Trc.NoOfEntries = 0;
				dev->TraceMaxBytes = dev->Trc.EntryLnth - sizeof(ADI_ETHER_BF537_TRACE_ENTRY);
				dev->TraceFirstByte = trcinfo->FirstByte;
			}
				
			break;
		case ADI_ETHER_CMD_BF537_GET_TRACE:
			memcpy(pArg,&dev->Trc,sizeof(ADI_ETHER_BF537_TRACE_DATA));
			break;
			
			
		case ADI_DEV_CMD_TABLE:
			break;
		
		default:
		
			// we don't understand this command
			Result = ADI_DEV_RESULT_NOT_SUPPORTED;
		
	}
		
	// return
	return(Result);
}


/*********************************************************************
*
*	Function:		InterruptHandler
*
*	Description:	Processes events in response to EMAC interrupts
*
*********************************************************************/
static void DmaError(FRAME_QUEUE *q)
{
	int k=10;
	
	k=q->Channel;
	k = q->Dma->IRQ_STATUS;
}
static ADI_INT_HANDLER(DmaErrorInterruptHandler)
{
	ADI_INT_HANDLER_RESULT result = ADI_INT_RESULT_NOT_PROCESSED;
	ADI_ETHER_BF537_DATA *dev = (ADI_ETHER_BF537_DATA *)ClientArg;
	BUFFER_INFO *bi;
	
	breakpoint(2);
	// check our two DMA channels
	if (dev->Tx.Dma->IRQ_STATUS & 0x02) {
		// error on TX channel
		bi = (BUFFER_INFO *)dev->Tx.Active;
		DmaError(&dev->Tx);
		result = ADI_INT_RESULT_PROCESSED;
	}
	if (dev->Rx.Dma->IRQ_STATUS & 0x02) {
		// error on RX channel
		bi = (BUFFER_INFO *)dev->Rx.Active;
		DmaError(&dev->Rx);
		result = ADI_INT_RESULT_PROCESSED;
	}
	return 	result;

}

//
//		EMAC ethernet event interrupt handler
//

static  ADI_INT_HANDLER(EtherInterruptHandler)			// EMAC ethernet event interrupt handler
{
	ADI_INT_HANDLER_RESULT result = ADI_INT_RESULT_NOT_PROCESSED;
	ADI_ETHER_BF537_DATA *dev = (ADI_ETHER_BF537_DATA *)ClientArg;
	u32 systat,mask, rirqs,tirqs,event;
	
	event = ADI_ETHER_EVENT_INTERRUPT;
	// Ethernet event interrupt
	systat = *pEMAC_SYSTAT;
	breakpoint(2);
	// ack W1C bits
	mask = systat&0xe1;
	if (mask) *pEMAC_SYSTAT = mask;
	// now to process individual bits
	if (systat&0x02) {
		// MMC counter interrupt
		rirqs = *pEMAC_MMC_RIRQS;
		tirqs = *pEMAC_MMC_TIRQS;
		UpdateStatistics((u64*)dev->Stats);
		// clear the interrupt
		*pEMAC_MMC_RIRQS = rirqs;
		*pEMAC_MMC_TIRQS = tirqs;
		result = ADI_INT_RESULT_PROCESSED;
	}
	if (systat&0x01) {
		//PHY_INT
		int full=0;
		u32 opmode;
		u16 reg3,reg2,reg,phydat;
		
		reg2 = RdPHYReg(dev->PhyAddr,2); // read PHY id 1
		reg3 = RdPHYReg(dev->PhyAddr,3); // read PHY id 2
		if ((reg2 == 0x07) && ((reg3>>4) == 0xc0a)) {
			// SMSC LAN83C185
			reg = RdPHYReg(dev->PhyAddr,31); // read special status
			full = (reg&0x10);
			if (full) {
				// does remote link support flow control
				phydat = RdPHYReg(dev->PhyAddr,PHYREG_ANLPAR);
				dev->FlowControl = (phydat &0x0400);
				if (dev->FlowControl) {
					// we enable flow control
					*pEMAC_FLC = FLCE;		/* flow control enabled */
				// advertize flow control supported
				}
			}
		}
		opmode = *pEMAC_OPMODE;
		if (full) {
			opmode |= 0x04000000;
		} else {
			opmode &= 0xfbffffff;
		}
		*pEMAC_OPMODE = opmode;
		
		systat = RdPHYReg(dev->PhyAddr,29); // read interrupt sources
		event = ADI_ETHER_EVENT_INTERRUPT_PHY;
		result = ADI_INT_RESULT_PROCESSED;
		
	}
	//invoke the callback function
	
	if (dev->DCBHandle) {
#ifdef ADI_ETHER_BF537_DEBUG		
		ADI_ETHER_BF537_OutstandingPosts++;
#endif
		adi_dcb_Post(dev->DCBHandle,0,dev->DMCallback, dev->DeviceHandle, event, (void *)systat);
	} else {
		(dev->DMCallback)(dev->DeviceHandle, event,(void *)systat);
	}
	
	return result;
}

//
//		Append Pending queue to the active queue
//
static AppendPending(FRAME_QUEUE *q, ADI_ETHER_BUFFER *lstact)
{
	BUFFER_INFO *bi,*bipend;
	
	
	CheckQueues(q);
	
	{
		ADI_ETHER_BUFFER *pnd = q->Active;
		while (pnd && pnd->pNext) {
			pnd = pnd->pNext;
		}
		if (lstact != pnd) {
			int k=4;
		}
	}
	
	// update the Active and Pending queues
	if (lstact == NULL) {
		if (q->Active != NULL) {
			int k=4;
		}
		CheckQueues(q);
		q->Active = q->Pending;
	} else {
		CheckQueues(q);
		lstact->pNext = q->Pending;
		// chain on the deswcriptors
		bi = (BUFFER_INFO*)lstact;
		bipend = (BUFFER_INFO*)q->Pending;
		bi->Last->NEXT_DESC_PTR = bipend->First;
		// update the config in the last desc
		if ((q->Rcve==0) && (q->Pending->PayLoad!=NULL)) {
			bi->Last->CONFIG &= 0xf0ff;		// remove the current ndsize
			bi->Last->CONFIG |= 0x7600;		// or in  flow as 7 and ndsize as 6
		} else {
			// the previous value will have been 8b
#ifdef 	USE_SYNC
			bi->Last->CONFIG |= 0x7520;		// or in  flow as 7 and ndsize as 5 as SYNC
#else		
			bi->Last->CONFIG |= 0x7500;		// or in  flow as 7 and ndsize as 5
#endif			
		}
	}
#ifdef ADI_ETHER_BF537_DEBUG	
	{
		ADI_ETHER_BUFFER *pnd = q->Pending;

⌨️ 快捷键说明

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