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

📄 nifce_driver.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 *   Description:
 *   Contains process packet functionality
 */
#include "lwip/debug.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#include "netif/etharp.h"

#include <kernel_abs.h>
#include <sys/exception.h>
#include <services/services.h>
#include <drivers/adi_dev.h>
#include <services/adi_dcb.h>
#include <services/adi_dma.h>
#include <services/adi_int.h>
#include <services/adi_ebiu.h>
#include "netif/nifce_driver.h"
#include  <ADI_ETHER.h>

// base of network interface identifiers
#define IFNAME0 'e'
#define IFNAME1 't'

// interface MTU size - max size of an ethernet frame 
#define MTU 1518
void eth_input(struct pbuf* p, struct netif* netif);
void process_rcvd_packets(void *nifce);
void process_xmtd_packets(void *nifce);

/* declared in pkthandler.c */
extern ADI_ETHER_BUFFER *rcv_list,*xmt_list;
/* Trace function */
int (*Trace_Function)( unsigned char EventId, unsigned short NoOfBytes, const unsigned char *Data)  = NULL;   

// Set trace function
void SetTraceFunction( int (*Trace_Event) ( unsigned char EventId, unsigned short NoOfBytes, const unsigned char *Data)) 
{
	Trace_Function = Trace_Event;
}


// Ethernet header as received from the wire
PACK_STRUCT_BEGIN
struct hw_eth_hdr
{
  PACK_STRUCT_FIELD(struct eth_addr dest);
  PACK_STRUCT_FIELD(struct eth_addr src);
  PACK_STRUCT_FIELD(u16_t type);
}
PACK_STRUCT_STRUCT;
PACK_STRUCT_END


/*##########################################################################
*
* This function should be called regularly to service the lists of receive
* buffers that the hardware might have filled and transmit buffers that it
* may have emptied since the last call. 
* This function is registered as tcp callback routine. see pkthandler.c
* currently the callback routines is called periodically and the period is
* configurable by the user.
*
*#########################################################################*/
void nifce_driver_poll(void* arg)
{
	// lazy to check in critical region if it fails first time gets nextime
	if(xmt_list) 
		process_xmtd_packets(arg); // TODO: directly process it in callback
	if(rcv_list)
	process_rcvd_packets(arg); // TODO: Check to process in callback
}
/*##########################################################################
 * 
 * processes the transmitted packets by releasing the memory
 *
 *#########################################################################*/
void process_xmtd_packets(void *arg_nif)
{
  struct netif* netif = (struct netif*)arg_nif;
  struct nifce_info* nip = (struct nifce_info*)netif->state;
  unsigned int *mangle_ptr;
  void *handle = nip->handle;
  int int_sts;

  ADI_ETHER_BUFFER* buffers_to_reuse;
  ADI_ETHER_BUFFER* buffers_to_process;
  ADI_ETHER_BUFFER* recycle_list = 0;
  ADI_ETHER_BUFFER* bp;
  ADI_ETHER_BUFFER* nbp;
  ADI_ETHER_BUFFER* lbp;

  int_sts = ker_disable_interrupts(ker_kPriorityLevelAll);
  buffers_to_reuse = xmt_list;
  xmt_list = NULL;
  ker_enable_interrupts(int_sts);

  // add transmitted buffers to the available list after resetting length
  lbp = bp = buffers_to_reuse;
  while (bp != 0)
  {
	  // this is a hack to use the num_rows and num_rows for the
	  // purpose of storing the buffer_info address. 
	  // TODO: getrid of using reserved area
	  //
	mangle_ptr = ((unsigned int*)&bp->Reserved)+4;
    bp->ElementCount = ((struct buffer_info*)((*(unsigned int*)mangle_ptr)))->max_buf_len;
    bp->CallbackParameter =bp;
	bp->StatusWord = 0;
	bp->PayLoad =0;
	bp->ProcessedElementCount=0;
	bp->ProcessedFlag =0;
    lbp = bp;
    bp = bp->pNext;
  } //while

  bp = buffers_to_reuse;
  if (bp) 
  {
    u32_t old_level;

    old_level = sys_arch_protect();
    lbp->pNext = nip->x;
    nip->x = bp;
    sys_arch_unprotect(old_level);
  }
}
void process_rcvd_packets(void *arg_nif)
{
  struct netif* netif = (struct netif*)arg_nif;
  struct nifce_info* nip = (struct nifce_info*)netif->state;
  unsigned int *mangle_ptr;
  void *handle = nip->handle;
  int int_sts;

  ADI_ETHER_BUFFER* buffers_to_reuse;
  ADI_ETHER_BUFFER* buffers_to_process;
  ADI_ETHER_BUFFER* recycle_list = 0;
  ADI_ETHER_BUFFER* bp;
  ADI_ETHER_BUFFER* nbp;
  ADI_ETHER_BUFFER* lbp;

  // now check for received buffers
  int_sts = ker_disable_interrupts(ker_kPriorityLevelAll);
  buffers_to_process = rcv_list;
  rcv_list = NULL;
  ker_enable_interrupts(int_sts);	


  // create a pbuf for each received buffer and call eth_input to process it
  bp = buffers_to_process;
  while (bp != 0) 
  {
    struct hw_eth_hdr* ethhdr = (struct hw_eth_hdr*)((char*)bp->Data+2);

    u16_t length = bp->ProcessedElementCount - 6; // 2 + 4crc byte to store length
    struct pbuf* p;
    int unpack_arp = 0;

    nbp = bp->pNext;
    bp->pNext = 0;
    // (char*)bp->Data + 2 contrain the actual data.
    if (Trace_Function) Trace_Function('R',length,((unsigned char *)bp->Data+2));
    
    // see whether we need two extra u16_t fields for alignment
    if (length >= (sizeof(struct etharp_hdr) - 6) &&
            htons(ethhdr->type) == ETHTYPE_ARP) {
      length += 4; // need fields unused2 and unused3 in struct etharp_hdr
      unpack_arp = 1;
    }
    length += 2;// for field unused1 in struct eth_hdr
	
    p = pbuf_alloc(PBUF_RAW, length, PBUF_RAM);

    if (p != NULL) 
	{
      //u8_t* psrc = (u8_t*)bp->Data;
      u8_t* psrc = (u8_t*)bp->Data+2;
      u8_t* pdst = (u8_t*)p->payload;

      // set field unused1 to 0
      *(u16_t*)pdst = 0;
      pdst += 2;

      // copy in eth_hdr data
      memcpy(pdst, psrc, 14);
      pdst += 14;
      psrc += 14;

		if (unpack_arp) 
		{
			// copy etharp frame into pbuf up to field unused2
			memcpy(pdst, psrc, 14);
			pdst += 14;
			psrc += 14;
			// set field unused2 to 0
			*(u16_t*)pdst = 0;
			pdst += 2;
			// copy more of frame up to field unused3
			memcpy(pdst, psrc, 10);
			pdst += 10;
			psrc += 10;
			// set field unused3 to 0
			*(u16_t*)pdst = 0;
			pdst += 2;
			// copy remainder of frame
			memcpy(pdst, psrc, 4);
		} else 
		{
			  // just copy the rest of the frame into the pbuf in one go
		  	 memcpy(pdst, psrc, length - 16);
		}
#ifdef LINK_STATS
      lwip_stats.link.recv++;
#endif

		mangle_ptr = ((unsigned int*)&bp->Reserved)+4; // TODO: get-rid of Reserved.
      eth_input(p, ((struct buffer_info*)(*((unsigned int*)mangle_ptr)))->netif);
    } // p!=NULL 
	else 
	{
#ifdef LINK_STATS
      lwip_stats.link.memerr++;  // had to drop frame - no memory for pbuf
#endif

    }
	mangle_ptr = ((unsigned int*)&bp->Reserved)+4;
    bp->ElementCount = ((struct buffer_info*)(*((unsigned int*)mangle_ptr)))->max_buf_len;
	bp->CallbackParameter = bp;
	bp->PayLoad =0;
	bp->StatusWord =0;
	bp->ProcessedElementCount=0;
	bp->ProcessedFlag =0;
    bp->pNext = recycle_list;
    recycle_list = bp;

    bp = nbp;
  } // while

  // return the buffers to the driver

  if (recycle_list != 0)
	  adi_dev_Read(nip->handle,ADI_DEV_1D,(ADI_DEV_BUFFER*)recycle_list);

}



/*##########################################################################
* 
* Output pbuf chain to hardware. It is assumed that there is a complete and
* correct ethernet frame in p. The only buffering in this system is in the
* list of tx ADI_ETHER_BUFFER's. If there is no room in it, then drop the frame.
*
*#########################################################################*/
static err_t
low_level_output(struct netif* netif, struct pbuf* p)
{
  struct nifce_info* nip = (struct nifce_info*)netif->state;
  ADI_ETHER_BUFFER* tx;
  struct pbuf *q;
  char* data;
  unsigned short *ps;
  struct hw_eth_hdr* ethhdr;
  u32_t old_level;
  int len;

  if (p->tot_len > nip->tx_buff_datalen)
  {
    // frame too big for our buffers
#ifdef LINK_STATS
    lwip_stats.link.memerr++;
#endif
    return ERR_MEM;

⌨️ 快捷键说明

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