/** * This function will read a single packet from the Stellaris ethernet * interface, if available, and return a pointer to a pbuf. The timestamp * of the packet will be placed into the pbuf structure. * * @param netif the lwip network interface structure for this ethernetif * @return pointer to pbuf packet if available, NULL otherswise. */ static struct pbuf * low_level_input(struct netif *netif) { struct pbuf *p, *q; u16_t len; u32_t temp; int i; unsigned long *ptr; #if LWIP_PTPD u32_t time_s, time_ns; /* Get the current timestamp if PTPD is enabled */ lwIPHostGetTime(&time_s, &time_ns); #endif /* Check if a packet is available, if not, return NULL packet. */ if ((HWREG(ETH_BASE + MAC_O_NP) & MAC_NP_NPR_M) == 0) { int err = ETHServiceTaskLastError(0); if ((ETH_ERROR & err) && (ETH_OVERFLOW & err)) { LWIP_DEBUGF(CORTEX_DEBUG, ("low_level_input: Ethernet overflow\n"));LINK_STATS_INC(link.drop); } return (NULL); } /** * Obtain the size of the packet and put it into the "len" variable. * Note: The length returned in the FIFO length position includes the * two bytes for the length + the 4 bytes for the FCS. * */ temp = HWREG(ETH_BASE + MAC_O_DATA); len = temp & 0xFFFF; /* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); /* If a pbuf was allocated, read the packet into the pbuf. */ if (p != NULL) { /* Place the first word into the first pbuf location. */ *(unsigned long *) p->payload = temp; p->payload = (char *) (p->payload) + 4; p->len -= 4; /* Process all but the last buffer in the pbuf chain. */ q = p; while (q != NULL) { /* Setup a byte pointer into the payload section of the pbuf. */ ptr = q->payload; /** * Read data from FIFO into the current pbuf * (assume pbuf length is modulo 4) * */ for (i = 0; i < q->len; i += 4) { *ptr++ = HWREG(ETH_BASE + MAC_O_DATA); } /* Link in the next pbuf in the chain. */ q = q->next; } /* Restore the first pbuf parameters to their original values. */ p->payload = (char *) (p->payload) - 4; p->len += 4; /* Adjust the link statistics */ LINK_STATS_INC(link.recv); #if LWIP_PTPD // Place the timestamp in the PBUF p->time_s = time_s; p->time_ns = time_ns; #endif } // If no pbuf available, just drain the RX fifo. else { for (i = 4; i < len; i += 4) { temp = HWREG(ETH_BASE + MAC_O_DATA); } // Adjust the link statistics LINK_STATS_INC(link.memerr);LINK_STATS_INC(link.drop); } return (p); }
/** * This function will read a single packet from the Stellaris ethernet * interface, if available, and return a pointer to a pbuf. The timestamp * of the packet will be placed into the pbuf structure. * * @param netif the lwip network interface structure for this ethernetif * @return pointer to pbuf packet if available, NULL otherswise. */ static struct pbuf *low_level_receive(struct netif *netif) { MAC_Type* mac = (MAC_Type*)netif->state; struct pbuf *p, *q; u16_t len; u32_t temp; int i; unsigned long *ptr; #if LWIP_PTPD u32_t time_s, time_ns; /* Get the current timestamp if PTPD is enabled */ lwIPHostGetTime(&time_s, &time_ns); #endif /* Check if a packet is available, if not, return NULL packet. */ if ((mac->MACNP & MAC_NP_NPR_M) == 0) { return (NULL); } /** * Obtain the size of the packet and put it into the "len" variable. * Note: The length returned in the FIFO length position includes the * two bytes for the length + the 4 bytes for the FCS. * */ temp = mac->MACDATA; len = temp & 0xFFFF; /* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); /* If a pbuf was allocated, read the packet into the pbuf. */ if (p != NULL) { /* Place the first word into the first pbuf location. */ *(unsigned long *) p->payload = temp; p->payload = (char *) (p->payload) + 4; p->len -= 4; /* Process all but the last buffer in the pbuf chain. */ q = p; while (q != NULL) { /* Setup a byte pointer into the payload section of the pbuf. */ ptr = (unsigned long *)q->payload; /** * Read data from FIFO into the current pbuf * (assume pbuf length is modulo 4) * */ for (i = 0; i < q->len; i += 4) { *ptr++ = mac->MACDATA; } /* Link in the next pbuf in the chain. */ q = q->next; } /* Restore the first pbuf parameters to their original values. */ p->payload = (char *) (p->payload) - 4; p->len += 4; /* Adjust the link statistics */ LINK_STATS_INC(link.recv); #if LWIP_PTPD /* Place the timestamp in the PBUF */ p->time_s = time_s; p->time_ns = time_ns; #endif } /* If no pbuf available, just drain the RX fifo. */ else { for (i = 4; i < len; i += 4) { temp = mac->MACDATA; } /* Adjust the link statistics */ LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); } return (p); }