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