Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / netif / ne2kif.c
1 /**\r
2  * @file\r
3  * Ethernet Interface for ne2k device\r
4  *\r
5  * Lei Xia (lxia@northwestern.edu\r
6  */\r
7 \r
8 #include "lwip/opt.h"\r
9  \r
10 \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
21 \r
22 \r
23 #include <geekos/ne2k.h>\r
24 #include <geekos/ktypes.h>\r
25 #include <geekos/debug.h>\r
26 \r
27 \r
28 struct netif ne2kif; \r
29 \r
30 /**\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
33  * might be chained.\r
34  *\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
39  *\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
44  */\r
45 \r
46 err_t\r
47 ne2kif_output(struct netif *netif, struct pbuf *p)\r
48 {\r
49   struct pbuf *q;\r
50   int size, offset, remlen;\r
51   uchar_t *packet;\r
52   \r
53 #if ETH_PAD_SIZE\r
54   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */\r
55 #endif\r
56 \r
57   size = p->tot_len;\r
58   offset = 0;\r
59   remlen = size;\r
60 \r
61   packet = (uchar_t *)Malloc (remlen);\r
62 \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
66        variable. */\r
67 \r
68         memcpy(packet+offset, q->payload, q->len < remlen? q->len:remlen);\r
69         remlen -= q->len;\r
70         offset += q->len;\r
71     \r
72   }\r
73   NE2K_Send_Packet(packet, size);\r
74 \r
75   //signal that packet should be sent();\r
76 \r
77 #if ETH_PAD_SIZE\r
78   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
79 #endif\r
80   \r
81   LINK_STATS_INC(link.xmit);\r
82 \r
83   return ERR_OK;\r
84 }\r
85 \r
86 \r
87 /**\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
93  *\r
94  * @param netif the lwip network interface structure for this ethernetif\r
95  */\r
96 void\r
97 ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt)\r
98 {\r
99   struct pbuf *p, *q;\r
100   uint_t offset;\r
101   uint_t len, rlen;\r
102   \r
103   len = info->size; \r
104 \r
105   PrintBoth("Ne2k: Packet REceived\n");\r
106 \r
107 #if ETH_PAD_SIZE\r
108   len += ETH_PAD_SIZE; // allow room for Ethernet padding  \r
109 #endif\r
110 \r
111   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);\r
112   \r
113   if (p != NULL) {\r
114 \r
115 #if ETH_PAD_SIZE\r
116     pbuf_header(p, -ETH_PAD_SIZE); // drop the padding word \r
117 #endif\r
118 \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
122       rlen -= q->len;\r
123       offset += q->len;\r
124     }\r
125 \r
126 #if ETH_PAD_SIZE\r
127     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
128 #endif\r
129 \r
130     LINK_STATS_INC(link.recv);\r
131   } else {\r
132     LINK_STATS_INC(link.memerr);\r
133     LINK_STATS_INC(link.drop);\r
134   }\r
135 \r
136   Free(pkt);\r
137   \r
138   if (p == NULL) return;\r
139   /* points to packet payload, which starts with an Ethernet header */\r
140   //ethhdr = p->payload;\r
141 \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
145        pbuf_free(p);\r
146        p = NULL;\r
147      }\r
148 \r
149 #if 0\r
150   switch (htons(ethhdr->type)) {\r
151   /* IP or ARP packet? */\r
152   case ETHTYPE_IP:\r
153   case ETHTYPE_ARP:\r
154 #if PPPOE_SUPPORT\r
155   /* PPPoE packet? */\r
156   case ETHTYPE_PPPOEDISC:\r
157   case ETHTYPE_PPPOE:\r
158 #endif /* PPPOE_SUPPORT */\r
159     \r
160     break;\r
161 \r
162   default:\r
163     pbuf_free(p);\r
164     p = NULL;\r
165     break;\r
166   }\r
167 #endif\r
168 \r
169 }\r
170 \r
171 /**\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
175  *\r
176  * This function should be passed as a parameter to netif_add().\r
177  *\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
182  */\r
183 err_t\r
184 ne2kif_init(struct netif *netif)\r
185 {\r
186 \r
187 #if LWIP_NETIF_HOSTNAME\r
188   /* Initialize interface hostname */\r
189   netif->hostname = "lwip";\r
190 #endif /* LWIP_NETIF_HOSTNAME */\r
191 \r
192   /*\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
196    */\r
197   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);\r
198 \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
208   \r
209 \r
210   /* set MAC hardware address length */\r
211   netif->hwaddr_len = ETHARP_HWADDR_LEN;\r
212 \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
220 \r
221   /* maximum transfer unit */\r
222   netif->mtu = 1500;\r
223   \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
227 \r
228   //initate ne2k hardware\r
229   Init_Ne2k(&ne2kif_input);\r
230 \r
231   return ERR_OK;\r
232 }\r