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, unsigned src,
  44                                 unsigned len)
  45{
  46        NetState = NETLOOP_SUCCESS;     /* got arp reply - quit net loop */
  47}
  48
  49static void nc_handler (uchar * pkt, unsigned dest, unsigned src,
  50                        unsigned len)
  51{
  52        if (input_size)
  53                NetState = NETLOOP_SUCCESS;     /* got input - quit net loop */
  54}
  55
  56static void nc_timeout (void)
  57{
  58        NetState = NETLOOP_SUCCESS;
  59}
  60
  61void NcStart (void)
  62{
  63        if (!output_packet_len || memcmp (nc_ether, NetEtherNullAddr, 6)) {
  64                /* going to check for input packet */
  65                NetSetHandler (nc_handler);
  66                NetSetTimeout (net_timeout, nc_timeout);
  67        } else {
  68                /* send arp request */
  69                uchar *pkt;
  70                NetSetHandler (nc_wait_arp_handler);
  71                pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
  72                memcpy (pkt, output_packet, output_packet_len);
  73                NetSendUDPPacket (nc_ether, nc_ip, nc_port, nc_port, output_packet_len);
  74        }
  75}
  76
  77int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len)
  78{
  79        int end, chunk;
  80
  81        if (dest != nc_port || !len)
  82                return 0;               /* not for us */
  83
  84        if (input_size == sizeof input_buffer)
  85                return 1;               /* no space */
  86        if (len > sizeof input_buffer - input_size)
  87                len = sizeof input_buffer - input_size;
  88
  89        end = input_offset + input_size;
  90        if (end > sizeof input_buffer)
  91                end -= sizeof input_buffer;
  92
  93        chunk = len;
  94        if (end + len > sizeof input_buffer) {
  95                chunk = sizeof input_buffer - end;
  96                memcpy(input_buffer, pkt + chunk, len - chunk);
  97        }
  98        memcpy (input_buffer + end, pkt, chunk);
  99
 100        input_size += len;
 101
 102        return 1;
 103}
 104
 105static void nc_send_packet (const char *buf, int len)
 106{
 107        struct eth_device *eth;
 108        int inited = 0;
 109        uchar *pkt;
 110        uchar *ether;
 111        IPaddr_t ip;
 112
 113        if ((eth = eth_get_dev ()) == NULL) {
 114                return;
 115        }
 116
 117        if (!memcmp (nc_ether, NetEtherNullAddr, 6)) {
 118                if (eth->state == ETH_STATE_ACTIVE)
 119                        return; /* inside net loop */
 120                output_packet = buf;
 121                output_packet_len = len;
 122                NetLoop (NETCONS);      /* wait for arp reply and send packet */
 123                output_packet_len = 0;
 124                return;
 125        }
 126
 127        if (eth->state != ETH_STATE_ACTIVE) {
 128                if (eth_init (gd->bd) < 0)
 129                        return;
 130                inited = 1;
 131        }
 132        pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
 133        memcpy (pkt, buf, len);
 134        ether = nc_ether;
 135        ip = nc_ip;
 136        NetSendUDPPacket (ether, ip, nc_port, nc_port, len);
 137
 138        if (inited)
 139                eth_halt ();
 140}
 141
 142static int nc_start(void)
 143{
 144        int netmask, our_ip;
 145
 146        nc_port = 6666;         /* default port */
 147
 148        if (getenv ("ncip")) {
 149                char *p;
 150
 151                nc_ip = getenv_IPaddr ("ncip");
 152                if (!nc_ip)
 153                        return -1;      /* ncip is 0.0.0.0 */
 154                if ((p = strchr (getenv ("ncip"), ':')) != NULL)
 155                        nc_port = simple_strtoul (p + 1, NULL, 10);
 156        } else
 157                nc_ip = ~0;             /* ncip is not set */
 158
 159        our_ip = getenv_IPaddr ("ipaddr");
 160        netmask = getenv_IPaddr ("netmask");
 161
 162        if (nc_ip == ~0 ||                              /* 255.255.255.255 */
 163            ((netmask & our_ip) == (netmask & nc_ip) && /* on the same net */
 164            (netmask | nc_ip) == ~0))                   /* broadcast to our net */
 165                memset (nc_ether, 0xff, sizeof nc_ether);
 166        else
 167                memset (nc_ether, 0, sizeof nc_ether);  /* force arp request */
 168
 169        return 0;
 170}
 171
 172static void nc_putc(char c)
 173{
 174        if (output_recursion)
 175                return;
 176        output_recursion = 1;
 177
 178        nc_send_packet (&c, 1);
 179
 180        output_recursion = 0;
 181}
 182
 183static void nc_puts(const char *s)
 184{
 185        int len;
 186
 187        if (output_recursion)
 188                return;
 189        output_recursion = 1;
 190
 191        if ((len = strlen (s)) > 512)
 192                len = 512;
 193
 194        nc_send_packet (s, len);
 195
 196        output_recursion = 0;
 197}
 198
 199static int nc_getc(void)
 200{
 201        uchar c;
 202
 203        input_recursion = 1;
 204
 205        net_timeout = 0;        /* no timeout */
 206        while (!input_size)
 207                NetLoop (NETCONS);
 208
 209        input_recursion = 0;
 210
 211        c = input_buffer[input_offset++];
 212
 213        if (input_offset >= sizeof input_buffer)
 214                input_offset -= sizeof input_buffer;
 215        input_size--;
 216
 217        return c;
 218}
 219
 220static int nc_tstc(void)
 221{
 222        struct eth_device *eth;
 223
 224        if (input_recursion)
 225                return 0;
 226
 227        if (input_size)
 228                return 1;
 229
 230        eth = eth_get_dev ();
 231        if (eth && eth->state == ETH_STATE_ACTIVE)
 232                return 0;       /* inside net loop */
 233
 234        input_recursion = 1;
 235
 236        net_timeout = 1;
 237        NetLoop (NETCONS);      /* kind of poll */
 238
 239        input_recursion = 0;
 240
 241        return input_size != 0;
 242}
 243
 244int drv_nc_init (void)
 245{
 246        struct stdio_dev dev;
 247        int rc;
 248
 249        memset (&dev, 0, sizeof (dev));
 250
 251        strcpy (dev.name, "nc");
 252        dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
 253        dev.start = nc_start;
 254        dev.putc = nc_putc;
 255        dev.puts = nc_puts;
 256        dev.getc = nc_getc;
 257        dev.tstc = nc_tstc;
 258
 259        rc = stdio_register (&dev);
 260
 261        return (rc == 0) ? 1 : rc;
 262}
 263