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

📄 adi_ether_bf537.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
📖 第 1 页 / 共 4 页
字号:
		while (pnd) {
			pnd->usage = Active;
			pnd = pnd->pNext;
		}
	}
#endif
	q->Pending = NULL;
	
	CheckQueues(q);
}
//
//		Queue Frames
//		this function assumes that it is running within a critical region
//


static void QueueFrames(ADI_ETHER_BF537_DATA *dev, FRAME_QUEUE *q)
{
	ADI_ETHER_BUFFER *lstpnd = q->Pending, *buf,*lstact,*nonact;
	int no_needed;
	BUFFER_INFO *bi,*bipend;
	DMA_DESCRIPTOR *dmr,*lstdmr,*remdmr;
	bool append=false;
	int NoActive=0;
	int i;
	ADI_ETHER_BUFFER  *iQ = q->Queued, *iQN=NULL, *iP= q->Pending,*iA = q->Active;
	int iNoa = q->NoAvail;
	int ists;
	STATUS_AREA *sts;

	
	CheckQueues(q);
	

	// find the end of the pendinq queue
	if (lstpnd) {
		while (lstpnd->pNext != NULL) lstpnd = lstpnd->pNext;
	}
	
	// step through the queued allocating descriptors and appending then to the pending queue
	buf = q->Queued;
	while (buf!=NULL) {
		no_needed = 2;
		if ((q->Rcve == 0) && (buf->PayLoad != NULL)) {
			no_needed = 3;
		} 
		if ((no_needed > q->NoAvail) || (q->AvailStatus==NULL)) {
			break;
		}
		
		if (((unsigned int)q->Avail)&3) {
			int k=1;//##avail
		}
		
		dmr = q->Avail;
		
		// update the CONFIG for the last descriptor to make it flow
		if (lstpnd!=NULL) {
			bi = (BUFFER_INFO *)lstpnd;
			bi->Last->NEXT_DESC_PTR = dmr;
			if (no_needed == 3) {
				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			
			}
		}

		// layout the descriptors for the buffer
		bi = (BUFFER_INFO *)buf;
		bi->NoDesc = no_needed;
		
		// set up the staus word area
		bi->Status = sts = q->AvailStatus;
		*((long long *)sts) = 0;
		q->AvailStatus = sts->Next;
		
		bi->First = dmr;
		// dmr NEXT_DESC_PTR is already set
		dmr->START_ADDR = (unsigned long)buf->Data;
		dmr->X_COUNT = (no_needed==3?(buf->ElementCount*buf->ElementWidth+3)>>2:0);
		if (q->Rcve == 0) {
			// we need to set the length half word
			unsigned short *lnth = (unsigned short *)buf->Data;			
			buf->ProcessedElementCount = (*lnth +2+buf->ElementWidth-1)/buf->ElementWidth;
			if (no_needed == 3) {
				// we need to get X_COUNT set to zero by next descriptor
#ifdef 	USE_SYNC
				dmr->CONFIG = 0x7629;		// flow=7,ndsize=6,wdsize=4,enable, mem read, use sync
#else				
				dmr->CONFIG = 0x7609;		// flow=7,ndsize=6,wdsize=4,enable, mem read
#endif			
			} else {
#ifdef 	USE_SYNC
				dmr->CONFIG = 0x7529;		// flow=7,ndsize=5,wdsize=4,enable, mem read, use sync
#else				
				dmr->CONFIG = 0x7509;		// flow=7,ndsize=5,wdsize=4,enable, mem read
#endif			
			}

		} else {
#ifdef 	USE_SYNC
			dmr->CONFIG = 0x752b;		// flow=7,ndsize=5,wdsize=4,enable, mem write, use sync	
#else				
			dmr->CONFIG = 0x750b;		// flow=7,ndsize=5,wdsize=4,enable, mem write	
#endif			
		}
		FlushArea(&dmr,((char *)&dmr)+18);
		dmr = dmr->NEXT_DESC_PTR;
		if (no_needed == 3)	{
			// set up payload descriptor
			dmr->START_ADDR = (unsigned long)buf->PayLoad;
#ifdef USE_SYNC
			dmr->CONFIG = 0x7529;		// flow=7,ndsize=5,wdsize=4,enable, mem read, use sync
#else
			dmr->CONFIG = 0x7509;		// flow=7,ndsize=5,wdsize=4,enable, mem read
#endif				
			dmr->X_COUNT = 0;
			FlushArea(&dmr,((char *)&dmr)+18);
			dmr = dmr->NEXT_DESC_PTR;
		}
		if (dev->Cache) {
			char *data = (char *)buf->Data;
			
			if (q->Rcve==0) {
				// we need to flush the buffer
				unsigned short lnth = *((unsigned short *)data);
				if (no_needed == 3) {
					// two data buffers
					int no_bytes = buf->ElementCount*buf->ElementWidth;
					FlushArea(data,data+no_bytes);
					FlushArea(buf->PayLoad,((char *)buf->PayLoad)+lnth-no_bytes);				
				} else {
					FlushArea(data,data+2+lnth);
				}
			} else {
				// we need to invalidate the cache lines
				FlushInvArea(data,data+MAX_RCVE_FRAME);
			}
		}
		// now set the descriptor for the status word
#if 1
		dmr->START_ADDR = ((q->Rcve!=0) && (dev->GenChksums!=0)?(unsigned long)&sts->IPHdrChksum:(unsigned long)&sts->StatusWord);
#else		
		dmr->START_ADDR = ((q->Rcve!=0) && (dev->GenChksums!=0)?(unsigned long)&buf->IPHdrChksum:(unsigned long)&buf->StatusWord);
#endif		
		// we also need to invalidate the status word space
		SIMPLEFLUSHINV(sts);	// flush and invalidate the staus owrr
		// status word is always written
#ifdef USE_SYNC		
		dmr->CONFIG = 0x00AB;		// flow=0,ndsize=0,wdsize=4,int enable, ensable, mem write, use sync
#else
		dmr->CONFIG = 0x008B;		// flow=0,ndsize=0,wdsize=4,int enable, ensable, mem write
#endif		
		bi->Last = dmr;
		remdmr = dmr->NEXT_DESC_PTR;
		// terminate the list of dmr's
		dmr->NEXT_DESC_PTR = 0;
		FlushArea(&dmr,((char *)&dmr)+18);
		
		if (lstpnd == NULL) {
			// form the pending queue
			q->Pending = buf;
		} else {
			lstpnd->pNext = buf;
		}
		// update last pending buffer
		lstpnd = buf;
#ifdef ADI_ETHER_BF537_DEBUG	
		buf->usage = Pending;
#endif
		// step buf onto the next buffer if any in the queued queue
		buf = buf->pNext;
		// now terminate the pending queue
		lstpnd->pNext = NULL;
		
		q->NoAvail -= no_needed;
		q->Avail = remdmr;
		if (((unsigned int)q->Avail)&3) {
			int k=1; //##avail
		}
		
		//## this only needed to allow CheckQueues to be invoked
		q->Queued = buf;	// remove frames from Queued list		
		CheckQueues(q);
		//##
		
	}
	
	q->Queued = buf;	// remove frames from Queued list
	
	CheckQueues(q);

	// check to see if there is anything in the pending queue
	if (q->Pending) {
		
		append = false;
		
		// check to see if we have at least two uncompleted entries in active queue
		NoActive = 0;
		lstact = NULL;
		buf = q->Active;
		lstact = buf;
		while (buf != NULL) {
			lstact = buf;
			bi = (BUFFER_INFO *)buf->Reserved;
			sts = bi->Status;
			SIMPLEFLUSHINV(sts);	// flush and invalidate the status word
			
			if ((sts->StatusWord&q->CompletedStatus)==0) {
				NoActive++;
			}
			buf = buf->pNext;
		}
		CheckQueues(q);
		if ((NoActive>=2) || (q->EnableMac!=0))	 {	
			// if two non completed frames or DMA not yet started
			CheckQueues(q);
			AppendPending(q,lstact);
			CheckQueues(q);
		}
		CheckQueues(q);
		// check to see if the DMA is running
		if (q->Dma == NULL) {
			q->Dma = (DMA_REGISTERS *)(DMA0_NEXT_DESC_PTR+0x40*q->Channel);
			//q->Dma->CONFIG = 0;
			q->Dma->X_COUNT = 0;
			q->Dma->X_MODIFY = 4;

			
		}
		
		iP = q->Pending; iA = q->Active;
		ists = (q->Dma != NULL?q->Dma->IRQ_STATUS: -1);
		
		if ((q->Dma != NULL) && ((q->Dma->IRQ_STATUS &0x8) == 0)) {
			// DMA assigned but not running 
			// anything in the pending queue
			if (q->Pending) {
				AppendPending(q,lstact);
			}
			// start the DMA if anything in the active queue
			nonact = q->Active;
			while (nonact!=NULL) {
				bi = (BUFFER_INFO *)nonact->Reserved;
				sts = bi->Status;
				SIMPLEFLUSHINV(sts);	// flush and invalidate the status word
				
				if ((sts->StatusWord&q->CompletedStatus)!=0) {
					nonact = nonact->pNext;
				} else {
					break;
				}
			}
			if (nonact) {
				if (q->Rcve==0) {
					NoTxStarts++;
				} else {
					NoRxStarts++;
				}
				// we need to trigger the DMA
				bi = (BUFFER_INFO *)nonact;
				q->Enabled = true;
				q->Dma->NEXT_DESC_PTR = bi->First;
				q->Dma->CONFIG = bi->First->CONFIG;	
				
				// now the DMA is running, we can enable the MAC
				if (q->EnableMac!=0) {
					u32 opmode = *pEMAC_OPMODE|q->EnableMac;
					*pEMAC_OPMODE = opmode;
					q->EnableMac = 0;
				}
			}
		} else {
			if (q->Rcve==0) {
				int sts = q->Dma->IRQ_STATUS;
				int k=2;
			}
			
		}
	}
	
	CheckQueues(q);
	
}

//
//		Process DMA completion
//

static ADI_INT_HANDLER_RESULT ProcessCompletion(ADI_ETHER_BF537_DATA *dev, FRAME_QUEUE *q)
{
	ADI_INT_HANDLER_RESULT result = ADI_INT_RESULT_NOT_PROCESSED;
	ADI_ETHER_BUFFER *act,*lst,*fst;
	BUFFER_INFO *bi;
	int noposted=0;
	STATUS_AREA *sts;

	
	void *xit = EnterCriticalRegion(NULL);
	breakpoint(2);
	
	CheckQueues(q);

	if (q->Dma->IRQ_STATUS&0x01) {
		// interrupt asserted
		result = ADI_INT_RESULT_PROCESSED;
		// acknowedge the interrupt
		q->Dma->IRQ_STATUS = 0x01;
		if (q->Rcve) {
			NoRxInts++;
		} else {
			NoTxInts++;
}
		
	}
	// check to see if any frames have completed
	fst = act = q->Active;
	lst = NULL;	
	while (act!=NULL) {
		bi = (BUFFER_INFO *)act->Reserved;
		sts = bi->Status;
		SIMPLEFLUSHINV(sts);	// flush and invalidate the status word
		
		if ((sts->StatusWord&q->CompletedStatus)==0) break;
		noposted++;
		
		*((long long *)&act->IPHdrChksum) = *((long long *)sts);
		// we can add the used descriptors to the Avail queue
		q->NoAvail += bi->NoDesc;
		bi->Last->NEXT_DESC_PTR = q->Avail;		
		q->Avail = bi->First;
		if (((unsigned int)q->Avail)&3) {
			int k=1;//##avail
		}
		// return the status area
		sts->Next = q->AvailStatus;
		q->AvailStatus = sts;
		
#ifdef ADI_ETHER_BF537_DEBUG	
		act->usage = Completed;
#endif
		act->ProcessedFlag = TRUE;
		// we need to set the processed element count for a received frame
		// in the case of a transmit it is set up before transmission
		if (q->Rcve) {
			int nobytes = act->StatusWord&0x7ff;
			if (!dev->NoRcveLnth) {
				ADI_ETHER_FRAME_BUFFER *frm = act->Data;
				frm->NoBytes = nobytes;
				act->ProcessedElementCount = (nobytes+2+3)/act->ElementWidth;
			} else {
				act->ProcessedElementCount = (nobytes+3)/act->ElementWidth;
			}
		}  
		
		if (dev->MaxTraceEntries>0) {
			// we need to trace the frame if it is OK
			ADI_ETHER_BF537_TRACE_ENTRY *te = dev->Trc.OldestEntry;
			
			if (q->Rcve) {
				// received
				if ((act->StatusWord&0x3000) == 0x3000) {
					// valid frame received
					int nobytes = act->StatusWord&0x7ff-dev->TraceFirstByte;
					if (nobytes>0) {
						if (nobytes>dev->TraceMaxBytes) nobytes = dev->TraceMaxBytes;
						te->NoBytes = nobytes;
						te->Dirn = 'R';
						te->Seqn = (u8)(dev->TraceSequence++);
						memcpy(te->Data,((char *)act->Data)+(dev->NoRcveLnth?0:2)+dev->TraceFirstByte,nobytes);
						te = (ADI_ETHER_BF537_TRACE_ENTRY *)(((char *)te) + dev->Trc.EntryLnth);
						if (dev->Trc.NoOfEntries<dev->MaxTraceEntries) {
							dev->Trc.NoOfEntries++;
						} else {
							if (te>=dev->Trc.EndOfData) {
								te = dev->Trc.BaseEntry;
							}
						}
						dev->Trc.OldestEntry = te;
					}
				}
			} else {
				// transmitted
				if ((act->StatusWord&0x3) == 0x3) {
					// valid frame trasmitted
					int nobytes = (act->StatusWord>>16)&0x7ff-dev->TraceFirstByte;
					if (nobytes>0) {
						if (nobytes>dev->TraceMaxBytes) nobytes = dev->TraceMaxBytes;
						te->NoBytes = nobytes;
						te->Dirn = 'T';
						te->Seqn = (u8)(dev->TraceSequence++);
						if (act->PayLoad!=NULL) {
							int first = act->ElementCount*act->ElementWidth;
							int pa = first - 2 - dev->TraceFirstByte;
							
							if (nobytes<= pa) {
								memcpy(te->Data,((char *)act->Data)+2+dev->TraceFirstByte,nobytes);
							} else {
								u8 *nxt = te->Data;
								if (pa>0) {
									memcpy(nxt,((char *)act->Data)+2+dev->TraceFirstByte,pa);
									nobytes -= pa;
									nxt += pa;
								}
								memcpy(nxt,((u8 *)act->PayLoad)-pa,nobytes);
							}
						} else {
							memcpy(te->Data,((char *)act->Data)+2+dev->TraceFirstByte,nobytes);
						}
						te = (ADI_ETHER_BF537_TRACE_ENTRY *)(((char *)te) + dev->Trc.EntryLnth);
						if (dev->Trc.NoOfEntries<dev->MaxTraceEntries) {
							dev->Trc.NoOfEntries++;
						} else {
							if (te>=dev->Trc.EndOfData) {
								te = dev->Trc.BaseEntry;
							}
						}
						dev->Trc.OldestEntry = te;
					}
				} else {
					TxErr++;
				}
				
			}
		}
		// step onto the next active element
		q->NoCompletions++;
		if ((q->NoCompletions%100000) == 0) {
			int a;
			a=1;
		}
		lst = act;
		act = act->pNext;
	}
	
	// fst points to first active buffer
	// lst if non NULL points to last completed buffer
	// act points to the new head of the Active list
	if (lst!=NULL) {
		u32 event = (q->Rcve?ADI_ETHER_EVENT_FRAME_RCVD:ADI_ETHER_EVENT_FRAME_XMIT);
		
		// at least one buffer has completed
		q->UnProcessed -= noposted;
		// detach the completed frames
		q->Active = act;
		
		// append the completed buffers to the Completed queue
		lst->pNext = NULL;
		if (q->Completed!=NULL) {
			lst = q->Completed;
			while (lst->pNext != NULL) {
				noposted++;
				lst = lst->pNext;
			}
			lst->pNext = fst;
		} else {
			q->Completed = fst;
		}
		
		// can we add any queued frames to the pending list and then to the active list
		QueueFrames(dev,q);
		if (q->Rcve && (q->Active == NULL) && (dev->FlowControl)) {
			// the control to send pause frame
			if ((*pEMAC_FLC & FLCBUSY) == 0) {
				// if we're not currently sending a previous PAUSE Frame...
				// send a PAUSE Frame for (almost) two max-length frame times
				*pEMAC_FLC = SET_FLCPAUSE(48) | FLCBUSY | (dev->FlowControl?FLCE:0);
			}
		}
		
		// q->Completed must be non-null
		act = q->Completed;
		q->Completed = NULL;
#ifdef ADI_ETHER_BF537_DEBUG	
		{
			ADI_ETHER_BUFFER *pst = act;
			noposted = 0;
			while (pst != NULL) {
				noposted++;
				pst->usage = Posted;
				pst = pst->pNext; 
			}
		}
#endif	

		// finally invoke the user call back
		if (dev->DMCallback!= NULL) {
			int res;

			
			if (dev->DCBHandle) {
#ifdef ADI_ETHER_BF537_DEBUG	
				ADI_ETHER_BF537_PostedBuffer = act->CallbackParameter;
				ADI_ETHER_BF537_OutstandingPosts++;
#endif				
				
				if (ADI_DEV_RESULT_SUCCESS!=(res=adi_dcb_Post(dev->DCBHandle,0,dev->DMCallback, dev->DeviceHandle, event, act->CallbackParameter))) {
#ifdef ADI_ETHER_BF537_DEBUG
					ADI_ETHER_BF537_OutstandingPosts--;	
					{
						ADI_ETHER_BUFFER *pst = act;
						while (pst != NULL) {
							pst->usage = Completed;
							pst = pst->pNext; 
						}
					}
#endif				
					q->Completed = act;
					FailedPosts++;
				} else {
#ifdef ADI_ETHER_BF537_DEBUG	
					ADI_ETHER_BF537_NoPosted += noposted;
#endif						
					if (q->Rcve) {
						NoRxPosts++;
					} else {
						NoTxPosts++;
					}
				}
			} else {
				ExitCriticalRegion(xit);
				(dev->DMCallback)(dev->DeviceHandle, event,act->CallbackParameter);
				xit = EnterCriticalRegion(NULL);
			}
		}
	} else {
		QueueFrames(dev,q);
	}
	
	CheckQueues(q);
	ExitCriticalRegion(xit);
	
	
	return result;
}



//
//		EMAC RX complete event interrupt handler
//

static ADI_INT_HANDLER(RxInterruptHandler)			// RX complete interrupt handler
{
	ADI_INT_HANDLER_RESULT result,result1;
	ADI_ETHER_BF537_DATA *dev =  (ADI_ETHER_BF537_DATA *)ClientArg;
	
	result = ProcessCompletion(dev,&dev->Rx);
	
	return result;
}



//
//		EMAC TX complete event interrupt handler
//

static ADI_INT_HANDLER(TxInterruptHandler)			// TX complete interrupt handler
{
	ADI_INT_HANDLER_RESULT result;
	ADI_ETHER_BF537_DATA *dev =  (ADI_ETHER_BF537_DATA *)ClientArg;
	
	result = ProcessCompletion(dev,&dev->Tx);
	return result;
}



#if defined(ADI_ETHER_DEBUG)

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

	Function:		ValidatePDDHandle

	Description:	Validates a PDD handle

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

static int ValidatePDDHandle(ADI_DEV_PDD_HANDLE PDDHandle) {
	if (PDDHandle == (ADI_DEV_PDD_HANDLE)&dev) {
		if (EtherDev.Open) {
			return (ADI_DEV_RESULT_SUCCESS);
		}
	}
	return (ADI_DEV_RESULT_BAD_PDD_HANDLE);
}


#endif


⌨️ 快捷键说明

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