A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rmii_if.c Source File

rmii_if.c

Go to the documentation of this file.
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 }