#include #include #include #include #include #include #include #include "notify_avmnet.h" #define DEBUG 1 #define LOG_TO_FILE 1 #define LOGFILE "/var/log/notify_avmnet.log" #define CONSOLE "/dev/console" #define ERROR -1 #define MODULE_BUFFER_SIZE 1024 #define DEVNAME_MAX_LEN 64 #define DATAPATH_PARAM_SIZE 128 /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ enum reboot_request { DONT_REBOOT_IF_MODULE_PRESENT = 0, REBOOT_IF_MODULE_PRESENT = 1 }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ enum system_state { NO_REBOOT = 0, REBOOT = 1 }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ enum module_state { MODULE_NOT_PRESENT = 0, MODULE_PRESENT = 1, MODULE_CHECK_FAILED = 2 }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void dbg_to_logfile(const char *logfile, const char *t,...){ FILE *log_fp; log_fp = fopen(logfile, "a"); if (log_fp != NULL){ va_list ap; va_start(ap, t); vfprintf(log_fp, t, ap); va_end(ap); fclose(log_fp); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define CONSOLE_PRINT(format, arg...) dbg_to_logfile( CONSOLE, format, ##arg ); #if defined(DEBUG) && DEBUG #if defined(LOG_TO_FILE) && LOG_TO_FILE #define DBG_PRINT(format, arg...) dbg_to_logfile(LOGFILE, "[%s/%d]: " format "\n", __func__, __LINE__, ##arg); #else //#if defined(LOG_TO_FILE) #define DBG_PRINT(format, arg...) printf("[%s/%d]: " format "\n", __func__, __LINE__, ##arg); #endif //#if defined(LOG_TO_FILE) #else //#if defined(DEBUG) #define DBG_PRINT(format, arg...) #endif //#if defined(DEBUG) /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static char module_buffer[MODULE_BUFFER_SIZE]; #if defined(CONFIG_VR9) #define CPU "vr9" #define HW_NEEDS_REBOOT_IF_MP DONT_REBOOT_IF_MODULE_PRESENT #endif #if defined(CONFIG_AR9) #define CPU "ar9" #define HW_NEEDS_REBOOT_IF_MP DONT_REBOOT_IF_MODULE_PRESENT #endif #if defined(CONFIG_AR10) #define CPU "ar10" #define HW_NEEDS_REBOOT_IF_MP DONT_REBOOT_IF_MODULE_PRESENT #endif #ifndef CPU #error CPU has to be AR9, AR10 or VR9 #endif static const char *all_modules_list[] = { "ifx_ppa_mini_qos", "ifx_ppa_mini_sessions", "ifxmips_ppa_hal_" CPU "_e5", "ifxmips_ppa_datapath_" CPU "_e5", "ifxmips_ppa_hal_" CPU "_a5", "ifxmips_ppa_datapath_" CPU "_a5"}; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static enum module_state check_module_present( const char *module_name ){ int read_len = 0; int fd = open("/proc/modules", O_RDONLY); if (fd < 0) return MODULE_CHECK_FAILED; // DBG_PRINT( "called module_name=%s", module_name ); while ( read_len = read(fd, module_buffer, MODULE_BUFFER_SIZE - 1) ) { if (read_len < 0 ) break; module_buffer[read_len] = 0; if( strstr(module_buffer, module_name) ){ close(fd); return MODULE_PRESENT; } } close(fd); return MODULE_NOT_PRESENT; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void modprobe_once( const char *module_name, const char *args ){ if ( check_module_present( module_name ) == MODULE_NOT_PRESENT ){ if (args) snprintf( module_buffer, MODULE_BUFFER_SIZE - 1, "modprobe %s %s", module_name, args ); else snprintf( module_buffer, MODULE_BUFFER_SIZE - 1, "modprobe %s", module_name ); DBG_PRINT("run cmd '%s' ", module_buffer ); system( module_buffer ); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static enum system_state unload_all_ppa_modules( enum reboot_request reboot_if_module_present ) { int i; DBG_PRINT("called"); for ( i = 0; i < sizeof(all_modules_list) / sizeof(all_modules_list[0]); i++){ if ( check_module_present( all_modules_list[i] ) == MODULE_PRESENT) { DBG_PRINT("%s is loaded", all_modules_list[i] ); if ( reboot_if_module_present == REBOOT_IF_MODULE_PRESENT ){ DBG_PRINT("PPA Module %s present -> we need to reboot the box", all_modules_list[i]); CONSOLE_PRINT("\nAVMNET:PPA Module %s present -> we need to reboot the box\n", all_modules_list[i]); system( "reboot" ); return REBOOT; } else { snprintf( module_buffer, MODULE_BUFFER_SIZE - 1, "rmmod %s", all_modules_list[i] ); DBG_PRINT("run cmd '%s' ", module_buffer ); system ( module_buffer ); if ( check_module_present( all_modules_list[i] ) == MODULE_PRESENT ) { DBG_PRINT("ERROR: unload '%s' did not work", all_modules_list[i] ); CONSOLE_PRINT("ERROR: unload '%s' did not work", all_modules_list[i] ); CONSOLE_PRINT("\nAVMNET:PPA Module %s present -> we need to reboot the box\n", all_modules_list[i]); system( "reboot" ); } } } else { DBG_PRINT("%s not loaded", all_modules_list[i] ); } } return NO_REBOOT; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int kernel_read_current_ata_dev(char *dst) { int read_len = 0; int fd; if (!dst) return ERROR; fd = open("/proc/eth/avm_ata_dev", O_RDONLY); if (fd < 0){ DBG_PRINT("cannot open /proc/eth/avm_ata_dev"); dst[0] = 0; return ERROR; } read_len = read(fd, dst, DEVNAME_MAX_LEN - 1) ; if (read_len > 0 ){ dst[read_len] = 0; } else { dst[0] = 0; } close(fd); DBG_PRINT("current_ata_dev: %s", dst ); return read_len; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int kernel_read_current_wan_mode() { int read_len = 0; int fd = open("/proc/eth/avm_wan_mode", O_RDONLY); if (fd < 0){ DBG_PRINT("cannot open /proc/eth/avm_wan_mode"); return ERROR; } while ( read_len = read(fd, module_buffer, MODULE_BUFFER_SIZE - 1) ) { if (read_len < 0 ) break; module_buffer[read_len] = 0; if( strstr(module_buffer, "ATM") ){ close(fd); return TRANSFER_MODE_ATM; } if( strstr(module_buffer, "PTM") ){ close(fd); return TRANSFER_MODE_PTM; } if( strstr(module_buffer, "ETH") ){ close(fd); return TRANSFER_MODE_ETH; } if( strstr(module_buffer, "KDEV") ){ close(fd); return TRANSFER_MODE_KDEV; } } close(fd); return TRANSFER_MODE_NONE; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void notify_avmnet_hw_start_selected_tm_generic( uint32_t new_transfer_mode, uint32_t broadband_type, uint32_t no_dsl_init ){ int current_transfer_mode; const char *datapath_param = NULL; char buffer[DATAPATH_PARAM_SIZE]; DBG_PRINT("called, avm_dsl_no_init=%lu",(unsigned long)no_dsl_init ); if ( no_dsl_init ) { #if(CONFIG_VR9) snprintf( buffer, DATAPATH_PARAM_SIZE - 1, "avm_dsl_no_init=%lu", (unsigned long)no_dsl_init ); datapath_param = buffer; #else DBG_PRINT("avm_dsl_no_init not supported on this platform!" ); #endif } if (broadband_type != BROADBAND_TYPE_DSL){ DBG_PRINT("ignoring unknown broadband type: %d", broadband_type); return; } current_transfer_mode = kernel_read_current_wan_mode(); if ( new_transfer_mode == current_transfer_mode ){ DBG_PRINT("Tranfermode: %d already set", current_transfer_mode); return; } if ( new_transfer_mode == TRANSFER_MODE_ATM ){ DBG_PRINT("Start Training ATM"); if ( unload_all_ppa_modules( HW_NEEDS_REBOOT_IF_MP ) == REBOOT) return; modprobe_once("ifxmips_ppa_datapath_" CPU "_a5", datapath_param ); } else if( new_transfer_mode == TRANSFER_MODE_PTM ) { DBG_PRINT("Start Training PTM"); if ( unload_all_ppa_modules( HW_NEEDS_REBOOT_IF_MP ) == REBOOT) return; modprobe_once("ifxmips_ppa_datapath_" CPU "_e5", datapath_param ); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_start_selected_tm( uint32_t new_transfer_mode, uint32_t broadband_type ){ notify_avmnet_hw_start_selected_tm_generic( new_transfer_mode, broadband_type, 0); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_start_selected_tm_no_dsl_init( uint32_t new_transfer_mode, uint32_t broadband_type ){ notify_avmnet_hw_start_selected_tm_generic( new_transfer_mode, broadband_type, 1 ); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_link_established( uint32_t transfer_mode, uint32_t broadband_type ) { DBG_PRINT("called"); if (broadband_type != BROADBAND_TYPE_DSL){ DBG_PRINT("ignoring unknown broadband type: %d", broadband_type); return; } if ( transfer_mode == TRANSFER_MODE_ATM ){ DBG_PRINT("Showtime ATM"); modprobe_once("ifxmips_ppa_hal_" CPU "_a5", NULL); } else if( transfer_mode == TRANSFER_MODE_PTM ) { DBG_PRINT("Showtime PTM"); modprobe_once("ifxmips_ppa_hal_" CPU "_e5", NULL); } if (( transfer_mode == TRANSFER_MODE_ATM ) || ( transfer_mode == TRANSFER_MODE_PTM ) ){ modprobe_once("ifx_ppa_mini_sessions", NULL); modprobe_once("ifx_ppa_mini_qos", NULL); } } /*------------------------------------------------------------------------------------------*\ * depricated, is replaced by notify_avmnet_hw_setup_ata_dev \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_disable_phy( uint32_t broadband_type ) { #if defined(USE_HW_DISABLE_PHY) && USE_HW_DISABLE_PHY int current_transfer_mode; if (broadband_type != BROADBAND_TYPE_DSL){ DBG_PRINT("ignoring unknown broadband type: %d", broadband_type); return; } current_transfer_mode = kernel_read_current_wan_mode(); if ( (current_transfer_mode == TRANSFER_MODE_ETH ) || (current_transfer_mode == TRANSFER_MODE_KDEV ) ) { DBG_PRINT("ATA-Mode already set"); return; } DBG_PRINT("starting AVM ATA Mode"); if ( unload_all_ppa_modules( HW_NEEDS_REBOOT_IF_MP ) == REBOOT) return; #if defined(CONFIG_VR9) //ethwan=2 --> EthernetWan modprobe_once("ifxmips_ppa_datapath_" CPU "_e5" ,"ethwan=2" ); modprobe_once("ifxmips_ppa_hal_" CPU "_e5", NULL); #else //ethwan=2 --> EthernetWan modprobe_once("ifxmips_ppa_datapath_" CPU "_a5" ,"ethwan=2" ); modprobe_once("ifxmips_ppa_hal_" CPU "_a5", NULL); #endif modprobe_once("ifx_ppa_mini_sessions", NULL); modprobe_once("ifx_ppa_mini_qos", NULL); #else //#if defined(USE_HW_DISABLE_PHY) && USE_HW_DISABLE_PHY DBG_PRINT("called, but obsolete - use notify_avmnet_hw_setup_wan_dev instead"); #endif //#if defined(USE_HW_DISABLE_PHY) && USE_HW_DISABLE_PHY } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_setup_ata_kdev( char *wan_dev_name ){ DBG_PRINT("warning: just ATA via Ethernet supported so far by IFX_PPA, unload PPA modules"); unload_all_ppa_modules( HW_NEEDS_REBOOT_IF_MP ); return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_setup_ata_eth_dev( char *wan_dev_name ){ int current_transfer_mode; char datapath_param[DATAPATH_PARAM_SIZE]; DBG_PRINT("called, wan_dev=%s", wan_dev_name?wan_dev_name:"NO_WAN_DEV"); current_transfer_mode = kernel_read_current_wan_mode(); if ( current_transfer_mode == TRANSFER_MODE_ETH ) { char current_ata_dev[DEVNAME_MAX_LEN]; DBG_PRINT("ATA-Mode already set"); kernel_read_current_ata_dev(current_ata_dev); if ((wan_dev_name == NULL) && ( strncmp( current_ata_dev,"NONE", DEVNAME_MAX_LEN) == 0) ){ // no wan dev in past, no wan dev in future return; } } if ( unload_all_ppa_modules( HW_NEEDS_REBOOT_IF_MP ) == REBOOT ) return; if ( wan_dev_name ){ snprintf( datapath_param, DATAPATH_PARAM_SIZE - 1, "ethwan=2 avm_ata_dev=%s", wan_dev_name ); } else { snprintf( datapath_param, DATAPATH_PARAM_SIZE - 1, "ethwan=2" ); } DBG_PRINT("starting AVM ATA Mode: datapath-param:%s", datapath_param); #if defined(CONFIG_AR9) || defined(CONFIG_AR10) //ethwan=2 --> EthernetWan modprobe_once("ifxmips_ppa_datapath_" CPU "_a5" , datapath_param ); modprobe_once("ifxmips_ppa_hal_" CPU "_a5", NULL); #else //ethwan=2 --> EthernetWan modprobe_once("ifxmips_ppa_datapath_" CPU "_e5" ,datapath_param ); modprobe_once("ifxmips_ppa_hal_" CPU "_e5", NULL); #endif modprobe_once("ifx_ppa_mini_sessions", NULL); modprobe_once("ifx_ppa_mini_qos", NULL); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void notify_avmnet_hw_exit( uint32_t broadband_type ){ DBG_PRINT("called"); if (broadband_type != BROADBAND_TYPE_DSL){ DBG_PRINT("ignoring unknown broadband type: %d", broadband_type); return; } DBG_PRINT("Unloading all PPA Modules"); unload_all_ppa_modules( DONT_REBOOT_IF_MODULE_PRESENT ); }