uboot/drivers/net/netconsole.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <command.h>
  26#include <stdio_dev.h>
  27#include <net.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31static char input_buffer[512];
  32static int input_size = 0;              /* char count in input buffer */
  33static int input_offset = 0;            /* offset to valid chars in input buffer */
  34static int input_recursion = 0;
  35static int output_recursion = 0;
  36static int net_timeout;
  37static uchar nc_ether[6];               /* server enet address */
  38static IPaddr_t nc_ip;                  /* server ip */
  39static short nc_port;                   /* source/target port */
  40static const char *output_packet;       /* used by first send udp */
  41static int output_packet_len = 0;
  42
  43static void nc_wait_arp_handler(uchar *pkt, unsigned dest,
  44                                 IPaddr_t sip, unsigned src,
  45                                 unsigned len)
  46{
  47        NetState = NETLOOP_SUCCESS;     /* got arp reply - quit net loop */
  48}
  49
  50static void nc_handler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
  51                        unsigned len)
  52{
  53        if (input_size)
  54                NetState = NETLOOP_SUCCESS;     /* got input - quit net loop */
  55}
  56
  57static void nc_timeout (void)
  58{
  59        NetState = NETLOOP_SUCCESS;
  60}
  61
  62void NcStart (void)
  63{
  64        if (!output_packet_len || memcmp (nc_ether, NetEtherNullAddr, 6)) {
  65                /* going to check for input packet */
  66                NetSetHandler (nc_handler);
  67                NetSetTimeout (net_timeout, nc_timeout);
  68        } else {
  69                /* send arp request */
  70                uchar *pkt;
  71                NetSetHandler (nc_wait_arp_handler);
  72                pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
  73                memcpy (pkt, output_packet, output_packet_len);
  74                NetSendUDPPacket (nc_ether, nc_ip, nc_port, nc_port, output_packet_len);
  75        }
  76}
  77
  78int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len)
  79{
  80        int end, chunk;
  81
  82        if (dest != nc_port || !len)
  83                return 0;               /* not for us */
  84
  85        if (input_size == sizeof input_buffer)
  86                return 1;               /* no space */
  87        if (len > sizeof input_buffer - input_size)
  88                len = sizeof input_buffer - input_size;
  89
  90        end = input_offset + input_size;
  91        if (end > sizeof input_buffer)
  92                end -= sizeof input_buffer;
  93
  94        chunk = len;
  95        if (end + len > sizeof input_buffer) {
  96                chunk = sizeof input_buffer - end;
  97                memcpy(input_buffer, pkt + chunk, len - chunk);
  98        }
  99        memcpy (input_buffer + end, pkt, chunk);
 100
 101        input_size += len;
 102
 103        return 1;
 104}
 105
 106static void nc_send_packet (const char *buf, int len)
 107{
 108        struct eth_device *eth;
 109        int inited = 0;
 110        uchar *pkt;
 111        uchar *ether;
 112        IPaddr_t ip;
 113
 114        if ((eth = eth_get_dev ()) == NULL) {
 115                return;
 116        }
 117
 118        if (!memcmp (nc_ether, NetEtherNullAddr, 6)) {
 119                if (eth->state == ETH_STATE_ACTIVE)
 120                        return; /* inside net loop */
 121                output_packet = buf;
 122                output_packet_len = len;
 123                NetLoop (NETCONS);      /* wait for arp reply and send packet */
 124                output_packet_len = 0;
 125                return;
 126        }
 127
 128        if (eth->state != ETH_STATE_ACTIVE) {
 129                if (eth_init (gd->bd) < 0)
 130                        return;
 131                inited = 1;
 132        }
 133        pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
 134        memcpy (pkt, buf, len);
 135        ether = nc_ether;
 136        ip = nc_ip;
 137        NetSendUDPPacket (ether, ip, nc_port, nc_port, len);
 138
 139        if (inited)
 140                eth_halt ();
 141}
 142
 143static int nc_start(void)
 144{
 145        int netmask, our_ip;
 146
 147        nc_port = 6666;         /* default port */
 148
 149        if (getenv ("ncip")) {
 150                char *p;
 151
 152                nc_ip = getenv_IPaddr ("ncip");
 153                if (!nc_ip)
 154                        return -1;      /* ncip is 0.0.0.0 */
 155                if ((p = strchr (getenv ("ncip"), ':')) != NULL)
 156                        nc_port = simple_strtoul (p + 1, NULL, 10);
 157        } else
 158                nc_ip = ~0;             /* ncip is not set */
 159
 160        our_ip = getenv_IPaddr ("ipaddr");
 161        netmask = getenv_IPaddr ("netmask");
 162
 163        if (nc_ip == ~0 ||                              /* 255.255.255.255 */
 164            ((netmask & our_ip) == (netmask & nc_ip) && /* on the same net */
 165            (netmask | nc_ip) == ~0))                   /* broadcast to our net */
 166                memset (nc_ether, 0xff, sizeof nc_ether);
 167        else
 168                memset (nc_ether, 0, sizeof nc_ether);  /* force arp request */
 169
 170        return 0;
 171}
 172
 173static void nc_putc(char c)
 174{
 175        if (output_recursion)
 176                return;
 177        output_recursion = 1;
 178
 179        nc_send_packet (&c, 1);
 180
 181        output_recursion = 0;
 182}
 183
 184static void nc_puts(const char *s)
 185{
 186        int len;
 187
 188        if (output_recursion)
 189                return;
 190        output_recursion = 1;
 191
 192        len = strlen(s);
 193        while (len) {
 194                int send_len = min(len, 512);
 195                nc_send_packet(s, send_len);
 196                len -= send_len;
 197                s += send_len;
 198        }
 199
 200        output_recursion = 0;
 201}
 202
 203static int nc_getc(void)
 204{
 205        uchar c;
 206
 207        input_recursion = 1;
 208
 209        net_timeout = 0;        /* no timeout */
 210        while (!input_size)
 211                NetLoop (NETCONS);
 212
 213        input_recursion = 0;
 214
 215        c = input_buffer[input_offset++];
 216
 217        if (input_offset >= sizeof input_buffer)
 218                input_offset -= sizeof input_buffer;
 219        input_size--;
 220
 221        return c;
 222}
 223
 224static int nc_tstc(void)
 225{
 226        struct eth_device *eth;
 227
 228        if (input_recursion)
 229                return 0;
 230
 231        if (input_size)
 232                return 1;
 233
 234        eth = eth_get_dev ();
 235        if (eth && eth->state == ETH_STATE_ACTIVE)
 236                return 0;       /* inside net loop */
 237
 238        input_recursion = 1;
 239
 240        net_timeout = 1;
 241        NetLoop (NETCONS);      /* kind of poll */
 242
 243        input_recursion = 0;
 244
 245        return input_size != 0;
 246}
 247
 248int drv_nc_init (void)
 249{
 250        struct stdio_dev dev;
 251        int rc;
 252
 253        memset (&dev, 0, sizeof (dev));
 254
 255        strcpy (dev.name, "nc");
 256        dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
 257        dev.start = nc_start;
 258        dev.putc = nc_putc;
 259        dev.puts = nc_puts;
 260        dev.getc = nc_getc;
 261        dev.tstc = nc_tstc;
 262
 263        rc = stdio_register (&dev);
 264
 265        return (rc == 0) ? 1 : rc;
 266}
 267