📄 c5471_ethernet.c
字号:
{ if (EIM_RXDESC_WRAP_NEXT & getreg32(c5471->c_rxcpudesc)) { /* Loop back around to base of descriptor queue */ c5471->c_rxcpudesc = getreg32(EIM_CPU_RXBA) + EIM_RAM_START; } else { c5471->c_rxcpudesc += 2*sizeof(uint32); } nvdbg("RX CPU desc: %08x\n", c5471->c_rxcpudesc);}/**************************************************************************** * Function: c5471_transmit * * Description: * Start hardware transmission. Called either from the txdone interrupt * handling or from watchdog based polling. * * Parameters: * c5471 - Reference to the driver state structure * * Returned Value: * OK on success; a negated errno on failure * * Assumptions: * ****************************************************************************/static int c5471_transmit(struct c5471_driver_s *c5471){ struct uip_driver_s *dev = &c5471->c_dev; volatile uint16 *packetmem; uint16 framelen; boolean bfirstframe; int nbytes; int nshorts; unsigned int i; unsigned int j; nbytes = (dev->d_len + 1) & ~1; j = 0; bfirstframe = TRUE; c5471->c_lastdescstart = c5471->c_rxcpudesc; nvdbg("Packet size: %d RX CPU desc: %08x\n", nbytes, c5471->c_rxcpudesc); c5471_dumpbuffer(dev->d_buf, dev->d_len); while (nbytes) { /* Verify that the hardware is ready to send another packet */ /* Words #0 and #1 of descriptor */ while (EIM_TXDESC_OWN_HOST & getreg32(c5471->c_rxcpudesc)) { /* Loop until the SWITCH lets go of the descriptor giving us access * rights to submit our new ether frame to it. */ } if (bfirstframe) { putreg32((getreg32(c5471->c_rxcpudesc) | EIM_RXDESC_FIF), c5471->c_rxcpudesc); } else { putreg32((getreg32(c5471->c_rxcpudesc) & ~EIM_RXDESC_FIF), c5471->c_rxcpudesc); } putreg32((getreg32(c5471->c_rxcpudesc) & ~EIM_RXDESC_PADCRC), c5471->c_rxcpudesc); if (bfirstframe) { putreg32((getreg32(c5471->c_rxcpudesc) | EIM_RXDESC_PADCRC), c5471->c_rxcpudesc); } if (nbytes >= EIM_PACKET_BYTES) { framelen = EIM_PACKET_BYTES; } else { framelen = nbytes; } /* Submit ether frame bytes to the C5472 Ether Module packet memory space. */ /* Get the number of 16-bit values to transfer by dividing by 2 with round up. */ nshorts = (framelen + 1) >> 1; /* Words #2 and #3 of descriptor */ packetmem = (uint16*)getreg32(c5471->c_rxcpudesc + sizeof(uint32)); for (i = 0; i < nshorts; i++, j++) { /* 16-bits at a time. */ packetmem[i] = htons(((uint16*)dev->d_buf)[j]); } putreg32(((getreg32(c5471->c_rxcpudesc) & ~EIM_RXDESC_BYTEMASK) | framelen), c5471->c_rxcpudesc); nbytes -= framelen; nvdbg("Wrote framelen: %d nbytes: %d nshorts: %d\n", framelen, nbytes, nshorts); if (0 == nbytes) { putreg32((getreg32(c5471->c_rxcpudesc) | EIM_RXDESC_LIF), c5471->c_rxcpudesc); } else { putreg32((getreg32(c5471->c_rxcpudesc) & ~EIM_RXDESC_LIF), c5471->c_rxcpudesc); } /* We're done with that descriptor; give access rights back to h/w */ putreg32((getreg32(c5471->c_rxcpudesc) | EIM_RXDESC_OWN_HOST), c5471->c_rxcpudesc); /* Next, tell Ether Module that those submitted bytes are ready for the wire */ putreg32(0x00000001, EIM_CPU_RXREADY); c5471->c_lastdescend = c5471->c_rxcpudesc; /* Advance to the next free descriptor */ c5471_incrxcpu(c5471); bfirstframe = FALSE; } /* Packet transferred .. Update statistics */#ifdef CONFIG_C5471_NET_STATS c5471->c_txpackets++;#endif /* Setup the TX timeout watchdog (perhaps restarting the timer) */ (void)wd_start(c5471->c_txtimeout, C5471_TXTIMEOUT, c5471_txtimeout, 1, (uint32)c5471); return OK;}/**************************************************************************** * Function: c5471_uiptxpoll * * Description: * The transmitter is available, check if uIP has any outgoing packets ready * to send. This is a callback from uip_poll(). uip_poll() may be called: * * 1. When the preceding TX packet send is complete, * 2. When the preceding TX packet send timesout and the interface is reset * 3. During normal TX polling * * Parameters: * dev - Reference to the NuttX driver state structure * * Returned Value: * OK on success; a negated errno on failure * * Assumptions: * ****************************************************************************/static int c5471_uiptxpoll(struct uip_driver_s *dev){ struct c5471_driver_s *c5471 = (struct c5471_driver_s *)dev->d_private; /* If the polling resulted in data that should be sent out on the network, * the field d_len is set to a value > 0. */ if (c5471->c_dev.d_len > 0) { uip_arp_out(&c5471->c_dev); c5471_transmit(c5471); /* Check if the ESM has let go of the RX descriptor giving us access * rights to submit another Ethernet frame. */ if ((EIM_TXDESC_OWN_HOST & getreg32(c5471->c_rxcpudesc)) != 0) { /* No, then return non-zero to terminate the poll */ return 1; } } /* If zero is returned, the polling will continue until all connections have * been examined. */ return 0;}/**************************************************************************** * Function: c5471_rxstatus * * Description: * An interrupt was received indicating that the last RX packet(s) is done * * Parameters: * c5471 - Reference to the driver state structure * * Returned Value: * None * * Assumptions: * ****************************************************************************/#ifdef CONFIG_C5471_NET_STATSstatic void c5471_rxstatus(struct c5471_driver_s *c5471){ uint32 desc = c5471->c_txcpudesc; uint32 rxstatus; /* Walk that last packet we just received to collect xmit status bits. */ rxstatus = 0; for (;;) { if (EIM_TXDESC_OWN_HOST & getreg32(desc)) { /* The incoming packet queue is empty. */ break; } rxstatus |= (getreg32(desc) & EIM_TXDESC_STATUSMASK); if ((getreg32(desc) & EIM_TXDESC_LIF) != 0) { break; } /* This packet is made up of several descriptors, find next one in chain. */ if (EIM_TXDESC_WRAP_NEXT & getreg32(desc)) { /* Loop back around to base of descriptor queue. */ desc = getreg32(EIM_CPU_TXBA) + EIM_RAM_START; } else { desc += 2 * sizeof(uint32); } } if (rxstatus != 0) { if ((rxstatus & EIM_TXDESC_RETRYERROR) != 0) { c5471->c_rxretries++; nvdbg("c_rxretries: %d\n", c5471->c_rxretries); } if ((rxstatus & EIM_TXDESC_HEARTBEAT) != 0) { c5471->c_rxheartbeat++; nvdbg("c_rxheartbeat: %d\n", c5471->c_rxheartbeat); } if ((rxstatus & EIM_TXDESC_LCOLLISON) != 0) { c5471->c_rxlcollision++; nvdbg("c_rxlcollision: %d\n", c5471->c_rxlcollision); } if ((rxstatus & EIM_TXDESC_COLLISION) != 0) { c5471->c_rxcollision++; nvdbg("c_rxcollision: %d\n", c5471->c_rxcollision); } if ((rxstatus & EIM_TXDESC_CRCERROR) != 0) { c5471->c_rxcrc++; nvdbg("c_rxcrc: %d\n", c5471->c_rxcrc); } if ((rxstatus & EIM_TXDESC_UNDERRUN) != 0) { c5471->c_rxunderrun++; nvdbg("c_rxunderrun: %d\n", c5471->c_rxunderrun); } if ((rxstatus & EIM_TXDESC_LOC) != 0) { c5471->c_rxloc++; nvdbg("c_rxloc: %d\n", c5471->c_rxloc); } }}#endif/**************************************************************************** * Function: c5471_receive * * Description: * An interrupt was received indicating the availability of a new RX packet * * Parameters: * c5471 - Reference to the driver state structure * * Returned Value: * None * * Assumptions: * ****************************************************************************/static void c5471_receive(struct c5471_driver_s *c5471){ struct uip_driver_s *dev = &c5471->c_dev; uint16 *packetmem; boolean bmore = TRUE; int packetlen = 0; int framelen; int nshorts; int i; int j = 0; /* Walk the newly received packet contained within the EIM and transfer * its contents to the uIP buffer. This frees up the memory contained within * the EIM for additional packets that might be received later from the network. */ nvdbg("Reading TX CPU desc: %08x\n", c5471->c_txcpudesc); while (bmore) { /* Words #0 and #1 of descriptor */ if (EIM_TXDESC_OWN_HOST & getreg32(c5471->c_txcpudesc)) { /* No further packets to receive. */ break; } /* Get the size of the frame from words #0 and #1 of the descriptor * and update the accumulated packet size */ framelen = (getreg32(c5471->c_txcpudesc) & EIM_TXDESC_BYTEMASK); packetlen += framelen; /* Check if the received packet will fit within the uIP packet buffer */ if (packetlen < (CONFIG_NET_BUFSIZE + 4)) { /* Get the packet memory from words #2 and #3 of descriptor */ packetmem = (uint16*)getreg32(c5471->c_txcpudesc + sizeof(uint32)); /* Divide by 2 with round up to get the number of 16-bit words. */ nshorts = (framelen + 1) >> 1; nvdbg("Reading framelen: %d packetlen: %d nshorts: %d packetmen: %p\n", framelen, packetlen, nshorts, packetmem); for (i = 0 ; i < nshorts; i++, j++) { /* Copy the data data from the hardware to c5471->c_dev.d_buf 16-bits at * a time. */ ((uint16*)dev->d_buf)[j] = htons(packetmem[i]); } } else { nvdbg("Discarding framelen: %d packetlen\n", framelen, packetlen); } if (getreg32(c5471->c_txcpudesc) & EIM_TXDESC_LIF) { bmore = FALSE; } /* Next, Clear all bits of words0/1 of the emptied descriptor except preserve * the settings of a select few. Can leave descriptor words 2/3 alone. */ putreg32((getreg32(c5471->c_txcpudesc) & (EIM_TXDESC_WRAP_NEXT|EIM_TXDESC_INTRE)), c5471->c_txcpudesc); /* Next, Give ownership of now emptied descriptor back to the Ether Module's SWITCH */ putreg32((getreg32(c5471->c_txcpudesc) | EIM_TXDESC_OWN_HOST), c5471->c_txcpudesc); /* Advance to the next data buffer */ c5471_inctxcpu(c5471); } /* Adjust the packet length to remove the CRC bytes that uIP doesn't care about. */ packetlen -= 4;#ifdef CONFIG_C5471_NET_STATS /* Increment the count of received packets */ c5471->c_rxpackets++;#endif /* If we successfully transferred the data into the uIP buffer, then pass it on * to uIP for processing. */ if (packetlen > 0 && packetlen < CONFIG_NET_BUFSIZE) { /* Set amount of data in c5471->c_dev.d_len. */ dev->d_len = packetlen; nvdbg("Received packet, packetlen: %d type: %02x\n", packetlen, ntohs(BUF->type)); c5471_dumpbuffer(dev->d_buf, dev->d_len); /* We only accept IP packets of the configured type and ARP packets */#ifdef CONFIG_NET_IPv6 if (BUF->type == HTONS(UIP_ETHTYPE_IP6))#else if (BUF->type == HTONS(UIP_ETHTYPE_IP))#endif { uip_arp_ipin(); uip_input(dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -