A version of LWIP, provided for backwards compatibility.
Dependents: AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more
rmii_if.c
00001 /** 00002 * @file 00003 * Ethernet Interface for RMII Devices 00004 */ 00005 00006 /* 00007 * Skeleton Author: Adam Dunkels <adam@sics.se> 00008 */ 00009 00010 #include "lwip/opt.h" 00011 00012 #include "lwip/def.h" 00013 #include "lwip/mem.h" 00014 #include "lwip/pbuf.h" 00015 #include "lwip/sys.h" 00016 #include "lwip/stats.h" 00017 #include "lwip/snmp.h" 00018 #include "netif/etharp.h" 00019 #include "netif/ppp_oe.h" 00020 00021 #include "netif/rmiiif.h" 00022 #include "LPC23xx.h" 00023 #include "ethnetif.h" 00024 00025 /* Define those to better describe your network interface. */ 00026 #define IFNAME0 'e' 00027 #define IFNAME1 'n' 00028 00029 /** 00030 * Helper struct to hold private data used to operate your ethernet interface. 00031 * Keeping the ethernet address of the MAC in this struct is not necessary 00032 * as it is already kept in the struct netif. 00033 * But this is only an example, anyway... 00034 */ 00035 struct emacif { 00036 struct eth_addr *ethaddr; 00037 /* Add whatever per-interface state that is needed here. */ 00038 unsigned long duplex; 00039 unsigned long speed; 00040 }; 00041 00042 /** 00043 * This function writes a specific value in a register of the PHY device. 00044 * 00045 * @param reg The specific register. 00046 * @param data The value to be stored. 00047 */ 00048 static void PHY_write(unsigned long reg, unsigned long data) { 00049 LPC_EMAC->MCMD = 0x0000; 00050 LPC_EMAC->MADR = PHY_ADDR | reg; 00051 LPC_EMAC->MWTD = data; 00052 while(LPC_EMAC->MIND!=0); 00053 } 00054 00055 /** 00056 * This function reads a value from a register of the PHY device. 00057 * 00058 * @param reg The specific register. 00059 * @return The readed value. 00060 */ 00061 static unsigned long PHY_read(unsigned long reg) { 00062 LPC_EMAC->MCMD = 0x0001; 00063 LPC_EMAC->MADR = PHY_ADDR | reg; 00064 while((LPC_EMAC->MIND&0x05) != 0); 00065 LPC_EMAC->MCMD = 0x0000; 00066 return LPC_EMAC->MRDD; 00067 } 00068 00069 /** 00070 * This function starts up the PHY device 00071 * 00072 * @return It returns TRUE if everything is fine. 00073 */ 00074 static int PHY_init(struct emacif *emac) { 00075 unsigned long timeout = MII_BMSR_TIMEOUT * 4; 00076 unsigned long regValue; 00077 00078 LPC_EMAC->MCFG = 0x8018; 00079 wait(0.2); // Short 00080 LPC_EMAC->MCFG = 0x0018; 00081 LPC_EMAC->MCMD = 0; 00082 LPC_EMAC->Command |= 0x0200; // RMII, &=~0x0200 for MII 00083 LPC_EMAC->SUPP = 0x0100; // RMII, 0x0000 for 10MBit 00084 wait(0.2); // Short 00085 PHY_write(PHY_BMCR, BMCR_RESET); 00086 wait(0.2); // Short 00087 00088 while(timeout--) { 00089 regValue = PHY_read(PHY_BMCR); 00090 if((regValue & BMCR_RESET)== 0x0) { 00091 break; 00092 } 00093 } 00094 if(!timeout) { 00095 return FALSE; 00096 } 00097 00098 regValue = PHY_read(PHY_PHYIDR1); 00099 if((regValue & 0x2000) != 0x2000) { 00100 return FALSE; 00101 } 00102 00103 regValue = PHY_read(PHY_PHYIDR2); 00104 if((regValue & 0x5C90) != 0x5C90) { 00105 return FALSE; 00106 } 00107 00108 PHY_write(PHY_BMCR, BMCR_AN | BMCR_RE_AN); 00109 /* auto negotiation, restart AN */ 00110 /* RE_AN should be self cleared */ 00111 00112 00113 timeout = MII_BMSR_TIMEOUT; 00114 while(timeout--) { 00115 regValue = PHY_read(PHY_PHYSTS); 00116 if((regValue & 0x0011) == 0x0011) { 00117 break; 00118 } 00119 } 00120 if(!timeout) { 00121 return FALSE; 00122 } 00123 00124 // Link should be established from here. 00125 if(regValue&0x4) { 00126 emac->duplex = FULL_DUPLEX; 00127 } else { 00128 emac->duplex = HALF_DUPLEX; 00129 } 00130 00131 if(regValue&0x2) { 00132 emac->speed = SPEED_10; 00133 } else { 00134 emac->speed = SPEED_100; 00135 } 00136 00137 return TRUE; 00138 } 00139 00140 /** 00141 * In this function, the Tx descriptor queue is set up for use with the DMA. 00142 */ 00143 void EMACTxDescriptor_init() { 00144 unsigned long i; 00145 unsigned long *tx_desc_addr; 00146 unsigned long *tx_status_addr; 00147 00148 for(i=0; i<EMAC_TX_DESCRIPTOR_COUNT; ++i) { 00149 tx_desc_addr = (unsigned long *)(TX_DESCRIPTOR_ADDR + i*8); // two words at a time, packet and control 00150 *tx_desc_addr = (unsigned long) (EMAC_TX_BUFFER_ADDR + i*EMAC_BLOCK_SIZE); 00151 *(tx_desc_addr+1) = (unsigned long) (EMAC_TX_DESC_INT | (EMAC_BLOCK_SIZE - 1)); // set size only 00152 00153 tx_status_addr = (unsigned long *)(TX_STATUS_ADDR + i*4); // TX status, one word only, status info. 00154 *tx_status_addr = (unsigned long) 0; // initially, set status info to 0 00155 } 00156 00157 LPC_EMAC->TxDescriptor = TX_DESCRIPTOR_ADDR; // Base addr of tx descriptor array 00158 LPC_EMAC->TxStatus = TX_STATUS_ADDR; // Base addr of tx status 00159 LPC_EMAC->TxDescriptorNumber = EMAC_TX_DESCRIPTOR_COUNT - 1; // number of tx descriptors, 16 00160 00161 LPC_EMAC->TxProduceIndex = 0x0; // TX descriptors point to zero 00162 } 00163 00164 /** 00165 * In this function, the Rx descriptor queue is set up for use with the DMA. 00166 */ 00167 void EMACRxDescriptor_init() { 00168 unsigned long i; 00169 unsigned long *rx_desc_addr; 00170 unsigned long *rx_status_addr; 00171 00172 for (i=0; i<EMAC_RX_DESCRIPTOR_COUNT; ++i) { 00173 rx_desc_addr = (unsigned long *)(RX_DESCRIPTOR_ADDR + i*8); // two words at a time, packet and control 00174 *rx_desc_addr = (unsigned long) (EMAC_RX_BUFFER_ADDR + i*EMAC_BLOCK_SIZE); 00175 *(rx_desc_addr+1) = (unsigned long) (EMAC_RX_DESC_INT | (EMAC_BLOCK_SIZE - 1)); // set size only 00176 00177 rx_status_addr = (unsigned long *)(RX_STATUS_ADDR + i * 8); // RX status, two words, status info. and status hash CRC. 00178 *rx_status_addr = (unsigned long)0; // initially, set both status info and hash CRC to 0 00179 *(rx_status_addr+1) = (unsigned long)0; 00180 } 00181 00182 LPC_EMAC->RxDescriptor = RX_DESCRIPTOR_ADDR; // Base addr of rx descriptor array 00183 LPC_EMAC->RxStatus = RX_STATUS_ADDR; // Base addr of rx status 00184 LPC_EMAC->RxDescriptorNumber = EMAC_RX_DESCRIPTOR_COUNT - 1; // number of rx descriptors, 16 00185 00186 LPC_EMAC->RxConsumeIndex = 0x0; // RX descriptor points to zero 00187 } 00188 00189 /** 00190 * In this function, the hardware will be initialized. 00191 * Called from ethernetif_init(). 00192 * 00193 * @param netif the already initialized lwip network interface structure 00194 * for this ethernetif 00195 */ 00196 static int emac_hw_init(struct netif *netif) { 00197 struct emacif *emac = static_cast<struct emacif *>(netif->state); 00198 // unsigned long timeout = MII_BMSR_TIMEOUT * 4; 00199 unsigned long regValue; 00200 00201 /* maximum transfer unit */ 00202 netif->mtu = EMAC_BLOCK_SIZE; 00203 00204 /* device capabilities */ 00205 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ 00206 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; 00207 00208 LPC_SC->PCONP |= PCONP_EMAC_CLOCK; 00209 00210 wait(0.01); //Short 00211 00212 // regValue = MAC_MODULEID; 00213 // if(regValue==PHILIPS_EMAC_MODULE_ID) { 00214 /* This is the rev."-" ID for the existing MCB2300 board, 00215 on rev. A, regVal should NOT equal to PHILIPS_EMAC_MODULE_ID, 00216 P1.6 should NOT be set. */ 00217 // Ethernet specific: Just Ethernet or GPIO 00218 // PINSEL2 = 0x50151105; /* selects P1[0,1,4,6,8,9,10,14,15] */ 00219 // } else { 00220 // Ethernet specific: Just Ethernet or GPIO 00221 LPC_PINCON->PINSEL2 = 0x50150105; /* selects P1[0,1,4,8,9,10,14,15] */ 00222 // } 00223 // Only the 4 lowest Bits are ethernet specific dont touch anything else. 00224 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0xF) | (0x5 & 0xF); /* selects P1[17:16] */ 00225 00226 00227 LPC_EMAC->MAC1 = 0xCF00; 00228 LPC_EMAC->Command = 0x0038; 00229 00230 wait(0.01); //Short 00231 00232 LPC_EMAC->MAC1 = 0x0000; 00233 LPC_EMAC->Command &= ~0x0003; // Disable Rx/Tx-Enable 00234 LPC_EMAC->MAC2 = 0x0000; 00235 LPC_EMAC->IPGR = 0x0012; 00236 LPC_EMAC->CLRT = 0x370F; 00237 LPC_EMAC->MAXF = 0x0600; 00238 00239 if(!PHY_init(emac)) { 00240 return FALSE; 00241 }; 00242 00243 LPC_EMAC->SA0 = ((netif->hwaddr[1] << 8) & 0x0000FF00) | ((netif->hwaddr[0]) & 0x000000FF); 00244 LPC_EMAC->SA1 = ((netif->hwaddr[3] << 8) & 0x0000FF00) | ((netif->hwaddr[2]) & 0x000000FF); 00245 LPC_EMAC->SA2 = ((netif->hwaddr[5] << 8) & 0x0000FF00) | ((netif->hwaddr[4]) & 0x000000FF); 00246 00247 // TODO: Please optimize 00248 if((emac->speed==SPEED_10)&&(emac->duplex==HALF_DUPLEX)) { 00249 LPC_EMAC->MAC2 = 0x30; // half duplex, CRC and PAD enabled. 00250 LPC_EMAC->SUPP &= ~0x0100; // RMII Support Reg. speed is set to 10M 00251 LPC_EMAC->Command |= 0x0200; 00252 //MAC_COMMAND |= 0x0040; // [10]-half duplex,[9]-MII mode,[6]-Pass runt frame, [5]-RxReset 00253 LPC_EMAC->IPGT = 0x0012; // IPG setting in half duplex mode 00254 00255 } else if((emac->speed==SPEED_100)&&(emac->duplex == HALF_DUPLEX)) { 00256 LPC_EMAC->MAC2 = 0x30; // half duplex, CRC and PAD enabled. 00257 LPC_EMAC->SUPP |= 0x0100; // RMII Support Reg. speed is set to 100M 00258 LPC_EMAC->Command |= 0x0200; 00259 //MAC_COMMAND |= 0x0040; // [10]-half duplex,[9]-MII mode,[6]-Pass runt frame, [5]-RxReset 00260 LPC_EMAC->IPGT = 0x0012; // IPG setting in half duplex mode 00261 00262 } else if((emac->speed == SPEED_10)&&(emac->duplex == FULL_DUPLEX)) { 00263 LPC_EMAC->MAC2 = 0x31; // full duplex, CRC and PAD enabled. 00264 LPC_EMAC->SUPP &= ~0x0100; // RMII Support Reg. speed is set to 10M 00265 LPC_EMAC->Command |= 0x0600; 00266 //MAC_COMMAND |= 0x0440; //[10]-full duplex,[9]-MII mode,[6]-Pass runt frame, [5]-RxReset 00267 LPC_EMAC->IPGT = 0x0015; // IPG setting in full duplex mode 00268 00269 } else if((emac->speed==SPEED_100)&&(emac->duplex==FULL_DUPLEX)) { 00270 LPC_EMAC->MAC2 = 0x31; // full duplex, CRC and PAD enabled. 00271 LPC_EMAC->SUPP |= 0x0100; // RMII Support Reg. speed is set to 100M 00272 LPC_EMAC->Command |= 0x0600; 00273 //MAC_COMMAND |= 0x0440; // [10]-full duplex,[9]-MII mode,[6]-Pass runt frame, [5]-RxReset 00274 LPC_EMAC->IPGT = 0x0015; // IPG setting in full duplex mode 00275 } 00276 00277 // TxDescriptor init (msg queues) 00278 EMACTxDescriptor_init(); 00279 00280 // RxDescriptor init (msg queues) 00281 EMACRxDescriptor_init(); 00282 00283 00284 LPC_EMAC->Command |= (0x03); // Tx/Rx-Enable 00285 LPC_EMAC->MAC1 |= 0x0001; // [1]-Pass All Rx Frame 00286 00287 /* Set up RX filter, accept broadcast and perfect station */ 00288 LPC_EMAC->RxFilterCtrl = ACC_UNICAST | ACC_BROADCAST | ACC_MATCH | ACC_MULTICAST;// | ACC_HASH; 00289 00290 LPC_EMAC->IntClear = 0xFFFF; // clear all MAC interrupts 00291 // MAC_INTENABLE = 0x00FF; // Enable all interrupts except SOFTINT and WOL 00292 00293 00294 // Wakeup on Lan 00295 // MAC_RXFILTERWOLCLR = 0xFFFF; // set all bits to clear receive filter WOLs 00296 // MAC_RXFILTERCTRL |= 0x2000; // enable Rx Magic Packet and RxFilter Enable WOL 00297 // MAC_INTENABLE = 0x2000; // only enable WOL interrupt 00298 // else 00299 //MAC_INTENABLE = 0x00FF; // Enable all interrupts except SOFTINT and WOL 00300 return TRUE; 00301 } 00302 00303 /** 00304 * This function should do the actual transmission of the packet. The packet is 00305 * contained in the pbuf that is passed to the function. This pbuf 00306 * might be chained. 00307 * 00308 * @param netif the lwip network interface structure for this ethernetif 00309 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) 00310 * @return ERR_OK if the packet could be sent 00311 * an err_t value if the packet couldn't be sent 00312 * 00313 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to 00314 * strange results. You might consider waiting for space in the DMA queue 00315 * to become availale since the stack doesn't retry to send a packet 00316 * dropped because of memory failure (except for the TCP timers). 00317 */ 00318 00319 static err_t low_level_output(struct netif *netif, struct pbuf *p) { 00320 LWIP_DEBUGF(NETIF_DEBUG, ("TXPRODUCEINDEX: %d, TXCONSUMEINDEX: %d\n", MAC_TXPRODUCEINDEX, MAC_TXCONSUMEINDEX)); 00321 // printf("TXPRODUCEINDEX: %d, TXCONSUMEINDEX: %d\n", MAC_TXPRODUCEINDEX, MAC_TXCONSUMEINDEX); 00322 // struct emacif *emac = static_cast<struct emacif *>(netif->state); 00323 struct pbuf *q; 00324 00325 unsigned long *tx_desc_addr; 00326 unsigned long TxProduceIndex; 00327 unsigned long TxConsumeIndex; 00328 00329 unsigned int offset = 0; 00330 unsigned int left = 0; 00331 unsigned int length = 0; 00332 00333 TxProduceIndex = LPC_EMAC->TxProduceIndex; 00334 TxConsumeIndex = LPC_EMAC->TxConsumeIndex; 00335 00336 if((TxProduceIndex == TxConsumeIndex-1) || (TxProduceIndex == EMAC_TX_DESCRIPTOR_COUNT-1 && TxConsumeIndex == 0)) { 00337 /* reach the limit, that probably should never happen */ 00338 /* To be tested */ 00339 LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: No MEM.\n")); 00340 LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output end.\n")); 00341 return ERR_MEM; 00342 } 00343 00344 #if ETH_PAD_SIZE 00345 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 00346 #endif 00347 00348 tx_desc_addr = (unsigned long *)(TX_DESCRIPTOR_ADDR + TxProduceIndex * 8); // two words at a time, packet and control 00349 #define min(x, y) ((x<y)? (x): (y)) 00350 // Deals only with 0x600 Byte width DMA Containern!!! 00351 printf("Size: %d\n", p->tot_len); 00352 for(q = p; q != NULL; q = q->next) { 00353 printf("PSize: %d\n", q->len); 00354 left = q->len; 00355 length = min(q->len, EMAC_BLOCK_SIZE - offset); 00356 LWIP_DEBUGF(NETIF_DEBUG, ("Try ro enqueue a new packet in the dma tx list.\n")); 00357 /* Send the data from the pbuf to the interface, one pbuf at a 00358 time. The size of the data in each pbuf is kept in the ->len 00359 variable. */ 00360 memcpy((void *)((unsigned int)(*tx_desc_addr)+offset),q->payload, q->len); 00361 offset += length; 00362 left -= length; 00363 if(offset==EMAC_BLOCK_SIZE&&left) { 00364 *(tx_desc_addr+1) = (unsigned)(EMAC_TX_DESC_INT | EMAC_TX_DESC_LAST | (EMAC_BLOCK_SIZE -1)); // set TX descriptor control field 00365 TxProduceIndex++; 00366 if(TxProduceIndex == EMAC_TX_DESCRIPTOR_COUNT) { 00367 TxProduceIndex = 0; 00368 } 00369 if((TxProduceIndex == TxConsumeIndex-1) || (TxProduceIndex == EMAC_TX_DESCRIPTOR_COUNT-1 && TxConsumeIndex == 0)) { 00370 /* reach the limit, that probably should never happen */ 00371 /* To be tested */ 00372 LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: No MEM.\n")); 00373 LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output end.\n")); 00374 printf("BAMM\n"); 00375 return ERR_MEM; 00376 } 00377 00378 memcpy((void *)*tx_desc_addr,(void *)((unsigned int)q->payload+length), left); 00379 offset = 0; 00380 } 00381 } 00382 00383 *(tx_desc_addr+1) = (unsigned)(EMAC_TX_DESC_INT | EMAC_TX_DESC_LAST | (offset -1)); // set TX descriptor control field 00384 TxProduceIndex++; 00385 LWIP_DEBUGF(NETIF_DEBUG, ("Packet: %d, Payload: %x, Status: %x.\n", TxProduceIndex-1, EMAC_TX_BUFFER(TxProduceIndex-1), TX_STATUS_INFO(TxProduceIndex-1))); 00386 00387 if(TxProduceIndex == EMAC_TX_DESCRIPTOR_COUNT) { 00388 TxProduceIndex = 0; 00389 } 00390 00391 LPC_EMAC->TxProduceIndex = TxProduceIndex; 00392 00393 #if ETH_PAD_SIZE 00394 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 00395 #endif 00396 00397 LINK_STATS_INC(link.xmit); 00398 LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output end.\n")); 00399 return ERR_OK; 00400 } 00401 /** 00402 * Should allocate a pbuf and transfer the bytes of the incoming 00403 * packet from the interface into the pbuf. 00404 * 00405 * @param netif the lwip network interface structure for this ethernetif 00406 * @return a pbuf filled with the received packet (including MAC header) 00407 * NULL on memory error 00408 */ 00409 static struct pbuf *low_level_input(struct netif *netif) { 00410 struct pbuf *p, *q; 00411 unsigned long packet; 00412 u16_t len; 00413 LWIP_DEBUGF(NETIF_DEBUG, ("RXPRODUCEINDEX: %d, RXCONSUMEINDEX: %d.\n", MAC_RXPRODUCEINDEX, MAC_RXCONSUMEINDEX)); 00414 // printf("RXPRODUCEINDEX: %d, RXCONSUMEINDEX: %d.\n", MAC_RXPRODUCEINDEX, MAC_RXCONSUMEINDEX); 00415 00416 if(LPC_EMAC->RxProduceIndex == LPC_EMAC->RxConsumeIndex) { 00417 // No Packet is received 00418 return NULL; 00419 } 00420 packet = LPC_EMAC->RxConsumeIndex; 00421 00422 /* Obtain the size of the packet and put it into the "len" 00423 variable. */ 00424 len = (RX_STATUS_INFO(packet) & DESC_SIZE_MASK) + 1; 00425 LWIP_DEBUGF(NETIF_DEBUG, ("Trying to receive packet no %d from dma with length %d.\n", packet, len)); 00426 LWIP_DEBUGF(NETIF_DEBUG, ("Packet status: %x\n", RX_STATUS_INFO(packet))); 00427 00428 #if ETH_PAD_SIZE 00429 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ 00430 #endif 00431 00432 /* We allocate a pbuf chain of pbufs from the pool. */ 00433 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 00434 00435 if(p != NULL) { 00436 #if ETH_PAD_SIZE 00437 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 00438 #endif 00439 00440 /* We iterate over the pbuf chain until we have read the entire 00441 * packet into the pbuf. */ 00442 unsigned long rest = 0; 00443 for(q = p; q != NULL; q = q->next) { 00444 /* Read enough bytes to fill this pbuf in the chain. The 00445 * available data in the pbuf is given by the q->len 00446 * variable. */ 00447 memcpy(q->payload,(void *)(RX_DESCRIPTOR_PACKET(packet)+rest),(q->len<len-rest)?q->len:(len-rest)); 00448 rest += q->len; 00449 LWIP_DEBUGF(NETIF_DEBUG, ("Buffer length: %d\n", q->len)); 00450 } 00451 if((++packet)==EMAC_RX_DESCRIPTOR_COUNT) { 00452 packet = 0; 00453 } 00454 00455 LPC_EMAC->RxConsumeIndex = packet; 00456 00457 #if ETH_PAD_SIZE 00458 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 00459 #endif 00460 00461 LINK_STATS_INC(link.recv); 00462 } else { 00463 printf("No Package space available\n"); 00464 LPC_EMAC->RxConsumeIndex++; 00465 LINK_STATS_INC(link.memerr); 00466 LINK_STATS_INC(link.drop); 00467 } 00468 return p; 00469 } 00470 00471 /** 00472 * This function should be called when a packet is ready to be read 00473 * from the interface. It uses the function low_level_input() that 00474 * should handle the actual reception of bytes from the network 00475 * interface. Then the type of the received packet is determined and 00476 * the appropriate input function is called. 00477 * 00478 * @param netif the lwip network interface structure for this ethernetif 00479 */ 00480 void emac_input(struct netif *netif) { 00481 //struct emacif *emac; 00482 struct eth_hdr *ethhdr; 00483 struct pbuf *p; 00484 int i = 0; 00485 00486 while(i++!=EMAC_RX_DESCRIPTOR_COUNT) { 00487 /* move received packet into a new pbuf */ 00488 p = low_level_input(netif); 00489 /* no packet could be read, silently ignore this */ 00490 if (p == NULL) { 00491 return; 00492 } 00493 // printf("HiReceive %020d\n", timer.read_us()); 00494 /* points to packet payload, which starts with an Ethernet header */ 00495 ethhdr = (struct eth_hdr *)(p->payload); 00496 switch(htons(ethhdr->type)) { 00497 /* IP or ARP packet? */ 00498 case ETHTYPE_IP: 00499 etharp_ip_input(netif, p); 00500 pbuf_header(p, -((s16_t) sizeof(struct eth_hdr))); 00501 if(netif->input(p, netif)!=ERR_OK) { 00502 } 00503 break; 00504 case ETHTYPE_ARP: 00505 etharp_arp_input(netif, (struct eth_addr *)&(netif->hwaddr[0]), p); 00506 break; 00507 #if PPPOE_SUPPORT 00508 /* PPPoE packet? */ 00509 case ETHTYPE_PPPOEDISC: 00510 case ETHTYPE_PPPOE: 00511 #endif /* PPPOE_SUPPORT */ 00512 /* full packet send to tcpip_thread to process */ 00513 default: 00514 break; 00515 } 00516 pbuf_free(p); 00517 p = NULL; 00518 } 00519 } 00520 00521 /** 00522 * Should be called at the beginning of the program to set up the 00523 * network interface. It calls the function low_level_init() to do the 00524 * actual setup of the hardware. 00525 * 00526 * This function should be passed as a parameter to netif_add(). 00527 * 00528 * @param netif the lwip network interface structure for this ethernetif 00529 * @return ERR_OK if the loopif is initialized 00530 * ERR_MEM if private data couldn't be allocated 00531 * any other err_t on error 00532 */ 00533 err_t emac_init(struct netif *netif) { 00534 struct emacif *emac; 00535 00536 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00537 00538 emac = static_cast<struct emacif *>(mem_malloc(sizeof(struct emacif))); 00539 if (emac == NULL) { 00540 return ERR_MEM; 00541 } 00542 00543 /* 00544 * Initialize the snmp variables and counters inside the struct netif. 00545 * The last argument should be replaced with your link speed, in units 00546 * of bits per second. 00547 */ 00548 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1500); // <-- TODO: Put the right speed in 00549 00550 netif->state = emac; 00551 netif->name[0] = IFNAME0; 00552 netif->name[1] = IFNAME1; 00553 /* We directly use etharp_output() here to save a function call. 00554 * You can instead declare your own function an call etharp_output() 00555 * from it if you have to do some checks before sending (e.g. if link 00556 * is available...) */ 00557 netif->output = etharp_output; 00558 netif->linkoutput = low_level_output; 00559 00560 emac->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); 00561 emac->duplex = FULL_DUPLEX; 00562 emac->speed = SPEED_100; 00563 00564 /* initialize the hardware */ 00565 emac_hw_init(netif); 00566 00567 return ERR_OK; 00568 } 00569
Generated on Tue Jul 12 2022 16:06:22 by 1.7.2