pktif.c

来自「picoos源码。The RTOS and the TCP/IP stack 」· C语言 代码 · 共 572 行 · 第 1/2 页

C
572
字号
 * ethernetif_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.
 *
 */
/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;


  ethernetif = netif->state;

  p = low_level_input(netif);

  if (p != NULL) {

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

    ethhdr = p->payload;

    /* changed by DK, 2005-01-22 : */
#ifndef ETHARP_OLDSTYLE
    switch (htons(ethhdr->type)) {
    case ETHTYPE_IP:
      posSemaGet(arpsem_g);
      etharp_ip_input(netif, p);
      posSemaSignal(arpsem_g);
      pbuf_header(p, -14);
      netif->input(p, netif);
      break;
    case ETHTYPE_ARP:
      posSemaGet(arpsem_g);
      etharp_arp_input(netif, ethernetif->ethaddr, p);
      posSemaSignal(arpsem_g);
      break;
    default:
      pbuf_free(p);
      break;
    }
#else
/* old code: */
    switch (htons(ethhdr->type)) {
    case ETHTYPE_IP:
      posSemaGet(arpsem_g);
      etharp_ip_input(netif, p);
      posSemaSignal(arpsem_g);
      pbuf_header(p, -14);
            /* if (ip_lookup(p->payload, netif)) */
          netif->input(p, netif);
      break;
    case ETHTYPE_ARP:
      posSemaGet(arpsem_g);
      p = etharp_arp_input(netif, ethernetif->ethaddr, p);
      posSemaSignal(arpsem_g);
      if (p != NULL) {
                low_level_output(netif, p);
                pbuf_free(p);
      }
      break;
    default:
      pbuf_free(p);
      break;
    }
#endif
  }
}
/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
  posSemaGet(arpsem_g);
  etharp_tmr();
  posSemaSignal(arpsem_g);
  sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
/*
 * ethernetif_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.
 *
 */
/*-----------------------------------------------------------------------------------*/
err_t
ethernetif_init(struct netif *netif)
{
  struct ethernetif *ethernetif;

  /* IMPORTANT: We are not allowed to use a lwIP sys semaphore here!!! */
  arpsem_g = posSemaCreate(1);
  LWIP_ASSERT("pktif.c: failed to allocate a semaphore", arpsem_g != NULL);
  POS_SETEVENTNAME(arpsem_g, "lwip-pktif-arp");
  if (arpsem_g == NULL)
    return ERR_MEM;

  ethernetif = mem_malloc(sizeof(struct ethernetif));
  if (ethernetif == NULL)
    return ERR_MEM;

  netif->state = ethernetif;
  netif->name[0] = IFNAME0;
  netif->name[1] = IFNAME1;
  netif->linkoutput = low_level_output;
  netif->output = ethernetif_output;

  netif->mtu = 1500;
  netif->flags = NETIF_FLAG_BROADCAST;
  netif->hwaddr_len = 6;
  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);

  low_level_init(netif);
  etharp_init();

  sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
  
  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
 * pktif_update():
 *
 * Needs to be called periodically to get new packets. This could
 * be done inside a thread.
 */
/*-----------------------------------------------------------------------------------*/
void process_input(void)
{
  ethernetif_input(pktif_netif);
}




/*-----------------------------------------------------------------------------------
 *  Hardware Emulation:
 *  Interface through simulated hardware registers to the NIC
 *---------------------------------------------------------------------------------*/
#ifdef NIC_EMU

#include "pktdrv.h"

#define NICADR_TO_LOCALADR(x)  ((void*)(x))

#define DISABLE_INTERRUPTS()  singleThreadEnter()
#define ENABLE_INTERRUPTS()   singleThreadExit()

static sys_sem_t  rxsem_g;
static POSSEMA_t  txsem_g;
static POSSEMA_t  txsyncsem_g;


void nic_interrupt(void)
{
  unsigned long is = PK_READREG(PK_REG_ISTATUS);

  if (is & PK_ISTATUS_RX)
  {
    sys_sem_signal(rxsem_g);
  }
  if (is & PK_ISTATUS_TX)
  {
    PK_WRITEREG(PK_REG_IMASK, PK_IMASK_RX);
    posSemaSignal(txsem_g);
  }
}


static int packet_send(void *buffer, int len)
{
  unsigned long r;
  void *txbuf;

  posSemaGet(txsyncsem_g);

  /* wait until a buffer is free in the tx fifo */
  if ((PK_READREG(PK_REG_FSTATUS) & PK_FSTATUS_TXBFREE) == 0)
  {
    DISABLE_INTERRUPTS();
    while ((PK_READREG(PK_REG_FSTATUS) & PK_FSTATUS_TXBFREE) == 0)
    {
      PK_WRITEREG(PK_REG_IMASK, PK_IMASK_RX | PK_IMASK_TX);
      ENABLE_INTERRUPTS();
      posSemaGet(txsem_g);
      DISABLE_INTERRUPTS();
    }
    ENABLE_INTERRUPTS();
  }

  /* copy the packet to the NIC and transmit it */
  r = PK_READREG(PK_REG_TXBUF);
  txbuf = NICADR_TO_LOCALADR(r);
  memcpy(txbuf, buffer, len);
  PK_WRITEREG(PK_REG_PSIZE, len);
  PK_WRITEREG(PK_REG_NOTIFY, PK_NFLAG_TRANSMITNOW);

  posSemaSignal(txsyncsem_g);
  return 0;
}


static void nic_thread(void *arg)
{
  struct netif *netif = (struct netif*) arg;
  unsigned long r, fs, rxlen;
  void *rxbuf;
  err_t rc;
  u8_t temp[4];

  /* read MAC address from nic */
  *((u32_t*)temp) = PK_READREG(PK_REG_MACHI);
  ethaddr[0] = temp[0];
  ethaddr[1] = temp[1];
  *((u32_t*)temp) = PK_READREG(PK_REG_MACLO);
  ethaddr[2] = temp[0];
  ethaddr[3] = temp[1];
  ethaddr[4] = temp[2];
  ethaddr[5] = temp[3];

  /* Note: We generally use pico]OS semaphores. Exceptions are the
           semaphores, that are used in lwip threads that are doing
           timeouts. In our case, that is only the nic-thread that
           needs to pend on a lwip semaphore. */
  rxsem_g = sys_sem_new(1);
  LWIP_ASSERT("pktif.c: failed to allocate a semaphore", rxsem_g != NULL);
  txsem_g = posSemaCreate(0);
  LWIP_ASSERT("pktif.c: failed to allocate a semaphore", txsem_g != NULL);
  POS_SETEVENTNAME(txsem_g, "lwip-pktif-tx1");
  txsyncsem_g = posSemaCreate(1);
  LWIP_ASSERT("pktif.c: failed to allocate a semaphore", txsyncsem_g != NULL);
  POS_SETEVENTNAME(txsyncsem_g, "lwip-pktif-tx2");

  rc = ethernetif_init(netif);
  LWIP_ASSERT("pktif.c: ethernetif_init() failed", rc == ERR_OK);

  /* enable interrupts */
  (void) PK_READREG(PK_REG_ISTATUS);
  PK_WRITEREG(PK_REG_IMASK, PK_IMASK_RX);

  /* receiver loop */
  for(;;)
  {
    /* wait for next packet */
    sys_sem_wait(rxsem_g);

    /* poll the receiver FIFO */
    fs = PK_READREG(PK_REG_FSTATUS);
    while (fs & PK_FSTATUS_RECEIVED)
    {
      r = PK_READREG(PK_REG_RXBUF);
      rxbuf = NICADR_TO_LOCALADR(r);
      rxlen = PK_READREG(PK_REG_PSIZE);

      cur_packet = (unsigned char*) rxbuf;
      cur_length = (unsigned int)   rxlen;
      ethernetif_input(netif);

      PK_WRITEREG(PK_REG_NOTIFY, PK_NFLAG_RECEIVENEXT);
      fs = PK_READREG(PK_REG_FSTATUS);
    }
  }
}


err_t
pktif_init(struct netif *netif)
{
  sys_thread_t  th;  
  th = sys_thread_new(nic_thread, netif, TCPIP_THREAD_PRIO + 1);
  return (th == NULL) ? ERR_IF : ERR_OK;
}


#endif /* NIC_EMU */

⌨️ 快捷键说明

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