📄 ethernetif.c
字号:
}void vEMACRead( char *pcTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength ){ static unsigned long ulSectionBytesReadSoFar = 0, ulBufferPosition = 0, ulFameBytesReadSoFar = 0; static char *pcSource; register unsigned long ulBytesRemainingInBuffer, ulRemainingSectionBytes; /* vEMACRead is called with pcTo set to NULL to indicate that we are about to read a new frame. Any fragments remaining in the frame we were processing during the last call should be dropped. */ if( pcTo == NULL ) { /* How many bytes are indicated as being in this buffer? If none then the buffer is completely full and the frame is contained within more than one buffer. */ /* Reset our state variables ready for the next read from this buffer. */ pcSource = ( char * )( RxtdList[ ulNextRxBuffer ].addr & emacADDRESS_MASK ); ulFameBytesReadSoFar = ( unsigned long ) 0; ulBufferPosition = ( unsigned long ) 0; } else { /* Loop until we have obtained the required amount of data. */ ulSectionBytesReadSoFar = 0; while( ulSectionBytesReadSoFar < ulSectionLength ) { /* We may have already read some data from this buffer. How much data remains in the buffer? */ ulBytesRemainingInBuffer = ( ETH_RX_BUFFER_SIZE - ulBufferPosition ); /* How many more bytes do we need to read before we have the required amount of data? */ ulRemainingSectionBytes = ulSectionLength - ulSectionBytesReadSoFar; /* Do we want more data than remains in the buffer? */ if( ulRemainingSectionBytes > ulBytesRemainingInBuffer ) { /* We want more data than remains in the buffer so we can write the remains of the buffer to the destination, then move onto the next buffer to get the rest. */ memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulBytesRemainingInBuffer ); ulSectionBytesReadSoFar += ulBytesRemainingInBuffer; ulFameBytesReadSoFar += ulBytesRemainingInBuffer; /* Mark the buffer as free again. */ RxtdList[ ulNextRxBuffer ].addr &= ~( AT91C_OWNERSHIP_BIT ); /* Move onto the next buffer. */ ulNextRxBuffer++; if( ulNextRxBuffer >= NB_RX_BUFFERS ) { ulNextRxBuffer = ( unsigned long ) 0; } /* Reset the variables for the new buffer. */ pcSource = ( char * )( RxtdList[ ulNextRxBuffer ].addr & emacADDRESS_MASK ); ulBufferPosition = ( unsigned long ) 0; } else { /* We have enough data in this buffer to send back. Read out enough data and remember how far we read up to. */ memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulRemainingSectionBytes ); /* There may be more data in this buffer yet. Increment our position in this buffer past the data we have just read. */ ulBufferPosition += ulRemainingSectionBytes; ulSectionBytesReadSoFar += ulRemainingSectionBytes; ulFameBytesReadSoFar += ulRemainingSectionBytes; /* Have we now finished with this buffer? */ if( ( ulBufferPosition >= ETH_RX_BUFFER_SIZE ) || ( ulFameBytesReadSoFar >= ulTotalFrameLength ) ) { /* Mark the buffer as free again. */ RxtdList[ ulNextRxBuffer ].addr &= ~( AT91C_OWNERSHIP_BIT ); /* Move onto the next buffer. */ ulNextRxBuffer++; if( ulNextRxBuffer >= NB_RX_BUFFERS ) { ulNextRxBuffer = 0; } pcSource = ( char * )( RxtdList[ ulNextRxBuffer ].addr & emacADDRESS_MASK ); ulBufferPosition = 0; } } } }}/* * low_level_input(): * * Should allocate a pbuf and transfer the bytes of the incoming * packet from the interface into the pbuf. * */static struct pbuf *low_level_input( struct netif *netif ){ struct pbuf *p, *q; u16_t len; INT8U err; OSSemPend(next, 0, &err); #if ETH_PAD_SIZE len += ETH_PAD_SIZE; /* allow room for Ethernet padding */#endif /* Obtain the size of the packet and put it into the "len" variable. */ len = ulEMACInputLength(); if(len){ /* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc( PBUF_RAW, len, PBUF_POOL ); if (p != NULL) {#if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */#endif /* Let the driver know we are going to read a new packet. */ vEMACRead( NULL, 0, len ); /* We 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. */ vEMACRead( q->payload, q->len, len ); }#if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */#endif#if LINK_STATS lwip_stats.link.recv++;#endif /* LINK_STATS */ } else {// drop packet();#if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++;#endif /* LINK_STATS */ } } OSSemPost(next); return p; }/* * 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 actual transmission of the packet. * */static err_t ethernetif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr){ /* resolve hardware address, then send (or queue) packet */ return etharp_output(netif, ipaddr, p);}/* * 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. * */void ethernetif_input(void *p_arg){ struct ethernetif *ethernetif; struct eth_hdr *ethhdr; struct pbuf *p; INT8U err; for(;;){ OSSemPend(lwip_input, 0, &err); ethernetif = netif_default->state; p = NULL; p = low_level_input(netif_default); /* no packet could be read, silently ignore this */ if (p != NULL) { /* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload;#if LINK_STATS lwip_stats.link.recv++;#endif /* LINK_STATS */ ethhdr = p->payload; switch (htons(ethhdr->type)) { /* IP packet? */ case ETHTYPE_IP: /* update ARP table */ etharp_ip_input(netif_default, p); /* skip Ethernet header */ pbuf_header(p, -sizeof(struct eth_hdr)); //pbuf_header(p, -14); /* pass to network layer */ netif_default->input(p, netif_default); break; case ETHTYPE_ARP: /* pass p to ARP module */ etharp_arp_input(netif_default, ethernetif->ethaddr, p); break; default: pbuf_free(p); //p = NULL; break; } } }}static void arp_timer(void *arg){ etharp_tmr(); sys_timeout(ARP_TMR_INTERVAL, 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; ethernetif = mem_malloc(sizeof(struct ethernetif)); if (ethernetif == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); return ERR_MEM; } netif->state = ethernetif; netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; netif->output = ethernetif_output; netif->linkoutput = low_level_output; ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); low_level_init(netif); etharp_init(); sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); return ERR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -