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 "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