--- /dev/null
+/**\r
+ * @file\r
+ * Ethernet Interface for ne2k device\r
+ *\r
+ * Lei Xia (lxia@northwestern.edu\r
+ */\r
+\r
+#include "lwip/opt.h"\r
+ \r
+\r
+#include "lwip/def.h"\r
+#include "lwip/mem.h"\r
+#include "lwip/pbuf.h"\r
+#include "lwip/sys.h"\r
+#include <lwip/stats.h>\r
+#include <lwip/snmp.h>\r
+#include "netif/etharp.h"\r
+#include "netif/ppp_oe.h"\r
+#include "lwip/netifapi.h"\r
+#include "netif/ne2kif.h"\r
+\r
+\r
+#include <geekos/ne2k.h>\r
+#include <geekos/ktypes.h>\r
+#include <geekos/debug.h>\r
+\r
+\r
+struct netif ne2kif; \r
+\r
+/**\r
+ * This function should do the actual transmission of the packet. The packet is\r
+ * contained in the pbuf that is passed to the function. This pbuf\r
+ * might be chained.\r
+ *\r
+ * @param netif the lwip network interface structure for this ethernetif\r
+ * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)\r
+ * @return ERR_OK if the packet could be sent\r
+ * an err_t value if the packet couldn't be sent\r
+ *\r
+ * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to\r
+ * strange results. You might consider waiting for space in the DMA queue\r
+ * to become availale since the stack doesn't retry to send a packet\r
+ * dropped because of memory failure (except for the TCP timers).\r
+ */\r
+\r
+err_t\r
+ne2kif_output(struct netif *netif, struct pbuf *p)\r
+{\r
+ struct pbuf *q;\r
+ int size, offset, remlen;\r
+ uchar_t *packet;\r
+ \r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */\r
+#endif\r
+\r
+ size = p->tot_len;\r
+ offset = 0;\r
+ remlen = size;\r
+\r
+ packet = (uchar_t *)Malloc (remlen);\r
+\r
+ for(q = p; q != NULL && remlen >0; q = q->next) {\r
+ /* Send the data from the pbuf to the interface, one pbuf at a\r
+ time. The size of the data in each pbuf is kept in the ->len\r
+ variable. */\r
+\r
+ memcpy(packet+offset, q->payload, q->len < remlen? q->len:remlen);\r
+ remlen -= q->len;\r
+ offset += q->len;\r
+ \r
+ }\r
+ NE2K_Send_Packet(packet, size);\r
+\r
+ //signal that packet should be sent();\r
+\r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
+#endif\r
+ \r
+ LINK_STATS_INC(link.xmit);\r
+\r
+ return ERR_OK;\r
+}\r
+\r
+\r
+/**\r
+ * This function should be called when a packet is ready to be read\r
+ * from the interface. It uses the function low_level_input() that\r
+ * should handle the actual reception of bytes from the network\r
+ * interface. Then the type of the received packet is determined and\r
+ * the appropriate input function is called.\r
+ *\r
+ * @param netif the lwip network interface structure for this ethernetif\r
+ */\r
+void\r
+ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt)\r
+{\r
+ struct pbuf *p, *q;\r
+ uint_t offset;\r
+ uint_t len, rlen;\r
+ \r
+ len = info->size; \r
+\r
+ PrintBoth("Ne2k: Packet REceived\n");\r
+\r
+#if ETH_PAD_SIZE\r
+ len += ETH_PAD_SIZE; // allow room for Ethernet padding \r
+#endif\r
+\r
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);\r
+ \r
+ if (p != NULL) {\r
+\r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, -ETH_PAD_SIZE); // drop the padding word \r
+#endif\r
+\r
+ // iterate over the pbuf chain until it has read the entire packet into the pbuf.\r
+ for(offset = 0, q = p; q != NULL && rlen > 0; q = q->next) {\r
+ memcpy(q->payload, pkt+offset, rlen > q->len? q->len: rlen);\r
+ rlen -= q->len;\r
+ offset += q->len;\r
+ }\r
+\r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
+#endif\r
+\r
+ LINK_STATS_INC(link.recv);\r
+ } else {\r
+ LINK_STATS_INC(link.memerr);\r
+ LINK_STATS_INC(link.drop);\r
+ }\r
+\r
+ Free(pkt);\r
+ \r
+ if (p == NULL) return;\r
+ /* points to packet payload, which starts with an Ethernet header */\r
+ //ethhdr = p->payload;\r
+\r
+ /* full packet send to tcpip_thread to process */\r
+ if (ne2kif.input(p, &ne2kif)!=ERR_OK)\r
+ { LWIP_DEBUGF(NETIF_DEBUG, ("ne2kif_input: IP input error\n"));\r
+ pbuf_free(p);\r
+ p = NULL;\r
+ }\r
+\r
+#if 0\r
+ switch (htons(ethhdr->type)) {\r
+ /* IP or ARP packet? */\r
+ case ETHTYPE_IP:\r
+ case ETHTYPE_ARP:\r
+#if PPPOE_SUPPORT\r
+ /* PPPoE packet? */\r
+ case ETHTYPE_PPPOEDISC:\r
+ case ETHTYPE_PPPOE:\r
+#endif /* PPPOE_SUPPORT */\r
+ \r
+ break;\r
+\r
+ default:\r
+ pbuf_free(p);\r
+ p = NULL;\r
+ break;\r
+ }\r
+#endif\r
+\r
+}\r
+\r
+/**\r
+ * Should be called at the beginning of the program to set up the\r
+ * network interface. It calls the function low_level_init() to do the\r
+ * actual setup of the hardware.\r
+ *\r
+ * This function should be passed as a parameter to netif_add().\r
+ *\r
+ * @param netif the lwip network interface structure for this ethernetif\r
+ * @return ERR_OK if the loopif is initialized\r
+ * ERR_MEM if private data couldn't be allocated\r
+ * any other err_t on error\r
+ */\r
+err_t\r
+ne2kif_init(struct netif *netif)\r
+{\r
+\r
+#if LWIP_NETIF_HOSTNAME\r
+ /* Initialize interface hostname */\r
+ netif->hostname = "lwip";\r
+#endif /* LWIP_NETIF_HOSTNAME */\r
+\r
+ /*\r
+ * Initialize the snmp variables and counters inside the struct netif.\r
+ * The last argument should be replaced with your link speed, in units\r
+ * of bits per second.\r
+ */\r
+ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);\r
+\r
+ netif->state = NULL;\r
+ netif->name[0] = 'n';\r
+ netif->name[1] = 'e';\r
+ /* We directly use etharp_output() here to save a function call.\r
+ * You can instead declare your own function an call etharp_output()\r
+ * from it if you have to do some checks before sending (e.g. if link\r
+ * is available...) */\r
+ netif->output = etharp_output;\r
+ netif->linkoutput = ne2kif_output;\r
+ \r
+\r
+ /* set MAC hardware address length */\r
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;\r
+\r
+ /* set MAC hardware address */\r
+ netif->hwaddr[0] = PHY_ADDR1;\r
+ netif->hwaddr[1] = PHY_ADDR2;\r
+ netif->hwaddr[2] = PHY_ADDR3;\r
+ netif->hwaddr[3] = PHY_ADDR4;\r
+ netif->hwaddr[4] = PHY_ADDR5;\r
+ netif->hwaddr[5] = PHY_ADDR6;\r
+\r
+ /* maximum transfer unit */\r
+ netif->mtu = 1500;\r
+ \r
+ /* device capabilities */\r
+ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */\r
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;\r
+\r
+ //initate ne2k hardware\r
+ Init_Ne2k(&ne2kif_input);\r
+\r
+ return ERR_OK;\r
+}\r