3 * Ethernet Interface for ne2k device
\r
5 * Lei Xia (lxia@northwestern.edu
\r
8 #include "lwip/opt.h"
\r
11 #include "lwip/def.h"
\r
12 #include "lwip/mem.h"
\r
13 #include "lwip/pbuf.h"
\r
14 #include "lwip/sys.h"
\r
15 #include <lwip/stats.h>
\r
16 #include <lwip/snmp.h>
\r
17 #include "netif/etharp.h"
\r
18 #include "netif/ppp_oe.h"
\r
19 #include "lwip/netifapi.h"
\r
20 #include "netif/ne2kif.h"
\r
23 #include <geekos/ne2k.h>
\r
24 #include <geekos/ktypes.h>
\r
25 #include <geekos/debug.h>
\r
28 struct netif ne2kif;
\r
31 * This function should do the actual transmission of the packet. The packet is
\r
32 * contained in the pbuf that is passed to the function. This pbuf
\r
35 * @param netif the lwip network interface structure for this ethernetif
\r
36 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
\r
37 * @return ERR_OK if the packet could be sent
\r
38 * an err_t value if the packet couldn't be sent
\r
40 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
\r
41 * strange results. You might consider waiting for space in the DMA queue
\r
42 * to become availale since the stack doesn't retry to send a packet
\r
43 * dropped because of memory failure (except for the TCP timers).
\r
47 ne2kif_output(struct netif *netif, struct pbuf *p)
\r
50 int size, offset, remlen;
\r
54 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
\r
61 packet = (uchar_t *)Malloc (remlen);
\r
63 for(q = p; q != NULL && remlen >0; q = q->next) {
\r
64 /* Send the data from the pbuf to the interface, one pbuf at a
\r
65 time. The size of the data in each pbuf is kept in the ->len
\r
68 memcpy(packet+offset, q->payload, q->len < remlen? q->len:remlen);
\r
73 NE2K_Send_Packet(packet, size);
\r
75 //signal that packet should be sent();
\r
78 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
\r
81 LINK_STATS_INC(link.xmit);
\r
88 * This function should be called when a packet is ready to be read
\r
89 * from the interface. It uses the function low_level_input() that
\r
90 * should handle the actual reception of bytes from the network
\r
91 * interface. Then the type of the received packet is determined and
\r
92 * the appropriate input function is called.
\r
94 * @param netif the lwip network interface structure for this ethernetif
\r
97 ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt)
\r
105 PrintBoth("Ne2k: Packet REceived\n");
\r
108 len += ETH_PAD_SIZE; // allow room for Ethernet padding
\r
111 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
\r
116 pbuf_header(p, -ETH_PAD_SIZE); // drop the padding word
\r
119 // iterate over the pbuf chain until it has read the entire packet into the pbuf.
\r
120 for(offset = 0, q = p; q != NULL && rlen > 0; q = q->next) {
\r
121 memcpy(q->payload, pkt+offset, rlen > q->len? q->len: rlen);
\r
127 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
\r
130 LINK_STATS_INC(link.recv);
\r
132 LINK_STATS_INC(link.memerr);
\r
133 LINK_STATS_INC(link.drop);
\r
138 if (p == NULL) return;
\r
139 /* points to packet payload, which starts with an Ethernet header */
\r
140 //ethhdr = p->payload;
\r
142 /* full packet send to tcpip_thread to process */
\r
143 if (ne2kif.input(p, &ne2kif)!=ERR_OK)
\r
144 { LWIP_DEBUGF(NETIF_DEBUG, ("ne2kif_input: IP input error\n"));
\r
150 switch (htons(ethhdr->type)) {
\r
151 /* IP or ARP packet? */
\r
155 /* PPPoE packet? */
\r
156 case ETHTYPE_PPPOEDISC:
\r
157 case ETHTYPE_PPPOE:
\r
158 #endif /* PPPOE_SUPPORT */
\r
172 * Should be called at the beginning of the program to set up the
\r
173 * network interface. It calls the function low_level_init() to do the
\r
174 * actual setup of the hardware.
\r
176 * This function should be passed as a parameter to netif_add().
\r
178 * @param netif the lwip network interface structure for this ethernetif
\r
179 * @return ERR_OK if the loopif is initialized
\r
180 * ERR_MEM if private data couldn't be allocated
\r
181 * any other err_t on error
\r
184 ne2kif_init(struct netif *netif)
\r
187 #if LWIP_NETIF_HOSTNAME
\r
188 /* Initialize interface hostname */
\r
189 netif->hostname = "lwip";
\r
190 #endif /* LWIP_NETIF_HOSTNAME */
\r
193 * Initialize the snmp variables and counters inside the struct netif.
\r
194 * The last argument should be replaced with your link speed, in units
\r
195 * of bits per second.
\r
197 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
\r
199 netif->state = NULL;
\r
200 netif->name[0] = 'n';
\r
201 netif->name[1] = 'e';
\r
202 /* We directly use etharp_output() here to save a function call.
\r
203 * You can instead declare your own function an call etharp_output()
\r
204 * from it if you have to do some checks before sending (e.g. if link
\r
205 * is available...) */
\r
206 netif->output = etharp_output;
\r
207 netif->linkoutput = ne2kif_output;
\r
210 /* set MAC hardware address length */
\r
211 netif->hwaddr_len = ETHARP_HWADDR_LEN;
\r
213 /* set MAC hardware address */
\r
214 netif->hwaddr[0] = PHY_ADDR1;
\r
215 netif->hwaddr[1] = PHY_ADDR2;
\r
216 netif->hwaddr[2] = PHY_ADDR3;
\r
217 netif->hwaddr[3] = PHY_ADDR4;
\r
218 netif->hwaddr[4] = PHY_ADDR5;
\r
219 netif->hwaddr[5] = PHY_ADDR6;
\r
221 /* maximum transfer unit */
\r
224 /* device capabilities */
\r
225 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
\r
226 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
\r
228 //initate ne2k hardware
\r
229 Init_Ne2k(&ne2kif_input);
\r