⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 net_io.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================
//
//      net/net_io.c
//
//      Stand-alone network logical I/O support for RedBoot
//
//==========================================================================
//####COPYRIGHTBEGIN####
//                                                                          
// -------------------------------------------                              
// The contents of this file are subject to the Red Hat eCos Public License 
// Version 1.1 (the "License"); you may not use this file except in         
// compliance with the License.  You may obtain a copy of the License at    
// http://www.redhat.com/                                                   
//                                                                          
// Software distributed under the License is distributed on an "AS IS"      
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
// License for the specific language governing rights and limitations under 
// the License.                                                             
//                                                                          
// The Original Code is eCos - Embedded Configurable Operating System,      
// released September 30, 1998.                                             
//                                                                          
// The Initial Developer of the Original Code is Red Hat.                   
// Portions created by Red Hat are                                          
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
// All Rights Reserved.                                                     
// -------------------------------------------                              
//                                                                          
//####COPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    gthomas
// Contributors: gthomas
// Date:         2000-07-14
// Purpose:      
// Description:  
//              
// This code is part of RedBoot (tm).
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <redboot.h>
#include <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("Master's Local IP address",
                      bootp_master_ip,
                      "bootp", false,
                      CONFIG_IP,
                      0
    );
RedBoot_config_option("Slave's Local IP address",
                      bootp_slave_ip,
                      "bootp", false,
                      CONFIG_IP,
                      0
    );
RedBoot_config_option("Default server IP address",
                      bootp_server_ip,
                      "bootp", false,
                      CONFIG_IP,
                      0
    );
#endif

#define TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS

#ifdef DEBUG_TCP
int 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[64];
static unsigned char *out_bufp;

// Functions in this module
static 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();  
            printf("%s:%d\n", __FUNCTION__, __LINE__);  
            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_bool
net_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_uint8
net_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 void
net_io_flush(void)
{
    int n;
    char *bp = out_buf;

    while (out_buflen) {
        if (tcp_sock.state == _CLOSE_WAIT) {
            // This connection is tring to close
            // This connection is breaking
            if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0)
                __tcp_close(&tcp_sock);
        }
        if (tcp_sock.state == _CLOSED) {
            // The connection is gone!
            net_io_revert_console();
            break;
        }
#ifdef DEBUG_TCP
        if (show_tcp) {
            int old_console;
            old_console = start_console();  
            printf("%s.%d\n", __FUNCTION__, __LINE__);
            dump_buf(out_buf, out_buflen);  
            end_console(old_console);
        }
#endif // SHOW_TCP
        n = __tcp_write(&tcp_sock, bp, out_buflen);
        if (n > 0) {
            out_buflen -= n;
            bp += n;
        }
        __tcp_poll();
    }
    out_bufp = out_buf;  out_buflen = 0;
    __tcp_drain(&tcp_sock);
    // Check interrupt flag
    if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
        CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
        cyg_hal_user_break(0);
    }
}

static void
net_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)) || (c == '\n') ||
        (have_hash && (++hash_count == 3))) {
        net_io_flush();
        have_dollar = false;
    }
    CYGARC_HAL_RESTORE_GP();
}

static void
net_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
{
    int old_console;

    old_console = start_console();
    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 void
net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -