Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/net/ethernetif.c need to be fixed.

0001 /*
0002  * Portions Copyright (c) 2001-2004 Swedish Institute of Computer Science.
0003  * All rights reserved.
0004  *
0005  * Redistribution and use in source and binary forms, with or without modification,
0006  * are permitted provided that the following conditions are met:
0007  *
0008  * 1. Redistributions of source code must retain the above copyright notice,
0009  *    this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright notice,
0011  *    this list of conditions and the following disclaimer in the documentation
0012  *    and/or other materials provided with the distribution.
0013  * 3. The name of the author may not be used to endorse or promote products
0014  *    derived from this software without specific prior written permission.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
0017  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
0019  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0021  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0024  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
0025  * OF SUCH DAMAGE.
0026  *
0027  * This file is part of the lwIP TCP/IP stack.
0028  *
0029  * Author: Adam Dunkels <adam@sics.se>
0030  *
0031  */
0032 
0033 /*                    The Quest Operating System
0034  *  Portions Copyright (C) 2005-2010  Richard West, Boston University
0035  *
0036  *  This program is free software: you can redistribute it and/or modify
0037  *  it under the terms of the GNU General Public License as published by
0038  *  the Free Software Foundation, either version 3 of the License, or
0039  *  (at your option) any later version.
0040  *
0041  *  This program is distributed in the hope that it will be useful,
0042  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0043  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0044  *  GNU General Public License for more details.
0045  *
0046  *  You should have received a copy of the GNU General Public License
0047  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0048  */
0049 
0050 /* Ported to Quest by: Matthew Danish (md) */
0051 
0052 #include "lwip/init.h"
0053 #include "lwip/opt.h"
0054 #include "lwip/def.h"
0055 #include "lwip/mem.h"
0056 #include "lwip/pbuf.h"
0057 #include "lwip/sys.h"
0058 #include "lwip/netif.h"
0059 #include "lwip/udp.h"
0060 #include "lwip/tcp.h"
0061 #include "lwip/dhcp.h"
0062 #include <lwip/stats.h>
0063 #include <lwip/snmp.h>
0064 #include "netif/etharp.h"
0065 #include "netif/ppp_oe.h"
0066 
0067 #include "types.h"
0068 #include "string.h"
0069 #include "drivers/net/ethernet.h"
0070 #include "util/debug.h"
0071 #include "util/printf.h"
0072 #include "util/circular.h"
0073 #include "sched/sched.h"
0074 #include "module/header.h"
0075 #include "kernel.h"
0076 
0077 //#define DEBUG_NETIF
0078 
0079 #ifdef DEBUG_NETIF
0080 #define DLOG(fmt,...) DLOG_PREFIX("netif",fmt,##__VA_ARGS__)
0081 #else
0082 #define DLOG(fmt,...) ;
0083 #endif
0084 
0085 /* Define those to better describe your network interface. */
0086 #define IFNAME0 'e'
0087 #define IFNAME1 'n'
0088 
0089 /**
0090  * Helper struct to hold private data used to operate your ethernet interface.
0091  * Keeping the ethernet address of the MAC in this struct is not necessary
0092  * as it is already kept in the struct netif.
0093  * But this is only an example, anyway...
0094  */
0095 struct ethernetif {
0096   /* current location and size of received buffer */
0097   uint8* cur_buf;
0098   uint cur_len;
0099   ethernet_device *dev;
0100 };
0101 
0102 /* Forward declarations. */
0103 static void  ethernetif_input(struct netif *netif);
0104 
0105 /**
0106  * In this function, the hardware should be initialized.
0107  * Called from ethernetif_init().
0108  *
0109  * @param netif the already initialized lwip network interface structure
0110  *        for this ethernetif
0111  */
0112 static void
0113 low_level_init(struct netif *netif)
0114 {
0115   struct ethernetif *ethernetif = netif->state;
0116   /* set MAC hardware address length */
0117   netif->hwaddr_len = ETHARP_HWADDR_LEN;
0118 
0119   ethernetif->dev->get_hwaddr_func (netif->hwaddr);
0120 
0121   /* maximum transfer unit */
0122   netif->mtu = 1500;
0123 
0124   /* device capabilities */
0125   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
0126   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
0127 }
0128 
0129 /**
0130  * This function should do the actual transmission of the packet. The packet is
0131  * contained in the pbuf that is passed to the function. This pbuf
0132  * might be chained.
0133  *
0134  * @param netif the lwip network interface structure for this ethernetif
0135  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
0136  * @return ERR_OK if the packet could be sent
0137  *         an err_t value if the packet couldn't be sent
0138  *
0139  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
0140  *       strange results. You might consider waiting for space in the DMA queue
0141  *       to become availale since the stack doesn't retry to send a packet
0142  *       dropped because of memory failure (except for the TCP timers).
0143  */
0144 
0145 static err_t
0146 low_level_output(struct netif *netif, struct pbuf *p)
0147 {
0148   struct ethernetif *ethernetif = netif->state;
0149   struct pbuf *q;
0150   uint8 buffer[MAX_FRAME_SIZE], *ptr; /* this is a kludge for the moment */
0151 
0152 #if ETH_PAD_SIZE
0153   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
0154 #endif
0155 
0156   ptr = buffer;
0157   for(q = p; q != NULL; q = q->next) {
0158     /* Send the data from the pbuf to the interface, one pbuf at a
0159        time. The size of the data in each pbuf is kept in the ->len
0160        variable. */
0161     memcpy(ptr, q->payload, q->len);
0162     ptr += q->len;
0163   }
0164 
0165   if (ethernetif->dev->send_func (buffer, p->tot_len) != p->tot_len)
0166     return ERR_BUF;
0167 
0168 #if ETH_PAD_SIZE
0169   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
0170 #endif
0171 
0172   LINK_STATS_INC(link.xmit);
0173 
0174   return ERR_OK;
0175 }
0176 
0177 /**
0178  * Should allocate a pbuf and transfer the bytes of the incoming
0179  * packet from the interface into the pbuf.
0180  *
0181  * @param netif the lwip network interface structure for this ethernetif
0182  * @return a pbuf filled with the received packet (including MAC header)
0183  *         NULL on memory error
0184  */
0185 static struct pbuf *
0186 low_level_input(struct netif *netif)
0187 {
0188   struct ethernetif *ethernetif = netif->state;
0189   struct pbuf *p, *q;
0190   uint8 *buffer;
0191   uint len, start;
0192 
0193   len = ethernetif->cur_len;
0194   buffer = ethernetif->cur_buf;
0195 
0196 #if ETH_PAD_SIZE
0197   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
0198 #endif
0199 
0200   /* We allocate a pbuf chain of pbufs from the pool. */
0201   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
0202 
0203   if (p != NULL) {
0204 
0205 #if ETH_PAD_SIZE
0206     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
0207 #endif
0208 
0209 
0210     /* Read enough bytes to fill this pbuf in the chain. The
0211      * available data in the pbuf is given by the q->len
0212      * variable.
0213      * This does not necessarily have to be a memcpy, you can also preallocate
0214      * pbufs for a DMA-enabled MAC and after receiving truncate it to the
0215      * actually received size. In this case, ensure the tot_len member of the
0216      * pbuf is the sum of the chained pbuf len members.
0217      */
0218     start=0;
0219     for (q = p; q != NULL; q = q->next) {
0220       /* Read enough bytes to fill this pbuf in the chain. The
0221          available data in the pbuf is given by the q->len
0222          variable. */
0223       /* read data into(q->payload, q->len); */
0224       memcpy(q->payload, (uint8 *)&buffer[start], q->len);
0225       start += q->len;
0226       len -= q->len;
0227       if (len<=0) {
0228         break;
0229       }
0230 
0231     }
0232 
0233 #if ETH_PAD_SIZE
0234     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
0235 #endif
0236 
0237     LINK_STATS_INC(link.recv);
0238   } else {
0239     LINK_STATS_INC(link.memerr);
0240     LINK_STATS_INC(link.drop);
0241   }
0242 
0243   return p;
0244 }
0245 
0246 /**
0247  * This function should be called when a packet is ready to be read
0248  * from the interface. It uses the function low_level_input() that
0249  * should handle the actual reception of bytes from the network
0250  * interface. Then the type of the received packet is determined and
0251  * the appropriate input function is called.
0252  *
0253  * @param netif the lwip network interface structure for this ethernetif
0254  */
0255 static void
0256 ethernetif_input(struct netif *netif)
0257 {
0258   /*struct ethernetif *ethernetif;*/
0259   struct eth_hdr *ethhdr;
0260   struct pbuf *p = low_level_input (netif);
0261 
0262   if (!p) return;
0263 
0264   /*ethernetif = netif->state;*/
0265 
0266   ethhdr = (struct eth_hdr*) (p->payload);
0267 
0268   switch (htons(ethhdr->type)) {
0269     /* IP or ARP packet? */
0270   case ETHTYPE_IP:
0271   case ETHTYPE_ARP:
0272     /* full packet send to tcpip_thread to process */
0273     if (netif->input(p, netif)!=ERR_OK) {
0274       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
0275       pbuf_free(p);
0276       p = NULL;
0277     }
0278     break;
0279 
0280   default:
0281     logger_printf("ethernetif_input: unknown type %d\n", htons (ethhdr->type));
0282     pbuf_free(p);
0283     p = NULL;
0284     break;
0285   }
0286 
0287 }
0288 
0289 /**
0290  * Should be called at the beginning of the program to set up the
0291  * network interface. It calls the function low_level_init() to do the
0292  * actual setup of the hardware.
0293  *
0294  * This function should be passed as a parameter to netif_add().
0295  *
0296  * @param netif the lwip network interface structure for this ethernetif
0297  * @return ERR_OK if the loopif is initialized
0298  *         ERR_MEM if private data couldn't be allocated
0299  *         any other err_t on error
0300  */
0301 err_t
0302 ethernetif_init(struct netif *netif)
0303 {
0304   struct ethernetif *ethernetif = netif->state;
0305 
0306   LWIP_ASSERT("netif != NULL", (netif != NULL));
0307 
0308 #if LWIP_NETIF_HOSTNAME
0309   /* Initialize interface hostname */
0310   netif->hostname = "lwip";
0311 #endif /* LWIP_NETIF_HOSTNAME */
0312 
0313   /*
0314    * Initialize the snmp variables and counters inside the struct netif.
0315    * The last argument should be replaced with your link speed, in units
0316    * of bits per second.
0317    */
0318   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
0319 
0320   netif->name[0] = IFNAME0;
0321   netif->name[1] = IFNAME1;
0322   netif->num = ethernetif->dev->num;
0323   /* We directly use etharp_output() here to save a function call.
0324    * You can instead declare your own function an call etharp_output()
0325    * from it if you have to do some checks before sending (e.g. if link
0326    * is available...) */
0327   netif->output = etharp_output;
0328   netif->linkoutput = low_level_output;
0329 
0330   /*ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);*/
0331 
0332   /* initialize the hardware */
0333   low_level_init(netif);
0334 
0335   return ERR_OK;
0336 }
0337 
0338 static void
0339 dispatch(ethernet_device *dev, uint8* buf, sint len)
0340 {
0341   struct ethernetif *ethernetif = dev->netif.state;
0342   ethernetif->cur_buf = buf;
0343   ethernetif->cur_len = len;
0344   ethernetif_input (&dev->netif);
0345 }
0346 
0347 /* ************************************************** */
0348 
0349 /* Demo Echo server on port 7 */
0350 
0351 static void
0352 echo_close (struct tcp_pcb* pcb)
0353 {
0354   tcp_close (pcb);
0355 }
0356 
0357 static err_t
0358 echo_sent (void* arg, struct tcp_pcb* pcb, u16_t len)
0359 {
0360   DLOG ("echo_sent (%p, %p, %p)", arg, pcb, len);
0361   return ERR_OK;
0362 }
0363 
0364 static err_t
0365 echo_send (struct tcp_pcb* pcb, struct pbuf* p)
0366 {
0367   err_t wr_err = ERR_OK;
0368   struct pbuf* q;
0369   u16_t plen;
0370 
0371   while (wr_err == ERR_OK &&
0372          p != NULL &&
0373          p->len <= tcp_sndbuf (pcb)) {
0374     q = p;
0375     wr_err = tcp_write (pcb, p->payload, p->len, 1);
0376     if (wr_err == ERR_OK) {
0377       plen = p->len;
0378       p = p->next;
0379       if (p)
0380         pbuf_ref (p);
0381       while (pbuf_free (q) == 0);
0382       tcp_recved (pcb, plen);
0383     }
0384   }
0385   return ERR_OK;
0386 }
0387 
0388 static err_t
0389 echo_recv (void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
0390 {
0391   err_t ret_err = ERR_OK;
0392   DLOG ("echo_recv (%p, %p, %p, %p)", arg, pcb, p, err);
0393   if (p == NULL) {
0394     if (p) pbuf_free (p);
0395     echo_close (pcb);
0396   } else if (err != ERR_OK) {
0397     if (p) pbuf_free (p);
0398   } else {
0399     tcp_sent(pcb, echo_sent);
0400     echo_send(pcb, p);
0401     ret_err = ERR_OK;
0402   }
0403   return ret_err;
0404 }
0405 
0406 static err_t
0407 echo_accept (void* arg, struct tcp_pcb* pcb, err_t err)
0408 {
0409   DLOG ("echo_accept (%p, (%p, %d, %d), %p)",
0410         arg, pcb, pcb->local_port, pcb->remote_port, err);
0411   tcp_accepted (pcb);
0412   tcp_recv (pcb, echo_recv);
0413 
0414   return ERR_OK;
0415 }
0416 
0417 static void
0418 echo_init (void)
0419 {
0420   struct tcp_pcb* echo_pcb = tcp_new ();
0421   tcp_bind (echo_pcb, IP_ADDR_ANY, 7);
0422   echo_pcb = tcp_listen (echo_pcb);
0423   tcp_accept (echo_pcb, echo_accept);
0424 }
0425 
0426 /* ************************************************** */
0427 
0428 /* Demo HTTP server on port 80 */
0429 
0430 #define KHTTPD_CPU 2
0431 #define KHTTPD_BUF_LEN 8
0432 #define KHTTPD_STR_SIZ 256
0433 typedef struct {
0434   struct tcp_pcb *pcb;
0435   u32 len;
0436   s8 str[KHTTPD_STR_SIZ];
0437 } khttpd_msg_t;
0438 khttpd_msg_t khttpd_circ_buf[KHTTPD_BUF_LEN];
0439 circular khttpd_circ;
0440 
0441 static void
0442 khttpd_close (struct tcp_pcb* pcb)
0443 {
0444   tcp_close (pcb);
0445 }
0446 
0447 static err_t
0448 khttpd_sent (void* arg, struct tcp_pcb* pcb, u16_t len)
0449 {
0450   DLOG ("khttpd_sent (%p, %p, %p)", arg, pcb, len);
0451   tcp_close (pcb);
0452   return ERR_OK;
0453 }
0454 
0455 static err_t
0456 khttpd_recv (void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
0457 {
0458   struct pbuf *q;
0459   u16 plen;
0460   err_t ret_err = ERR_OK;
0461   khttpd_msg_t msg;
0462 
0463   DLOG ("khttpd_recv (%p, %p, %p, %p)", arg, pcb, p, err);
0464   if (p == NULL) {
0465     if (p) pbuf_free (p);
0466     khttpd_close (pcb);
0467   } else if (err != ERR_OK) {
0468     if (p) pbuf_free (p);
0469   } else {
0470     while (p != NULL) {
0471       s8 *s = p->payload;
0472       q = p;
0473       plen = p->len;
0474 
0475       do {
0476         u16 curlen = plen > KHTTPD_STR_SIZ ? KHTTPD_STR_SIZ : plen;
0477         memset (msg.str, 0, KHTTPD_STR_SIZ);
0478         memcpy (msg.str, s, curlen);
0479         msg.pcb = pcb;
0480         msg.len = curlen;
0481         circular_insert (&khttpd_circ, &msg);
0482         plen -= curlen;
0483         s += curlen;
0484       } while (plen > 0);
0485 
0486       p = p->next;
0487       if (p)
0488         pbuf_ref (p);
0489       while (pbuf_free (q) == 0);
0490       tcp_recved (pcb, plen);
0491     }
0492     ret_err = ERR_OK;
0493   }
0494   return ret_err;
0495 }
0496 
0497 static err_t
0498 khttpd_accept (void* arg, struct tcp_pcb* pcb, err_t err)
0499 {
0500   DLOG ("khttpd_accept (%p, (%p, %d, %d), %p)",
0501         arg, pcb, pcb->local_port, pcb->remote_port, err);
0502   tcp_accepted (pcb);
0503   tcp_recv (pcb, khttpd_recv);
0504 
0505   return ERR_OK;
0506 }
0507 
0508 static task_id khttpd_id;
0509 static u32 khttpd_stack[1024] ALIGNED (0x1000);
0510 static void
0511 khttpd_thread (void)
0512 {
0513   logger_printf ("khttpd_thread: hello from 0x%x\n", str ());
0514   for (;;) {
0515     khttpd_msg_t msg;
0516     circular_remove (&khttpd_circ, &msg);
0517     tcp_sent(msg.pcb, khttpd_sent);
0518     //tcp_write (msg.pcb, msg.str, strlen ((const char *) msg.str), 1);
0519 #define send(s) tcp_write (msg.pcb, s, strlen ((const char *) s), 1)
0520     send ("HTTP/1.0 200 OK\r\n"
0521           "Server: Quest\r\n"
0522           "Content-Type: text/html\r\n"
0523           "\r\n"
0524           "<html><head><title>The Quest OS</title></head>"
0525           "<body><p>Hello World!</p></body></html>\r\n");
0526 #undef send
0527   }
0528 }
0529 
0530 static void
0531 khttpd_init (void)
0532 {
0533   circular_init (&khttpd_circ,
0534                  (void *) khttpd_circ_buf,
0535                  KHTTPD_BUF_LEN,
0536                  KHTTPD_STR_SIZ);
0537 
0538   khttpd_id =
0539     start_kernel_thread ((u32) khttpd_thread, (u32) &khttpd_stack[1023]);
0540   lookup_TSS (khttpd_id)->cpu = KHTTPD_CPU;
0541   struct tcp_pcb* khttpd_pcb = tcp_new ();
0542   tcp_bind (khttpd_pcb, IP_ADDR_ANY, 80);
0543   khttpd_pcb = tcp_listen (khttpd_pcb);
0544   tcp_accept (khttpd_pcb, khttpd_accept);
0545 }
0546 
0547 /* ************************************************** */
0548 
0549 /* gdbstub debugging over tcp */
0550 
0551 #ifdef GDBSTUB_TCP
0552 static struct tcp_pcb* debug_client = NULL;    /* current gdbstub client */
0553 static char debug_buffer[GDBSTUB_BUFFER_SIZE]; /* ring buffer */
0554 static uint debug_ins_pt=0;                    /* insert point */
0555 static uint debug_buf_cnt=0;                   /* count of chars in buffer */
0556 static uint debug_send_cnt=0;                  /* count of chars awaiting send ACK */
0557 static struct netif* debug_netif = NULL;       /* netif for ethernet device */
0558 
0559 bool break_requested = FALSE;
0560 
0561 /* buffer received data from TCP until getDebugChar can read it */
0562 static err_t
0563 debug_recv (void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
0564 {
0565   struct pbuf* q;
0566   int i;
0567 
0568   if (p == NULL) {
0569     _printf ("GDBstub disconnected\n");
0570     /* reset state */
0571     tcp_close (debug_client);
0572     debug_client = NULL;
0573     debug_ins_pt = debug_buf_cnt = 0;
0574     debug_send_cnt = 0;
0575     return ERR_OK; /* disconnected */
0576   }
0577 
0578   if (p->payload && *((char *)p->payload) == 3) {
0579     /* Ctrl-C */
0580     q = p; p = p->next;
0581     if (p) pbuf_ref (p);
0582     while (q->ref > 0) pbuf_free (q);
0583     break_requested = TRUE;
0584   }
0585 
0586   /* read the pbufs into the ring buffer */
0587   while (p != NULL &&
0588          p->payload != NULL &&
0589          debug_buf_cnt < GDBSTUB_BUFFER_SIZE) {
0590     q = p;
0591     for (i=0; i<p->len;
0592          i++, debug_ins_pt=(debug_ins_pt+1)%GDBSTUB_BUFFER_SIZE)
0593       debug_buffer[debug_ins_pt] = ((char *)p->payload)[i];
0594     p = p->next;
0595     if (p) pbuf_ref (p);
0596     while (q->ref > 0) pbuf_free (q);
0597     tcp_recved (pcb, i);
0598     debug_buf_cnt += i;
0599   }
0600 
0601   return ERR_OK;
0602 }
0603 
0604 /* record how many bytes were sent successfully */
0605 static err_t
0606 debug_sent (void* arg, struct tcp_pcb* pcb, u16_t len)
0607 {
0608   if (debug_send_cnt > 0)
0609     debug_send_cnt--;
0610   return ERR_OK;
0611 }
0612 
0613 #endif
0614 
0615 /* accept a gdbstub connection */
0616 static err_t
0617 debug_accept (void* arg, struct tcp_pcb* pcb, err_t err)
0618 {
0619 #ifdef GDBSTUB_TCP
0620   void set_debug_traps (void);
0621 
0622   tcp_accepted (pcb);
0623   tcp_recv (pcb, debug_recv);
0624   tcp_sent (pcb, debug_sent);
0625   debug_client = pcb;
0626   debug_netif = netif_find (GDBSTUB_ETHDEV);
0627   if (!debug_netif) return ERR_ARG;
0628   _printf ("Accepted GDBstub TCP client\n");
0629   set_debug_traps ();
0630   BREAKPOINT ();
0631   return ERR_OK;
0632 #else
0633   return ERR_ARG;
0634 #endif
0635 }
0636 
0637 #ifdef GDBSTUB_TCP
0638 
0639 /* drive the lwip engine without interrupts */
0640 static void
0641 debug_poll (void)
0642 {
0643   struct ethernetif* ethernetif;
0644   ethernetif = debug_netif->state;
0645 
0646   /* poll, since interrupts are disabled */
0647   ethernetif->dev->poll_func ();
0648   /* run lwip processes */
0649   tcp_tmr ();
0650   etharp_tmr ();
0651 }
0652 
0653 /* send/recv chars over TCP */
0654 void
0655 putDebugChar (int c)
0656 {
0657   char buf[2]; buf[0] = c; buf[1] = 0;
0658 
0659   if (!debug_netif) return;
0660 
0661   if (debug_client) {
0662     while (tcp_write (debug_client, buf, 1, 1) != ERR_OK) {
0663       debug_poll ();
0664     }
0665     debug_send_cnt++;
0666     /* wait for send to finish */
0667     while (debug_send_cnt > 0) {
0668       debug_poll ();
0669     }
0670   }
0671 }
0672 
0673 int
0674 getDebugChar (void)
0675 {
0676   sint i;
0677 
0678   if (!debug_netif) return 0;
0679 
0680   while (debug_buf_cnt == 0) {
0681     debug_poll ();
0682   }
0683   i = debug_ins_pt - debug_buf_cnt;
0684   i %= GDBSTUB_BUFFER_SIZE;
0685   debug_buf_cnt--;
0686   return debug_buffer[i];
0687 }
0688 #endif
0689 
0690 /* ************************************************** */
0691 
0692 /* external init routine */
0693 
0694 static task_id net_tmr_pid;
0695 static uint32 net_tmr_stack[1024] ALIGNED (0x1000);
0696 
0697 #define NET_TMR_THREAD_WAIT_MSEC 50
0698 
0699 static void
0700 net_tmr_thread (void)
0701 {
0702   DLOG ("net_tmr_thread id=0x%x", str ());
0703   for (;;) {
0704     void net_tmr_process (void);
0705     net_tmr_process ();
0706     sched_usleep (NET_TMR_THREAD_WAIT_MSEC * 1000);
0707   }
0708 }
0709 
0710 bool
0711 net_init(void)
0712 {
0713   lwip_init ();
0714   echo_init ();
0715   khttpd_init ();
0716 
0717   net_tmr_pid = start_kernel_thread ((uint) net_tmr_thread,
0718                                      (uint) &net_tmr_stack[1023]);
0719   uint select_iovcpu (u32);
0720   lookup_TSS (net_tmr_pid)->cpu = select_iovcpu (0);
0721 
0722 #ifdef GDBSTUB_TCP
0723   {
0724     struct tcp_pcb* debug_pcb = tcp_new ();
0725     tcp_bind (debug_pcb, IP_ADDR_ANY, GDBSTUB_TCP_PORT);
0726     debug_pcb = tcp_listen (debug_pcb);
0727     tcp_accept (debug_pcb, debug_accept);
0728   }
0729 #endif
0730   return TRUE;
0731 }
0732 
0733 static uint ethernet_device_count = 0;
0734 
0735 bool
0736 net_register_device (ethernet_device *dev)
0737 {
0738   struct ethernetif *ethernetif;
0739 
0740   ethernetif = (struct ethernetif*) mem_malloc (sizeof(struct ethernetif));
0741   if (ethernetif == NULL) {
0742     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
0743     return FALSE;
0744   }
0745 
0746   dev->num = ethernet_device_count++;
0747   dev->recv_func = dispatch;
0748 
0749   DLOG ("net_register_device num=%d", dev->num);
0750 
0751   ethernetif->dev = dev;
0752 
0753   if (netif_add (&dev->netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY,
0754                  (void *)ethernetif, ethernetif_init, ethernet_input) == NULL) {
0755     ethernet_device_count--;
0756     mem_free (ethernetif);
0757     DLOG ("netif_add failed");
0758     return FALSE;
0759   }
0760 
0761   return TRUE;
0762 }
0763 
0764 /* devname is something like "enX" where X is a number */
0765 
0766 /* set device as default interface */
0767 bool
0768 net_set_default (char *devname)
0769 {
0770   struct netif *netif = netif_find (devname);
0771   if (netif) {
0772     netif_set_default (netif);
0773     return TRUE;
0774   }
0775   return FALSE;
0776 }
0777 
0778 /* start dhcp on device (and set "up" on device) */
0779 bool
0780 net_dhcp_start (char *devname)
0781 {
0782   struct netif *netif = netif_find (devname);
0783   if (netif) {
0784     dhcp_start (netif);
0785     return TRUE;
0786   }
0787   return FALSE;
0788 }
0789 
0790 /* set device to "up" status */
0791 bool
0792 net_set_up (char *devname)
0793 {
0794   struct netif *netif = netif_find (devname);
0795   if (netif) {
0796     netif_set_up (netif);
0797     return TRUE;
0798   }
0799   return FALSE;
0800 }
0801 
0802 /* give device a static configuration */
0803 bool
0804 net_static_config(char *devname, char *myip_s, char *gwip_s, char *netmask_s)
0805 {
0806   struct in_addr inaddr;
0807   struct ip_addr ipaddr, netmask, gw;
0808 
0809   struct netif *netif = netif_find (devname);
0810   if (netif == NULL) return FALSE;
0811 
0812   inet_aton (myip_s, &inaddr);
0813   ipaddr.addr = inaddr.s_addr;
0814 
0815   inet_aton (gwip_s, &inaddr);
0816   gw.addr = inaddr.s_addr;
0817 
0818   inet_aton (netmask_s, &inaddr);
0819   netmask.addr = inaddr.s_addr;
0820 
0821   netif_set_ipaddr  (netif, &ipaddr);
0822   netif_set_gw      (netif, &gw);
0823   netif_set_netmask (netif, &netmask);
0824 
0825   return TRUE;
0826 }
0827 
0828 void
0829 net_tmr_process(void)
0830 {
0831   extern volatile uint32 tick;
0832   static uint32 next_tcp_time = 0;
0833   static uint32 next_etharp_time = 0;
0834 #if LWIP_DHCP
0835   static uint32 next_dhcp_coarse_time = 0;
0836   static uint32 next_dhcp_fine_time = 0;
0837 #endif
0838 
0839   uint32 now = tick;
0840 
0841   /* assume HZ=100 */
0842 
0843   if (now >= next_tcp_time) {
0844     tcp_tmr ();
0845     next_tcp_time = now + (TCP_TMR_INTERVAL / 10);
0846   }
0847 
0848   if (now >= next_etharp_time) {
0849     etharp_tmr ();
0850     next_etharp_time = now + (ARP_TMR_INTERVAL / 10);
0851   }
0852 
0853 #if LWIP_DHCP
0854   if (now >= next_dhcp_coarse_time) {
0855     dhcp_coarse_tmr ();
0856     next_dhcp_coarse_time = now + (DHCP_COARSE_TIMER_MSECS / 10);
0857   }
0858 
0859   if (now >= next_dhcp_fine_time) {
0860     dhcp_fine_tmr ();
0861     next_dhcp_fine_time = now + (DHCP_FINE_TIMER_MSECS / 10);
0862   }
0863 #endif
0864 }
0865 
0866 static const struct module_ops mod_ops = {
0867   .init = net_init
0868 };
0869 
0870 DEF_MODULE (net___ethernet, "ethernet driver", &mod_ops, {});
0871 
0872 /*
0873  * Local Variables:
0874  * indent-tabs-mode: nil
0875  * mode: C
0876  * c-file-style: "gnu"
0877  * c-basic-offset: 2
0878  * End:
0879  */
0880 
0881 /* vi: set et sw=2 sts=2: */