xemacif.c

来自「Keil下移植好的lwip基于c166」· C语言 代码 · 共 512 行 · 第 1/2 页

C
512
字号
}
#endif /* LWIP_XEMAC_USE_INTMODE */

/*---------------------------------------------------------------------------*/
/* low_level_output()                                                        */
/*                                                                           */
/* Should do the actual transmission of the packet. The packet is            */
/* contained in the pbuf that is passed to the function. This pbuf           */
/* might be chained.                                                         */
/*---------------------------------------------------------------------------*/
static err_t low_level_output(struct xemacif *xemacif_ptr, struct pbuf *p)
{
   struct pbuf *q;
   u32_t frame_buffer[XEM_MAX_FRAME_SIZE_IN_WORDS];  /* word aligned */
   Xuint8 *frame_ptr;
   int payload_size = 0, i;
   XStatus Result;

   frame_ptr = (Xuint8 *) frame_buffer;

   for(q = p; q != NULL; q = q->next) {
      /*
       * Send the data from the pbuf to the interface, one pbuf at a
       * time. The size of the data in each pbuf is kept in the ->len
       * variable.
       */
      for(i = 0 ; i < q->len ; i++) {
         *(frame_ptr++) = (Xuint8) *(((u8_t *) q->payload) + i);
         payload_size++;
      }
   }

#ifdef LWIP_XEMAC_USE_INTMODE

   Result = XEmac_FifoSend(xemacif_ptr->instance_ptr, 
                           (Xuint8 *) frame_buffer,
                           payload_size);

#else /* LWIP_XEMAC_USE_INTMODE */

   Result = XEmac_PollSend(xemacif_ptr->instance_ptr, 
                           (Xuint8 *) frame_buffer,
                           payload_size);

#endif /* LWIP_XEMAC_USE_INTMODE */

   if (Result != XST_SUCCESS) return ERR_MEM;      

#ifdef LINK_STATS
   lwip_stats.link.xmit++;
#endif /* LINK_STATS */

   return ERR_OK;
}

/*---------------------------------------------------------------------------*/
/* low_level_input()                                                         */
/*                                                                           */
/* Allocates a pbuf pool and transfers bytes of                              */
/* incoming packet from the interface into the pbuf.                         */
/*---------------------------------------------------------------------------*/
static struct pbuf * low_level_input(struct xemacif *xemacif_ptr)
{
   struct pbuf *p = NULL, *q = NULL;
   XEmac *EmacPtr = (XEmac *) xemacif_ptr->instance_ptr;
   
   Xuint32 RecvBuffer[XEM_MAX_FRAME_SIZE_IN_WORDS];
   Xuint32 FrameLen = XEM_MAX_FRAME_SIZE;
   Xuint32 i;
   u8_t * frame_bytes = (u8_t *) RecvBuffer;
   XStatus Result;

#ifdef CHRIS_DEBUG
   char ascii[2];
#endif /* CHRIS_DEBUG */

#ifdef LWIP_XEMAC_USE_INTMODE
   Result = XEmac_FifoRecv(EmacPtr, (Xuint8 *)RecvBuffer, &FrameLen);
#else
   Result = XEmac_PollRecv(EmacPtr, (Xuint8 *)RecvBuffer, &FrameLen);
#endif /* LWIP_XEMAC_USE_INTMODE */

   if (Result != XST_SUCCESS)
      return p;

#if 0
   printf("\r\n");
   for (i=0 ; i < FrameLen ; i++) {
      printf("%4X", frame_bytes[i]);
      if (! (i%20) && i) printf("\r\n");
      else printf(" ");
   }
   printf ("\r\n");
#endif

   /* Allocate a pbuf chain of pbufs from the pool. */
   p = pbuf_alloc(PBUF_LINK, FrameLen, PBUF_POOL);

   if(p != NULL) {
   /* Iterate over the pbuf chain until we have
    * read the entire packet into the pbuf. */
      for(q = p; q != NULL; q = q->next) {
         /* Read enough bytes to fill this pbuf 
          * in the chain.  The available data in 
          * the pbuf is given by the q->len variable. */
         for (i = 0 ; i < q->len ; i++) {
            ((u8_t *)q->payload)[i] = *(frame_bytes++);
         }
      }

#ifdef LINK_STATS
      lwip_stats.link.recv++;
#endif /* LINK_STATS */      

   } else {

#ifdef LINK_STATS
      lwip_stats.link.memerr++;
      lwip_stats.link.drop++;
#endif /* LINK_STATS */ 
      ;
   }
   return p;  
}

/*---------------------------------------------------------------------------*/
/* xemacif_output():                                                         */
/*                                                                           */
/* This function is called by the TCP/IP stack when an IP packet             */
/* should be sent. It calls the function called low_level_output() to        */
/* do the actuall transmission of the packet.                                */
/*---------------------------------------------------------------------------*/
static err_t xemacif_output(struct netif *netif_ptr,
                            struct pbuf *p,
                            struct ip_addr *ipaddr)
{
   struct xemacif *xemacif_ptr = xemacif_ptr = netif_ptr->state;

   p = etharp_output(netif_ptr, ipaddr, p);
   if (p != NULL)
      return low_level_output(xemacif_ptr, p);
   return ERR_OK;
}

/*---------------------------------------------------------------------------*/
/* xemacif_input():                                                          */
/*                                                                           */
/* This function should be called when a packet is ready to be read          */
/* from the interface. It uses the function low_level_input() that           */
/* should handle the actual reception of bytes from the network              */
/* interface.                                                                */
/*---------------------------------------------------------------------------*/
void xemacif_input(void *CallBackRef)
{
   struct netif * netif_ptr = (struct netif *) CallBackRef;
   struct xemacif * xemacif_ptr;
   struct eth_hdr * ethernet_header;
   struct pbuf *p, *q;

#ifdef LWIP_XEMAC_USE_INTMODE
   /* Disable Interrupts */
   XIntc_Disable(XIntc_GetInstance(0), XPAR_INTC_0_DEVICE_ID);
#endif /* LWIP_XEMAC_USE_INTMODE */

   xemacif_ptr = netif_ptr->state;

   p = low_level_input(xemacif_ptr);

   if(p != NULL) {
      ethernet_header = p->payload;

      q = NULL;
      switch(htons(ethernet_header->type)) {
      case ETHTYPE_IP:
         q = etharp_ip_input(netif_ptr, p);
         pbuf_header(p, -14);
         netif_ptr->input(p, netif_ptr);
         break;
      case ETHTYPE_ARP:
         q = etharp_arp_input(netif_ptr, xemacif_ptr->ethaddr, p);
         break;
      default:
         pbuf_free(p);
         break;
      }

      if(q != NULL) {
         low_level_output(xemacif_ptr, q);
         pbuf_free(q);
      }
   }

#ifdef LWIP_XEMAC_USE_INTMODE
   /* Enable Interrupts again */
   XIntc_Enable(XIntc_GetInstance(0), XPAR_INTC_0_DEVICE_ID);
#endif /* LWIP_XEMAC_USE_INTMODE */
}

/*---------------------------------------------------------------------------*/
/* xemacif_setmac():                                                         */
/*                                                                           */
/* Sets the MAC address of the system.                                       */
/* Note:  Can only be called before xemacif_init is called.                  */
/*---------------------------------------------------------------------------*/
void xemacif_setmac(u8_t *addr)
{
   mymac.addr[0] = addr[0];
   mymac.addr[1] = addr[1];
   mymac.addr[2] = addr[2];
   mymac.addr[3] = addr[3];
   mymac.addr[4] = addr[4];
   mymac.addr[5] = addr[5];
}

/*---------------------------------------------------------------------------*/
/* xemacif_getmac():                                                         */
/*                                                                           */
/* Returns a pointer to the mymac variable (6 bytes in length)               */
/*---------------------------------------------------------------------------*/
u8_t * xemacif_getmac(void) { return &(mymac.addr[0]); }

/*---------------------------------------------------------------------------*/
/* xemacif_init():                                                           */
/*                                                                           */
/* Should be called at the beginning of the program to set up the            */
/* network interface. It calls the function low_level_init() to do the       */
/* actual setup of the hardware.                                             */
/*---------------------------------------------------------------------------*/
void xemacif_init(struct netif *netif_ptr)
{
   struct xemacif *xemacif_ptr;

   xemacif_ptr = mem_malloc(sizeof(struct xemacif));

   netif_ptr->state = xemacif_ptr;
   netif_ptr->hwaddr[0] = mymac.addr[0];
   netif_ptr->hwaddr[1] = mymac.addr[1];
   netif_ptr->hwaddr[2] = mymac.addr[2];
   netif_ptr->hwaddr[3] = mymac.addr[3];
   netif_ptr->hwaddr[4] = mymac.addr[4];
   netif_ptr->hwaddr[5] = mymac.addr[5];
   netif_ptr->name[0] = IFNAME0;
   netif_ptr->name[1] = IFNAME1;
   netif_ptr->output = xemacif_output;
   netif_ptr->linkoutput = NULL;

   /* Copy pointer to netif_ptr->hwaddr into the xemacif_ptr->ethaddr */
   xemacif_ptr->ethaddr = (struct eth_addr *)&(netif_ptr->hwaddr[0]);

   /* Set EXmac instance pointer to NULL. It gets set in low_level_init() */
   xemacif_ptr->instance_ptr = NULL;
   
   low_level_init(netif_ptr);
   etharp_init();
}

⌨️ 快捷键说明

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