Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
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:07:14 by
1.7.2
