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

📄 ethernetif.c

📁 凌阳单片机之以太网通讯模组模组
💻 C
📖 第 1 页 / 共 2 页
字号:

struct pbuf *
low_level_input(struct netif *netif)
{
	struct EtherDev *dev = netif->state;
	struct pbuf *skb = NULL;
	u16_t rxbyte, *rdptr;
	u16_t i, RxStatus, RxLen, GoodPacket, tmplen;
	/* Check packet ready or not */
		ior(0xf0);			/* Dummy read */
		rxbyte = inb(DM9KDATA);	/* Got most updated data */
		/* Status check: this byte must be 0 or 1 */
   		/* packet ready to receive check */
		if (rxbyte == DM9K_PKT_RDY) {
			/* A packet ready now  & Get status/length */
			GoodPacket = TRUE;
			outb(0xf2, DM9KADDR);
			#if 0
			if (dev->io_mode == DM9K_BYTE_MODE) {
				/* Byte mode */
				RxStatus = inb(DM9KDATA)+(inb(DM9KDATA) << 8);
				RxLen    = inb(DM9KDATA)+(inb(DM9KDATA) << 8);
			} else 
			#endif 
			if (dev->io_mode == DM9K_WORD_MODE) {
				/* Word mode */
				RxStatus = inw(DM9KDATA);
				RxLen    = inw(DM9KDATA);
			} 

			/* Packet Status check */
			if (RxLen < 0x40) { 
				GoodPacket = FALSE; 
				//dev->runt_length_counter++; 
			}
			
			if (RxLen > DM9K_PKT_MAX) { 
				DEBUGF(DM9K_DEBUG | DBG_TRACE, ("<DM9K> RST: RX Len:%x\n", RxLen));
				//dev->long_length_counter++; 
			}
			
			if (RxStatus & 0xbf00) {
				GoodPacket = FALSE;
				if (RxStatus & 0x100) 
					//dev->rx_fifo_errors++;
					;
				if (RxStatus & 0x200) 
					//dev->rx_crc_errors++;
					;
				if (RxStatus & 0x8000) 
					//dev->rx_length_errors++;
					;
			}

			/* Move data from DM9K */
		if ( GoodPacket && ((skb = pbuf_alloc(PBUF_LINK,RxLen, PBUF_POOL)) != NULL ) ) {
			rdptr = skb->payload;			
			/* Read received packet from RX SARM */
			#if 0
			if (dev->io_mode == DM9K_BYTE_MODE) {
						/* Byte mode */
				for (i=0; i<RxLen; i++)
				rdptr[i]=inb(DM9KDATA);
				} else 
			#endif 
			if (dev->io_mode == DM9K_WORD_MODE) {
						/* Word mode */
				tmplen = (RxLen + 1) / 2;
					    r_pack(tmplen, rdptr);
					   
				//for (i=0;i<tmplen;i++)
				
			     //*((u16_t *)rdptr++) = inw(DM9KDATA);
				}
					/* Pass to upper layer */
					dev->rx_packets++; 
					return(skb);					
				} else {
				    if (skb!=NULL) pbuf_free(skb);
					tmplen = (RxLen + 1) / 2;
					drop(tmplen);
					//dev->drop_packets++; 
					return(NULL);
			}
		}

	return (NULL);
}


/*
  Read a word data from SROM
*/


/*
  Set DM9K multicast address
*/
#if 0

static u16_t read_srom_word( int offset)
{
	iow( 0xc, offset);
	iow( 0xb, 0x4);
	delay(200);
	iow( 0xb, 0x0);
	return (ior( 0xd) + (ior( 0xe) << 8) );
}


void DM9K_hash_table(struct net_device *dev)
{
	//EtherDev_t *db = (EtherDev_t *)dev->priv;
	struct dev_mc_list *mcptr = dev->mc_list;
	int mc_cnt = dev->mc_count;
	u16_t hash_val;
	u16_t i, oft, hash_table[4];
	DMFE_DBUG(0, "DM9K_hash_table()", 0);
	/* Set Node address */
	for (i = 0, oft = 0x10; i < 6; i++, oft++)
	iow( oft, GETMAC(dev->dev_addr, i));
  
	/* Clear Hash Table */
	for (i = 0; i < 4; i++)
		hash_table[i] = 0x0;
	/* broadcast address */
	hash_table[3] = 0x8000;
	/* the multicast address in Hash Table : 64 bits */
	for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
		hash_val = cal_CRC((u8_t *)mcptr->dmi_addr, 6, 0) & 0x3f; 
		hash_table[hash_val / 16] |=(u16_t) 1 << (hash_val % 16);
	}
	/* Write the hash table to MAC MD table */
	for (i = 0, oft = 0x16; i < 4; i++) 
	{
		iow( oft++, hash_table[i] & 0xff);
		iow( oft++, (hash_table[i] >> 8) & 0xff);
	}
}


/*
  Calculate the CRC valude of the Rx packet
  flag = 1 : return the reverse CRC (for the received packet CRC)
         0 : return the normal CRC (for Hash Table index)
*/
static unsigned long cal_CRC(u8_t * Data, unsigned int Len, u8_t flag)
{
u32_t crc = CRC_32(Data,Len);
    if (flag) 
		return ~crc;
		return crc;
	 
}

/* CRC_32 运算 */
u32_t CRC_32(u8_t *CRC_Data , u16_t Data_len)
{
  u32_t crc ,carry ;
  u16_t  iTemp;
  u16_t iTemp1;

  /* 将输入的资料,进行 crc-32 运算 */
  crc = 0xffffffff;
  for(iTemp = 0 ; iTemp < Data_len ; iTemp++)
    {
      carry = (crc ^ *CRC_Data++) & 0xff;
      for(iTemp1 = 0 ; iTemp1 < 8 ; iTemp1++)
        {
          if(carry & 1)
            carry = (carry >> 1) ^ 0xedb88320;
          else
            carry >>= 1;
        }
      crc = ((crc >> 8) & 0x00ffffff) ^ carry;
    }
  return(crc);
}
#endif

/*
   Read a byte from I/O port
*/
volatile static u8_t ior(int reg)
{
	outb(reg, DM9KADDR);
	return inb(DM9KDATA);
}

/*
   Write a byte to I/O port
*/
static void iow(int reg, u8_t value)
{
	outb(reg, DM9KADDR);
	outb(value, DM9KDATA);
}

/*
   Read a word from phyxcer
*/
volatile static u16_t phy_read(int reg)
{
	/* Fill the phyxcer register into REG_0C */
	iow(0xc, DM9K_PHY | reg);
	iow(0xb, 0xc); 	/* Issue phyxcer read command */
	delay(100);		/* Wait read complete */
	while((ior(EPCR) & 0x01) == 0x01);
	iow( 0xb, 0x0); 	/* Clear phyxcer read command */
	/* The read data keeps on REG_0D & REG_0E */
	return ( ior(0xe) << 8 ) | ior(0xd);
}

/*
   Write a word to phyxcer
*/
static void phy_write(int reg, u16_t value)
{
	/* Fill the phyxcer register into REG_0C */
	iow(0xc, DM9K_PHY | reg);
	/* Fill the written data into REG_0D & REG_0E */
	iow(0xd, (value & 0xff));
	iow(0xe, ( (value >> 8) & 0xff));
	iow(0xb, 0xa);		/* Issue phyxcer write command */
	delay(200);			/* Wait write complete */
	while((ior(EPCR) & 0x01) == 0x01);
	iow(0xb, 0x0);		/* Clear phyxcer write command */
}

/*-----------------------------------------------------------------------------------*/
/*
 * ethernetif_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
ethernetif_output(struct netif *netif, struct pbuf *p,
      struct ip_addr *ipaddr)
{
  struct EtherDev *dev;
  struct pbuf *q;
  struct eth_hdr *ethhdr;
  struct eth_addr *dest;
  struct ip_addr *queryaddr;
  err_t err;
  u8_t i;
  DMFE_DBUG(1, "ethernetif_output()\n", p);
  
 dev = netif->state;

  /* Make room for Ethernet header. */
  if (pbuf_header(p, 14) != 0) {
    /* The pbuf_header() call shouldn't fail, but we allocate an extra
       pbuf just in case. */
    q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
    if (q == NULL) {
#ifdef LINK_STATS
      lwip_stats.link.drop++;
      lwip_stats.link.memerr++;
#endif /* LINK_STATS */      
      return ERR_MEM;
    }
    pbuf_chain(q, p);
    p = q;
  }
  /* Construct Ethernet header. Start with looking up deciding which
     MAC address to use as a destination address. Broadcasts and
     multicasts are special, all other addresses are looked up in the
     ARP table. */
  queryaddr = ipaddr;
  if (ip_addr_isany(ipaddr) ||
     ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
    dest = (struct eth_addr *)&ethbroadcast;
  } else if (ip_addr_ismulticast(ipaddr)) {
    /* Hash IP multicast address to MAC address. */
    /*to do : */
  } else {

    if (ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
      /* Use destination IP address if the destination is on the same
         subnet as we are. */
      queryaddr = ipaddr;
    } else {
      /* Otherwise we use the default router as the address to send
         the Ethernet frame to. */
      queryaddr = &(netif->gw);
    }
    dest = etharp_lookup(queryaddr);
  }
  /* If the etharp_lookup() didn't find an address, we send out an ARP
     query for the IP address. */
  if (dest == NULL) {
    err = etharp_query(netif,  queryaddr, p);
     return err;    
  }
  ethhdr = p->payload;
  for(i = 0; i < 3; i++) {
    ethhdr->dest.addr[i] = dest->addr[i];
    ethhdr->src.addr[i] = dev->dev_addr.addr[i];
  }
ethhdr->type = htons(ETHTYPE_IP);
#ifdef LINK_STATS
    lwip_stats.link.xmit++;
#endif /* LINK_STATS */
   return low_level_output(netif, p);

}

/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
  struct EtherDev *dev;
  struct eth_hdr *ethhdr;
  struct pbuf *p;
  dev = netif->state;
  p = low_level_input(netif);
  if (p != NULL) {
#ifdef LINK_STATS
    lwip_stats.link.recv++;
#endif /* LINK_STATS */
    ethhdr = p->payload;    
    switch (htons(ethhdr->type)) {
    case ETHTYPE_IP:
      etharp_ip_input(netif, p);
      pbuf_header(p, -14);
      netif->input(p, netif);
      break;
    case ETHTYPE_ARP:
      p = etharp_arp_input(netif, &(dev->dev_addr), p);
      if (p != NULL) {
  low_level_output(netif, p);
  pbuf_free(p);
      }
      break;
    default:
      pbuf_free(p);
      break;
    }
  }
}
/*-----------------------------------------------------------------------------------*/
void
etharp_timer(void *arg)
{
struct EtherDev *dev = arg;
if (!(ior(NSR) & 1<<6))
    dev->link_mode = DM9K_DISCONN;
    else dev->link_mode = dev->op_mode;
etharp_tmr();
sys_timeout(etharp_TMR_INTERVAL, etharp_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)
{
int i;
  if (dmfe_probe(dmfe_dev)!=0) 
  {
  	DEBUGF(DM9K_DEBUG | DBG_TRACE, ("device not found!\n"));
  	return ERR_IF;
}; 	
  netif->state =  dmfe_dev;
  netif->name[0] = IFNAME0;
  netif->name[1] = IFNAME1;
  netif->hwaddr_len = 3;
  netif->output = ethernetif_output;
  netif->linkoutput = low_level_output;
   for (i = 0; i < netif->hwaddr_len; ++i) {
     netif->hwaddr[i] = dmfe_dev->dev_addr.addr[i];
      }
  low_level_init(netif);
  etharp_init();
  return ERR_OK;
  sys_timeout(etharp_TMR_INTERVAL, etharp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/




/* 检查 DM9K 接收内存是否还有新的封包 */
u8_t CheckNetPack(struct EtherDev *dev)
{
u16_t temp;
  ior(MRCMDX);
  switch(ior(MRCMDX))//DM9KREG_r(MRCMDX))                      /* 检查是否有新的封包进入 */
    {
      case 0x00 :
        {
          return(0);                             /* 尚无封包进入 */
        }
      case 0x01 : return(1);              /* 有封包进入 */
      default   : 
            temp = ior(0xF4) + ior(0xF5)*256;
      		DEBUGF(DM9K_DEBUG | DBG_TRACE,("%02x",ior(MRCMDX)));
			dev->reset_rx_status++;
			dmfe_stop(dev);
			delay(200);
		    dmfe_init_DM9K(dev);      /* 内存出错,重置 DM9K */
            return(0);
    }
}

void Ethernet_poll(struct netif *netif)
{
    if (((struct EtherDev *)(netif->state))->link_mode == DM9K_DISCONN)
    {
    DEBUGF(DM9K_DEBUG | DBG_TRACE,
        ("Hardware error!No Active network connected.\n \
           Please check your network interface.\n"));
    return;
    }
    if(CheckNetPack((struct EtherDev *)(netif->state))) 
      ethernetif_input(netif);   
}


⌨️ 快捷键说明

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