500 lines
15 KiB
C++
500 lines
15 KiB
C++
//////////////////////////////////////////////////////////////////////
|
|
// driver_configurator.cpp: implementation of the driver_configurator class.
|
|
//
|
|
// Author : David Rokhvarg <davidr@sangoma.com>
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#if defined WIN32 && defined NDEBUG
|
|
#pragma optimize("gt",on)
|
|
#endif
|
|
|
|
#include "driver_configurator.h"
|
|
|
|
#define DBG_CFG if(0)printf("DRVCFG:");if(0)printf
|
|
#define _DBG_CFG if(0)printf
|
|
|
|
#define INFO_CFG if(0)printf("DRVCFG:");if(0)printf
|
|
#define _INFO_CFG if(0)printf
|
|
|
|
#define ERR_CFG if(0)printf("Error:%s():line:%d: ", __FUNCTION__, __LINE__);if(0)printf
|
|
#define _ERR_CFG if(0)printf
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
driver_configurator::driver_configurator()
|
|
{
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
wp_handle = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
driver_configurator::~driver_configurator()
|
|
{
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
cleanup();
|
|
}
|
|
|
|
void driver_configurator::cleanup()
|
|
{
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
if(wp_handle != INVALID_HANDLE_VALUE){
|
|
sangoma_close(&wp_handle);
|
|
wp_handle = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
//GET current configuraion of the API driver
|
|
int driver_configurator::get_configuration(port_cfg_t *out_port_cfg)
|
|
{
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
int err = sangoma_driver_port_get_config(wp_handle, out_port_cfg, wp_number);
|
|
if (err) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//SET new configuration of the API driver
|
|
int driver_configurator::set_configuration(port_cfg_t *port_cfg)
|
|
{
|
|
port_management_struct_t port_mgmnt;
|
|
int err;
|
|
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
memset(&port_mgmnt, 0x00, sizeof(port_mgmnt));
|
|
port_mgmnt.operation_status = SANG_STATUS_GENERAL_ERROR;
|
|
|
|
err = sangoma_driver_port_stop(wp_handle, &port_mgmnt, wp_number);
|
|
if (err) {
|
|
ERR_CFG("%s: failed to stop Port for re-configuration!\n", wanpipe_name_str);
|
|
return 1;
|
|
}
|
|
|
|
switch(port_mgmnt.operation_status)
|
|
{
|
|
case SANG_STATUS_SUCCESS:
|
|
case SANG_STATUS_CAN_NOT_STOP_DEVICE_WHEN_ALREADY_STOPPED:
|
|
//OK
|
|
break;
|
|
default:
|
|
ERR_CFG("%s: %s(): return code: %s\n", wanpipe_name_str,
|
|
__FUNCTION__, SDLA_DECODE_SANG_STATUS(port_mgmnt.operation_status));
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
err = sangoma_driver_port_set_config(wp_handle, port_cfg, wp_number);
|
|
if (err) {
|
|
ERR_CFG("%s: failed to set Port configuration!\n", wanpipe_name_str);
|
|
return 1;
|
|
}
|
|
|
|
DBG_CFG("%s(): return code: %s (%d)\n", __FUNCTION__,
|
|
SDLA_DECODE_SANG_STATUS(port_cfg->operation_status), port_cfg->operation_status);
|
|
switch(port_cfg->operation_status)
|
|
{
|
|
case SANG_STATUS_DEVICE_BUSY:
|
|
ERR_CFG("Error: open handles exist for '%s_IF\?\?' interfaces!\n", wanpipe_name_str);
|
|
return port_cfg->operation_status;
|
|
case SANG_STATUS_SUCCESS:
|
|
//OK
|
|
break;
|
|
default:
|
|
//error
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
memset(&port_mgmnt, 0x00, sizeof(port_mgmnt));
|
|
port_mgmnt.operation_status = SANG_STATUS_GENERAL_ERROR;
|
|
|
|
err=sangoma_driver_port_start(wp_handle, &port_mgmnt, wp_number);
|
|
if(err || port_mgmnt.operation_status){
|
|
ERR_CFG("%s: failed to start Port after re-configuration!\n", wanpipe_name_str);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int driver_configurator::init(unsigned int wanpipe_number, unsigned int port_number)
|
|
{
|
|
DBG_CFG("%s():\n", __FUNCTION__);
|
|
|
|
memset(&port_cfg, 0x00, sizeof(port_cfg_t));
|
|
port_cfg.num_of_ifs = 1;//1 Group always
|
|
|
|
//this the MAPPED port number
|
|
wp_number = wanpipe_number + port_number + 1;
|
|
|
|
wp_snprintf(wanpipe_name_str, sizeof(wanpipe_name_str), "wanpipe%d", wp_number);
|
|
DBG_CFG("%s\n", wanpipe_name_str);
|
|
|
|
wp_handle = sangoma_open_driver_ctrl(wp_number);
|
|
|
|
if(wp_handle == INVALID_HANDLE_VALUE){
|
|
// ERR_CFG("Error: failed to open %s!!\n", wanpipe_name_str);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int driver_configurator::print_port_cfg_structure(port_cfg_t *port_cfg)
|
|
{
|
|
wandev_conf_t *wandev_conf = &port_cfg->wandev_conf;
|
|
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
|
wanif_conf_t *wanif_conf = &port_cfg->if_cfg[0];
|
|
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
_INFO_CFG("\n================================================\n");
|
|
|
|
INFO_CFG("Card Type\t: %s(%d)\n", SDLA_DECODE_CARDTYPE(wandev_conf->card_type),
|
|
wandev_conf->card_type);/* Sangoma Card type - S514, S518 or AFT.*/
|
|
|
|
INFO_CFG("Number of TimeSlot Groups: %d\n", port_cfg->num_of_ifs);
|
|
|
|
INFO_CFG("MTU\t\t: %d\n", wandev_conf->mtu);
|
|
|
|
print_sdla_fe_cfg_t_structure(sdla_fe_cfg);
|
|
|
|
for(unsigned int i = 0; i < port_cfg->num_of_ifs; i++){
|
|
_INFO_CFG("\n************************************************\n");
|
|
_INFO_CFG("Configration of Group Number %d:\n", i);
|
|
print_wanif_conf_t_structure(&wanif_conf[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int driver_configurator::print_sdla_fe_cfg_t_structure(sdla_fe_cfg_t *sdla_fe_cfg)
|
|
{
|
|
_INFO_CFG("\n################################################\n");
|
|
INFO_CFG("MEDIA\t\t: %s\n", MEDIA_DECODE(sdla_fe_cfg));
|
|
if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1 || FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_E1){
|
|
INFO_CFG("Line CODE\t: %s\n", LCODE_DECODE(sdla_fe_cfg));
|
|
INFO_CFG("Framing\t\t: %s\n", FRAME_DECODE(sdla_fe_cfg));
|
|
INFO_CFG("Clock Mode\t: %s\n", TECLK_DECODE(sdla_fe_cfg));
|
|
INFO_CFG("Clock Reference port: %d (0 - not used)\n", FE_REFCLK(sdla_fe_cfg));
|
|
INFO_CFG("Signalling Insertion Mode: %s\n", TE1SIG_DECODE(sdla_fe_cfg));
|
|
|
|
INFO_CFG("High Impedance Mode: %s\n",
|
|
(FE_HIMPEDANCE_MODE(sdla_fe_cfg) == WANOPT_YES ? "Yes":"No"));
|
|
INFO_CFG("FE_RX_SLEVEL: %d\n", FE_RX_SLEVEL(sdla_fe_cfg));
|
|
}//if()
|
|
INFO_CFG("TDMV LAW\t: %s\n", (FE_TDMV_LAW(sdla_fe_cfg) == WAN_TDMV_MULAW ?"MuLaw":"ALaw"));
|
|
|
|
switch(FE_MEDIA(sdla_fe_cfg))
|
|
{
|
|
case WAN_MEDIA_T1:
|
|
INFO_CFG("LBO\t\t: %s\n", LBO_DECODE(sdla_fe_cfg));
|
|
break;
|
|
case WAN_MEDIA_E1:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int driver_configurator::print_wanif_conf_t_structure(wanif_conf_t *wanif_conf)
|
|
{
|
|
INFO_CFG("Operation Mode\t: %s\n", wanif_conf->usedby);
|
|
INFO_CFG("Timeslot BitMap\t: 0x%08X\n", wanif_conf->active_ch);
|
|
INFO_CFG("Line Mode\t: %s\n",
|
|
(wanif_conf->hdlc_streaming == WANOPT_YES ? "HDLC":"BitStream"));
|
|
INFO_CFG("MTU\\MRU\t\t: %d\n", wanif_conf->mtu);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int driver_configurator::get_hardware_info(hardware_info_t *hardware_info)
|
|
{
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
port_management_struct_t port_management;
|
|
|
|
int err=sangoma_driver_get_hw_info(wp_handle,&port_management, wp_number);
|
|
|
|
if (err) {
|
|
ERR_CFG("Error: failed to get hw info for wanpipe%d!\n", wp_number);
|
|
return 1;
|
|
}
|
|
|
|
memcpy(hardware_info,port_management.data,sizeof(hardware_info_t));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int driver_configurator::get_driver_version(wan_driver_version_t *version)
|
|
{
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
port_management_struct_t port_management;
|
|
|
|
int err = sangoma_driver_get_version(wp_handle, &port_management, wp_number);
|
|
|
|
if (err) {
|
|
ERR_CFG("Error: failed to get Driver Version from wanpipe%d!\n", wp_number);
|
|
return 1;
|
|
}
|
|
|
|
memcpy(version, port_management.data, sizeof(*version));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int driver_configurator::push_a_card_into_wanpipe_info_array(
|
|
wanpipe_instance_info_t *wanpipe_info_array,
|
|
hardware_info_t *new_hw_info)
|
|
{
|
|
unsigned int card_ind;
|
|
hardware_info_t *tmp_hw_info;
|
|
|
|
//check this card is not in the array already
|
|
for(card_ind = 0; card_ind < MAX_CARDS; card_ind++){
|
|
tmp_hw_info = &wanpipe_info_array[card_ind].hardware_info;
|
|
|
|
if( (new_hw_info->pci_bus_number == tmp_hw_info->pci_bus_number) &&
|
|
(new_hw_info->pci_slot_number == tmp_hw_info->pci_slot_number)){
|
|
//already in array. not an error.
|
|
DBG_CFG("already in array.\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
//find an empty slot in the array and place the new card there
|
|
for(card_ind = 0; card_ind < MAX_CARDS; card_ind++){
|
|
tmp_hw_info = &wanpipe_info_array[card_ind].hardware_info;
|
|
if(tmp_hw_info->card_model == -1){
|
|
//found an empty slot in array
|
|
memcpy(tmp_hw_info, new_hw_info, sizeof(hardware_info_t));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//too many cards in the computer.
|
|
INFO_CFG("Warning: number of cards in the computer is greater than the maximum of %d.\n",
|
|
MAX_CARDS);
|
|
return 2;
|
|
}
|
|
|
|
//
|
|
//Scan all running wanpipes, check which ones are on the same card,
|
|
//figure out how many physical cards installed.
|
|
//
|
|
//Returns: -1 - if error.
|
|
// number of cards, starting from zero.
|
|
int driver_configurator::scan_for_sangoma_cards(wanpipe_instance_info_t *wanpipe_info_array, int card_model)
|
|
{
|
|
int card_counter = 0, wp_ind;
|
|
hardware_info_t hardware_info;
|
|
|
|
//initialize hardware information array.
|
|
memset(wanpipe_info_array, -1, sizeof(wanpipe_instance_info_t)*MAX_CARDS);
|
|
|
|
DBG_CFG("%s(): wanpipe_info_array: 0x%p\n", __FUNCTION__, wanpipe_info_array);
|
|
|
|
for(wp_ind = 0; wp_ind < (MAX_CARDS * MAX_PORTS_PER_CARD); wp_ind++){
|
|
if(init(wp_ind, 0)){
|
|
continue;
|
|
}
|
|
if(get_hardware_info(&hardware_info)){
|
|
//Port was opened but could not read hw info - dont add the port to the list
|
|
//and also consider there are no more ports, so exit the loop.
|
|
break;
|
|
}
|
|
|
|
DBG_CFG("card_model : %s (0x%08X)\n",
|
|
SDLA_ADPTR_NAME(hardware_info.card_model), hardware_info.card_model);
|
|
DBG_CFG("firmware_version\t: 0x%02X\n", hardware_info.firmware_version);
|
|
DBG_CFG("pci_bus_number\t\t: %d\n", hardware_info.pci_bus_number);
|
|
DBG_CFG("pci_slot_number\t\t: %d\n", hardware_info.pci_slot_number);
|
|
|
|
if(card_model == hardware_info.card_model){
|
|
if(push_a_card_into_wanpipe_info_array(wanpipe_info_array, &hardware_info) == 0){
|
|
//At this point we know: 1. WANPIPE number, for example WANPIPE1.
|
|
// 2. Card type, for example A104.
|
|
//It allows to figure out Device Name of each port on the card.
|
|
//For example: for A104 it will be WANPIPE1, WANPIPE2, WANPIPE3, WANPIPE4
|
|
wanpipe_info_array[card_counter].wanpipe_number = wp_ind;
|
|
DBG_CFG("%s(): wp_ind: %u\n", __FUNCTION__, wp_ind);
|
|
card_counter++;
|
|
}
|
|
}else{
|
|
DBG_CFG("Found a Card but Card Model is different from what was searched for.\n");
|
|
}
|
|
|
|
//it is important to Close each port which was opened during the scan.
|
|
cleanup();
|
|
}//for()
|
|
|
|
return card_counter;
|
|
}
|
|
|
|
int driver_configurator::set_dchan(int dchan, int seven_bit, int mtp1_filter)
|
|
{
|
|
wandev_conf_t *wandev_conf = &port_cfg.wandev_conf;
|
|
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
|
|
|
|
if(!dchan) {
|
|
return -1;
|
|
}
|
|
|
|
if (seven_bit) {
|
|
wanif_cfg->u.aft.sw_hdlc=1;
|
|
wanif_cfg->u.aft.seven_bit_hdlc=1;
|
|
}
|
|
if (mtp1_filter) {
|
|
wanif_cfg->u.aft.sw_hdlc=1;
|
|
wanif_cfg->u.aft.mtp1_filter=1;
|
|
wanif_cfg->u.aft.hdlc_repeat=1;
|
|
}
|
|
|
|
dchan--;
|
|
wandev_conf->tdmv_conf.dchan=(1<<dchan);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int driver_configurator::set_chunk_ms(int chunk_ms)
|
|
{
|
|
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
|
|
|
|
wanif_cfg->u.aft.mru = chunk_ms*8;
|
|
wanif_cfg->u.aft.mtu = chunk_ms*8;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int driver_configurator::set_data_api_mode(void)
|
|
{
|
|
wandev_conf_t *wandev_conf = &port_cfg.wandev_conf;
|
|
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
|
|
sprintf(wanif_cfg->usedby, "DATA_API");
|
|
|
|
if (wandev_conf->tdmv_conf.dchan) {
|
|
wanif_cfg->hdlc_streaming=1;
|
|
wanif_cfg->active_ch=wandev_conf->tdmv_conf.dchan;
|
|
}
|
|
return 0;
|
|
}
|
|
int driver_configurator::set_chan_api_mode(void)
|
|
{
|
|
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
|
|
sprintf(wanif_cfg->usedby, SDLA_DECODE_USEDBY_FIELD(TDM_CHAN_VOICE_API));
|
|
return 0;
|
|
}
|
|
int driver_configurator::set_span_api_mode(void)
|
|
{
|
|
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
|
|
sprintf(wanif_cfg->usedby, SDLA_DECODE_USEDBY_FIELD(TDM_SPAN_VOICE_API));
|
|
return 0;
|
|
}
|
|
|
|
//function to switch between T1 and E1
|
|
int driver_configurator::set_t1_e1_configuration(sdla_fe_cfg_t *in_sdla_fe_cfg, buffer_settings_t *buffer_settings)
|
|
{
|
|
wandev_conf_t *wandev_conf = &port_cfg.wandev_conf;
|
|
sdla_fe_cfg_t *sdla_fe_cfg = &wandev_conf->fe_cfg;
|
|
wan_tdmv_conf_t *tdmv_cfg = &wandev_conf->tdmv_conf;
|
|
wanif_conf_t *wanif_cfg = &port_cfg.if_cfg[0];
|
|
hardware_info_t tmp_hardware_info;
|
|
|
|
DBG_CFG("%s()\n", __FUNCTION__);
|
|
|
|
get_hardware_info(&tmp_hardware_info);
|
|
|
|
//copy T1/E1 configuration into the Driver configuration structure.
|
|
memcpy(sdla_fe_cfg, in_sdla_fe_cfg, sizeof(sdla_fe_cfg_t));
|
|
|
|
port_cfg.buffer_settings.buffer_multiplier_factor = buffer_settings->buffer_multiplier_factor;
|
|
port_cfg.buffer_settings.number_of_buffers_per_api_interface = buffer_settings->number_of_buffers_per_api_interface;
|
|
|
|
wandev_conf->fe_cfg.cfg.te_cfg.active_ch = 0xFFFFFFFF;//a constant
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
wandev_conf->config_id = WANCONFIG_AFT_TE1;
|
|
wandev_conf->magic = ROUTER_MAGIC;
|
|
|
|
wandev_conf->mtu = 2048;
|
|
|
|
DBG_CFG("%s(): slot: %d, bus: %d, port_number:%d\n", __FUNCTION__,
|
|
tmp_hardware_info.pci_slot_number, tmp_hardware_info.pci_bus_number,
|
|
tmp_hardware_info.port_number);
|
|
|
|
wandev_conf->PCI_slot_no = tmp_hardware_info.pci_slot_number;
|
|
wandev_conf->pci_bus_no = tmp_hardware_info.pci_bus_number;
|
|
wandev_conf->card_type = WANOPT_AFT; //m_DeviceInfoData.card_model;
|
|
|
|
wanif_cfg->magic = ROUTER_MAGIC;
|
|
|
|
if (wandev_conf->tdmv_conf.dchan && FE_FRAME(sdla_fe_cfg) == WAN_FR_D4) {
|
|
wanif_cfg->u.aft.sw_hdlc=1;
|
|
wanif_cfg->u.aft.seven_bit_hdlc=1;
|
|
}
|
|
|
|
wanif_cfg->u.aft.idle_flag=0xFF;
|
|
|
|
sprintf(wanif_cfg->name, "w%dg1", wp_number);
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
port_cfg.port_no = FE_LINENO(sdla_fe_cfg) = tmp_hardware_info.port_number;
|
|
|
|
//
|
|
//Set MTU/MRU per-TIMESLOT - the API driver will multiply this value by the
|
|
//number of timeslots this interface is using - t1:24, e1:31 or 32.
|
|
//The 'buffer_multiplier_factor' value will control how many of these
|
|
//buffers will be received on each RX indication.
|
|
//
|
|
if (!wanif_cfg->u.aft.mru) {
|
|
if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1){
|
|
//320*24=7680
|
|
wanif_cfg->mtu = wanif_cfg->u.aft.mtu = wanif_cfg->u.aft.mru = 320;
|
|
} else {
|
|
//240*31=7440, 240*32=7680
|
|
wanif_cfg->mtu = wanif_cfg->u.aft.mtu = wanif_cfg->u.aft.mru = 240;
|
|
}
|
|
}
|
|
|
|
if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_T1){
|
|
//T1, 1 Group of 24 Timeslots.
|
|
if (!wanif_cfg->active_ch) {
|
|
wanif_cfg->active_ch = 0xFFFFFF;
|
|
}
|
|
|
|
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_MULAW;
|
|
|
|
}else if(FE_MEDIA(sdla_fe_cfg) == WAN_MEDIA_E1){
|
|
//E1, 1 Group of 31 or 32 Timeslots.
|
|
//API driver will automatically adjust timeslot bitmap for "framed" e1
|
|
if (!wanif_cfg->active_ch) {
|
|
wanif_cfg->active_ch = 0xFFFFFFFF;
|
|
}
|
|
|
|
FE_TDMV_LAW(sdla_fe_cfg) = WAN_TDMV_ALAW;
|
|
FE_LBO(sdla_fe_cfg) = WAN_T1_LBO_NONE;//important to set to a valid value!!
|
|
}else{
|
|
ERR_CFG("%s(): Error: invalid Media Type %d!\n", __FUNCTION__, sdla_fe_cfg->media);
|
|
return 1;
|
|
}
|
|
|
|
tdmv_cfg->span_no = (unsigned char)wp_number;
|
|
|
|
print_port_cfg_structure(&port_cfg);
|
|
|
|
return set_configuration(&port_cfg);
|
|
}
|