//==========================================================================
|
//==========================================================================
|
//
|
//
|
// net/net_io.c
|
// net/net_io.c
|
//
|
//
|
// Stand-alone network logical I/O support for RedBoot
|
// Stand-alone network logical I/O support for RedBoot
|
//
|
//
|
//==========================================================================
|
//==========================================================================
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
// -------------------------------------------
|
// -------------------------------------------
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
// Copyright (C) 2002 Gary Thomas
|
// Copyright (C) 2002 Gary Thomas
|
//
|
//
|
// eCos is free software; you can redistribute it and/or modify it under
|
// eCos is free software; you can redistribute it and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
// Software Foundation; either version 2 or (at your option) any later version.
|
// Software Foundation; either version 2 or (at your option) any later version.
|
//
|
//
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License along
|
// You should have received a copy of the GNU General Public License along
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
//
|
//
|
// As a special exception, if other files instantiate templates or use macros
|
// As a special exception, if other files instantiate templates or use macros
|
// or inline functions from this file, or you compile this file and link it
|
// or inline functions from this file, or you compile this file and link it
|
// with other works to produce a work based on this file, this file does not
|
// with other works to produce a work based on this file, this file does not
|
// by itself cause the resulting work to be covered by the GNU General Public
|
// by itself cause the resulting work to be covered by the GNU General Public
|
// License. However the source code for this file must still be made available
|
// License. However the source code for this file must still be made available
|
// in accordance with section (3) of the GNU General Public License.
|
// in accordance with section (3) of the GNU General Public License.
|
//
|
//
|
// This exception does not invalidate any other reasons why a work based on
|
// This exception does not invalidate any other reasons why a work based on
|
// this file might be covered by the GNU General Public License.
|
// this file might be covered by the GNU General Public License.
|
//
|
//
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
// at http://sources.redhat.com/ecos/ecos-license/
|
// at http://sources.redhat.com/ecos/ecos-license/
|
// -------------------------------------------
|
// -------------------------------------------
|
//####ECOSGPLCOPYRIGHTEND####
|
//####ECOSGPLCOPYRIGHTEND####
|
//==========================================================================
|
//==========================================================================
|
//#####DESCRIPTIONBEGIN####
|
//#####DESCRIPTIONBEGIN####
|
//
|
//
|
// Author(s): gthomas
|
// Author(s): gthomas
|
// Contributors: gthomas
|
// Contributors: gthomas
|
// Date: 2000-07-14
|
// Date: 2000-07-14
|
// Purpose:
|
// Purpose:
|
// Description:
|
// Description:
|
//
|
//
|
// This code is part of RedBoot (tm).
|
// This code is part of RedBoot (tm).
|
//
|
//
|
//####DESCRIPTIONEND####
|
//####DESCRIPTIONEND####
|
//
|
//
|
//==========================================================================
|
//==========================================================================
|
|
|
#include <redboot.h>
|
#include <redboot.h>
|
#include <cyg/io/eth/eth_drv.h> // Logical driver interfaces
|
#include <cyg/io/eth/eth_drv.h> // Logical driver interfaces
|
#include <net/net.h>
|
#include <net/net.h>
|
#include <cyg/hal/hal_misc.h> // Helper functions
|
#include <cyg/hal/hal_misc.h> // Helper functions
|
#include <cyg/hal/hal_if.h> // HAL I/O interfaces
|
#include <cyg/hal/hal_if.h> // HAL I/O interfaces
|
#include <cyg/hal/drv_api.h>
|
#include <cyg/hal/drv_api.h>
|
#include <cyg/hal/hal_intr.h>
|
#include <cyg/hal/hal_intr.h>
|
|
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
#include <flash_config.h>
|
#include <flash_config.h>
|
|
|
RedBoot_config_option("GDB connection port",
|
RedBoot_config_option("GDB connection port",
|
gdb_port,
|
gdb_port,
|
ALWAYS_ENABLED, true,
|
ALWAYS_ENABLED, true,
|
CONFIG_INT,
|
CONFIG_INT,
|
CYGNUM_REDBOOT_NETWORKING_TCP_PORT
|
CYGNUM_REDBOOT_NETWORKING_TCP_PORT
|
);
|
);
|
RedBoot_config_option("Network debug at boot time",
|
RedBoot_config_option("Network debug at boot time",
|
net_debug,
|
net_debug,
|
ALWAYS_ENABLED, true,
|
ALWAYS_ENABLED, true,
|
CONFIG_BOOL,
|
CONFIG_BOOL,
|
false
|
false
|
);
|
);
|
// Note: the following options are related. If 'bootp' is false, then
|
// Note: the following options are related. If 'bootp' is false, then
|
// the other values are used in the configuration. Because of the way
|
// the other values are used in the configuration. Because of the way
|
// that configuration tables are generated, they should have names which
|
// that configuration tables are generated, they should have names which
|
// are related. The configuration options will show up lexicographically
|
// are related. The configuration options will show up lexicographically
|
// ordered, thus the peculiar naming. In this case, the 'use' option is
|
// ordered, thus the peculiar naming. In this case, the 'use' option is
|
// negated (if false, the others apply) which makes the names even more
|
// negated (if false, the others apply) which makes the names even more
|
// confusing.
|
// confusing.
|
RedBoot_config_option("Use BOOTP for network configuration",
|
RedBoot_config_option("Use BOOTP for network configuration",
|
bootp,
|
bootp,
|
ALWAYS_ENABLED, true,
|
ALWAYS_ENABLED, true,
|
CONFIG_BOOL,
|
CONFIG_BOOL,
|
true
|
true
|
);
|
);
|
RedBoot_config_option("Local IP address",
|
RedBoot_config_option("Local IP address",
|
bootp_my_ip,
|
bootp_my_ip,
|
"bootp", false,
|
"bootp", false,
|
CONFIG_IP,
|
CONFIG_IP,
|
0
|
0
|
);
|
);
|
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
|
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
|
RedBoot_config_option("Local IP address mask",
|
RedBoot_config_option("Local IP address mask",
|
bootp_my_ip_mask,
|
bootp_my_ip_mask,
|
"bootp", false,
|
"bootp", false,
|
CONFIG_IP,
|
CONFIG_IP,
|
0
|
0
|
);
|
);
|
RedBoot_config_option("Gateway IP address",
|
RedBoot_config_option("Gateway IP address",
|
bootp_my_gateway_ip,
|
bootp_my_gateway_ip,
|
"bootp", false,
|
"bootp", false,
|
CONFIG_IP,
|
CONFIG_IP,
|
0
|
0
|
);
|
);
|
#endif
|
#endif
|
RedBoot_config_option("Default server IP address",
|
RedBoot_config_option("Default server IP address",
|
bootp_server_ip,
|
bootp_server_ip,
|
"bootp", false,
|
"bootp", false,
|
CONFIG_IP,
|
CONFIG_IP,
|
0
|
0
|
);
|
);
|
|
|
// Note: the following options are related too.
|
// Note: the following options are related too.
|
RedBoot_config_option("Force console for special debug messages",
|
RedBoot_config_option("Force console for special debug messages",
|
info_console_force,
|
info_console_force,
|
ALWAYS_ENABLED, true,
|
ALWAYS_ENABLED, true,
|
CONFIG_BOOL,
|
CONFIG_BOOL,
|
false
|
false
|
);
|
);
|
RedBoot_config_option("Console number for special debug messages",
|
RedBoot_config_option("Console number for special debug messages",
|
info_console_number,
|
info_console_number,
|
"info_console_force", true,
|
"info_console_force", true,
|
CONFIG_INT,
|
CONFIG_INT,
|
0
|
0
|
);
|
);
|
#endif
|
#endif
|
|
|
#define TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
|
#define TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
|
|
|
#ifdef DEBUG_TCP
|
#ifdef DEBUG_TCP
|
int show_tcp = 0;
|
int show_tcp = 0;
|
#endif
|
#endif
|
|
|
static tcp_socket_t tcp_sock;
|
static tcp_socket_t tcp_sock;
|
static int state;
|
static int state;
|
static int _timeout = 500;
|
static int _timeout = 500;
|
static int orig_console, orig_debug;
|
static int orig_console, orig_debug;
|
|
|
static int in_buflen = 0;
|
static int in_buflen = 0;
|
static unsigned char in_buf[64];
|
static unsigned char in_buf[64];
|
static unsigned char *in_bufp;
|
static unsigned char *in_bufp;
|
static int out_buflen = 0;
|
static int out_buflen = 0;
|
static unsigned char out_buf[1024];
|
static unsigned char out_buf[1024];
|
static unsigned char *out_bufp;
|
static unsigned char *out_bufp;
|
static bool flush_output_lines = false;
|
static bool flush_output_lines = false;
|
|
|
// Functions in this module
|
// Functions in this module
|
static void net_io_flush(void);
|
static void net_io_flush(void);
|
static void net_io_revert_console(void);
|
static void net_io_revert_console(void);
|
static void net_io_putc(void*, cyg_uint8);
|
static void net_io_putc(void*, cyg_uint8);
|
|
|
// Special characters used by Telnet - must be interpretted here
|
// Special characters used by Telnet - must be interpretted here
|
#define TELNET_IAC 0xFF // Interpret as command (escape)
|
#define TELNET_IAC 0xFF // Interpret as command (escape)
|
#define TELNET_IP 0xF4 // Interrupt process
|
#define TELNET_IP 0xF4 // Interrupt process
|
#define TELNET_WONT 0xFC // I Won't do it
|
#define TELNET_WONT 0xFC // I Won't do it
|
#define TELNET_DO 0xFD // Will you XXX
|
#define TELNET_DO 0xFD // Will you XXX
|
#define TELNET_TM 0x06 // Time marker (special DO/WONT after IP)
|
#define TELNET_TM 0x06 // Time marker (special DO/WONT after IP)
|
|
|
static cyg_bool
|
static cyg_bool
|
_net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch)
|
_net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch)
|
{
|
{
|
if (in_buflen == 0) {
|
if (in_buflen == 0) {
|
__tcp_poll();
|
__tcp_poll();
|
if (tcp_sock.state == _CLOSE_WAIT) {
|
if (tcp_sock.state == _CLOSE_WAIT) {
|
// This connection is breaking
|
// This connection is breaking
|
if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) {
|
if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) {
|
__tcp_close(&tcp_sock);
|
__tcp_close(&tcp_sock);
|
return false;
|
return false;
|
}
|
}
|
}
|
}
|
if (tcp_sock.state == _CLOSED) {
|
if (tcp_sock.state == _CLOSED) {
|
// The connection is gone
|
// The connection is gone
|
net_io_revert_console();
|
net_io_revert_console();
|
*ch = '\n';
|
*ch = '\n';
|
return true;
|
return true;
|
}
|
}
|
in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf));
|
in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf));
|
in_bufp = in_buf;
|
in_bufp = in_buf;
|
#ifdef DEBUG_TCP
|
#ifdef DEBUG_TCP
|
if (show_tcp && (in_buflen > 0)) {
|
if (show_tcp && (in_buflen > 0)) {
|
int old_console;
|
int old_console;
|
old_console = start_console();
|
old_console = start_console();
|
diag_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
diag_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
diag_dump_buf(in_buf, in_buflen);
|
diag_dump_buf(in_buf, in_buflen);
|
end_console(old_console);
|
end_console(old_console);
|
}
|
}
|
#endif // DEBUG_TCP
|
#endif // DEBUG_TCP
|
}
|
}
|
if (in_buflen) {
|
if (in_buflen) {
|
*ch = *in_bufp++;
|
*ch = *in_bufp++;
|
in_buflen--;
|
in_buflen--;
|
return true;
|
return true;
|
} else {
|
} else {
|
return false;
|
return false;
|
}
|
}
|
}
|
}
|
|
|
static cyg_bool
|
static cyg_bool
|
net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch)
|
net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch)
|
{
|
{
|
cyg_uint8 esc;
|
cyg_uint8 esc;
|
|
|
if (!_net_io_getc_nonblock(__ch_data, ch))
|
if (!_net_io_getc_nonblock(__ch_data, ch))
|
return false;
|
return false;
|
|
|
if (gdb_active || *ch != TELNET_IAC)
|
if (gdb_active || *ch != TELNET_IAC)
|
return true;
|
return true;
|
|
|
// Telnet escape - need to read/handle more
|
// Telnet escape - need to read/handle more
|
while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
|
while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
|
|
|
switch (esc) {
|
switch (esc) {
|
case TELNET_IAC:
|
case TELNET_IAC:
|
// The other special case - escaped escape
|
// The other special case - escaped escape
|
return true;
|
return true;
|
case TELNET_IP:
|
case TELNET_IP:
|
// Special case for ^C == Interrupt Process
|
// Special case for ^C == Interrupt Process
|
*ch = 0x03;
|
*ch = 0x03;
|
// Just in case the other end needs synchronizing
|
// Just in case the other end needs synchronizing
|
net_io_putc(__ch_data, TELNET_IAC);
|
net_io_putc(__ch_data, TELNET_IAC);
|
net_io_putc(__ch_data, TELNET_WONT);
|
net_io_putc(__ch_data, TELNET_WONT);
|
net_io_putc(__ch_data, TELNET_TM);
|
net_io_putc(__ch_data, TELNET_TM);
|
net_io_flush();
|
net_io_flush();
|
return true;
|
return true;
|
case TELNET_DO:
|
case TELNET_DO:
|
// Telnet DO option
|
// Telnet DO option
|
while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
|
while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
|
// Respond with WONT option
|
// Respond with WONT option
|
net_io_putc(__ch_data, TELNET_IAC);
|
net_io_putc(__ch_data, TELNET_IAC);
|
net_io_putc(__ch_data, TELNET_WONT);
|
net_io_putc(__ch_data, TELNET_WONT);
|
net_io_putc(__ch_data, esc);
|
net_io_putc(__ch_data, esc);
|
return false; // Ignore this whole thing!
|
return false; // Ignore this whole thing!
|
default:
|
default:
|
return false;
|
return false;
|
}
|
}
|
}
|
}
|
|
|
static cyg_uint8
|
static cyg_uint8
|
net_io_getc(void* __ch_data)
|
net_io_getc(void* __ch_data)
|
{
|
{
|
cyg_uint8 ch;
|
cyg_uint8 ch;
|
int idle_timeout = 10; // 10ms
|
int idle_timeout = 10; // 10ms
|
|
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
while (true) {
|
while (true) {
|
if (net_io_getc_nonblock(__ch_data, &ch)) break;
|
if (net_io_getc_nonblock(__ch_data, &ch)) break;
|
if (--idle_timeout == 0) {
|
if (--idle_timeout == 0) {
|
net_io_flush();
|
net_io_flush();
|
idle_timeout = 10;
|
idle_timeout = 10;
|
}
|
}
|
}
|
}
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
return ch;
|
return ch;
|
}
|
}
|
|
|
static void
|
static void
|
net_io_flush(void)
|
net_io_flush(void)
|
{
|
{
|
int n;
|
int n;
|
char *bp = out_buf;
|
char *bp = out_buf;
|
|
|
#ifdef DEBUG_TCP
|
#ifdef DEBUG_TCP
|
if (show_tcp) {
|
if (show_tcp) {
|
int old_console;
|
int old_console;
|
old_console = start_console();
|
old_console = start_console();
|
diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
|
diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
|
diag_dump_buf(out_buf, out_buflen);
|
diag_dump_buf(out_buf, out_buflen);
|
end_console(old_console);
|
end_console(old_console);
|
}
|
}
|
#endif // SHOW_TCP
|
#endif // SHOW_TCP
|
n = __tcp_write_block(&tcp_sock, bp, out_buflen);
|
n = __tcp_write_block(&tcp_sock, bp, out_buflen);
|
if (n < 0) {
|
if (n < 0) {
|
// The connection is gone!
|
// The connection is gone!
|
net_io_revert_console();
|
net_io_revert_console();
|
} else {
|
} else {
|
out_buflen -= n;
|
out_buflen -= n;
|
bp += n;
|
bp += n;
|
}
|
}
|
out_bufp = out_buf; out_buflen = 0;
|
out_bufp = out_buf; out_buflen = 0;
|
// Check interrupt flag
|
// Check interrupt flag
|
if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
|
if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
|
CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
|
CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
|
cyg_hal_user_break(0);
|
cyg_hal_user_break(0);
|
}
|
}
|
}
|
}
|
|
|
static void
|
static void
|
net_io_putc(void* __ch_data, cyg_uint8 c)
|
net_io_putc(void* __ch_data, cyg_uint8 c)
|
{
|
{
|
static bool have_dollar, have_hash;
|
static bool have_dollar, have_hash;
|
static int hash_count;
|
static int hash_count;
|
|
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
*out_bufp++ = c;
|
*out_bufp++ = c;
|
if (c == '$') have_dollar = true;
|
if (c == '$') have_dollar = true;
|
if (have_dollar && (c == '#')) {
|
if (have_dollar && (c == '#')) {
|
have_hash = true;
|
have_hash = true;
|
hash_count = 0;
|
hash_count = 0;
|
}
|
}
|
if ((++out_buflen == sizeof(out_buf)) ||
|
if ((++out_buflen == sizeof(out_buf)) ||
|
(flush_output_lines && c == '\n') ||
|
(flush_output_lines && c == '\n') ||
|
(have_hash && (++hash_count == 3))) {
|
(have_hash && (++hash_count == 3))) {
|
net_io_flush();
|
net_io_flush();
|
have_dollar = false;
|
have_dollar = false;
|
}
|
}
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
}
|
}
|
|
|
static void
|
static void
|
net_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
|
net_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
|
{
|
{
|
int old_console;
|
int old_console;
|
|
|
old_console = start_console();
|
old_console = start_console();
|
diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
|
diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
|
end_console(old_console);
|
end_console(old_console);
|
#if 0
|
#if 0
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
|
|
while(__len-- > 0)
|
while(__len-- > 0)
|
net_io_putc(__ch_data, *__buf++);
|
net_io_putc(__ch_data, *__buf++);
|
|
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
#endif
|
#endif
|
}
|
}
|
|
|
static void
|
static void
|
net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
|
net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
|
{
|
{
|
int old_console;
|
int old_console;
|
|
|
old_console = start_console();
|
old_console = start_console();
|
diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
|
diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
|
end_console(old_console);
|
end_console(old_console);
|
#if 0
|
#if 0
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
|
|
while(__len-- > 0)
|
while(__len-- > 0)
|
*__buf++ = net_io_getc(__ch_data);
|
*__buf++ = net_io_getc(__ch_data);
|
|
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
#endif
|
#endif
|
}
|
}
|
|
|
static cyg_bool
|
static cyg_bool
|
net_io_getc_timeout(void* __ch_data, cyg_uint8* ch)
|
net_io_getc_timeout(void* __ch_data, cyg_uint8* ch)
|
{
|
{
|
int delay_count;
|
int delay_count;
|
cyg_bool res;
|
cyg_bool res;
|
|
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
net_io_flush(); // Make sure any output has been sent
|
net_io_flush(); // Make sure any output has been sent
|
delay_count = _timeout;
|
delay_count = _timeout;
|
|
|
for(;;) {
|
for(;;) {
|
res = net_io_getc_nonblock(__ch_data, ch);
|
res = net_io_getc_nonblock(__ch_data, ch);
|
if (res || 0 == delay_count--)
|
if (res || 0 == delay_count--)
|
break;
|
break;
|
}
|
}
|
|
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
|
|
return res;
|
return res;
|
}
|
}
|
|
|
static int
|
static int
|
net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...)
|
net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...)
|
{
|
{
|
static int vector = 0;
|
static int vector = 0;
|
int ret = 0;
|
int ret = 0;
|
static int irq_state = 0;
|
static int irq_state = 0;
|
|
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
|
|
switch (__func) {
|
switch (__func) {
|
case __COMMCTL_IRQ_ENABLE:
|
case __COMMCTL_IRQ_ENABLE:
|
irq_state = 1;
|
irq_state = 1;
|
if (vector == 0) {
|
if (vector == 0) {
|
vector = eth_drv_int_vector();
|
vector = eth_drv_int_vector();
|
}
|
}
|
HAL_INTERRUPT_UNMASK(vector);
|
HAL_INTERRUPT_UNMASK(vector);
|
break;
|
break;
|
case __COMMCTL_IRQ_DISABLE:
|
case __COMMCTL_IRQ_DISABLE:
|
ret = irq_state;
|
ret = irq_state;
|
irq_state = 0;
|
irq_state = 0;
|
if (vector == 0) {
|
if (vector == 0) {
|
vector = eth_drv_int_vector();
|
vector = eth_drv_int_vector();
|
}
|
}
|
HAL_INTERRUPT_MASK(vector);
|
HAL_INTERRUPT_MASK(vector);
|
break;
|
break;
|
case __COMMCTL_DBG_ISR_VECTOR:
|
case __COMMCTL_DBG_ISR_VECTOR:
|
ret = vector;
|
ret = vector;
|
break;
|
break;
|
case __COMMCTL_SET_TIMEOUT:
|
case __COMMCTL_SET_TIMEOUT:
|
{
|
{
|
va_list ap;
|
va_list ap;
|
|
|
va_start(ap, __func);
|
va_start(ap, __func);
|
|
|
ret = _timeout;
|
ret = _timeout;
|
_timeout = va_arg(ap, cyg_uint32);
|
_timeout = va_arg(ap, cyg_uint32);
|
|
|
va_end(ap);
|
va_end(ap);
|
break;
|
break;
|
}
|
}
|
case __COMMCTL_FLUSH_OUTPUT:
|
case __COMMCTL_FLUSH_OUTPUT:
|
net_io_flush();
|
net_io_flush();
|
break;
|
break;
|
case __COMMCTL_ENABLE_LINE_FLUSH:
|
case __COMMCTL_ENABLE_LINE_FLUSH:
|
flush_output_lines = true;
|
flush_output_lines = true;
|
break;
|
break;
|
case __COMMCTL_DISABLE_LINE_FLUSH:
|
case __COMMCTL_DISABLE_LINE_FLUSH:
|
flush_output_lines = false;
|
flush_output_lines = false;
|
break;
|
break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
return ret;
|
return ret;
|
}
|
}
|
|
|
static int
|
static int
|
net_io_isr(void *__ch_data, int* __ctrlc,
|
net_io_isr(void *__ch_data, int* __ctrlc,
|
CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
|
CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
|
{
|
{
|
char ch;
|
char ch;
|
|
|
CYGARC_HAL_SAVE_GP();
|
CYGARC_HAL_SAVE_GP();
|
*__ctrlc = 0;
|
*__ctrlc = 0;
|
if (net_io_getc_nonblock(__ch_data, &ch)) {
|
if (net_io_getc_nonblock(__ch_data, &ch)) {
|
if (ch == 0x03) {
|
if (ch == 0x03) {
|
*__ctrlc = 1;
|
*__ctrlc = 1;
|
}
|
}
|
}
|
}
|
CYGARC_HAL_RESTORE_GP();
|
CYGARC_HAL_RESTORE_GP();
|
return CYG_ISR_HANDLED;
|
return CYG_ISR_HANDLED;
|
}
|
}
|
|
|
// TEMP
|
// TEMP
|
|
|
int
|
int
|
start_console(void)
|
start_console(void)
|
{
|
{
|
int cur_console =
|
int cur_console =
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
|
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
int i = 0;
|
int i = 0;
|
if ( flash_get_config( "info_console_force", &i, CONFIG_BOOL) )
|
if ( flash_get_config( "info_console_force", &i, CONFIG_BOOL) )
|
if ( i )
|
if ( i )
|
if ( ! flash_get_config( "info_console_number", &i, CONFIG_INT) )
|
if ( ! flash_get_config( "info_console_number", &i, CONFIG_INT) )
|
i = 0; // the default, if that call failed.
|
i = 0; // the default, if that call failed.
|
if ( i )
|
if ( i )
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
|
else
|
else
|
#endif
|
#endif
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
|
|
|
return cur_console;
|
return cur_console;
|
}
|
}
|
|
|
void
|
void
|
end_console(int old_console)
|
end_console(int old_console)
|
{
|
{
|
// Restore original console
|
// Restore original console
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console);
|
}
|
}
|
// TEMP
|
// TEMP
|
|
|
static void
|
static void
|
net_io_revert_console(void)
|
net_io_revert_console(void)
|
{
|
{
|
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
|
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
|
console_selected = false;
|
console_selected = false;
|
#endif
|
#endif
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console);
|
CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug);
|
CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug);
|
console_echo = true;
|
console_echo = true;
|
}
|
}
|
|
|
static void
|
static void
|
net_io_assume_console(void)
|
net_io_assume_console(void)
|
{
|
{
|
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
|
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
|
console_selected = true;
|
console_selected = true;
|
#endif
|
#endif
|
console_echo = false;
|
console_echo = false;
|
orig_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
orig_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
|
orig_debug = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
orig_debug = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL);
|
CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL);
|
}
|
}
|
|
|
static void
|
static void
|
net_io_init(void)
|
net_io_init(void)
|
{
|
{
|
static int init = 0;
|
static int init = 0;
|
if (!init) {
|
if (!init) {
|
hal_virtual_comm_table_t* comm;
|
hal_virtual_comm_table_t* comm;
|
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
|
|
|
// Setup procs in the vector table
|
// Setup procs in the vector table
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
|
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
|
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
|
//CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
|
//CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
|
CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write);
|
CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write);
|
CYGACC_COMM_IF_READ_SET(*comm, net_io_read);
|
CYGACC_COMM_IF_READ_SET(*comm, net_io_read);
|
CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc);
|
CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc);
|
CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc);
|
CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc);
|
CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control);
|
CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control);
|
CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr);
|
CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr);
|
CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout);
|
CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout);
|
|
|
// Disable interrupts via this interface to set static
|
// Disable interrupts via this interface to set static
|
// state into correct state.
|
// state into correct state.
|
net_io_control( comm, __COMMCTL_IRQ_DISABLE );
|
net_io_control( comm, __COMMCTL_IRQ_DISABLE );
|
|
|
// Restore original console
|
// Restore original console
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
|
CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
|
|
|
init = 1;
|
init = 1;
|
gdb_active = false;
|
gdb_active = false;
|
}
|
}
|
__tcp_listen(&tcp_sock, gdb_port);
|
__tcp_listen(&tcp_sock, gdb_port);
|
state = tcp_sock.state;
|
state = tcp_sock.state;
|
#ifdef DEBUG_TCP
|
#ifdef DEBUG_TCP
|
diag_printf("show tcp = %p\n", (void *)&show_tcp);
|
diag_printf("show tcp = %p\n", (void *)&show_tcp);
|
#endif
|
#endif
|
}
|
}
|
|
|
// Check for incoming TCP debug connection
|
// Check for incoming TCP debug connection
|
void
|
void
|
net_io_test(bool is_idle)
|
net_io_test(bool is_idle)
|
{
|
{
|
if (!is_idle) return; // Only care about idle case
|
if (!is_idle) return; // Only care about idle case
|
if (!have_net) return;
|
if (!have_net) return;
|
__tcp_poll();
|
__tcp_poll();
|
if (state != tcp_sock.state) {
|
if (state != tcp_sock.state) {
|
// Something has changed
|
// Something has changed
|
if (tcp_sock.state == _ESTABLISHED) {
|
if (tcp_sock.state == _ESTABLISHED) {
|
// A new connection has arrived
|
// A new connection has arrived
|
net_io_assume_console();
|
net_io_assume_console();
|
in_bufp = in_buf; in_buflen = 1; *in_bufp = '\r';
|
in_bufp = in_buf; in_buflen = 1; *in_bufp = '\r';
|
out_bufp = out_buf; out_buflen = 0;
|
out_bufp = out_buf; out_buflen = 0;
|
}
|
}
|
if (tcp_sock.state == _CLOSED) {
|
if (tcp_sock.state == _CLOSED) {
|
net_io_init(); // Get ready for another connection
|
net_io_init(); // Get ready for another connection
|
}
|
}
|
}
|
}
|
state = tcp_sock.state;
|
state = tcp_sock.state;
|
}
|
}
|
|
|
// This schedules the 'net_io_test()' function to be run by RedBoot's
|
// This schedules the 'net_io_test()' function to be run by RedBoot's
|
// main command loop when idle (i.e. when no input arrives after some
|
// main command loop when idle (i.e. when no input arrives after some
|
// period of time).
|
// period of time).
|
RedBoot_idle(net_io_test, RedBoot_IDLE_NETIO);
|
RedBoot_idle(net_io_test, RedBoot_IDLE_NETIO);
|
|
|
//
|
//
|
// Network initialization
|
// Network initialization
|
//
|
//
|
#include <cyg/io/eth/eth_drv.h>
|
#include <cyg/io/eth/eth_drv.h>
|
#include <cyg/io/eth/netdev.h>
|
#include <cyg/io/eth/netdev.h>
|
#include <cyg/hal/hal_tables.h>
|
#include <cyg/hal/hal_tables.h>
|
|
|
// Define table boundaries
|
// Define table boundaries
|
CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
|
CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
|
CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
|
CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
|
|
|
RedBoot_init(net_init, RedBoot_INIT_LAST);
|
RedBoot_init(net_init, RedBoot_INIT_LAST);
|
|
|
static void
|
static void
|
show_addrs(void)
|
show_addrs(void)
|
{
|
{
|
diag_printf("IP: %s", inet_ntoa((in_addr_t *)&__local_ip_addr));
|
diag_printf("IP: %s", inet_ntoa((in_addr_t *)&__local_ip_addr));
|
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
|
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
|
diag_printf("/%s", inet_ntoa((in_addr_t *)&__local_ip_mask));
|
diag_printf("/%s", inet_ntoa((in_addr_t *)&__local_ip_mask));
|
diag_printf(", Gateway: %s\n", inet_ntoa((in_addr_t *)&__local_ip_gate));
|
diag_printf(", Gateway: %s\n", inet_ntoa((in_addr_t *)&__local_ip_gate));
|
#else
|
#else
|
diag_printf(", ");
|
diag_printf(", ");
|
#endif
|
#endif
|
diag_printf("Default server: %s", inet_ntoa(&my_bootp_info.bp_siaddr));
|
diag_printf("Default server: %s", inet_ntoa(&my_bootp_info.bp_siaddr));
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
show_dns();
|
show_dns();
|
#endif
|
#endif
|
diag_printf("\n");
|
diag_printf("\n");
|
}
|
}
|
|
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
static void
|
static void
|
flash_get_IP(char *id, ip_addr_t *val)
|
flash_get_IP(char *id, ip_addr_t *val)
|
{
|
{
|
ip_addr_t my_ip;
|
ip_addr_t my_ip;
|
int i;
|
int i;
|
|
|
if (flash_get_config(id, &my_ip, CONFIG_IP)) {
|
if (flash_get_config(id, &my_ip, CONFIG_IP)) {
|
if (my_ip[0] != 0 || my_ip[1] != 0 ||
|
if (my_ip[0] != 0 || my_ip[1] != 0 ||
|
my_ip[2] != 0 || my_ip[3] != 0) {
|
my_ip[2] != 0 || my_ip[3] != 0) {
|
// 'id' is set to something so let it override any static IP
|
// 'id' is set to something so let it override any static IP
|
for (i=0; i<4; i++)
|
for (i=0; i<4; i++)
|
(*val)[i] = my_ip[i];
|
(*val)[i] = my_ip[i];
|
}
|
}
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
|
|
void
|
void
|
net_init(void)
|
net_init(void)
|
{
|
{
|
cyg_netdevtab_entry_t *t;
|
cyg_netdevtab_entry_t *t;
|
|
|
// Set defaults as appropriate
|
// Set defaults as appropriate
|
#ifdef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
|
#ifdef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
|
use_bootp = false;
|
use_bootp = false;
|
#else
|
#else
|
use_bootp = true;
|
use_bootp = true;
|
#endif
|
#endif
|
#ifdef CYGDBG_REDBOOT_NET_DEBUG
|
#ifdef CYGDBG_REDBOOT_NET_DEBUG
|
net_debug = true;
|
net_debug = true;
|
#else
|
#else
|
net_debug = false;
|
net_debug = false;
|
#endif
|
#endif
|
gdb_port = CYGNUM_REDBOOT_NETWORKING_TCP_PORT;
|
gdb_port = CYGNUM_REDBOOT_NETWORKING_TCP_PORT;
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
|
// Fetch values from saved config data, if available
|
// Fetch values from saved config data, if available
|
flash_get_config("net_debug", &net_debug, CONFIG_BOOL);
|
flash_get_config("net_debug", &net_debug, CONFIG_BOOL);
|
flash_get_config("gdb_port", &gdb_port, CONFIG_INT);
|
flash_get_config("gdb_port", &gdb_port, CONFIG_INT);
|
flash_get_config("bootp", &use_bootp, CONFIG_BOOL);
|
flash_get_config("bootp", &use_bootp, CONFIG_BOOL);
|
if (!use_bootp)
|
if (!use_bootp)
|
{
|
{
|
flash_get_IP("bootp_my_ip", &__local_ip_addr);
|
flash_get_IP("bootp_my_ip", &__local_ip_addr);
|
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
|
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
|
flash_get_IP("bootp_my_ip_mask", &__local_ip_mask);
|
flash_get_IP("bootp_my_ip_mask", &__local_ip_mask);
|
flash_get_IP("bootp_my_gateway_ip", &__local_ip_gate);
|
flash_get_IP("bootp_my_gateway_ip", &__local_ip_gate);
|
#endif
|
#endif
|
flash_get_config("bootp_server_ip", &my_bootp_info.bp_siaddr,
|
flash_get_config("bootp_server_ip", &my_bootp_info.bp_siaddr,
|
CONFIG_IP);
|
CONFIG_IP);
|
}
|
}
|
#endif
|
#endif
|
# ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
|
# ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
|
// Don't override if the user has deliberately set something more
|
// Don't override if the user has deliberately set something more
|
// verbose.
|
// verbose.
|
if (0 == cyg_io_eth_net_debug)
|
if (0 == cyg_io_eth_net_debug)
|
cyg_io_eth_net_debug = net_debug;
|
cyg_io_eth_net_debug = net_debug;
|
# endif
|
# endif
|
have_net = false;
|
have_net = false;
|
// Make sure the recv buffers are set up
|
// Make sure the recv buffers are set up
|
eth_drv_buffers_init();
|
eth_drv_buffers_init();
|
__pktbuf_init();
|
__pktbuf_init();
|
// Initialize all network devices
|
// Initialize all network devices
|
for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
|
for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
|
if (t->init(t)) {
|
if (t->init(t)) {
|
t->status = CYG_NETDEVTAB_STATUS_AVAIL;
|
t->status = CYG_NETDEVTAB_STATUS_AVAIL;
|
} else {
|
} else {
|
// What to do if device init fails?
|
// What to do if device init fails?
|
t->status = 0; // Device not [currently] available
|
t->status = 0; // Device not [currently] available
|
}
|
}
|
}
|
}
|
if (!__local_enet_sc) {
|
if (!__local_enet_sc) {
|
diag_printf("No network interfaces found\n");
|
diag_printf("No network interfaces found\n");
|
return;
|
return;
|
}
|
}
|
// Initialize the network [if present]
|
// Initialize the network [if present]
|
if (use_bootp) {
|
if (use_bootp) {
|
if (__bootp_find_local_ip(&my_bootp_info) == 0) {
|
if (__bootp_find_local_ip(&my_bootp_info) == 0) {
|
have_net = true;
|
have_net = true;
|
} else {
|
} else {
|
// Is it an unset address, or has it been set to a static addr
|
// Is it an unset address, or has it been set to a static addr
|
if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 &&
|
if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 &&
|
__local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) {
|
__local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) {
|
diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
__local_enet_sc->dev_name,
|
__local_enet_sc->dev_name,
|
__local_enet_addr[0],
|
__local_enet_addr[0],
|
__local_enet_addr[1],
|
__local_enet_addr[1],
|
__local_enet_addr[2],
|
__local_enet_addr[2],
|
__local_enet_addr[3],
|
__local_enet_addr[3],
|
__local_enet_addr[4],
|
__local_enet_addr[4],
|
__local_enet_addr[5]);
|
__local_enet_addr[5]);
|
diag_printf("Can't get BOOTP info for device!\n");
|
diag_printf("Can't get BOOTP info for device!\n");
|
} else {
|
} else {
|
diag_printf("Can't get BOOTP info, using default IP address\n");
|
diag_printf("Can't get BOOTP info, using default IP address\n");
|
have_net = true;
|
have_net = true;
|
}
|
}
|
}
|
}
|
} else {
|
} else {
|
have_net = true; // Assume values in FLASH were OK
|
have_net = true; // Assume values in FLASH were OK
|
}
|
}
|
if (have_net) {
|
if (have_net) {
|
diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
|
__local_enet_sc->dev_name,
|
__local_enet_sc->dev_name,
|
__local_enet_addr[0],
|
__local_enet_addr[0],
|
__local_enet_addr[1],
|
__local_enet_addr[1],
|
__local_enet_addr[2],
|
__local_enet_addr[2],
|
__local_enet_addr[3],
|
__local_enet_addr[3],
|
__local_enet_addr[4],
|
__local_enet_addr[4],
|
__local_enet_addr[5]);
|
__local_enet_addr[5]);
|
|
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
redboot_dns_res_init();
|
redboot_dns_res_init();
|
#endif
|
#endif
|
show_addrs();
|
show_addrs();
|
net_io_init();
|
net_io_init();
|
}
|
}
|
}
|
}
|
|
|
static char usage[] = "[-l <local_ip_address>] [-h <server_address>]";
|
static char usage[] = "[-l <local_ip_address>] [-h <server_address>]";
|
|
|
// Exported CLI function
|
// Exported CLI function
|
static void do_ip_addr(int argc, char *argv[]);
|
static void do_ip_addr(int argc, char *argv[]);
|
RedBoot_cmd("ip_address",
|
RedBoot_cmd("ip_address",
|
"Set/change IP addresses",
|
"Set/change IP addresses",
|
usage,
|
usage,
|
do_ip_addr
|
do_ip_addr
|
);
|
);
|
|
|
void
|
void
|
do_ip_addr(int argc, char *argv[])
|
do_ip_addr(int argc, char *argv[])
|
{
|
{
|
struct option_info opts[3];
|
struct option_info opts[3];
|
char *ip_addr, *host_addr;
|
char *ip_addr, *host_addr;
|
bool ip_addr_set, host_addr_set;
|
bool ip_addr_set, host_addr_set;
|
struct sockaddr_in host;
|
struct sockaddr_in host;
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
char *dns_addr;
|
char *dns_addr;
|
bool dns_addr_set;
|
bool dns_addr_set;
|
#endif
|
#endif
|
int num_opts;
|
int num_opts;
|
|
|
init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR,
|
init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR,
|
(void **)&ip_addr, (bool *)&ip_addr_set, "local IP address");
|
(void **)&ip_addr, (bool *)&ip_addr_set, "local IP address");
|
init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR,
|
init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR,
|
(void **)&host_addr, (bool *)&host_addr_set, "default server address");
|
(void **)&host_addr, (bool *)&host_addr_set, "default server address");
|
num_opts = 2;
|
num_opts = 2;
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_STR,
|
init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_STR,
|
(void **)&dns_addr, (bool *)&dns_addr_set, "DNS server address");
|
(void **)&dns_addr, (bool *)&dns_addr_set, "DNS server address");
|
num_opts++;
|
num_opts++;
|
#endif
|
#endif
|
if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) {
|
if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) {
|
return;
|
return;
|
}
|
}
|
if (ip_addr_set) {
|
if (ip_addr_set) {
|
if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) {
|
if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) {
|
diag_printf("Invalid local IP address: %s\n", ip_addr);
|
diag_printf("Invalid local IP address: %s\n", ip_addr);
|
return;
|
return;
|
}
|
}
|
// Of course, each address goes in its own place :-)
|
// Of course, each address goes in its own place :-)
|
memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr));
|
memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr));
|
}
|
}
|
if (host_addr_set) {
|
if (host_addr_set) {
|
if (!_gethostbyname(host_addr, (in_addr_t *)&host)) {
|
if (!_gethostbyname(host_addr, (in_addr_t *)&host)) {
|
diag_printf("Invalid server address: %s\n", host_addr);
|
diag_printf("Invalid server address: %s\n", host_addr);
|
return;
|
return;
|
}
|
}
|
my_bootp_info.bp_siaddr = host.sin_addr;
|
my_bootp_info.bp_siaddr = host.sin_addr;
|
}
|
}
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
#ifdef CYGPKG_REDBOOT_NETWORKING_DNS
|
if (dns_addr_set) {
|
if (dns_addr_set) {
|
set_dns(dns_addr);
|
set_dns(dns_addr);
|
}
|
}
|
#endif
|
#endif
|
show_addrs();
|
show_addrs();
|
if (!have_net) {
|
if (!have_net) {
|
have_net = true;
|
have_net = true;
|
net_io_init();
|
net_io_init();
|
}
|
}
|
}
|
}
|
|
|
// EOF net_io.c
|
// EOF net_io.c
|
|
|