source: SVN/cambria/redboot/packages/redboot/current/src/net/net_io.c @ 1

Last change on this file since 1 was 1, checked in by Tim Harvey, 2 years ago

restored latest version of files from server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 24.9 KB
Line 
1//==========================================================================
2//
3//      net/net_io.c
4//
5//      Stand-alone network logical I/O support for RedBoot
6//
7//==========================================================================
8//####ECOSGPLCOPYRIGHTBEGIN####
9// -------------------------------------------
10// This file is part of eCos, the Embedded Configurable Operating System.
11// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
12// Copyright (C) 2002, 2003, 2004 Gary Thomas
13//
14// eCos is free software; you can redistribute it and/or modify it under
15// the terms of the GNU General Public License as published by the Free
16// Software Foundation; either version 2 or (at your option) any later version.
17//
18// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19// WARRANTY; without even the implied warranty of MERCHANTABILITY or
20// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21// for more details.
22//
23// You should have received a copy of the GNU General Public License along
24// with eCos; if not, write to the Free Software Foundation, Inc.,
25// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26//
27// As a special exception, if other files instantiate templates or use macros
28// or inline functions from this file, or you compile this file and link it
29// with other works to produce a work based on this file, this file does not
30// by itself cause the resulting work to be covered by the GNU General Public
31// License. However the source code for this file must still be made available
32// in accordance with section (3) of the GNU General Public License.
33//
34// This exception does not invalidate any other reasons why a work based on
35// this file might be covered by the GNU General Public License.
36//
37// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38// at http://sources.redhat.com/ecos/ecos-license/
39// -------------------------------------------
40//####ECOSGPLCOPYRIGHTEND####
41//==========================================================================
42//#####DESCRIPTIONBEGIN####
43//
44// Author(s):    gthomas
45// Contributors: gthomas
46// Date:         2000-07-14
47// Purpose:     
48// Description: 
49//             
50// This code is part of RedBoot (tm).
51//
52//####DESCRIPTIONEND####
53//
54//==========================================================================
55
56#include <redboot.h>
57#include <net/net.h>
58#include <cyg/hal/hal_misc.h>   // Helper functions
59#include <cyg/hal/hal_if.h>     // HAL I/O interfaces
60#include <cyg/hal/drv_api.h>
61#include <cyg/hal/hal_intr.h>
62#include <cyg/infra/cyg_ass.h>         // assertion macros
63
64#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
65#include <flash_config.h>
66
67RedBoot_config_option("GDB connection port",
68                      gdb_port,
69                      ALWAYS_ENABLED, true,
70                      CONFIG_INT,
71                      CYGNUM_REDBOOT_NETWORKING_TCP_PORT
72    );
73RedBoot_config_option("Network debug at boot time", 
74                      net_debug, 
75                      ALWAYS_ENABLED, true,
76                      CONFIG_BOOL,
77                      false
78    );
79#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
80RedBoot_config_option("Default network device", 
81                      net_device, 
82                      ALWAYS_ENABLED, true,
83                      CONFIG_NETPORT,
84                      ""
85    );
86#endif
87// Note: the following options are related.  If 'bootp' is false, then
88// the other values are used in the configuration.  Because of the way
89// that configuration tables are generated, they should have names which
90// are related.  The configuration options will show up lexicographically
91// ordered, thus the peculiar naming.  In this case, the 'use' option is
92// negated (if false, the others apply) which makes the names even more
93// confusing.
94
95#ifndef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
96#define CYGSEM_REDBOOT_DEFAULT_NO_BOOTP 0
97#endif
98RedBoot_config_option("Use BOOTP for network configuration",
99                      bootp, 
100                      ALWAYS_ENABLED, true,
101                      CONFIG_BOOL,
102                      !CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
103    );
104RedBoot_config_option("Local IP address",
105                      bootp_my_ip,
106                      "bootp", false,
107                      CONFIG_IP,
108                      0
109    );
110#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
111RedBoot_config_option("Local IP address mask",
112                      bootp_my_ip_mask,
113                      "bootp", false,
114                      CONFIG_IP,
115                      0
116    );
117RedBoot_config_option("Gateway IP address",
118                      bootp_my_gateway_ip,
119                      "bootp", false,
120                      CONFIG_IP,
121                      0
122    );
123#endif
124RedBoot_config_option("Default server IP address",
125                      bootp_server_ip,
126                      ALWAYS_ENABLED, true,
127                      CONFIG_IP,
128                      0
129    );
130
131// Note: the following options are related too.
132RedBoot_config_option("Force console for special debug messages",
133                      info_console_force, 
134                      ALWAYS_ENABLED, true,
135                      CONFIG_BOOL,
136                      false
137    );
138RedBoot_config_option("Console number for special debug messages",
139                      info_console_number, 
140                      "info_console_force", true,
141                      CONFIG_INT,
142                      0
143    );
144#endif
145
146#define TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
147
148#ifdef DEBUG_TCP
149int show_tcp = 0;
150#endif
151
152static tcp_socket_t tcp_sock;
153static int state;
154static int _timeout = 500;
155static int orig_console, orig_debug;
156
157static int in_buflen = 0;
158static unsigned char in_buf[64];
159static unsigned char *in_bufp;
160static int out_buflen = 0;
161static unsigned char out_buf[1024];
162static unsigned char *out_bufp;
163static bool flush_output_lines = false;
164
165// Functions in this module
166static void net_io_flush(void);
167static void net_io_revert_console(void);
168static void net_io_putc(void*, cyg_uint8);
169
170// Special characters used by Telnet - must be interpretted here
171#define TELNET_IAC    0xFF // Interpret as command (escape)
172#define TELNET_IP     0xF4 // Interrupt process
173#define TELNET_WONT   0xFC // I Won't do it
174#define TELNET_DO     0xFD // Will you XXX
175#define TELNET_TM     0x06 // Time marker (special DO/WONT after IP)
176
177static cyg_bool
178_net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch)
179{
180    if (in_buflen == 0) {
181        __tcp_poll();
182        if (tcp_sock.state == _CLOSE_WAIT) {
183            // This connection is breaking
184            if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) {
185                __tcp_close(&tcp_sock);
186                return false;
187            }
188        }
189        if (tcp_sock.state == _CLOSED) {
190            // The connection is gone
191            net_io_revert_console();
192            *ch = '\n';
193            return true;
194        }
195        in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf));
196        in_bufp = in_buf;
197#ifdef DEBUG_TCP
198        if (show_tcp && (in_buflen > 0)) {
199            int old_console;
200            old_console = start_console(); 
201            diag_printf("%s:%d\n", __FUNCTION__, __LINE__); 
202            diag_dump_buf(in_buf, in_buflen); 
203            end_console(old_console);
204        }
205#endif // DEBUG_TCP
206    }
207    if (in_buflen) {
208        *ch = *in_bufp++;
209        in_buflen--;
210        return true;
211    } else {
212        return false;
213    }
214}
215
216static cyg_bool
217net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch)
218{
219    cyg_uint8 esc;
220
221    if (!_net_io_getc_nonblock(__ch_data, ch))
222        return false;
223
224    if (gdb_active || *ch != TELNET_IAC)
225        return true;
226
227    // Telnet escape - need to read/handle more
228    while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
229
230    switch (esc) {
231    case TELNET_IAC:
232        // The other special case - escaped escape
233        return true;
234    case TELNET_IP:
235        // Special case for ^C == Interrupt Process
236        *ch = 0x03; 
237        // Just in case the other end needs synchronizing
238        net_io_putc(__ch_data, TELNET_IAC);
239        net_io_putc(__ch_data, TELNET_WONT);
240        net_io_putc(__ch_data, TELNET_TM);
241        net_io_flush();
242        return true;
243    case TELNET_DO:
244        // Telnet DO option
245        while (!_net_io_getc_nonblock(__ch_data, &esc)) ;               
246        // Respond with WONT option
247        net_io_putc(__ch_data, TELNET_IAC);
248        net_io_putc(__ch_data, TELNET_WONT);
249        net_io_putc(__ch_data, esc);
250        return false;  // Ignore this whole thing!
251    default:
252        return false;
253    }
254}
255
256static cyg_uint8
257net_io_getc(void* __ch_data)
258{
259    cyg_uint8 ch;
260    int idle_timeout = 10;  // 10ms
261
262    CYGARC_HAL_SAVE_GP();
263    while (true) {
264        if (net_io_getc_nonblock(__ch_data, &ch)) break;
265        if (--idle_timeout == 0) {
266            net_io_flush();
267            idle_timeout = 10;
268        }
269    }
270    CYGARC_HAL_RESTORE_GP();
271    return ch;
272}
273
274static void
275net_io_flush(void)
276{
277    int n;
278    char *bp = out_buf;
279
280#ifdef DEBUG_TCP
281    if (show_tcp) {
282        int old_console;
283        old_console = start_console(); 
284        diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
285        diag_dump_buf(out_buf, out_buflen); 
286        end_console(old_console);
287    }
288#endif // SHOW_TCP
289    n = __tcp_write_block(&tcp_sock, bp, out_buflen);
290    if (n < 0) {
291        // The connection is gone!
292        net_io_revert_console();
293    } else {
294        out_buflen -= n;
295        bp += n;
296    }
297    out_bufp = out_buf;  out_buflen = 0;
298    // Check interrupt flag
299    if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
300        CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
301        cyg_hal_user_break(0);
302    }
303}
304
305static void
306net_io_putc(void* __ch_data, cyg_uint8 c)
307{
308    static bool have_dollar, have_hash;
309    static int hash_count;
310
311    CYGARC_HAL_SAVE_GP();
312    *out_bufp++ = c;
313    if (c == '$') have_dollar = true;
314    if (have_dollar && (c == '#')) {
315        have_hash = true;
316        hash_count = 0;
317    }
318    if ((++out_buflen == sizeof(out_buf)) ||
319        (flush_output_lines && c == '\n') ||
320        (have_hash && (++hash_count == 3))) {
321        net_io_flush();
322        have_dollar = false;
323    }
324    CYGARC_HAL_RESTORE_GP();
325}
326
327static void
328net_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
329{
330    int old_console;
331
332    old_console = start_console();
333    diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
334    end_console(old_console);
335#if 0
336    CYGARC_HAL_SAVE_GP();
337
338    while(__len-- > 0)
339        net_io_putc(__ch_data, *__buf++);
340
341    CYGARC_HAL_RESTORE_GP();
342#endif
343}
344
345static void
346net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
347{
348    int old_console;
349
350    old_console = start_console();
351    diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
352    end_console(old_console);
353#if 0
354    CYGARC_HAL_SAVE_GP();
355
356    while(__len-- > 0)
357        *__buf++ = net_io_getc(__ch_data);
358
359    CYGARC_HAL_RESTORE_GP();
360#endif
361}
362
363static cyg_bool
364net_io_getc_timeout(void* __ch_data, cyg_uint8* ch)
365{
366    int delay_count;
367    cyg_bool res;
368
369    CYGARC_HAL_SAVE_GP();
370    net_io_flush();  // Make sure any output has been sent
371    delay_count = _timeout;
372
373    for(;;) {
374        res = net_io_getc_nonblock(__ch_data, ch);
375        if (res || 0 == delay_count--)
376            break;
377    }
378
379    CYGARC_HAL_RESTORE_GP();
380
381    return res;
382}
383
384static int
385net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...)
386{
387    static int vector = 0;
388    int ret = 0;
389    static int irq_state = 0;
390
391    CYGARC_HAL_SAVE_GP();
392
393    switch (__func) {
394    case __COMMCTL_IRQ_ENABLE:
395        irq_state = 1;
396        if (vector == 0) {
397            vector = eth_drv_int_vector();
398        }
399        HAL_INTERRUPT_UNMASK(vector); 
400        break;
401    case __COMMCTL_IRQ_DISABLE:
402        ret = irq_state;
403        irq_state = 0;
404        if (vector == 0) {
405            vector = eth_drv_int_vector();
406        }
407        HAL_INTERRUPT_MASK(vector);
408        break;
409    case __COMMCTL_DBG_ISR_VECTOR:
410        ret = vector;
411        break;
412    case __COMMCTL_SET_TIMEOUT:
413    {
414        va_list ap;
415
416        va_start(ap, __func);
417
418        ret = _timeout;
419        _timeout = va_arg(ap, cyg_uint32);
420
421        va_end(ap);
422        break;
423    }
424    case __COMMCTL_FLUSH_OUTPUT:
425        net_io_flush();
426        break;
427    case __COMMCTL_ENABLE_LINE_FLUSH:
428        flush_output_lines = true;
429        break;
430    case __COMMCTL_DISABLE_LINE_FLUSH:
431        flush_output_lines = false;
432        break;
433    default:
434        break;
435    }
436    CYGARC_HAL_RESTORE_GP();
437    return ret;
438}
439
440static int
441net_io_isr(void *__ch_data, int* __ctrlc, 
442           CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
443{
444    char ch;
445
446    CYGARC_HAL_SAVE_GP();
447    *__ctrlc = 0;
448    if (net_io_getc_nonblock(__ch_data, &ch)) {
449        if (ch == 0x03) {
450            *__ctrlc = 1;
451        }
452    }
453    CYGARC_HAL_RESTORE_GP();
454    return CYG_ISR_HANDLED;
455}
456
457// TEMP
458
459int 
460start_console(void)
461{
462    int cur_console =
463        CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
464
465#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
466    int i = 0;
467    if ( flash_get_config( "info_console_force", &i, CONFIG_BOOL) )
468        if ( i )
469            if ( ! flash_get_config( "info_console_number", &i, CONFIG_INT) )
470                i = 0; // the default, if that call failed.
471    if ( i )
472        CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
473    else
474#endif
475        CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
476
477    return cur_console;
478}
479
480void
481end_console(int old_console)
482{
483    // Restore original console
484    CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console);
485}
486// TEMP
487
488static void
489net_io_revert_console(void)
490{
491#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
492    console_selected = false;
493#endif
494    CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console);
495    CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug);
496    console_echo = true;
497}
498
499static void
500net_io_assume_console(void)
501{
502#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
503    console_selected = true;
504#endif
505    console_echo = false;
506    orig_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
507    CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
508    orig_debug = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
509    CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL);
510}
511
512static void
513net_io_init(void)
514{
515    static int init = 0;
516    if (!init) {
517        hal_virtual_comm_table_t* comm;
518        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
519
520        // Setup procs in the vector table
521        CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
522        comm = CYGACC_CALL_IF_CONSOLE_PROCS();
523        //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
524        CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write);
525        CYGACC_COMM_IF_READ_SET(*comm, net_io_read);
526        CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc);
527        CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc);
528        CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control);
529        CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr);
530        CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout);
531
532        // Disable interrupts via this interface to set static
533        // state into correct state.
534        net_io_control( comm, __COMMCTL_IRQ_DISABLE );
535       
536        // Restore original console
537        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
538
539        init = 1;
540        gdb_active = false;
541    }
542    __tcp_listen(&tcp_sock, gdb_port);
543    state = tcp_sock.state; 
544#ifdef DEBUG_TCP
545    diag_printf("show tcp = %p\n", (void *)&show_tcp);
546#endif
547}
548
549// Check for incoming TCP debug connection
550void
551net_io_test(bool is_idle)
552{
553    if (!is_idle) return;  // Only care about idle case
554    if (!have_net) return;
555    __tcp_poll();
556    if (state != tcp_sock.state) {
557        // Something has changed
558        if (tcp_sock.state == _ESTABLISHED) {
559            // A new connection has arrived
560            net_io_assume_console();
561            in_bufp = in_buf;  in_buflen = 1;  *in_bufp = '\r';
562            out_bufp = out_buf;  out_buflen = 0;
563        }
564        if (tcp_sock.state == _CLOSED) {
565            net_io_init();  // Get ready for another connection
566        }
567    }
568    state = tcp_sock.state;
569}
570
571// This schedules the 'net_io_test()' function to be run by RedBoot's
572// main command loop when idle (i.e. when no input arrives after some
573// period of time).
574RedBoot_idle(net_io_test, RedBoot_IDLE_NETIO);
575
576//
577// Network initialization
578//
579#include <cyg/io/eth/eth_drv.h>
580#include <cyg/io/eth/netdev.h>
581#include <cyg/hal/hal_tables.h>
582
583// Define table boundaries
584CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
585CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
586
587RedBoot_init(net_init, RedBoot_INIT_LAST);
588
589static void
590show_addrs(void)
591{
592    diag_printf("IP: %s", inet_ntoa((in_addr_t *)&__local_ip_addr));
593#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
594    diag_printf("/%s", inet_ntoa((in_addr_t *)&__local_ip_mask));
595    diag_printf(", Gateway: %s\n", inet_ntoa((in_addr_t *)&__local_ip_gate));
596#else
597    diag_printf(", ");
598#endif
599    diag_printf("Default server: %s", inet_ntoa(&my_bootp_info.bp_siaddr));
600#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
601    show_dns();
602#endif
603    diag_printf("\n");
604}
605
606#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
607static void
608flash_get_IP(char *id, ip_addr_t *val)
609{
610    ip_addr_t my_ip;
611    int i;
612
613    if (flash_get_config(id, &my_ip, CONFIG_IP)) {
614        if (my_ip[0] != 0 || my_ip[1] != 0 ||
615            my_ip[2] != 0 || my_ip[3] != 0) {
616            // 'id' is set to something so let it override any static IP
617            for (i=0; i<4; i++)
618                (*val)[i] = my_ip[i];
619        }       
620    }
621}
622#endif
623
624static cyg_netdevtab_entry_t *
625net_devtab_entry(unsigned index)
626{
627    cyg_netdevtab_entry_t *t = &__NETDEVTAB__[index];
628
629    if (t < &__NETDEVTAB__[0] || t >= &__NETDEVTAB_END__)
630        return NULL;
631
632    return t;
633}
634
635const char *
636net_devname(unsigned index)
637{
638    cyg_netdevtab_entry_t *t = net_devtab_entry(index);
639    if (t)
640        return t->name;
641    return NULL;
642}
643
644int
645net_devindex(char *name)
646{
647    const char *devname;
648    int index;
649
650    for (index = 0; (devname = net_devname(index)) != NULL; index++)
651        if (!strcmp(name, devname))
652            return index;
653    return -1;
654}
655
656static void
657show_eth_info(void)
658{
659    diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
660                __local_enet_sc->dev_name,
661                __local_enet_addr[0],
662                __local_enet_addr[1],
663                __local_enet_addr[2],
664                __local_enet_addr[3],
665                __local_enet_addr[4],
666                __local_enet_addr[5]);
667}
668
669void
670net_init(void)
671{
672    cyg_netdevtab_entry_t *t;
673    unsigned index;
674    struct eth_drv_sc *primary_net = (struct eth_drv_sc *)0;
675#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
676    char *default_devname;
677    int default_index;
678#endif
679#ifdef CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR
680    char ip_addr[16];
681#endif
682
683    // Set defaults as appropriate
684#ifdef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
685    use_bootp = false;
686#else
687    use_bootp = true;
688#endif
689#ifdef CYGDBG_REDBOOT_NET_DEBUG
690    net_debug = true;
691#else
692    net_debug = false;
693#endif
694    gdb_port = CYGNUM_REDBOOT_NETWORKING_TCP_PORT;
695#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
696    // Fetch values from saved config data, if available
697#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
698    flash_get_config("net_device", &default_devname, CONFIG_NETPORT);
699#endif
700    flash_get_config("net_debug", &net_debug, CONFIG_BOOL);
701    flash_get_config("gdb_port", &gdb_port, CONFIG_INT);
702    flash_get_config("bootp", &use_bootp, CONFIG_BOOL);
703    if (!use_bootp) {
704        flash_get_IP("bootp_my_ip", &__local_ip_addr);
705#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
706        flash_get_IP("bootp_my_ip_mask", &__local_ip_mask);
707        flash_get_IP("bootp_my_gateway_ip", &__local_ip_gate);
708#endif
709    }
710#endif
711# ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
712    // Don't override if the user has deliberately set something more
713    // verbose.
714    if (0 == cyg_io_eth_net_debug)
715        cyg_io_eth_net_debug = net_debug;
716# endif
717    have_net = false;
718    // Make sure the recv buffers are set up
719    eth_drv_buffers_init();
720    __pktbuf_init();
721
722    // Initialize network device(s).
723#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
724    default_index = net_devindex(default_devname);
725    if (default_index < 0)
726        default_index = 0;
727#ifdef CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE
728    if ((t = net_devtab_entry(default_index)) != NULL && t->init(t)) {
729        t->status = CYG_NETDEVTAB_STATUS_AVAIL;
730        primary_net = __local_enet_sc;
731    } else
732#endif
733#endif
734    for (index = 0; (t = net_devtab_entry(index)) != NULL; index++) {
735#if defined(CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE)
736        if (index == default_index)
737            continue;
738#endif
739        if (t->init(t)) {
740            t->status = CYG_NETDEVTAB_STATUS_AVAIL;
741            if (primary_net == (struct eth_drv_sc *)0) {
742                primary_net = __local_enet_sc;
743            }
744#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
745#if !defined(CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE)
746            if (index == default_index) {
747                primary_net = __local_enet_sc;
748            }
749#else
750            break;
751#endif
752#endif
753        }
754    }
755    __local_enet_sc = primary_net;
756
757    if (!__local_enet_sc) {
758        diag_printf("No network interfaces found\n");
759        return;
760    }   
761    // Initialize the network [if present]
762    if (use_bootp) {
763        if (__bootp_find_local_ip(&my_bootp_info) == 0) {
764            have_net = true;
765        } else {
766            // Is it an unset address, or has it been set to a static addr
767            if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 &&
768                __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) {
769                show_eth_info();
770                diag_printf("Can't get BOOTP info for device!\n");
771            } else {
772                diag_printf("Can't get BOOTP info, using default IP address\n");
773                have_net = true;
774            }
775        }
776    } else {
777        enet_addr_t enet_addr;
778        have_net = true;  // Assume values in FLASH were OK
779        // Tell the world that we are using this fixed IP address
780        if (__arp_request((ip_addr_t *)__local_ip_addr, &enet_addr, 1) >= 0) {
781            diag_printf("Warning: IP address %s in use\n", inet_ntoa((in_addr_t *)&__local_ip_addr));
782        }
783    }
784    if (have_net) {
785        show_eth_info();
786#ifdef CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR
787        diag_sprintf(ip_addr, "%d.%d.%d.%d", 
788                     CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR);
789        inet_aton(ip_addr, &my_bootp_info.bp_siaddr);
790#endif
791#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
792        flash_get_IP("bootp_server_ip", (ip_addr_t *)&my_bootp_info.bp_siaddr);
793#endif
794#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
795        redboot_dns_res_init();
796#endif
797        show_addrs();
798        net_io_init();
799    }
800}
801
802static char usage[] = "[-l <local_ip_address>[/<mask_len>]] [-h <server_address>]";
803
804// Exported CLI function
805static void do_ip_addr(int argc, char *argv[]);
806RedBoot_cmd("ip_address", 
807            "Set/change IP addresses", 
808            usage,
809            do_ip_addr
810    );
811
812void 
813do_ip_addr(int argc, char *argv[])
814{
815    struct option_info opts[3];
816    char *ip_addr, *host_addr;
817    bool ip_addr_set, host_addr_set;
818    struct sockaddr_in host;
819#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
820    char *dns_addr;
821    bool dns_addr_set;
822#endif
823    int num_opts;
824
825    init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR, 
826              (void *)&ip_addr, (bool *)&ip_addr_set, "local IP address");
827    init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR, 
828              (void *)&host_addr, (bool *)&host_addr_set, "default server address");
829    num_opts = 2;
830#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
831    init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_STR, 
832              (void *)&dns_addr, (bool *)&dns_addr_set, "DNS server address");
833    num_opts++;
834#endif
835
836    CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options");
837
838    if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) {
839        return;
840    }
841    if (ip_addr_set) {
842#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
843        char *slash_pos;
844        /* see if the (optional) mask length was given */
845        if( (slash_pos = strchr(ip_addr, '/')) ) {
846            int mask_len;
847            unsigned long mask;
848            *slash_pos = '\0';
849            slash_pos++;
850            if( !parse_num(slash_pos, (unsigned long *)&mask_len, 0, 0) || 
851                mask_len <= 0 || mask_len > 32 ) {
852                diag_printf("Invalid mask length: %s\n", slash_pos);
853                return;
854            }
855            mask = htonl((0xffffffff << (32-mask_len))&0xffffffff);
856            memcpy(&__local_ip_mask, &mask, 4);
857        }
858#endif       
859        if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) {
860            diag_printf("Invalid local IP address: %s\n", ip_addr);
861            return;
862        }
863        // Of course, each address goes in its own place :-)
864        memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr));
865    }
866    if (host_addr_set) {
867        if (!_gethostbyname(host_addr, (in_addr_t *)&host)) {
868            diag_printf("Invalid server address: %s\n", host_addr);
869            return;
870        }
871        my_bootp_info.bp_siaddr = host.sin_addr;
872    }
873#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
874    if (dns_addr_set) {
875        set_dns(dns_addr);
876    }
877#endif
878    show_addrs();
879    if (!have_net) {
880        have_net = true;
881        net_io_init();
882    }
883}
884
885// EOF net_io.c
Note: See TracBrowser for help on using the repository browser.