📄 net_io.c
字号:
//==========================================================================//// net/net_io.c//// Stand-alone network logical I/O support for RedBoot////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Gary Thomas//// 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// 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// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// 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// 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// License. However the source code for this file must still be made available// 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 file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-07-14// Purpose: // Description: // // This code is part of RedBoot (tm).////####DESCRIPTIONEND####////==========================================================================#include <redboot.h>#include <cyg/io/eth/eth_drv.h> // Logical driver interfaces#include <net/net.h>#include <cyg/hal/hal_misc.h> // Helper functions#include <cyg/hal/hal_if.h> // HAL I/O interfaces#include <cyg/hal/drv_api.h>#include <cyg/hal/hal_intr.h>#ifdef CYGSEM_REDBOOT_FLASH_CONFIG#include <flash_config.h>RedBoot_config_option("GDB connection port", gdb_port, ALWAYS_ENABLED, true, CONFIG_INT, CYGNUM_REDBOOT_NETWORKING_TCP_PORT );RedBoot_config_option("Network debug at boot time", net_debug, ALWAYS_ENABLED, true, CONFIG_BOOL, false );// Note: the following options are related. If 'bootp' is false, then// the other values are used in the configuration. Because of the way// that configuration tables are generated, they should have names which// are related. The configuration options will show up lexicographically// ordered, thus the peculiar naming. In this case, the 'use' option is// negated (if false, the others apply) which makes the names even more// confusing.RedBoot_config_option("Use BOOTP for network configuration", bootp, ALWAYS_ENABLED, true, CONFIG_BOOL, true );RedBoot_config_option("Local IP address", bootp_my_ip, "bootp", false, CONFIG_IP, 0 );#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAYRedBoot_config_option("Local IP address mask", bootp_my_ip_mask, "bootp", false, CONFIG_IP, 0 );RedBoot_config_option("Gateway IP address", bootp_my_gateway_ip, "bootp", false, CONFIG_IP, 0 );#endifRedBoot_config_option("Default server IP address", bootp_server_ip, "bootp", false, CONFIG_IP, 0 );// Note: the following options are related too.RedBoot_config_option("Force console for special debug messages", info_console_force, ALWAYS_ENABLED, true, CONFIG_BOOL, false );RedBoot_config_option("Console number for special debug messages", info_console_number, "info_console_force", true, CONFIG_INT, 0 );#endif#define TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS#ifdef DEBUG_TCPint show_tcp = 0;#endif static tcp_socket_t tcp_sock;static int state;static int _timeout = 500;static int orig_console, orig_debug;static int in_buflen = 0;static unsigned char in_buf[64];static unsigned char *in_bufp;static int out_buflen = 0;static unsigned char out_buf[1024];static unsigned char *out_bufp;static bool flush_output_lines = false;// Functions in this modulestatic void net_io_flush(void);static void net_io_revert_console(void);static void net_io_putc(void*, cyg_uint8);// Special characters used by Telnet - must be interpretted here#define TELNET_IAC 0xFF // Interpret as command (escape)#define TELNET_IP 0xF4 // Interrupt process#define TELNET_WONT 0xFC // I Won't do it#define TELNET_DO 0xFD // Will you XXX#define TELNET_TM 0x06 // Time marker (special DO/WONT after IP)static cyg_bool_net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch){ if (in_buflen == 0) { __tcp_poll(); if (tcp_sock.state == _CLOSE_WAIT) { // This connection is breaking if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) { __tcp_close(&tcp_sock); return false; } } if (tcp_sock.state == _CLOSED) { // The connection is gone net_io_revert_console(); *ch = '\n'; return true; } in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf)); in_bufp = in_buf;#ifdef DEBUG_TCP if (show_tcp && (in_buflen > 0)) { int old_console; old_console = start_console(); diag_printf("%s:%d\n", __FUNCTION__, __LINE__); diag_dump_buf(in_buf, in_buflen); end_console(old_console); }#endif // DEBUG_TCP } if (in_buflen) { *ch = *in_bufp++; in_buflen--; return true; } else { return false; }}static cyg_boolnet_io_getc_nonblock(void* __ch_data, cyg_uint8* ch){ cyg_uint8 esc; if (!_net_io_getc_nonblock(__ch_data, ch)) return false; if (gdb_active || *ch != TELNET_IAC) return true; // Telnet escape - need to read/handle more while (!_net_io_getc_nonblock(__ch_data, &esc)) ; switch (esc) { case TELNET_IAC: // The other special case - escaped escape return true; case TELNET_IP: // Special case for ^C == Interrupt Process *ch = 0x03; // Just in case the other end needs synchronizing net_io_putc(__ch_data, TELNET_IAC); net_io_putc(__ch_data, TELNET_WONT); net_io_putc(__ch_data, TELNET_TM); net_io_flush(); return true; case TELNET_DO: // Telnet DO option while (!_net_io_getc_nonblock(__ch_data, &esc)) ; // Respond with WONT option net_io_putc(__ch_data, TELNET_IAC); net_io_putc(__ch_data, TELNET_WONT); net_io_putc(__ch_data, esc); return false; // Ignore this whole thing! default: return false; }}static cyg_uint8net_io_getc(void* __ch_data){ cyg_uint8 ch; int idle_timeout = 10; // 10ms CYGARC_HAL_SAVE_GP(); while (true) { if (net_io_getc_nonblock(__ch_data, &ch)) break; if (--idle_timeout == 0) { net_io_flush(); idle_timeout = 10; } } CYGARC_HAL_RESTORE_GP(); return ch;}static voidnet_io_flush(void){ int n; char *bp = out_buf;#ifdef DEBUG_TCP if (show_tcp) { int old_console; old_console = start_console(); diag_printf("%s.%d\n", __FUNCTION__, __LINE__); diag_dump_buf(out_buf, out_buflen); end_console(old_console); }#endif // SHOW_TCP n = __tcp_write_block(&tcp_sock, bp, out_buflen); if (n < 0) { // The connection is gone! net_io_revert_console(); } else { out_buflen -= n; bp += n; } out_bufp = out_buf; out_buflen = 0; // Check interrupt flag if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); cyg_hal_user_break(0); }}static voidnet_io_putc(void* __ch_data, cyg_uint8 c){ static bool have_dollar, have_hash; static int hash_count; CYGARC_HAL_SAVE_GP(); *out_bufp++ = c; if (c == '$') have_dollar = true; if (have_dollar && (c == '#')) { have_hash = true; hash_count = 0; } if ((++out_buflen == sizeof(out_buf)) || (flush_output_lines && c == '\n') || (have_hash && (++hash_count == 3))) { net_io_flush(); have_dollar = false; } CYGARC_HAL_RESTORE_GP();}static voidnet_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len){ int old_console; old_console = start_console(); diag_printf("%s.%d\n", __FUNCTION__, __LINE__); end_console(old_console);#if 0 CYGARC_HAL_SAVE_GP(); while(__len-- > 0) net_io_putc(__ch_data, *__buf++); CYGARC_HAL_RESTORE_GP();#endif}static voidnet_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len){ int old_console; old_console = start_console(); diag_printf("%s.%d\n", __FUNCTION__, __LINE__); end_console(old_console);#if 0 CYGARC_HAL_SAVE_GP(); while(__len-- > 0) *__buf++ = net_io_getc(__ch_data); CYGARC_HAL_RESTORE_GP();#endif}static cyg_boolnet_io_getc_timeout(void* __ch_data, cyg_uint8* ch){ int delay_count; cyg_bool res; CYGARC_HAL_SAVE_GP(); net_io_flush(); // Make sure any output has been sent delay_count = _timeout; for(;;) { res = net_io_getc_nonblock(__ch_data, ch); if (res || 0 == delay_count--) break; } CYGARC_HAL_RESTORE_GP(); return res;}static intnet_io_control(void *__ch_data, __comm_control_cmd_t __func, ...){ static int vector = 0; int ret = 0; static int irq_state = 0; CYGARC_HAL_SAVE_GP(); switch (__func) { case __COMMCTL_IRQ_ENABLE: irq_state = 1; if (vector == 0) { vector = eth_drv_int_vector(); } HAL_INTERRUPT_UNMASK(vector); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -