bprd_ctl/bprd_mod.c
2020-10-21 09:41:05 +02:00

6657 lines
153 KiB
C
Executable file

/**************************************************************************
Copyright (c) 2005-2015, Silicom
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Silicom nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
#include <linux/config.h>
#endif
#if defined(CONFIG_SMP) && ! defined(__SMP__)
#define __SMP__
#endif
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/fs.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#ifdef BP_SELF_TEST
#include <linux/etherdevice.h>
#endif
#include <asm/uaccess.h> /* for get_user and put_user */
#include <linux/sched.h>
#include <linux/ethtool.h>
#include <linux/proc_fs.h>
#include <linux/reboot.h>
#include <linux/etherdevice.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include "bprd_ioctl.h"
#include "bprd_mod.h"
#include "bypass.h"
#include "libbp_rd.h"
#include "bp_cmd.h"
#define SUCCESS 0
#define BP_MOD_VER VER_STR_SET
#define BP_MOD_DESCR "Silicom Bypass-RD Control driver"
static int Device_Open = 0;
static int major_num=0;
spinlock_t bypass_wr_lock;
MODULE_AUTHOR("Anna Lukin, annal@silicom.co.il");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION(BP_MOD_DESCR);
MODULE_VERSION(BP_MOD_VER);
enum ies_port_state {
/* NOTE! Order is important. See the table in ies_port_set_state. */
/* The port is in working order (symbol lock, alignment done) and
* ready to receive a frame.
*/
IES_PORT_STATE_UP = 0,
/* Deprecated. Use ''IES_PORT_MODE_ADMIN_DOWN'' instead. */
IES_PORT_STATE_ADMIN_DOWN,
/* Deprecated. Use ''IES_PORT_MODE_ADMIN_PWRDOWN'' instead. */
IES_PORT_STATE_ADMIN_PWRDOWN,
/* Deprecated. Use ''IES_PORT_MODE_BIST'' instead. */
IES_PORT_STATE_BIST,
/* The SERDES transmits remote fault constantly and the receiver is
* disabled.
*/
IES_PORT_STATE_REMOTE_FAULT,
/* Indicates the absence of any signal on any lane. */
IES_PORT_STATE_DOWN,
/* Some lanes have either signal or partial synchronization. */
IES_PORT_STATE_PARTIALLY_UP,
/* Indicates continuous reception of a local fault condition. A remote
* fault is automatically sent continuously.
*/
IES_PORT_STATE_LOCAL_FAULT,
/* Indicates that DFE tuning is still in progress. */
IES_PORT_STATE_DFE_TUNING
};
enum ies_port_mode {
/* NOTE! Order is important. See the table in ies_port_set_state. */
/* The port is in working order (symbol lock, alignment done) and
* ready to receive a frame.
*/
IES_PORT_MODE_UP = IES_PORT_STATE_UP,
/* The port is administratively set down with the SERDES
* transmitting an idle pattern but the receiver disabled.
*/
IES_PORT_MODE_ADMIN_DOWN = IES_PORT_STATE_ADMIN_DOWN,
/* The port is administratively set down with the SERDES
* shut down and no signal transmitted.
*/
IES_PORT_MODE_ADMIN_PWRDOWN = IES_PORT_STATE_ADMIN_PWRDOWN,
/* The receiver is expecting a Built In Self Test sequence. The subMode
* argument to ies_port_set_state or ies_set_port_state_v2 is used to
* specify the test pattern.
*/
IES_PORT_MODE_BIST = IES_PORT_STATE_BIST,
/* The SERDES transmits remote fault constantly and the receiver is
* disabled.
*/
IES_PORT_MODE_REMOTE_FAULT = IES_PORT_STATE_REMOTE_FAULT,
/* Indicates continuous reception of a local fault condition. A remote
* fault is automatically sent continuously.
*/
IES_PORT_MODE_LOCAL_FAULT = IES_PORT_STATE_LOCAL_FAULT
};
#define IES10K_EPL_BASE (0x0E0000)
/* MAC and Reconciliation Sublayer configuration */
#define IES10K_MAC_CFG(index1, index0, word) \
(0x000400 * (index1) + 0x000080 * (index0) + \
(word) + 0x000010 + IES10K_EPL_BASE)
#define IES10K_MAC_CFG_WIDTH 7
#define IES10K_MAC_CFG_ENTRIES_0 4
#define IES10K_MAC_CFG_ENTRIES_1 9
#define IES10K_MAC_CFG_L_TXANTIBUBBLEWATERMARK 0
#define IES10K_MAC_CFG_H_TXANTIBUBBLEWATERMARK 5
#define IES10K_MAC_CFG_L_TXRATEFIFOWATERMARK 6
#define IES10K_MAC_CFG_H_TXRATEFIFOWATERMARK 9
#define IES10K_MAC_CFG_L_TXRATEFIFOFASTINC 10
#define IES10K_MAC_CFG_H_TXRATEFIFOFASTINC 17
#define IES10K_MAC_CFG_L_TXRATEFIFOSLOWINC 18
#define IES10K_MAC_CFG_H_TXRATEFIFOSLOWINC 25
#define IES10K_MAC_CFG_L_TXIDLEMINIFGBYTES 26
#define IES10K_MAC_CFG_H_TXIDLEMINIFGBYTES 31
#define IES10K_MAC_CFG_L_TXCLOCKCOMPENSATIONTIMEOUT 32
#define IES10K_MAC_CFG_H_TXCLOCKCOMPENSATIONTIMEOUT 47
#define IES10K_MAC_CFG_B_TXCLOCKCOMPENSATIONENABLE 48
#define IES10K_MAC_CFG_L_TXFAULTMODE 49
#define IES10K_MAC_CFG_H_TXFAULTMODE 51
#define IES10K_MAC_CFG_L_TXPCACTTIMESCALE 52
#define IES10K_MAC_CFG_H_TXPCACTTIMESCALE 55
#define IES10K_MAC_CFG_L_TXPCACTTIMEOUT 56
#define IES10K_MAC_CFG_H_TXPCACTTIMEOUT 63
#define IES10K_MAC_CFG_L_TXDRAINMODE 64
#define IES10K_MAC_CFG_H_TXDRAINMODE 65
#define IES10K_MAC_CFG_L_TXMINCOLUMNS 66
#define IES10K_MAC_CFG_H_TXMINCOLUMNS 71
#define IES10K_MAC_CFG_B_TXLPIDLEREQUEST 108
#define IES10K_MAC_CFG_B_TXLPIAUTOMATIC 109
#define IES10K_MAC_CFG_L_TXLPITIMEOUT 110
#define IES10K_MAC_CFG_H_TXLPITIMEOUT 117
#define IES10K_MAC_CFG_L_TXLPITIMESCALE 118
#define IES10K_MAC_CFG_H_TXLPITIMESCALE 119
#define IES10K_MAC_CFG_L_TXLPIHOLDTIMEOUT 120
#define IES10K_MAC_CFG_H_TXLPIHOLDTIMEOUT 127
#define IES10K_MAC_CFG_L_TXLPIHOLDTIMESCALE 128
#define IES10K_MAC_CFG_H_TXLPIHOLDTIMESCALE 129
#define IES10K_MAC_CFG_L_TXFCSMODE 130
#define IES10K_MAC_CFG_H_TXFCSMODE 132
#define IES10K_MAC_CFG_B_TXIDLEENABLEDIC 134
#define IES10K_MAC_CFG_L_RXMINFRAMELENGTH 136
#define IES10K_MAC_CFG_H_RXMINFRAMELENGTH 143
#define IES10K_MAC_CFG_L_RXMAXFRAMELENGTH 144
#define IES10K_MAC_CFG_H_RXMAXFRAMELENGTH 159
#define IES10K_MAC_CFG_B_IEEE1588ENABLE 168
#define IES10K_MAC_CFG_B_PREAMBLEMODE 170
#define IES10K_MAC_CFG_B_RXDRAIN 173
#define IES10K_MAC_CFG_B_RXIGNOREIFGERRORS 180
#define DBI410_IF_SERIES(pid) \
((pid==0x01B0)|| \
(pid==0x01B1)|| \
(pid==0x01B2)|| \
(pid==0x01B3)|| \
(pid==0x01B4))
#define DBI410T_IF_SERIES(pid) \
(pid==0x01B0)
#define DBI240_IF_SERIES(pid) \
((pid==0x01B8)|| \
(pid==0x01B9)|| \
(pid==0x01BC)|| \
(pid==0x01BA))
#define DBI100H_IF_SERIES(pid) \
((pid==0x01C0)|| \
(pid==0x01C2))
#define DBI100L_IF_SERIES(pid) \
(pid==0x01C1)
#define DBI25_IF_SERIES(pid) \
(pid==0x01C8)
#define DBI410_IF_SERIES(pid) \
((pid==0x01B0)|| \
(pid==0x01B1)|| \
(pid==0x01B2)|| \
(pid==0x01B3)|| \
(pid==0x01B4))
#define BPCTL_WRITE_REG(a, reg, value) \
(writel((value), (void *)(((a)->mem_map) + reg*4)))
#define BPCTL_READ_REG(a, reg) ( \
readl((void *)((a)->mem_map) + reg*4))
inline static u32 ies_bitfield_get32_multi32(const u32 *array, int hi_bit, int lo_bit)
{
u32 result = 0;
int result_pos = 0;
int word = lo_bit / 32;
int rel_lo_bit = lo_bit % 32;
int rel_hi_bit = rel_lo_bit + (hi_bit - lo_bit);
u32 mask = (2 << (hi_bit - lo_bit)) - 1;
do {
result |= (array[word++] >> rel_lo_bit) << result_pos;
result_pos += (32 - rel_lo_bit);
rel_hi_bit -= 32;
rel_lo_bit = 0;
} while (rel_hi_bit >= 0);
return result & mask;
}
inline static void ies_bitfield_set32_multi32(u32 *array, int hi_bit, int lo_bit,
u32 value)
{
int value_pos = 0;
int word = lo_bit / 32;
int rel_lo_bit = lo_bit % 32;
int rel_hi_bit = rel_lo_bit + (hi_bit - lo_bit);
do {
u32 mask;
mask = (rel_hi_bit < 31 ? (2 << rel_hi_bit) : 0) - 1;
mask >>= rel_lo_bit;
mask <<= rel_lo_bit;
array[word] = ((array[word] & ~mask) |
(((value >> value_pos) << rel_lo_bit) & mask));
value_pos += (32 - rel_lo_bit);
rel_hi_bit -= 32;
rel_lo_bit = 0;
++word;
} while (rel_hi_bit >= 0);
}
/* Get a named field of 2-32 bits within an array of 32-bit values. */
#define IES_ARRAY_GET_FIELD(array, regname, fieldname) \
ies_bitfield_get32_multi32(array, regname ## _H_ ## fieldname, \
regname ## _L_ ## fieldname)
/* Set a named field of 2-32 bits within an array of 32-bit values. */
#define IES_ARRAY_SET_FIELD(array, regname, fieldname, fieldvalue) \
ies_bitfield_set32_multi32(array, regname ## _H_ ## fieldname, \
regname ## _L_ ## fieldname, fieldvalue)
inline static int convert_adminmode_txlinkfault(int mode)
{
int link_fault;
/* Program the output pattern based on the TxFaultMode */
switch (mode) {
case IES_PORT_MODE_ADMIN_DOWN:
link_fault = 1;
break;
case IES_PORT_MODE_LOCAL_FAULT:
link_fault = 2;
break;
case IES_PORT_MODE_REMOTE_FAULT:
link_fault = 3;
break;
default:
link_fault = 0;
break;
}
return link_fault;
}
#define lock_bpctl() \
if (down_interruptible(&bpctl_sema)) { \
return -ERESTARTSYS; \
} \
#define unlock_bpctl() \
up(&bpctl_sema);
static int bp_shutdown = 0;
/* Media Types */
typedef enum {
bp_copper = 0,
bp_fiber,
bp_cx4,
bp_none,
} bp_media_type;
struct pfs_unit_rd {
struct proc_dir_entry *proc_entry;
char proc_name[32];
} ;
typedef struct _bpctl_dev_mng {
char *name;
char *desc;
struct pci_dev *pdev; /* PCI device */
struct net_device *ndev; /* net device */
unsigned long mem_map;
uint8_t bus;
uint8_t slot;
uint8_t func;
uint8_t bus_p;
uint8_t slot_p;
uint8_t func_p;
u_int32_t device;
u_int32_t vendor;
u_int32_t subvendor;
u_int32_t subdevice;
int ifindex;
spinlock_t bypass_wr_lock;
int port_num;
int sw_num;
struct mutex i2c_bus_lock;
int mutex_owner_module;
/* #endif */
} bpctl_dev_mng_t;
#ifdef BP_PROC_SUPPORT
struct pfs_unit_rd {
struct proc_dir_entry *proc_entry;
char proc_name[32];
} ;
struct bypass_pfs_rd {
char dir_name[32];
struct proc_dir_entry *bypass_entry;
struct pfs_unit_rd bypass_info;
struct pfs_unit_rd bypass_slave;
struct pfs_unit_rd bypass_caps;
struct pfs_unit_rd wd_set_caps;
struct pfs_unit_rd bypass;
struct pfs_unit_rd bypass_change;
struct pfs_unit_rd bypass_wd;
struct pfs_unit_rd wd_expire_time;
struct pfs_unit_rd reset_bypass_wd;
struct pfs_unit_rd dis_bypass;
struct pfs_unit_rd bypass_pwup;
struct pfs_unit_rd bypass_pwoff;
struct pfs_unit_rd std_nic;
struct pfs_unit_rd tap;
struct pfs_unit_rd dis_tap;
struct pfs_unit_rd tap_pwup;
struct pfs_unit_rd tap_change;
struct pfs_unit_rd wd_exp_mode;
struct pfs_unit_rd wd_autoreset;
struct pfs_unit_rd tpl;
};
#endif
typedef struct _bpctl_dev {
char *name;
char *desc;
struct pci_dev *pdev; /* PCI device */
struct net_device *ndev; /* net device */
bpctl_dev_mng_t *pbpctl_dev_c;
struct pci_dev *pdev_mng;
struct pci_dev *pdev_pf_master;
struct pci_dev *pdev_pf_slave;
unsigned long mem_map;
uint8_t bus;
uint8_t slot;
uint8_t func;
uint8_t bus_p;
uint8_t slot_p;
uint8_t func_p;
u_int32_t device;
u_int32_t vendor;
u_int32_t subvendor;
u_int32_t subdevice;
int ifindex;
uint32_t bp_caps;
uint32_t bp_caps_ex;
uint8_t bp_fw_ver;
int bp_ext_ver;
int wdt_status;
unsigned long bypass_wdt_on_time;
uint32_t bypass_timer_interval;
struct timer_list bp_timer;
uint32_t reset_time;
uint8_t bp_status_un;
atomic_t wdt_busy;
bp_media_type media_type;
int bp_master_flag;
int bp_tpl_flag;
struct timer_list bp_tpl_timer;
int tpl_wait;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
const struct net_device_ops *old_ops;
struct net_device_ops new_ops;
#endif
int bp_self_test_flag;
char *bp_tx_data;
uint8_t rb_oem;
uint8_t oem_data[20];
uint32_t ledctl_default;
uint32_t ledctl_mode1;
uint32_t ledctl_mode2;
uint32_t led_status;
//#endif
struct timer_list blink_timer;
struct timer_list wait_timer;
#ifdef BP_PROC_SUPPORT
struct bypass_pfs_rd bypass_pfs_set;
char proc_dir[128];
#endif
int port_num;
int epl_num;
int epl;
int lane_num;
int sw_num;
/* #endif */
} bpctl_dev_t;
inline static int iespl_read_mult_u32(bpctl_dev_mng_t *interface, u32 addr, int n, u32 *val)
{
u32 value;
int i;
for (i = 0; i < n; i++) {
value = BPCTL_READ_REG(interface, (addr + i));
val[i] = value;
}
return 0;
}
inline static int iespl_write_mult_u32(bpctl_dev_mng_t *interface, u32 addr, int n, u32 *val)
{
int i;
for (i = 0; i < n; i++) {
BPCTL_WRITE_REG(interface, (addr + i), val[i]);
}
return 0;
}
static bpctl_dev_t *bpctl_dev_arr;
static bpctl_dev_mng_t *bpctl_dev_mng_arr;
static int device_num=0;
static int mng_device_num=0;
static struct semaphore bpctl_sema;
static int usec_delay_bp1(unsigned long x);
static void usec_delay_bp(unsigned long x);
static void msec_delay_bp(unsigned long x);
static int get_dev_idx_bsf(int bus, int slot, int func);
static int get_dev_mng_idx_bsf(int bus, int slot, int func);
static int get_dev_idx(int ifindex);
static void if_scan_init(void);
static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev);
static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev);
#ifdef BP_PROC_SUPPORT
int bypass_proc_create_dev_rd(bpctl_dev_t * pbp_device_block);
int bypass_proc_remove_dev_rd(bpctl_dev_t * pbp_device_block);
int bp_proc_create(void);
#endif
int get_tx_rd_fn(bpctl_dev_t *pbpctl_dev);
int set_tx_rd_fn(bpctl_dev_t *pbpctl_dev, int tx_state);
int is_bypass_rd_fn(bpctl_dev_t *pbpctl_dev);
int get_bypass_caps_rd_fn(bpctl_dev_t *pbpctl_dev);
int get_wd_expire_rd_fn (bpctl_dev_t *pbpctl_dev);
int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout);
static int TAKE_PLAT_I2C_BUS_LOCK_IDX(struct file * file, int dev_idx){
int rc;
rc = mutex_lock_interruptible(&bpctl_dev_mng_arr[dev_idx].i2c_bus_lock);
bpctl_dev_mng_arr[dev_idx].mutex_owner_module = 0;
file->private_data = &bpctl_dev_mng_arr[dev_idx].i2c_bus_lock;
return(rc) ? -ERESTARTSYS: 0;
}
static void DROP_PLAT_I2C_BUS_LOCK_IDX(struct file * file, int dev_idx){
mutex_unlock(&bpctl_dev_mng_arr[dev_idx].i2c_bus_lock);
file->private_data = NULL;
}
static void TAKE_PLAT_I2C_BUS_LOCK(bpctl_dev_mng_t *pbpctl_dev_c) {
int rc= mutex_lock_interruptible( &pbpctl_dev_c->i2c_bus_lock);
pbpctl_dev_c->mutex_owner_module = (rc) ? 1 :0;
}
static void DROP_PLAT_I2C_BUS_LOCK(bpctl_dev_mng_t *pbpctl_dev_c){
pbpctl_dev_c->mutex_owner_module = 0;
mutex_unlock( &pbpctl_dev_c->i2c_bus_lock);
}
int usec_delay_bp1(unsigned long x) {
struct timeval tv, tv_end;
do_gettimeofday(&tv);
udelay(x);
do_gettimeofday(&tv_end);
if (tv_end.tv_usec>tv.tv_usec) {
if ((tv_end.tv_usec-tv.tv_usec)<(x))
return 0;
}
else if ((~tv.tv_usec+tv_end.tv_usec)<(x))
return 0;
return 1;
}
void usec_delay_bp(unsigned long x) {
#if 1
int i=2;
while (i--) {
if (usec_delay_bp1(x))
return;
}
#else
udelay(x);
#endif
}
void msec_delay_bp(unsigned long x){
#ifdef BP_NDELAY_MODE
return;
#else
int i;
if (in_interrupt()) {
for (i = 0; i < 1000; i++) {
usec_delay_bp(x) ;
}
}
else {
msleep(x);
}
#endif
}
#define FM_SET_FIELD(lvalue, regname, fieldname, fieldvalue) \
(lvalue ^= ( ( (lvalue >> regname ## _l_ ## fieldname) ^ fieldvalue ) & \
( ( 2 << (regname ## _h_ ## fieldname - regname ## _l_ ## fieldname) ) - 1 ) ) \
<< regname ## _l_ ## fieldname)
#define FM_GET_FIELD(rvalue, regname, fieldname) \
( (rvalue >> regname ## _l_ ## fieldname) & \
( ( 2 << (regname ## _h_ ## fieldname - regname ## _l_ ## fieldname) ) - 1 ) )
#define FM_GET_BIT(rvalue, regname, bitname) \
( (rvalue >> regname ## _b_ ## bitname) & 1 )
#define FM_SET_BIT(lvalue, regname, bitname, bitvalue) \
( lvalue = ( lvalue & ~(1 << regname ## _b_ ## bitname) ) | \
( (bitvalue & 1) << regname ## _b_ ## bitname ) )
#define FM10000_I2C_DATA(index) ((0x000001) * ((index) - 0) + (0x000C1C))
#define FM10000_I2C_CTRL 0x000C20
#define FM10000_GPIO_CFG 0x000C15
#define FM10000_GPIO_DATA 0x000C16
#define FM10000_I2C_CTRL_l_Addr 0
#define FM10000_I2C_CTRL_h_Addr 7
#define FM10000_I2C_CTRL_l_Command 8
#define FM10000_I2C_CTRL_h_Command 9
#define FM10000_I2C_CTRL_l_LengthW 10
#define FM10000_I2C_CTRL_h_LengthW 13
#define FM10000_I2C_CTRL_l_LengthR 14
#define FM10000_I2C_CTRL_h_LengthR 17
#define FM10000_I2C_CTRL_l_LengthSent 18
#define FM10000_I2C_CTRL_h_LengthSent 21
#define FM10000_I2C_CTRL_l_CommandCompleted 22
#define FM10000_I2C_CTRL_h_CommandCompleted 25
#define FM10000_I2C_CTRL_b_InterruptPending 26
static int I2cWriteRead(bpctl_dev_mng_t *pbpctl_dev_c,
unsigned int device,
unsigned char *data,
unsigned int wl,
unsigned int rl)
{
uint32_t regValue;
unsigned int i;
unsigned int j;
uint i2c_try = 40;
uint32_t tmp;
/*printk("I2cWriteRead device=0x%x wl=%d rl=%d\n",
device, wl, rl);*/
if (rl > 12)
{
return -1;
}
if (wl > 12)
{
return -1;
}
if (data == NULL)
{
return -1;
}
if (!pbpctl_dev_c)
return -1;
for (i = 0 ; i < (wl+3)/4 ; i++)
{
regValue = 0;
for (j = 0 ; j < 4 ; j++)
{
if ((i*4 + j) < wl)
{
regValue |= (data[i*4 + j] << ((3 - j)*8));
}
}
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_I2C_DATA(i), regValue);
/*printk("WRITEDATA#%d : 0x%08x\n",i, regValue); */
}
regValue = 0;
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Addr, (device << 1));
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 0);
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, LengthW, wl);
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, LengthR, rl);
/* printk("WRITE: eg 0x%08x Cmd %d wl %d rl %d "
"Comp %x LenSent %d intr %d\n",
regValue,
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent),
FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending));*/
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_I2C_CTRL, regValue);
tmp = BPCTL_READ_REG(pbpctl_dev_c, FM10000_I2C_CTRL);
/*printk("READ: reg 0x%08x Cmd %d wl %d rl %d "
"Comp %x LenSent %d intr %d\n", tmp,
FM_GET_FIELD(tmp, FM10000_I2C_CTRL, Command),
FM_GET_FIELD(tmp, FM10000_I2C_CTRL, LengthW),
FM_GET_FIELD(tmp, FM10000_I2C_CTRL, LengthR),
FM_GET_FIELD(tmp, FM10000_I2C_CTRL, CommandCompleted),
FM_GET_FIELD(tmp, FM10000_I2C_CTRL, LengthSent),
FM_GET_BIT(tmp, FM10000_I2C_CTRL, InterruptPending));*/
/* Now change command to start the transaction */
if (rl == 0)
{
/* Write only allow write of 0 length */
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 1);
}
else if ((wl > 0) && (rl > 0))
{
/* Write Read */
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 2);
}
else
{
/* Read */
FM_SET_FIELD(regValue, FM10000_I2C_CTRL, Command, 3);
}
/*printk("WRITE2: reg 0x%08x Cmd %d wl %d rl %d "
"Comp %x LenSent %d intr %d\n", regValue,
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent),
FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending));*/
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_I2C_CTRL, regValue);
regValue = BPCTL_READ_REG(pbpctl_dev_c, FM10000_I2C_CTRL);
/*printk("READ2: reg 0x%08x Cmd %d wl %d rl %d "
"Comp %x LenSent %d intr %d\n", regValue,
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, Command),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthW),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthR),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted),
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, LengthSent),
FM_GET_BIT(regValue, FM10000_I2C_CTRL, InterruptPending));*/
/* Poll to check for command done */
do
{
msec_delay_bp(1);
regValue = BPCTL_READ_REG(pbpctl_dev_c, FM10000_I2C_CTRL);
} while ((FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted) == 0)&&(i2c_try--));
if (FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted) != 1)
{
/*printk("Dev=0x%02x: I2C Command completed with error 0x%x. "
"I2C_CTRL(0x%x)=0x%x\n",
device,
FM_GET_FIELD(regValue, FM10000_I2C_CTRL, CommandCompleted),
FM10000_I2C_CTRL,
regValue);*/
return -1;
}
for (i = 0 ; i < (rl+3)/4 ; i++)
{
regValue = BPCTL_READ_REG(pbpctl_dev_c, FM10000_I2C_DATA(i));
for (j = 0 ; j < 4 ; j++)
{
if ((i*4 + j) < rl)
{
data[i*4 + j] = (regValue >> ((3 - j)*8)) & 0xFF;
}
}
}
return 0;
} /* end I2cWriteRead */
static int WriteBypass(bpctl_dev_mng_t *pbpctl_dev_c,
unsigned int device,
unsigned char *data,
unsigned int wl,
unsigned int rl)
{
int status;
if (!pbpctl_dev_c)
return -1;
#if 0
{
int num, i;
num = rl?rl:wl;
printk("data ");
for (i = 0; i < num; i++){
printk("%x ", data[i]);
}
printk("\n");
}
#endif
status = I2cWriteRead(pbpctl_dev_c, device, data, wl, rl);
return status;
} /* end WriteSfppPhy */
int fmPlatformFm10000BypassWriteRead(bpctl_dev_mng_t *pbpctl_dev_c,
unsigned int device,
unsigned char *data,
unsigned int wl,
unsigned int rl)
{
int status = 0;
unsigned char mux_pin = 2;
if (!pbpctl_dev_c)
return -1;
TAKE_PLAT_I2C_BUS_LOCK(pbpctl_dev_c);
if (!DBI410T_IF_SERIES(pbpctl_dev_c->subdevice)) {
if (DBI410_IF_SERIES(pbpctl_dev_c->subdevice))
status = I2cWriteRead(pbpctl_dev_c, 0x75, &mux_pin, 1, 0);
else
status = I2cWriteRead(pbpctl_dev_c, 0x70, &mux_pin, 1, 0);
}
if (status == 0)
status = WriteBypass(pbpctl_dev_c, device, data, wl, rl);
DROP_PLAT_I2C_BUS_LOCK(pbpctl_dev_c);
return status;
} /* end fmPlatformPhyEnable1000BaseTAutoNeg */
/*static bpctl_dev_t *bpctl_dev_a;
static bpctl_dev_t *bpctl_dev_b;*/
static int bp_get_dev_idx_bsf(struct net_device *dev, int *index)
{
struct ethtool_drvinfo drvinfo = {0};
char *buf;
int bus, slot, func;
if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
else
return -EOPNOTSUPP;
if (!drvinfo.bus_info)
return -ENODATA;
if (!strcmp(drvinfo.bus_info, "N/A"))
return -ENODATA;
buf = strchr(drvinfo.bus_info, ':');
if (!buf)
return -EINVAL;
buf++;
if (sscanf(buf, "%x:%x.%x", &bus, &slot, &func) != 3)
return -EINVAL;
*index = get_dev_idx_bsf(bus, slot, func);
return 0;
}
static int bp_get_dev_mng_idx_bsf(struct net_device *dev, int *index)
{
struct ethtool_drvinfo drvinfo = {0};
char *buf;
int bus, slot, func;
if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
else
return -EOPNOTSUPP;
if (!drvinfo.bus_info)
return -ENODATA;
if (!strcmp(drvinfo.bus_info, "N/A"))
return -ENODATA;
buf = strchr(drvinfo.bus_info, ':');
if (!buf)
return -EINVAL;
buf++;
if (sscanf(buf, "%x:%x.%x", &bus, &slot, &func) != 3)
return -EINVAL;
*index = get_dev_mng_idx_bsf(bus, slot, func);
return 0;
}
static bpctl_dev_mng_t *get_mng_port_rd_fn(bpctl_dev_t *pbpctl_dev) {
int idx_dev=0;
if (pbpctl_dev==NULL)
return NULL;
for (idx_dev = 0; ((bpctl_dev_mng_arr[idx_dev].pdev != NULL)&&(idx_dev < mng_device_num)); idx_dev++) {
if (DBI410_IF_SERIES(pbpctl_dev->subdevice)) {
if ((bpctl_dev_mng_arr[idx_dev].bus == pbpctl_dev->bus) &&
(bpctl_dev_mng_arr[idx_dev].slot == pbpctl_dev->slot) &&
(bpctl_dev_mng_arr[idx_dev].func == 0)) {
return(&(bpctl_dev_mng_arr[idx_dev]));
}
}
else {
if (bpctl_dev_mng_arr[idx_dev].pdev == pbpctl_dev->pdev_mng)
return(&(bpctl_dev_mng_arr[idx_dev]));
}
}
return NULL;
}
/*
* This routine tries to find the Master/Slave NICs base on the following
* hardware configuration.
*
* GrandParent--+--Uncle1
* +--Parent/Uncle--+--Me?(Slave)
* |
* +--Parent/Uncle--+-Me?(Master)
* +--Uncle3
* Input:
* me - pci_dev pointer to the Broadcom device
* Output:
* pdev_master - pci_dev pointer to Master(NIC Controler1)
* pdev_slave - pci_dev pointer to Slave(NIC Controler2)
*/
static void
rdi_find_master_slave_plx(struct pci_dev *me,
struct pci_dev **pdev_master,
struct pci_dev **pdev_slave)
{
struct pci_bus *grand_parent, *uncle, *parent;
struct list_head *tmp, *tmp2;
struct pci_dev *pdev;
*pdev_master = NULL;
*pdev_slave = NULL;
if ((parent = me->bus) == NULL) {
pr_err("rdi cannot find its parent\n");
return;
}
if ((grand_parent = parent->parent) == NULL) {
return;
}
list_for_each(tmp, &grand_parent->children) {
uncle = list_entry(tmp, struct pci_bus, node);
if (uncle == parent)
continue;
if (uncle) {
list_for_each(tmp2, &uncle->devices) {
pdev = list_entry(tmp2, struct pci_dev, bus_list);
if (pdev == NULL || pdev->bus == NULL) {
pr_err("%s:%d: t not found\n", __FUNCTION__, __LINE__);
continue;
}
if (pdev->bus->number > me->bus->number) {
*pdev_master = pdev;
*pdev_slave = me;
}
else {
*pdev_master = me;
*pdev_slave = pdev;
}
return;
}
}
}
}
#if 1
static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev) {
int idx_dev=0;
if ( pbpctl_dev == NULL ) {
return NULL;
}
if ((pbpctl_dev->epl_num == 2) ||
(pbpctl_dev->epl_num == 4)) {
return pbpctl_dev;
}
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev != NULL)&&(idx_dev < device_num)); idx_dev++) {
if (DBI410_IF_SERIES(pbpctl_dev->subdevice)) {
if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)&&
(bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)&&
((bpctl_dev_arr[idx_dev].epl_num == 2)&&(pbpctl_dev->epl_num == 1))) {
return(&(bpctl_dev_arr[idx_dev]));
}
if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)&&
(bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)&&
((bpctl_dev_arr[idx_dev].epl_num == 4)&&(pbpctl_dev->epl_num == 3))) {
return(&(bpctl_dev_arr[idx_dev]));
}
}
else {
if ((bpctl_dev_arr[idx_dev].pdev == pbpctl_dev->pdev_pf_slave)&&
((bpctl_dev_arr[idx_dev].epl_num == 2)&&(pbpctl_dev->epl_num == 1))) {
return(&(bpctl_dev_arr[idx_dev]));
}
}
}
return NULL;
}
static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev) {
int idx_dev=0;
if (pbpctl_dev==NULL) {
return NULL;
}
if ((pbpctl_dev->epl_num == 1) ||
(pbpctl_dev->epl_num == 3)) {
return pbpctl_dev;
}
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev != NULL)&&(idx_dev < device_num)); idx_dev++) {
if (DBI410_IF_SERIES(pbpctl_dev->subdevice)) {
if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)&&
(bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)&&
((bpctl_dev_arr[idx_dev].epl_num == 1)&&(pbpctl_dev->epl_num == 2))) {
return(&(bpctl_dev_arr[idx_dev]));
}
if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)&&
(bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)&&
((bpctl_dev_arr[idx_dev].epl_num == 3)&&(pbpctl_dev->epl_num == 4))) {
return(&(bpctl_dev_arr[idx_dev]));
}
}
else {
if ((bpctl_dev_arr[idx_dev].pdev == pbpctl_dev->pdev_pf_master)&&
((bpctl_dev_arr[idx_dev].epl_num == 1)&&(pbpctl_dev->epl_num == 2))) {
return(&(bpctl_dev_arr[idx_dev]));
}
}
}
return NULL;
}
#endif
static int
bp_reboot_event(struct notifier_block *nb,
unsigned long event,
void *ptr)
{
bp_shutdown = 1;
return NOTIFY_DONE;
}
static int bp_device_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0))
struct net_device *dev = ptr;
#else
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
#endif
static bpctl_dev_t *pbpctl_dev, *pbpctl_dev_m, *pbpctl_dev2;
int dev_num = 0;
#if 0
static bpctl_dev_t *pbpctl_dev_m;
int ret = 0;
#endif
/*printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex );
return NOTIFY_DONE;*/
if (!dev)
return NOTIFY_DONE;
if (event == NETDEV_REGISTER) {
int idx_dev;
if (bp_get_dev_idx_bsf(dev, &idx_dev))
return NOTIFY_DONE;
if (idx_dev == -1)
return NOTIFY_DONE;
bpctl_dev_arr[idx_dev].ifindex = dev->ifindex;
bpctl_dev_arr[idx_dev].ndev = dev;
if ((!bp_get_dev_mng_idx_bsf(dev, &idx_dev)) &&
(idx_dev != -1)) {
bpctl_dev_mng_arr[idx_dev].ifindex = dev->ifindex;
bpctl_dev_mng_arr[idx_dev].ndev = dev;
}
#ifdef BP_PROC_SUPPORT
bypass_proc_remove_dev_rd(&bpctl_dev_arr[idx_dev]);
bypass_proc_create_dev_rd(&bpctl_dev_arr[idx_dev]);
#endif
return NOTIFY_DONE;
}
if (event == NETDEV_UNREGISTER) {
int idx_dev = 0;
for (idx_dev = 0;
((bpctl_dev_arr[idx_dev].pdev != NULL)
&& (idx_dev < device_num)); idx_dev++) {
if (bpctl_dev_arr[idx_dev].ndev == dev) {
#ifdef BP_PROC_SUPPORT
bypass_proc_remove_dev_rd(&bpctl_dev_arr
[idx_dev]);
#endif
bpctl_dev_arr[idx_dev].ndev = NULL;
return NOTIFY_DONE;
}
}
return NOTIFY_DONE;
}
if (event == NETDEV_CHANGENAME) {
int idx_dev = 0;
for (idx_dev = 0;
((bpctl_dev_arr[idx_dev].pdev != NULL)
&& (idx_dev < device_num)); idx_dev++) {
if (bpctl_dev_arr[idx_dev].ndev == dev) {
#ifdef BP_PROC_SUPPORT
bypass_proc_remove_dev_rd(&bpctl_dev_arr
[idx_dev]);
bypass_proc_create_dev_rd(&bpctl_dev_arr
[idx_dev]);
#endif
return NOTIFY_DONE;
}
}
return NOTIFY_DONE;
}
switch (event) {
case NETDEV_CHANGE:{
if (((dev_num = get_dev_idx(dev->ifindex)) == -1) ||
(!(pbpctl_dev = &bpctl_dev_arr[dev_num])))
return NOTIFY_DONE;
if (bp_shutdown == 1)
return NOTIFY_DONE;
if ((is_bypass_rd_fn(pbpctl_dev)) == 1){
pbpctl_dev_m = pbpctl_dev;
pbpctl_dev2 = get_status_port_fn(pbpctl_dev);
}
else {
pbpctl_dev2 = pbpctl_dev_m = get_master_port_fn(pbpctl_dev);
}
if ((!pbpctl_dev_m)||(!pbpctl_dev2))
return NOTIFY_DONE;
if (netif_carrier_ok(dev)) {
if (pbpctl_dev_m->bp_tpl_flag){
if (get_tx_rd_fn(pbpctl_dev)) {
pbpctl_dev->tpl_wait = 0;
if (!get_tx_rd_fn(pbpctl_dev2)) {
pbpctl_dev2->tpl_wait = 1;
set_tx_rd_fn(pbpctl_dev2, 1);
}
}
}
return NOTIFY_DONE;
}
if (pbpctl_dev_m->bp_tpl_flag){
if (get_tx_rd_fn(pbpctl_dev)) {
if (get_tx_rd_fn(pbpctl_dev2)) {
set_tx_rd_fn(pbpctl_dev2, 0);
}
}
}
return NOTIFY_DONE;
}
default:
return NOTIFY_DONE;
}
return NOTIFY_DONE;
}
static struct notifier_block bp_notifier_block = {
.notifier_call = bp_device_event,
};
static struct notifier_block bp_reboot_block = {
.notifier_call = bp_reboot_event,
};
static int device_open(struct inode *inode, struct file *file)
{
file->private_data = NULL;
#ifdef DEBUG
printk("device_open(%p)\n", file);
#endif
Device_Open++;
/*
* Initialize the message
*/
return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
int i;
#ifdef DEBUG
printk("device_release(%p,%p)\n", inode, file);
#endif
Device_Open--;
if ( file->private_data != NULL )
{
mutex_unlock((struct mutex *) file->private_data);
for (i=0; i< mng_device_num; i++) {
if (! bpctl_dev_mng_arr[i].mutex_owner_module) {
/*if (bpctl_dev_mng_arr[i].i2c_bus_lock.owner == current )*/
mutex_unlock(&bpctl_dev_mng_arr[i].i2c_bus_lock);
}
}
}
return SUCCESS;
}
static int get_dev_idx(int ifindex){
int idx_dev=0;
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev!=NULL)&&(idx_dev<device_num)); idx_dev++) {
if (ifindex==bpctl_dev_arr[idx_dev].ifindex)
return idx_dev;
}
return -1;
}
static bpctl_dev_t *get_dev_idx_p(int ifindex){
int idx_dev=0;
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev!=NULL)&&(idx_dev<device_num)); idx_dev++) {
if (ifindex==bpctl_dev_arr[idx_dev].ifindex)
return &bpctl_dev_arr[idx_dev];
}
return NULL;
}
static int get_dev_idx_bsf(int bus, int slot, int func){
int idx_dev=0;
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev!=NULL)&&(idx_dev<device_num)); idx_dev++) {
if ((bus==bpctl_dev_arr[idx_dev].bus) &&
(slot==bpctl_dev_arr[idx_dev].slot) &&
(func==bpctl_dev_arr[idx_dev].func) ) {
return idx_dev;
}
}
return -1;
}
static int get_dev_mng_idx(int ifindex){
int idx_dev=0;
for (idx_dev = 0; ((bpctl_dev_mng_arr[idx_dev].pdev!=NULL)&&(idx_dev<mng_device_num)); idx_dev++) {
if (ifindex == bpctl_dev_mng_arr[idx_dev].ifindex)
return idx_dev;
}
return -1;
}
#if 0
static bpctl_dev_mng_t *get_dev_mng_idx_p(int ifindex){
int idx_dev=0;
for (idx_dev = 0; ((bpctl_dev_mng_arr[idx_dev].pdev!=NULL)&&(idx_dev<mng_device_num)); idx_dev++) {
if (ifindex==bpctl_dev_mng_arr[idx_dev].ifindex)
return &bpctl_dev_mng_arr[idx_dev];
}
return NULL;
}
#endif
static int get_dev_mng_idx_bsf(int bus, int slot, int func){
int idx_dev=0;
for (idx_dev = 0; ((bpctl_dev_mng_arr[idx_dev].pdev!=NULL)&&(idx_dev<mng_device_num)); idx_dev++) {
if ((bus==bpctl_dev_mng_arr[idx_dev].bus) &&
(slot==bpctl_dev_mng_arr[idx_dev].slot) &&
(func==bpctl_dev_mng_arr[idx_dev].func) ) {
return idx_dev;
}
}
return -1;
}
static void if_scan_init(void)
{
struct net_device *dev;
#if (LINUX_VERSION_CODE >= 0x020618)
for_each_netdev(&init_net, dev)
#elif (LINUX_VERSION_CODE >= 0x20616)
for_each_netdev(dev)
#else
for (dev = dev_base; dev; dev = dev->next)
#endif
{
int idx_dev;
if (bp_get_dev_idx_bsf(dev, &idx_dev))
continue;
if (idx_dev == -1)
continue;
bpctl_dev_arr[idx_dev].ifindex = dev->ifindex;
bpctl_dev_arr[idx_dev].ndev = dev;
}
}
static void if_scan_mng_init(void)
{
struct net_device *dev;
#if (LINUX_VERSION_CODE >= 0x020618)
for_each_netdev(&init_net, dev)
#elif (LINUX_VERSION_CODE >= 0x20616)
for_each_netdev(dev)
#else
for (dev = dev_base; dev; dev = dev->next)
#endif
{
int idx_dev;
if (bp_get_dev_mng_idx_bsf(dev, &idx_dev))
continue;
if (idx_dev == -1)
continue;
bpctl_dev_mng_arr[idx_dev].ifindex = dev->ifindex;
bpctl_dev_mng_arr[idx_dev].ndev = dev;
}
}
#define FM10K_UC_ADDR_START 0x000000 /* start of standard regs */
#define FM10K_WC_ADDR_START 0x100000 /* start of Tx Desc Cache */
#define FM10K_DBI_ADDR_START 0x200000 /* start of debug registers */
#define FM10K_UC_ADDR_SIZE (FM10K_WC_ADDR_START - FM10K_UC_ADDR_START)
#define FM10K_WC_ADDR_SIZE (FM10K_DBI_ADDR_START - FM10K_WC_ADDR_START)
static int bp_cmd_request(bpctl_dev_mng_t *pbpctl_dev_c, bp_cmd_t *bp_cmd_buf, bp_cmd_rsp_t *bp_rsp_buf);
static int bp_cmd_request(bpctl_dev_mng_t *pbpctl_dev_c, bp_cmd_t *bp_cmd_buf, bp_cmd_rsp_t *bp_rsp_buf) {
int ret_val;
int try_num = 10;
/* atomic_set(&pbpctl_dev->wdt_busy,1); */
/*
* Send command
*/
if (!pbpctl_dev_c)
return -1;
while (try_num--) {
memset(bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
usec_delay_bp(CMND_INTERVAL);
if ((ret_val = fmPlatformFm10000BypassWriteRead(pbpctl_dev_c,
0x57,
(unsigned char *)bp_cmd_buf,
sizeof(bp_cmd_t),
0))) {
printk("bp_cmd_request(write): Not supported!\n");
continue;
// return 0;
}
usec_delay_bp(CMND_INTERVAL);
#if 1
/*
* Receive replay
*/
if ((ret_val = fmPlatformFm10000BypassWriteRead(pbpctl_dev_c, 0x57,
(unsigned char *)bp_rsp_buf, 0,
sizeof(bp_cmd_rsp_t))) < 0) {
printk("bp_cmd_request(read): Not supported!\n");
continue;
//return 0;
}
#endif
// if (bp_rsp_buf->rsp.rsp_id != BP_ERR_OK)
// continue;
if (bp_rsp_buf->rsp.rsp_id != BP_ERR_OK)
continue;
#if 1
if (bp_rsp_buf->rsp.rsp_id != BP_ERR_OK)
printk("bp_cmd_request(got err code or corrupted data!) (%x %x %x %x %x %x)\n",
bp_rsp_buf->cmd_bytes[0],bp_rsp_buf->cmd_bytes[1],bp_rsp_buf->cmd_bytes[2],
bp_rsp_buf->cmd_bytes[3],bp_rsp_buf->cmd_bytes[4],bp_rsp_buf->cmd_bytes[5]);
#endif
break;
}
/*atomic_set(&pbpctl_dev->wdt_busy,0);*/
if (!try_num) {
return 0;
}
return 1;
}
int is_bypass_port_rd_fn(int port){
return(((port == 1)||(port == 3)) ? 1:0);
}
int is_bypass_rd_fn(bpctl_dev_t *pbpctl_dev){
if (!pbpctl_dev) {
return -1;
}
return(pbpctl_dev->bp_master_flag);
}
int set_bypass_rd_fn (bpctl_dev_t *pbpctl_dev, int bypass_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num= (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id=CMD_SET_BYPASS;
bp_cmd_buf.cmd.cmd_data.bypass_mode=bypass_mode?1:0;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(LATCH_DELAY);
return ret;
}
int get_wd_expire_rd_fn (bpctl_dev_t *pbpctl_dev){
int ret = -1, gpio = 0, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
uint32_t cfg;
if (!pbpctl_dev) {
return -1;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
gpio = (port == 1)?9:10;
cfg = BPCTL_READ_REG(pbpctl_dev_c, FM10000_GPIO_CFG);
cfg &= ~(1 << gpio);
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_GPIO_CFG, cfg);
cfg = 0;
cfg = BPCTL_READ_REG(pbpctl_dev_c, FM10000_GPIO_DATA);
ret = cfg & (1 << gpio);
return(ret==0?1:0);
}
int get_bypass_rd_fn (bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret=-1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.bypass_pwoff == BYPASS_PWOFF_EN) {
ret = 1;
}
else if (bp_rsp_buf.rsp.rsp_data.bypass_pwoff == BYPASS_PWOFF_DIS) {
ret = 0;
}
}
}
return ret;
}
int get_bypass_change_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
int port = 0;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_CHANGE;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_data.bypass_change == BYPASS_CHANGED) {
ret = 1;
}
else if (bp_rsp_buf.rsp.rsp_data.bypass_change == BYPASS_NOT_CHANGED) {
ret = 0;
}
}
return ret;
}
int set_dis_bypass_rd_fn(bpctl_dev_t *pbpctl_dev, int dis_bypass){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret=-1;
int port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_DIS_BYPASS;
bp_cmd_buf.cmd.cmd_data.dis_bypass =
dis_bypass?DIS_BYPASS_DISABLE:DIS_BYPASS_ENABLE;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(BYPASS_CAP_DELAY);
return ret;
}
int get_dis_bypass_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret=-1;
int port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_DIS_BYPASS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_data.dis_bypass==DIS_BYPASS_DISABLE) {
ret=1;
}
else if (bp_rsp_buf.rsp.rsp_data.dis_bypass==DIS_BYPASS_ENABLE) {
ret=0;
}
}
return ret;
}
int set_bypass_pwoff_rd_fn (bpctl_dev_t *pbpctl_dev, int bypass_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port =0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_BYPASS_PWOFF;
bp_cmd_buf.cmd.cmd_data.bypass_pwoff =
bypass_mode?BYPASS_PWOFF_EN:BYPASS_PWOFF_DIS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(EEPROM_WR_DELAY);
return ret;
}
int get_bypass_pwoff_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_PWOFF;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.bypass_pwoff == BYPASS_PWOFF_EN) {
ret = 1;
}
else if (bp_rsp_buf.rsp.rsp_data.bypass_pwoff == BYPASS_PWOFF_DIS) {
ret = 0;
}
}
}
return ret;
}
int set_bypass_pwup_rd_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_BYPASS_PWUP;
bp_cmd_buf.cmd.cmd_data.bypass_pwup =
bypass_mode?BYPASS_PWUP_EN:BYPASS_PWUP_DIS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(EEPROM_WR_DELAY);
return ret;
}
int get_bypass_pwup_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev) {
return ret;
}
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c) {
return ret;
}
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port)) {
return ret;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_PWUP;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.bypass_pwup == BYPASS_PWUP_EN)
ret=1;
else if (bp_rsp_buf.rsp.rsp_data.bypass_pwup == BYPASS_PWUP_DIS)
ret=0;
}
}
return ret;
}
int set_bypass_wd_rd_fn(bpctl_dev_t *pbpctl_dev, int timeout){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_BYPASS_WD;
bp_cmd_buf.cmd.cmd_data.timeout = htonl(timeout);
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret = ntohl(bp_rsp_buf.rsp.rsp_data.timeout_set);
}
}
return ret;
}
int get_bypass_wd_rd_fn(bpctl_dev_t *pbpctl_dev, int *timeout){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_WD;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
*timeout = ntohl(bp_rsp_buf.rsp.rsp_data.timeout_set);
ret = 0;
}
}
return ret;
}
int get_wd_expire_time_rd_fn(bpctl_dev_t *pbpctl_dev, int *time_left){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id=CMD_GET_WD_EXPIRE_TIME;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
*time_left = ntohl(bp_rsp_buf.rsp.rsp_data.time_left);
if (*time_left == 0)
ret = 0;
else ret = 1;
}
}
return ret;
}
int reset_bypass_wd_timer_rd_fn(bpctl_dev_t *pbpctl_dev){
int ret=-1, gpio = 0, port = 0;
uint32_t cfg = 0, data = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
gpio = (port==1)?9:10;
cfg = BPCTL_READ_REG(pbpctl_dev_c, FM10000_GPIO_CFG);
cfg |= (1 << gpio);
cfg &= ~( 1 << (gpio + 16) );
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_GPIO_CFG, cfg);
data = BPCTL_READ_REG(pbpctl_dev_c, FM10000_GPIO_DATA);
data |= (1 << gpio);
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_GPIO_DATA, data);
data &= ~(1 << gpio);
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_GPIO_DATA, data);
usec_delay_bp(WDT_INTERVAL);
data |= (1 << gpio);
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_GPIO_DATA, data);
cfg &= ~(1 << gpio);
BPCTL_WRITE_REG(pbpctl_dev_c, FM10000_GPIO_CFG, cfg);
return 1;
}
int get_wd_set_caps_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_WD_SET_CAPS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK)
ret=ntohl(bp_rsp_buf.rsp.rsp_data.wd_set_caps);
}
}
return ret;
}
int set_std_nic_rd_fn(bpctl_dev_t *pbpctl_dev, int nic_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id=CMD_SET_STD_NIC;
bp_cmd_buf.cmd.cmd_data.std_nic =
nic_mode?STD_NIC_EN:STD_NIC_DIS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(BYPASS_CAP_DELAY);
return ret;
}
int get_std_nic_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_STD_NIC;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.std_nic==STD_NIC_EN)
ret=1;
else if (bp_rsp_buf.rsp.rsp_data.std_nic==STD_NIC_DIS)
ret=0;
}
}
return ret;
}
int set_disc_rd_fn (bpctl_dev_t *pbpctl_dev, int disc_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_DISC;
bp_cmd_buf.cmd.cmd_data.disc_mode=disc_mode?1:0;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(LATCH_DELAY);
return ret;
}
int get_disc_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_DISC;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.disc_mode==1)
ret=1;
else if (bp_rsp_buf.rsp.rsp_data.disc_mode==0)
ret=0;
}
}
return ret;
}
int set_disc_pwup_rd_fn(bpctl_dev_t *pbpctl_dev, int disc_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_DISC_PWUP;
bp_cmd_buf.cmd.cmd_data.disc_pwup =
disc_mode?DISC_PWUP_EN:DISC_PWUP_DIS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(EEPROM_WR_DELAY);
return ret;
}
int get_disc_pwup_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_DISC_PWUP;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.disc_pwup==DISC_PWUP_EN)
ret=1;
else if (bp_rsp_buf.rsp.rsp_data.disc_pwup==DISC_PWUP_DIS)
ret=0;
}
}
return ret;
}
int get_disc_change_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_DISC_CHANGE;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.disc_change==DISC_CHANGED)
ret=1;
else if (bp_rsp_buf.rsp.rsp_data.disc_change==DISC_NOT_CHANGED)
ret=0;
}
}
return ret;
}
int set_dis_disc_rd_fn(bpctl_dev_t *pbpctl_dev, int dis_param){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_DIS_DISC;
bp_cmd_buf.cmd.cmd_data.dis_disc =
dis_param?DIS_DISC_DISABLE:DIS_DISC_ENABLE;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(BYPASS_CAP_DELAY);
return ret;
}
int get_dis_disc_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_DIS_DISC;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.dis_disc == DIS_DISC_DISABLE)
ret=1;
else if (bp_rsp_buf.rsp.rsp_data.dis_disc == DIS_DISC_ENABLE)
ret=0;
}
}
return ret;
}
int get_wd_exp_mode_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_WD_EXP_MODE;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=bp_rsp_buf.rsp.rsp_data.wd_exp_mode;
}
}
return ret;
}
int set_wd_exp_mode_rd_fn(bpctl_dev_t *pbpctl_dev, int param){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_WD_EXP_MODE;
bp_cmd_buf.cmd.cmd_data.wd_exp_mode = param;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(BYPASS_CAP_DELAY);
return ret;
}
int set_tx_rd_fn(bpctl_dev_t *pbpctl_dev, int tx_state){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
if ((!port) || (port > 4))
return -1;
if (DBI240_IF_SERIES(pbpctl_dev_c->subdevice)) {
unsigned int mac_cfg[IES10K_MAC_CFG_WIDTH];
memset(mac_cfg, 0, IES10K_MAC_CFG_WIDTH*4);
if (tx_state) {
iespl_read_mult_u32(pbpctl_dev_c, IES10K_MAC_CFG(pbpctl_dev->epl, pbpctl_dev->lane_num, 0 ),
IES10K_MAC_CFG_WIDTH, mac_cfg);
IES_ARRAY_SET_FIELD(mac_cfg, IES10K_MAC_CFG, TXFAULTMODE, 0);
iespl_write_mult_u32(pbpctl_dev_c, IES10K_MAC_CFG(pbpctl_dev->epl, pbpctl_dev->lane_num, 0 ), IES10K_MAC_CFG_WIDTH, mac_cfg);
}
else {
iespl_read_mult_u32(pbpctl_dev_c, IES10K_MAC_CFG(pbpctl_dev->epl, pbpctl_dev->lane_num, 0 ),
IES10K_MAC_CFG_WIDTH, mac_cfg);
IES_ARRAY_SET_FIELD(mac_cfg, IES10K_MAC_CFG, TXFAULTMODE,
convert_adminmode_txlinkfault(IES_PORT_MODE_LOCAL_FAULT));
iespl_write_mult_u32(pbpctl_dev_c, IES10K_MAC_CFG(pbpctl_dev->epl, pbpctl_dev->lane_num, 0 ), IES10K_MAC_CFG_WIDTH, mac_cfg);
}
return 0;
}
if (is_bypass_port_rd_fn(port)) {
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_data.tx_dis.port_num = 0;
}
else {
bp_cmd_buf.cmd.cmd_dev_num = (port == 2)? 0:1;
bp_cmd_buf.cmd.cmd_data.tx_dis.port_num = 1;
}
bp_cmd_buf.cmd.cmd_id = CMD_SET_TX;
bp_cmd_buf.cmd.cmd_data.tx_dis.mode = tx_state?TX_OFF:TX_ON;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
return ret;
}
int get_tx_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
if ((!port) || (port > 4))
return -1;
if (DBI240_IF_SERIES(pbpctl_dev_c->subdevice)) {
unsigned int mac_cfg[IES10K_MAC_CFG_WIDTH];
int tx_fault = 0;
memset(mac_cfg, 0, IES10K_MAC_CFG_WIDTH*4);
iespl_read_mult_u32(pbpctl_dev_c, IES10K_MAC_CFG(pbpctl_dev->epl, pbpctl_dev->lane_num, 0 ),
IES10K_MAC_CFG_WIDTH, mac_cfg);
tx_fault = IES_ARRAY_GET_FIELD(mac_cfg, IES10K_MAC_CFG, TXFAULTMODE);
ret = (tx_fault == 2) ? 0:1;
return ret;
}
if (is_bypass_port_rd_fn(port)) {
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_data.tx_dis.port_num = 0;
}
else {
bp_cmd_buf.cmd.cmd_dev_num = (port == 2)? 0:1;
bp_cmd_buf.cmd.cmd_data.tx_dis.port_num = 1;
}
bp_cmd_buf.cmd.cmd_id = CMD_GET_TX;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
if (bp_rsp_buf.rsp.rsp_data.tx_dis.mode==TX_ON)
ret=0;
else if (bp_rsp_buf.rsp.rsp_data.tx_dis.mode==TX_OFF)
ret=1;
}
else return -1;
}
return ret;
}
int set_bp_force_link_rd_fn(int dev_num, int tx_state){
return -1;
}
int get_bp_force_link_rd_fn(int dev_num){
return -1;
}
int set_bypass_wd_rd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param){
if (pbpctl_dev->bp_caps&WD_CTL_CAP) {
if (pbpctl_dev->reset_time!=param) {
pbpctl_dev->reset_time=param;
if (param)
mod_timer(&pbpctl_dev->bp_timer, jiffies);
}
return 0;
}
return BP_NOT_CAP;
}
int get_bypass_wd_rd_auto(bpctl_dev_t *pbpctl_dev){
if (pbpctl_dev->bp_caps&WD_CTL_CAP) {
return pbpctl_dev->reset_time;
}
return BP_NOT_CAP;
}
int set_wd_autoreset_rd_fn(bpctl_dev_t *pbpctl_dev, int param){
if (!pbpctl_dev)
return -1;
return(set_bypass_wd_rd_auto(pbpctl_dev, param));
}
int get_wd_autoreset_rd_fn(bpctl_dev_t *pbpctl_dev){
if (!pbpctl_dev)
return -1;
return(get_bypass_wd_rd_auto(pbpctl_dev));
}
int get_bypass_caps_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
if ((!port) || (port > 4))
return -1;
if (is_bypass_port_rd_fn(port)) {
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
}
else {
bp_cmd_buf.cmd.cmd_dev_num = (port == 2)? 0:1;
}
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_CAPS;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=(ntohl(bp_rsp_buf.rsp.rsp_data.bypass_caps));
if (!(is_bypass_port_rd_fn(port))){
int ret1 = 0;
if (ret&TX_CTL_CAP)
ret1 = (TX_CTL_CAP|TX_STATUS_CAP);
return ret1;
}
if (DBI240_IF_SERIES(pbpctl_dev_c->subdevice)) {
ret |= TX_CTL_CAP;
if (is_bypass_port_rd_fn(port))
ret |= TPL_CAP;
}
}
}
return ret;
}
int get_bypass_caps_ex_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_CAPS_EX;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=ntohl(bp_rsp_buf.rsp.rsp_data.bypass_caps);
}
}
return ret;
}
int get_bypass_slave_rd_fn(bpctl_dev_t *pbpctl_dev,bpctl_dev_t **pbpctl_dev_out){
int idx_dev=0;
if (!pbpctl_dev)
return -1;
if ((pbpctl_dev->epl_num == 1)||(pbpctl_dev->epl_num == 3)) {
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev != NULL)&&(idx_dev<device_num)); idx_dev++) {
if (DBI410_IF_SERIES(pbpctl_dev->subdevice)) {
if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus)&&
(bpctl_dev_arr[idx_dev].slot == pbpctl_dev->slot)) {
if ((pbpctl_dev->epl_num == 1) &&
(bpctl_dev_arr[idx_dev].epl_num == 2)) {
*pbpctl_dev_out = &bpctl_dev_arr[idx_dev];
return 1;
}
if ((pbpctl_dev->epl_num == 3) &&
(bpctl_dev_arr[idx_dev].epl_num == 4)) {
*pbpctl_dev_out = &bpctl_dev_arr[idx_dev];
return 1;
}
}
}
else {
if (bpctl_dev_arr[idx_dev].pdev == pbpctl_dev->pdev_pf_slave) {
if ((pbpctl_dev->epl_num == 1) &&
(bpctl_dev_arr[idx_dev].epl_num == 2)) {
*pbpctl_dev_out = &bpctl_dev_arr[idx_dev];
return 1;
}
}
}
}
return -1;
}
else return 0;
}
int set_tpl_rd_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
if (DBI240_IF_SERIES(pbpctl_dev_c->subdevice)) {
uint32_t link1, link2;
bpctl_dev_t *pbpctl_dev_m, *pbpctl_dev2;
pbpctl_dev_m = pbpctl_dev;
pbpctl_dev2 = get_status_port_fn(pbpctl_dev);
if ((!pbpctl_dev_m)||(!pbpctl_dev2))
return -1;
if ((!pbpctl_dev->ndev)||(!pbpctl_dev2->ndev))
return -1;
pbpctl_dev->bp_tpl_flag = tpl_mode;
set_tx_rd_fn(pbpctl_dev2, 1);
set_tx_rd_fn(pbpctl_dev, 1);
if (!tpl_mode)
return 0;
link1 = netif_carrier_ok(pbpctl_dev->ndev);
link2 = netif_carrier_ok(pbpctl_dev2->ndev);
if ((!link1)&&(link2))
set_tx_rd_fn(pbpctl_dev2, 0);
if ((link1)&&(!link2))
set_tx_rd_fn(pbpctl_dev, 0);
mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies+BP_LINK_MON_DELAY*HZ);
return 0;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_TPL;
bp_cmd_buf.cmd.cmd_data.tpl_mode = tpl_mode?TPL_ON:TPL_OFF;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret = 0;
}
}
return ret;
}
int get_tpl_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
if (DBI240_IF_SERIES(pbpctl_dev_c->subdevice)) {
return pbpctl_dev->bp_tpl_flag;
}
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_TPL;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_data.tpl_mode == TPL_ON)
ret = 1;
else if (bp_rsp_buf.rsp.rsp_data.tpl_mode == TPL_OFF)
ret = 0;
}
return ret;
}
int set_bp_wait_at_pwup_rd_fn(bpctl_dev_t *pbpctl_dev, int bp_wait_at_pwup){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_BP_WAIT_AT_PWUP;
bp_cmd_buf.cmd.cmd_data.bp_wait_at_pwup = bp_wait_at_pwup?1:0;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(EEPROM_WR_DELAY);
return ret;
}
int get_bp_wait_at_pwup_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BP_WAIT_AT_PWUP;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_data.bp_wait_at_pwup == 1)
ret = 1;
else if (bp_rsp_buf.rsp.rsp_data.bp_wait_at_pwup == 0)
ret = 0;
}
return ret;
}
int set_bp_hw_reset_rd_fn(bpctl_dev_t *pbpctl_dev, int bp_hw_reset){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_BP_HW_RESET;
bp_cmd_buf.cmd.cmd_data.bp_hw_reset = bp_hw_reset?1:0;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(EEPROM_WR_DELAY);
return ret;
}
int get_bp_hw_reset_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BP_HW_RESET;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_data.bp_hw_reset == 1)
ret = 1;
else if (bp_rsp_buf.rsp.rsp_data.bp_hw_reset == 0)
ret = 0;
}
return ret;
}
int get_bypass_info_rd_fn(bpctl_dev_t *pbpctl_dev, char *dev_name, unsigned char *add_param){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_GET_BYPASS_INFO;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
strcpy(dev_name, pbpctl_dev->name);
/**add_param = bp_rsp_buf.rsp.rsp_data.bypass_info.fw_ver;*/
memcpy(add_param,(char *)&(bp_rsp_buf.rsp.rsp_data.bypass_info.fw_ver), 1);
ret=0;
}
return ret;
}
int set_bp_manuf_rd_fn(bpctl_dev_t *pbpctl_dev){
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret = -1, port = 0;
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
if (!pbpctl_dev)
return ret;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return ret;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return ret;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num = (port == 1)? 0:1;
bp_cmd_buf.cmd.cmd_id = CMD_SET_BP_MANUF;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
if (bp_rsp_buf.rsp.rsp_id == BP_ERR_OK) {
ret=0;
}
}
msec_delay_bp(BYPASS_CAP_DELAY);
return ret;
}
int bypass_fw_ver_rd(bpctl_dev_t *pbpctl_dev){
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
bp_cmd_t bp_cmd_buf;
bp_cmd_rsp_t bp_rsp_buf;
int ret=-1, port = 0;
if (!pbpctl_dev)
return -1;
pbpctl_dev_c = pbpctl_dev->pbpctl_dev_c;
if (!pbpctl_dev_c)
return -1;
port = pbpctl_dev->epl_num;
if (!is_bypass_port_rd_fn(port))
return -1;
memset(&bp_cmd_buf, 0, sizeof(bp_cmd_buf));
memset(&bp_rsp_buf, 0, sizeof(bp_cmd_rsp_t));
bp_cmd_buf.cmd.cmd_dev_num= (pbpctl_dev->func == 0)? 0:1;
bp_cmd_buf.cmd.cmd_id=CMD_GET_BYPASS_INFO;
if (bp_cmd_request(pbpctl_dev_c, &bp_cmd_buf, &bp_rsp_buf)) {
ret = bp_rsp_buf.rsp.rsp_data.bypass_info.fw_ver;
}
return ret;
}
static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev){
if (pbpctl_dev->bp_caps&WD_CTL_CAP) {
reset_bypass_wd_timer_rd_fn(pbpctl_dev);
return 1;
}
else return BP_NOT_CAP;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
static void wd_reset_timer(unsigned long param){
bpctl_dev_t *pbpctl_dev= (bpctl_dev_t *) param;
#else
static void wd_reset_timer(struct timer_list *t){
bpctl_dev_t *pbpctl_dev= from_timer(pbpctl_dev, t, bp_timer);
#endif
if ((pbpctl_dev->bp_ext_ver>=PXG2BPI_VER)&&
((atomic_read(&pbpctl_dev->wdt_busy))==1)) {
mod_timer(&pbpctl_dev->bp_timer, jiffies+1);
return;
}
wdt_timer_reload(pbpctl_dev);
if (pbpctl_dev->reset_time) {
mod_timer(&pbpctl_dev->bp_timer, jiffies+(HZ*pbpctl_dev->reset_time)/1000);
}
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
static void bp_tpl_timer_fn(unsigned long param){
bpctl_dev_t *pbpctl_dev=(bpctl_dev_t *) param;
#else
static void bp_tpl_timer_fn(struct timer_list *t){
bpctl_dev_t *pbpctl_dev=from_timer(pbpctl_dev, t, bp_tpl_timer);
#endif
uint32_t link1, link2;
bpctl_dev_t *pbpctl_dev_b=NULL;
if (!(pbpctl_dev_b=get_status_port_fn(pbpctl_dev)))
return;
if (!pbpctl_dev->bp_tpl_flag) {
return;
}
if ((!pbpctl_dev->ndev)||(!pbpctl_dev_b->ndev))
return;
link1 = netif_carrier_ok(pbpctl_dev->ndev);
link2 = netif_carrier_ok(pbpctl_dev_b->ndev);
if (link1)
pbpctl_dev->tpl_wait = 0;
if (link2)
pbpctl_dev_b->tpl_wait = 0;
if ((link1) && (!link2)) {
if (!get_tx_rd_fn(pbpctl_dev_b)) {
set_tx_rd_fn(pbpctl_dev_b, 1);
mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies+BP_LINK_MON_DELAY*2*HZ);
return;
}
}
if ((link2) && (!link1)) {
if (!get_tx_rd_fn(pbpctl_dev)) {
set_tx_rd_fn(pbpctl_dev, 1);
mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies+BP_LINK_MON_DELAY*2*HZ);
return;
}
}
if ((link1)&&(get_tx_rd_fn(pbpctl_dev))) {
if ((!link2)&&(get_tx_rd_fn(pbpctl_dev_b))) {
if (pbpctl_dev_b->tpl_wait){
pbpctl_dev_b->tpl_wait = 0;
mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies+BP_LINK_MON_DELAY*2*HZ);
return;
}
set_tx_rd_fn(pbpctl_dev,0);
}
else if (!get_tx_rd_fn(pbpctl_dev_b)) {
pbpctl_dev_b->tpl_wait = 1;
set_tx_rd_fn(pbpctl_dev_b,1);
}
}
else if ((!link1)&&(get_tx_rd_fn(pbpctl_dev))) {
if ((link2)&&(get_tx_rd_fn(pbpctl_dev_b))) {
if (pbpctl_dev->tpl_wait){
pbpctl_dev->tpl_wait = 0;
mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies+BP_LINK_MON_DELAY*2*HZ);
return;
}
set_tx_rd_fn(pbpctl_dev_b,0);
}
}
else if ((link1)&&(!get_tx_rd_fn(pbpctl_dev))) {
if ((link2)&&(get_tx_rd_fn(pbpctl_dev_b))) {
pbpctl_dev->tpl_wait = 1;
set_tx_rd_fn(pbpctl_dev,1);
}
}
else if ((!link1)&&(!get_tx_rd_fn(pbpctl_dev))) {
if ((link2)&&(get_tx_rd_fn(pbpctl_dev_b))) {
pbpctl_dev->tpl_wait = 1;
set_tx_rd_fn(pbpctl_dev,1);
}
}
mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies+BP_LINK_MON_DELAY*HZ);
}
static void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev){
if (pbpctl_dev->bp_caps&WD_CTL_CAP) {
del_timer_sync(&pbpctl_dev->bp_timer);
}
}
void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev){
if ((is_bypass_rd_fn(pbpctl_dev)) &&
(DBI240_IF_SERIES(pbpctl_dev->subdevice)))
{
set_tpl_rd_fn(pbpctl_dev, 0);
del_timer_sync(&pbpctl_dev->bp_tpl_timer);
}
return;
}
static int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev){
if (pbpctl_dev->bp_caps&WD_CTL_CAP) {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
init_timer(&pbpctl_dev->bp_timer);
pbpctl_dev->bp_timer.function=&wd_reset_timer;
pbpctl_dev->bp_timer.data=(unsigned long)pbpctl_dev;
#else
timer_setup(&pbpctl_dev->bp_timer, wd_reset_timer, 0);
#endif
return 1;
}
return BP_NOT_CAP;
}
int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev){
if (!pbpctl_dev)
return BP_NOT_CAP;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
init_timer(&pbpctl_dev->bp_tpl_timer);
pbpctl_dev->bp_tpl_timer.function=&bp_tpl_timer_fn;
pbpctl_dev->bp_tpl_timer.data=(unsigned long)pbpctl_dev;
#else
timer_setup(&pbpctl_dev->bp_tpl_timer, bp_tpl_timer_fn, 0);
#endif
return BP_OK;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
static int device_ioctl(struct inode *inode, /* see include/linux/fs.h */
struct file *file, /* ditto */
unsigned int ioctl_num, /* number and param for ioctl */
unsigned long ioctl_param)
#else
static long device_ioctl(struct file *file, /* ditto */
unsigned int ioctl_num, /* number and param for ioctl */
unsigned long ioctl_param)
#endif
{
struct bpctl_cmd bpctl_cmd;
int dev_idx=0;
bpctl_dev_t *pbpctl_dev_out;
void __user *argp = (void __user *)ioctl_param;
int ret=0;
bpctl_dev_t *pbpctl_dev;
if (ioctl_num == IOCTL_TX_MSG(EXCLUSIVE_LOCK)) {
dev_idx = get_dev_mng_idx(ioctl_param);
if ( dev_idx < 0 || dev_idx > mng_device_num) {
return -1;
}
TAKE_PLAT_I2C_BUS_LOCK_IDX(file, dev_idx);
return SUCCESS;
}
if (ioctl_num == IOCTL_TX_MSG(DROP_EXCLUSIVE)) {
dev_idx = get_dev_mng_idx(ioctl_param);
if ( dev_idx < 0 || dev_idx > mng_device_num) {
return -1;
}
DROP_PLAT_I2C_BUS_LOCK_IDX(file, dev_idx);
return SUCCESS;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
//lock_kernel();
#endif
lock_bpctl();
/*
* Switch according to the ioctl called
*/
if (ioctl_num==IOCTL_TX_MSG(IF_SCAN)) {
if_scan_init();
ret=SUCCESS;
goto bp_exit;
}
if (copy_from_user(&bpctl_cmd, argp, sizeof(struct bpctl_cmd))) {
ret= -EFAULT;
goto bp_exit;
}
if (ioctl_num==IOCTL_TX_MSG(GET_DEV_NUM)) {
bpctl_cmd.out_param[0]= device_num;
if (copy_to_user(argp,(void *)&bpctl_cmd,sizeof(struct bpctl_cmd))) {
ret=-EFAULT;
goto bp_exit;
}
ret=SUCCESS;
goto bp_exit;
}
if ((bpctl_cmd.in_param[5])||
(bpctl_cmd.in_param[6])||
(bpctl_cmd.in_param[7]))
dev_idx=get_dev_idx_bsf(bpctl_cmd.in_param[5],
bpctl_cmd.in_param[6],
bpctl_cmd.in_param[7]);
else if (bpctl_cmd.in_param[1]==0)
dev_idx= bpctl_cmd.in_param[0];
else dev_idx=get_dev_idx(bpctl_cmd.in_param[1]);
if (dev_idx<0||dev_idx>device_num) {
ret= -EOPNOTSUPP;
goto bp_exit;
}
bpctl_cmd.out_param[0]= bpctl_dev_arr[dev_idx].bus;
bpctl_cmd.out_param[1]= bpctl_dev_arr[dev_idx].slot;
bpctl_cmd.out_param[2]= bpctl_dev_arr[dev_idx].func;
bpctl_cmd.out_param[3]= bpctl_dev_arr[dev_idx].ifindex;
if ((dev_idx<0)||(dev_idx>device_num)||(bpctl_dev_arr[dev_idx].pdev==NULL)) {
bpctl_cmd.status=-1;
goto bpcmd_exit;
}
pbpctl_dev=&bpctl_dev_arr[dev_idx];
switch (ioctl_num) {
case IOCTL_TX_MSG(SET_BYPASS_PWOFF) :
bpctl_cmd.status= set_bypass_pwoff_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BYPASS_PWOFF) :
bpctl_cmd.status= get_bypass_pwoff_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_BYPASS_PWUP) :
bpctl_cmd.status= set_bypass_pwup_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BYPASS_PWUP) :
bpctl_cmd.status= get_bypass_pwup_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_BYPASS_WD) :
bpctl_cmd.status= set_bypass_wd_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BYPASS_WD) :
bpctl_cmd.status= get_bypass_wd_rd_fn(pbpctl_dev,(int *)&(bpctl_cmd.data[0]));
break;
case IOCTL_TX_MSG(GET_WD_EXPIRE_TIME) :
bpctl_cmd.status= get_wd_expire_time_rd_fn(pbpctl_dev, (int *)&(bpctl_cmd.data[0]));
break;
case IOCTL_TX_MSG(RESET_BYPASS_WD_TIMER) :
bpctl_cmd.status= reset_bypass_wd_timer_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_WD_SET_CAPS) :
bpctl_cmd.status= get_wd_set_caps_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_STD_NIC) :
bpctl_cmd.status= set_std_nic_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_STD_NIC) :
bpctl_cmd.status= get_std_nic_rd_fn(pbpctl_dev);
break;
#if 0
case IOCTL_TX_MSG(SET_TAP) :
bpctl_cmd.status= set_tap_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_TAP) :
bpctl_cmd.status= get_tap_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_TAP_CHANGE) :
bpctl_cmd.status= get_tap_change_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_DIS_TAP) :
bpctl_cmd.status= set_dis_tap_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_DIS_TAP) :
bpctl_cmd.status= get_dis_tap_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_TAP_PWUP) :
bpctl_cmd.status= set_tap_pwup_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_TAP_PWUP) :
bpctl_cmd.status= get_tap_pwup_rd_fn(pbpctl_dev);
break;
#endif
case IOCTL_TX_MSG(SET_WD_EXP_MODE):
bpctl_cmd.status= set_wd_exp_mode_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_WD_EXP_MODE):
bpctl_cmd.status= get_wd_exp_mode_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_DIS_BYPASS):
bpctl_cmd.status= get_dis_bypass_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_DIS_BYPASS):
bpctl_cmd.status= set_dis_bypass_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BYPASS_CHANGE):
bpctl_cmd.status= get_bypass_change_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_WD_EXPIRE):
bpctl_cmd.status= get_wd_expire_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_BYPASS):
bpctl_cmd.status= get_bypass_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_BYPASS):
bpctl_cmd.status= set_bypass_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BYPASS_CAPS):
bpctl_cmd.status= get_bypass_caps_rd_fn(pbpctl_dev);
if (copy_to_user(argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) {
ret= -EFAULT;
goto bp_exit;
}
goto bp_exit;
case IOCTL_TX_MSG(GET_BYPASS_SLAVE):
bpctl_cmd.status = get_bypass_slave_rd_fn(pbpctl_dev, &pbpctl_dev_out);
if (bpctl_cmd.status==1) {
bpctl_cmd.out_param[4]= pbpctl_dev_out->bus;
bpctl_cmd.out_param[5]= pbpctl_dev_out->slot;
bpctl_cmd.out_param[6]= pbpctl_dev_out->func;
bpctl_cmd.out_param[7]= pbpctl_dev_out->ifindex;
}
break;
case IOCTL_TX_MSG(IS_BYPASS):
bpctl_cmd.status= is_bypass_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_TX):
bpctl_cmd.status= set_tx_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_TX):
bpctl_cmd.status= get_tx_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_WD_AUTORESET):
bpctl_cmd.status= set_wd_autoreset_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_WD_AUTORESET):
bpctl_cmd.status= get_wd_autoreset_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_DISC) :
bpctl_cmd.status=set_disc_rd_fn(pbpctl_dev,bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_DISC) :
bpctl_cmd.status=get_disc_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_DISC_CHANGE) :
bpctl_cmd.status=get_disc_change_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_DIS_DISC) :
bpctl_cmd.status=set_dis_disc_rd_fn(pbpctl_dev,bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_DIS_DISC) :
bpctl_cmd.status=get_dis_disc_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_DISC_PWUP) :
bpctl_cmd.status=set_disc_pwup_rd_fn(pbpctl_dev,bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_DISC_PWUP) :
bpctl_cmd.status=get_disc_pwup_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(GET_BYPASS_INFO):
bpctl_cmd.status= get_bypass_info_rd_fn(pbpctl_dev, (char *)&bpctl_cmd.data, (char *)&bpctl_cmd.out_param[4]);
break;
case IOCTL_TX_MSG(SET_TPL) :
bpctl_cmd.status= set_tpl_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_TPL) :
bpctl_cmd.status= get_tpl_rd_fn(pbpctl_dev);
break;
//#ifdef PMC_FIX_FLAG
case IOCTL_TX_MSG(SET_BP_WAIT_AT_PWUP) :
bpctl_cmd.status= set_bp_wait_at_pwup_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BP_WAIT_AT_PWUP) :
bpctl_cmd.status= get_bp_wait_at_pwup_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_BP_HW_RESET) :
bpctl_cmd.status= set_bp_hw_reset_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BP_HW_RESET) :
bpctl_cmd.status= get_bp_hw_reset_rd_fn(pbpctl_dev);
break;
//#endif
#ifdef BP_SELF_TEST
case IOCTL_TX_MSG(SET_BP_SELF_TEST):
bpctl_cmd.status= set_bp_self_test_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BP_SELF_TEST):
bpctl_cmd.status= get_bp_self_test_rd_fn(pbpctl_dev);
break;
#endif
#if 0
case IOCTL_TX_MSG(SET_DISC_PORT) :
bpctl_cmd.status= set_disc_port_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_DISC_PORT) :
bpctl_cmd.status= get_disc_port_rd_fn(pbpctl_dev);
break;
case IOCTL_TX_MSG(SET_DISC_PORT_PWUP) :
bpctl_cmd.status= set_disc_port_pwup_rd_fn(pbpctl_dev, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_DISC_PORT_PWUP) :
bpctl_cmd.status= get_disc_port_pwup_rd_fn(pbpctl_dev);
break;
#endif
case IOCTL_TX_MSG(SET_BP_FORCE_LINK):
bpctl_cmd.status= set_bp_force_link_rd_fn(dev_idx, bpctl_cmd.in_param[2]);
break;
case IOCTL_TX_MSG(GET_BP_FORCE_LINK):
bpctl_cmd.status= get_bp_force_link_rd_fn(dev_idx);
break;
case IOCTL_TX_MSG(SET_BP_MANUF) :
bpctl_cmd.status= set_bp_manuf_rd_fn(pbpctl_dev);
break;
default:
ret= -EOPNOTSUPP;
goto bp_exit;
}
bpcmd_exit:
if (copy_to_user(argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd)))
ret= -EFAULT;
ret= SUCCESS;
bp_exit:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
#endif
unlock_bpctl();
return ret;
}
static struct file_operations Fops = {
.owner = THIS_MODULE,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
.ioctl = device_ioctl,
#else
.unlocked_ioctl = device_ioctl,
#endif
.open = device_open,
.release = device_release, /* a.k.a. close */
};
typedef struct _bpmod_info_t {
unsigned int vendor;
unsigned int device;
unsigned int subvendor;
unsigned int subdevice;
unsigned int index;
char *bp_name;
} bpmod_info_t;
#define SILICOM_SVID 0x1374
static bpmod_info_t tx_ctl_pci_tbl[] = {
{0x8086, 0x15A4, SILICOM_SVID, 0x01B0, 0, "PE310G4DBiR-T"},
{0x8086, 0x15A4, 0x1B2E, 0x01B0, 0, "PE310G4DBiR-T-RB2"},
{0x8086, 0x15A4, 0x8086, 0x000, 0, "PE310G4DBiR"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01B1, 0, "PE310G4DBiR-SRD"},
{0x8086, 0x15A4, 0x1B2E, 0x01B1, 0, "PE310G4DBiR-SRD-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01B2, 0, "PE310G4DBiR-LRD"},
{0x8086, 0x15A4, 0x1B2E, 0x01B2, 0, "PE310G4DBiR-LRD-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01B3, 0, "PE310G4DBiR-ERD"},
{0x8086, 0x15A4, 0x1B2E, 0x01B3, 0, "PE310G4DBiR-ERD-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01B4, 0, "PE310G4DBiR-DA"},
{0x8086, 0x15A4, 0x1B2E, 0x01B4, 0, "PE310G4DBiR-DA-RB2"},
{0x8086, 0x15A5, SILICOM_SVID, 0x01B0, 0, "PE310G4DBiR-T"},
{0x8086, 0x15A5, 0x1B2E, 0x01B0, 0, "PE310G4DBiR-T-RB2"},
{0x8086, 0x15A5, 0x8086, 0x000, 0, "PE310G4DBiR"},
{0x8086, 0x15A5, SILICOM_SVID, 0x01B1, 0, "PE310G4DBiR-SRD"},
{0x8086, 0x15A5, 0x1B2E, 0x01B1, 0, "PE310G4DBiR-SRD-RB2"},
{0x8086, 0x15A5, SILICOM_SVID, 0x01B2, 0, "PE310G4DBiR-LRD"},
{0x8086, 0x15A5, 0x1B2E, 0x01B2, 0, "PE310G4DBiR-LRD-RB2"},
{0x8086, 0x15A5, SILICOM_SVID, 0x01B3, 0, "PE310G4DBiR-ERD"},
{0x8086, 0x15A5, 0x1B2E, 0x01B3, 0, "PE310G4DBiR-ERD-RB2"},
{0x8086, 0x15A5, SILICOM_SVID, 0x01B4, 0, "PE310G4DBiR-DA"},
{0x8086, 0x15A5, 0x1B2E, 0x01B4, 0, "PE310G4DBiR-DA-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01B8, 0, "PE340G2DBIR-QS41"},
{0x8086, 0x15A4, 0x1B2E, 0x01B8, 0, "PE340G2DBIR-QS41-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01B9, 0, "PE340G2DBIR-QS43"},
{0x8086, 0x15A4, 0x1B2E, 0x01B9, 0, "PE340G2DBIR-QS43-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01BA, 0, "PE340G2DBIR-QL4"},
{0x8086, 0x15A4, 0x1B2E, 0x01BA, 0, "PE340G2DBIR-QL4-RB2"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01BC, 0, "PE3100G2DBIR-ZS4"},
{0x8086, 0x15A4, 0x1B2E, 0x01BC, 0, "PE3100G2DBIR-ZS4-RB2"},
#if 0
{0x8086, 0x15A4, SILICOM_SVID, 0x01C0, 0, "PE3100G2DQIR-QX4/QS4/QL4"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01C1, 0, "PE3100G2DQIRL-QX4/QS4/QL4"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01C2, 0, "PE3100G2DQIRM-QX4/QS4/QL4"},
{0x8086, 0x15A4, SILICOM_SVID, 0x01C8, 0, "PE325G2DSIR"},
#endif
/* required last entry */
{0,}
};
static int v2_bypass_init_module(void)
{
int ret_val, idx, idx_dev = 0, idx_dev_mng = 0;
struct pci_dev *pdev1 = NULL;
unsigned long mmio_start, mmio_len;
ret_val = register_chrdev (major_num, DEVICE_NAME, &Fops);
if (ret_val < 0) {
printk("%s failed with %d\n",DEVICE_NAME,ret_val);
return ret_val;
}
major_num = ret_val; /* dynamic */
for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) {
while ((pdev1=pci_get_subsys(tx_ctl_pci_tbl[idx].vendor,
tx_ctl_pci_tbl[idx].device,
tx_ctl_pci_tbl[idx].subvendor,
tx_ctl_pci_tbl[idx].subdevice,
pdev1))) {
u32 __iomem *uc_addr;
if (tx_ctl_pci_tbl[idx].device == 0x15a4) {
uc_addr = ioremap(pci_resource_start(pdev1, 0),
FM10K_UC_ADDR_SIZE);
if (uc_addr) {
if (readl((void *)(uc_addr+0)) & 0x4) {
mng_device_num++;
}
if (!(DBI410_IF_SERIES(tx_ctl_pci_tbl[idx].subdevice)))
device_num++;
}
}
else if (DBI410_IF_SERIES(tx_ctl_pci_tbl[idx].subdevice)){
if ((PCI_FUNC(pdev1->devfn) == 1) ||
(PCI_FUNC(pdev1->devfn) == 2) ||
(PCI_FUNC(pdev1->devfn) == 3) ||
(PCI_FUNC(pdev1->devfn) == 4))
device_num++;
}
}
}
if (!device_num) {
printk("No such device\n");
unregister_chrdev(major_num, DEVICE_NAME);
return -1;
}
bpctl_dev_arr=kmalloc ((device_num) * sizeof (bpctl_dev_t), GFP_KERNEL);
bpctl_dev_mng_arr=kmalloc ((mng_device_num) * sizeof (bpctl_dev_mng_t), GFP_KERNEL);
if (!bpctl_dev_arr || (! bpctl_dev_mng_arr)) {
printk("Allocation error\n");
unregister_chrdev(major_num, DEVICE_NAME);
return -1;
}
memset(bpctl_dev_arr,0,((device_num) * sizeof (bpctl_dev_t)));
pdev1=NULL;
for (idx = 0; tx_ctl_pci_tbl[idx].vendor; idx++) {
while ((pdev1=pci_get_subsys(tx_ctl_pci_tbl[idx].vendor,
tx_ctl_pci_tbl[idx].device,
tx_ctl_pci_tbl[idx].subvendor,
tx_ctl_pci_tbl[idx].subdevice,
pdev1))) {
u32 __iomem *uc_addr;
mmio_start = 0;
mmio_len = 0;
if ((tx_ctl_pci_tbl[idx].device == 0x15a5) &&
(DBI410_IF_SERIES(tx_ctl_pci_tbl[idx].subdevice))) {
if ((PCI_FUNC(pdev1->devfn) == 1) ||
(PCI_FUNC(pdev1->devfn) == 2) ||
(PCI_FUNC(pdev1->devfn) == 3) ||
(PCI_FUNC(pdev1->devfn) == 4)) {
bpctl_dev_arr[idx_dev].pdev=pdev1;
bpctl_dev_arr[idx_dev].name = tx_ctl_pci_tbl[idx].bp_name;
bpctl_dev_arr[idx_dev].device = tx_ctl_pci_tbl[idx].device;
bpctl_dev_arr[idx_dev].vendor = tx_ctl_pci_tbl[idx].vendor;
bpctl_dev_arr[idx_dev].subdevice = tx_ctl_pci_tbl[idx].subdevice;
bpctl_dev_arr[idx_dev].subvendor = tx_ctl_pci_tbl[idx].subvendor;
//ctl_dev_arr[idx_dev].pdev=pdev1;
bpctl_dev_arr[idx_dev].func = PCI_FUNC(pdev1->devfn);
bpctl_dev_arr[idx_dev].slot = PCI_SLOT(pdev1->devfn);
bpctl_dev_arr[idx_dev].bus = pdev1->bus->number;
bpctl_dev_arr[idx_dev].bp_master_flag =
(((bpctl_dev_arr[idx_dev].func == 1)||(bpctl_dev_arr[idx_dev].func == 3)) ? 1:0);
bpctl_dev_arr[idx_dev].epl_num = bpctl_dev_arr[idx_dev].func;
bpctl_dev_arr[idx_dev].lane_num = bpctl_dev_arr[idx_dev].func - 1;
bpctl_dev_arr[idx_dev].port_num = 49999 + bpctl_dev_arr[idx_dev].func;
bpctl_dev_arr[idx_dev].epl = 0;
idx_dev++;
}
}
else {
uc_addr = ioremap(pci_resource_start(pdev1, 0),
FM10K_UC_ADDR_SIZE);
if (uc_addr) {
if (readl((void *)(uc_addr+0)) & 0x4) {
mmio_start = pci_resource_start (pdev1, 4);
mmio_len = pci_resource_len (pdev1, 4);
if ((!mmio_len)||(!mmio_start))
continue;
bpctl_dev_mng_arr[idx_dev_mng].pdev=pdev1;
bpctl_dev_mng_arr[idx_dev_mng].name=tx_ctl_pci_tbl[idx].bp_name;
bpctl_dev_mng_arr[idx_dev_mng].device=tx_ctl_pci_tbl[idx].device;
bpctl_dev_mng_arr[idx_dev_mng].vendor=tx_ctl_pci_tbl[idx].vendor;
bpctl_dev_mng_arr[idx_dev_mng].subdevice=tx_ctl_pci_tbl[idx].subdevice;
bpctl_dev_mng_arr[idx_dev_mng].subvendor=tx_ctl_pci_tbl[idx].subvendor;
//ctl_dev_arr[idx_dev].pdev=pdev1;
bpctl_dev_mng_arr[idx_dev_mng].func= PCI_FUNC(pdev1->devfn);
bpctl_dev_mng_arr[idx_dev_mng].slot= PCI_SLOT(pdev1->devfn);
bpctl_dev_mng_arr[idx_dev_mng].bus=pdev1->bus->number;
bpctl_dev_mng_arr[idx_dev_mng].mem_map=(unsigned long)ioremap(mmio_start,mmio_len);
spin_lock_init(&bpctl_dev_mng_arr[idx_dev_mng].bypass_wr_lock);
if (DBI410_IF_SERIES(tx_ctl_pci_tbl[idx].subdevice)) {
bpctl_dev_mng_arr[idx_dev_mng].port_num = 5;
}
else bpctl_dev_mng_arr[idx_dev_mng].port_num = 4;
mutex_init(&bpctl_dev_mng_arr[idx_dev_mng].i2c_bus_lock);
idx_dev_mng++;
}
}
if (!(DBI410_IF_SERIES(tx_ctl_pci_tbl[idx].subdevice))) {
bpctl_dev_arr[idx_dev].pdev=pdev1;
bpctl_dev_arr[idx_dev].name = tx_ctl_pci_tbl[idx].bp_name;
bpctl_dev_arr[idx_dev].device = tx_ctl_pci_tbl[idx].device;
bpctl_dev_arr[idx_dev].vendor = tx_ctl_pci_tbl[idx].vendor;
bpctl_dev_arr[idx_dev].subdevice = tx_ctl_pci_tbl[idx].subdevice;
bpctl_dev_arr[idx_dev].subvendor = tx_ctl_pci_tbl[idx].subvendor;
bpctl_dev_arr[idx_dev].func = PCI_FUNC(pdev1->devfn);
bpctl_dev_arr[idx_dev].slot = PCI_SLOT(pdev1->devfn);
bpctl_dev_arr[idx_dev].bus = pdev1->bus->number;
if (!mmio_start) {
bpctl_dev_arr[idx_dev].bp_master_flag = 1;
bpctl_dev_arr[idx_dev].epl_num = 1;
bpctl_dev_arr[idx_dev].port_num = 3;
bpctl_dev_arr[idx_dev].epl = 0;
}
else {
bpctl_dev_arr[idx_dev].epl_num = 2;
bpctl_dev_arr[idx_dev].port_num = 4;
bpctl_dev_arr[idx_dev].epl = 6;
}
bpctl_dev_arr[idx_dev].lane_num = 0;
idx_dev++;
}
}
}
}
if_scan_init();
if_scan_mng_init();
sema_init (&bpctl_sema, 1);
{
for (idx_dev = 0; ((bpctl_dev_arr[idx_dev].pdev!=NULL)&&(idx_dev<device_num)); idx_dev++)
{
{
bpctl_dev_mng_t *pbpctl_dev_c = NULL;
struct pci_dev *pdev_mng = NULL;
struct pci_dev *pdev_slave = NULL;
if (!DBI410_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)) {
rdi_find_master_slave_plx(bpctl_dev_arr[idx_dev].pdev,
&pdev_mng,
&pdev_slave);
bpctl_dev_arr[idx_dev].pdev_mng = pdev_mng;
/* for 420 chip */
bpctl_dev_arr[idx_dev].pdev_pf_slave = pdev_mng;
bpctl_dev_arr[idx_dev].pdev_pf_master = pdev_slave;
}
pbpctl_dev_c = get_mng_port_rd_fn(&bpctl_dev_arr[idx_dev]);
bpctl_dev_arr[idx_dev].pbpctl_dev_c = pbpctl_dev_c;
if ((!bpctl_dev_arr[idx_dev].pdev_mng) && (pbpctl_dev_c))
bpctl_dev_arr[idx_dev].pdev_mng = pbpctl_dev_c->pdev;
}
if (is_bypass_rd_fn(&bpctl_dev_arr[idx_dev])) {
printk(KERN_INFO "%s found, ", bpctl_dev_arr[idx_dev].name);
bpctl_dev_arr[idx_dev].bp_fw_ver=bypass_fw_ver_rd(&bpctl_dev_arr[idx_dev]);
//bpctl_dev_arr[idx_dev].bp_fw_ver=0xa8;
printk("firmware version: 0x%x\n",bpctl_dev_arr[idx_dev].bp_fw_ver);
}
bpctl_dev_arr[idx_dev].wdt_status=WDT_STATUS_UNKNOWN;
bpctl_dev_arr[idx_dev].reset_time=0;
atomic_set(&bpctl_dev_arr[idx_dev].wdt_busy,0);
bpctl_dev_arr[idx_dev].bp_status_un=1;
bpctl_dev_arr[idx_dev].bp_caps = get_bypass_caps_rd_fn(&bpctl_dev_arr[idx_dev]);
get_tpl_rd_fn(&bpctl_dev_arr[idx_dev]);
init_bypass_wd_auto(&bpctl_dev_arr[idx_dev]);
if ((is_bypass_rd_fn(&bpctl_dev_arr[idx_dev])) &&
(DBI240_IF_SERIES(bpctl_dev_arr[idx_dev].subdevice)))
init_bypass_tpl_auto(&bpctl_dev_arr[idx_dev]);
}
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
inter_module_register("is_bypass_rd", THIS_MODULE, &is_bypass_rd);
inter_module_register("get_bypass_slave_rd", THIS_MODULE, &get_bypass_slave_rd);
inter_module_register("get_bypass_caps_rd", THIS_MODULE, &get_bypass_caps_rd);
inter_module_register("get_wd_set_caps_rd", THIS_MODULE, &get_wd_set_caps_rd);
inter_module_register("set_bypass_rd", THIS_MODULE, &set_bypass_rd);
inter_module_register("get_bypass_rd", THIS_MODULE, &get_bypass_rd);
inter_module_register("get_bypass_change_rd", THIS_MODULE, &get_bypass_change_rd);
inter_module_register("set_dis_bypass_rd", THIS_MODULE, &set_dis_bypass_rd);
inter_module_register("get_dis_bypass_rd", THIS_MODULE, &get_dis_bypass_rd);
inter_module_register("set_bypass_pwoff_rd", THIS_MODULE, &set_bypass_pwoff_rd);
inter_module_register("get_bypass_pwoff_rd", THIS_MODULE, &get_bypass_pwoff_rd);
inter_module_register("set_bypass_pwup_rd", THIS_MODULE, &set_bypass_pwup_rd);
inter_module_register("get_bypass_pwup_rd", THIS_MODULE, &get_bypass_pwup_rd);
inter_module_register("get_bypass_wd_rd", THIS_MODULE, &get_bypass_wd_rd);
inter_module_register("set_bypass_wd_rd", THIS_MODULE, &set_bypass_wd_rd);
inter_module_register("get_wd_expire_time_rd", THIS_MODULE, &get_wd_expire_time_rd);
inter_module_register("reset_bypass_wd_timer_rd", THIS_MODULE, &reset_bypass_wd_timer_rd);
inter_module_register("set_std_nic_rd", THIS_MODULE, &set_std_nic_rd);
inter_module_register("get_std_nic_rd", THIS_MODULE, &get_std_nic_rd);
inter_module_register("set_tx_rd", THIS_MODULE, &set_tx_rd);
inter_module_register("get_tx_rd", THIS_MODULE, &get_tx_rd);
inter_module_register("set_tpl_rd", THIS_MODULE, &set_tpl_rd);
inter_module_register("get_tpl_rd", THIS_MODULE, &get_tpl_rd);
inter_module_register("set_bp_hw_reset_rd", THIS_MODULE, &set_bp_hw_reset_rd);
inter_module_register("get_bp_hw_reset_rd", THIS_MODULE, &get_bp_hw_reset_rd);
#if 0
inter_module_register("set_tap_rd", THIS_MODULE, &set_tap_rd);
inter_module_register("get_tap_rd", THIS_MODULE, &get_tap_rd);
inter_module_register("get_tap_change_rd", THIS_MODULE, &get_tap_change_rd);
inter_module_register("set_dis_tap_rd", THIS_MODULE, &set_dis_tap_rd);
inter_module_register("get_dis_tap_rd", THIS_MODULE, &get_dis_tap_rd);
inter_module_register("set_tap_pwup_rd", THIS_MODULE, &set_tap_pwup_rd);
inter_module_register("get_tap_pwup_rd", THIS_MODULE, &get_tap_pwup_rd);
#endif
inter_module_register("set_bp_disc_rd", THIS_MODULE, &set_bp_disc_rd);
inter_module_register("get_bp_disc_rd", THIS_MODULE, &get_bp_disc_rd);
inter_module_register("get_bp_disc_change_rd", THIS_MODULE, &get_bp_disc_change_rd);
inter_module_register("set_bp_dis_disc_rd", THIS_MODULE, &set_bp_dis_disc_rd);
inter_module_register("get_bp_dis_disc_rd", THIS_MODULE, &get_bp_dis_disc_rd);
inter_module_register("set_bp_disc_pwup_rd", THIS_MODULE, &set_bp_disc_pwup_rd);
inter_module_register("get_bp_disc_pwup_rd", THIS_MODULE, &get_bp_disc_pwup_rd);
inter_module_register("set_wd_exp_mode_rd", THIS_MODULE, &set_wd_exp_mode_rd);
inter_module_register("get_wd_exp_mode_rd", THIS_MODULE, &get_wd_exp_mode_rd);
inter_module_register("set_wd_autoreset_rd", THIS_MODULE, &set_wd_autoreset_rd);
inter_module_register("get_wd_autoreset_rd", THIS_MODULE, &get_wd_autoreset_rd);
inter_module_register("get_bypass_info_rd", THIS_MODULE, &get_bypass_info_rd);
inter_module_register("bp_if_scan_rd", THIS_MODULE, &bp_if_scan_rd);
#endif
register_netdevice_notifier(&bp_notifier_block);
register_reboot_notifier(&bp_reboot_block);
#ifdef BP_PROC_SUPPORT
{
int i=0;
bp_proc_create();
for (i = 0; i < device_num; i++) {
if (bpctl_dev_arr[i].ifindex) {
bypass_proc_remove_dev_rd(&bpctl_dev_arr[i]);
bypass_proc_create_dev_rd(&bpctl_dev_arr[i]);
}
}
}
#endif
return 0;
}
static void __exit bypass_cleanup_module(void)
{
int i ;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
int ret;
#endif
unregister_netdevice_notifier(&bp_notifier_block);
unregister_reboot_notifier(&bp_reboot_block);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
inter_module_unregister("is_bypass_rd");
inter_module_unregister("get_bypass_slave_rd");
inter_module_unregister("get_bypass_caps_rd");
inter_module_unregister("get_wd_set_caps_rd");
inter_module_unregister("set_bypass_rd");
inter_module_unregister("get_bypass_rd");
inter_module_unregister("get_bypass_change_rd");
inter_module_unregister("set_dis_bypass_rd");
inter_module_unregister("get_dis_bypass_rd");
inter_module_unregister("set_bypass_pwoff_rd");
inter_module_unregister("get_bypass_pwoff_rd");
inter_module_unregister("set_bypass_pwup_rd");
inter_module_unregister("get_bypass_pwup_rd");
inter_module_unregister("set_bypass_wd_rd");
inter_module_unregister("get_bypass_wd_rd");
inter_module_unregister("get_wd_expire_time_rd");
inter_module_unregister("reset_bypass_wd_timer_rd");
inter_module_unregister("set_std_nic_rd");
inter_module_unregister("get_std_nic_rd");
inter_module_unregister("set_tx_rd");
inter_module_unregister("get_tx_rd");
inter_module_unregister("set_tpl_rd");
inter_module_unregister("get_tpl_rd");
#if 0
inter_module_unregister("set_tap_rd");
inter_module_unregister("get_tap_rd");
inter_module_unregister("get_tap_change_rd");
inter_module_unregister("set_dis_tap_rd");
inter_module_unregister("get_dis_tap_rd");
inter_module_unregister("set_tap_pwup_rd");
inter_module_unregister("get_tap_pwup_rd");
#endif
inter_module_unregister("set_bp_disc_rd");
inter_module_unregister("get_bp_disc_rd");
inter_module_unregister("get_bp_disc_change_rd");
inter_module_unregister("set_bp_dis_disc_rd");
inter_module_unregister("get_bp_dis_disc_rd");
inter_module_unregister("set_bp_disc_pwup_rd");
inter_module_unregister("get_bp_disc_pwup_rd");
inter_module_unregister("set_wd_exp_mode_rd");
inter_module_unregister("get_wd_exp_mode_rd");
inter_module_unregister("set_wd_autoreset_rd");
inter_module_unregister("get_wd_autoreset_rd");
inter_module_unregister("get_bypass_info_rd");
inter_module_unregister("bp_if_scan_rd");
#endif
for (i = 0; i < device_num; i++) {
//unsigned long flags;
#ifdef BP_PROC_SUPPORT
bypass_proc_remove_dev_rd(&bpctl_dev_arr[i]);
#endif
remove_bypass_wd_auto(&bpctl_dev_arr[i]);
bpctl_dev_arr[i].reset_time=0;
remove_bypass_tpl_auto(&bpctl_dev_arr[i]);
}
#ifdef BP_PROC_SUPPORT
remove_proc_entry(BP_PROC_DIR, init_net.proc_net);
#endif
/* unmap all devices */
for (i = 0; i < device_num; i++) {
#ifdef BP_SELF_TEST
if (bpctl_dev_arr[i].bp_tx_data)
kfree (bpctl_dev_arr[i].bp_tx_data);
#endif
iounmap ((void *)(bpctl_dev_arr[i].mem_map));
}
/* free all devices space */
if (bpctl_dev_arr)
kfree (bpctl_dev_arr);
/*
* Unregister the device
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
ret = unregister_chrdev(major_num, DEVICE_NAME);
/*
* If there's an error, report it
*/
if (ret < 0)
printk("Error in module_unregister_chrdev: %d\n", ret);
#else
unregister_chrdev(major_num, DEVICE_NAME);
#endif
}
static int __init bprd_init_module(void)
{
int ret;
printk(KERN_INFO BP_MOD_DESCR" v"BP_MOD_VER"\n");
ret=v2_bypass_init_module();
return ret;
}
static void __exit bprd_exit_module(void)
{
/* pci_unregister_driver(&bpvm_driver); */
bypass_cleanup_module();
#ifdef BPVM_KVM
unregister_netdev(netdev);
free_netdev(netdev);
#endif /* BPVM_KVM */
}
module_exit(bprd_exit_module);
module_init(bprd_init_module);
int is_bypass_rd(int ifindex){
return(is_bypass_rd_fn(get_dev_idx_p(ifindex)));
}
int set_bypass_rd (int ifindex, int bypass_mode){
return(set_bypass_rd_fn(get_dev_idx_p(ifindex),bypass_mode));
}
int get_bypass_rd (int ifindex){
return(get_bypass_rd_fn(get_dev_idx_p(ifindex)));
}
int get_wd_expire_rd (int ifindex){
return(get_wd_expire_rd_fn(get_dev_idx_p(ifindex)));
}
int get_bypass_change_rd(int ifindex){
return(get_bypass_change_rd_fn(get_dev_idx_p(ifindex)));
}
int set_dis_bypass_rd(int ifindex, int dis_param){
return(set_dis_bypass_rd_fn(get_dev_idx_p(ifindex),dis_param));
}
int get_dis_bypass_rd(int ifindex){
return(get_dis_bypass_rd_fn(get_dev_idx_p(ifindex)));
}
int set_bypass_pwoff_rd (int ifindex, int bypass_mode){
return(set_bypass_pwoff_rd_fn(get_dev_idx_p(ifindex),bypass_mode));
}
int get_bypass_pwoff_rd(int ifindex){
return(get_bypass_pwoff_rd_fn(get_dev_idx_p(ifindex)));
}
int set_bypass_pwup_rd(int ifindex, int bypass_mode){
return(set_bypass_pwup_rd_fn(get_dev_idx_p(ifindex),bypass_mode));
}
int get_bypass_pwup_rd(int ifindex){
return(get_bypass_pwup_rd_fn(get_dev_idx_p(ifindex)));
}
int set_bypass_wd_rd(int if_index, int ms_timeout, int *ms_timeout_set){
if ((is_bypass_rd_fn(get_dev_idx_p(if_index)))<=0)
return BP_NOT_CAP;
*ms_timeout_set= set_bypass_wd_rd_fn(get_dev_idx_p(if_index),ms_timeout);
return 0;
}
int get_bypass_wd_rd(int ifindex, int *timeout){
return(get_bypass_wd_rd_fn(get_dev_idx_p(ifindex),timeout));
}
int get_wd_expire_time_rd(int ifindex, int *time_left){
return(get_wd_expire_time_rd_fn(get_dev_idx_p(ifindex),time_left));
}
int reset_bypass_wd_timer_rd(int ifindex){
return(reset_bypass_wd_timer_rd_fn(get_dev_idx_p(ifindex)));
}
int get_wd_set_caps_rd(int ifindex){
return(get_wd_set_caps_rd_fn(get_dev_idx_p(ifindex)));
}
int set_std_nic_rd(int ifindex, int nic_mode){
return(set_std_nic_rd_fn(get_dev_idx_p(ifindex),nic_mode));
}
int get_std_nic_rd(int ifindex){
return(get_std_nic_rd_fn(get_dev_idx_p(ifindex)));
}
#if 0
int set_tap_rd (int ifindex, int tap_mode){
return(set_tap_rd_fn(get_dev_idx_p(ifindex),tap_mode));
}
int get_tap_rd (int ifindex){
return(get_tap_rd_fn(get_dev_idx_p(ifindex)));
}
int set_tap_pwup_rd(int ifindex, int tap_mode){
return(set_tap_pwup_rd_fn(get_dev_idx_p(ifindex),tap_mode));
}
int get_tap_pwup_rd(int ifindex){
return(get_tap_pwup_rd_fn(get_dev_idx_p(ifindex)));
}
int get_tap_change_rd(int ifindex){
return(get_tap_change_rd_fn(get_dev_idx_p(ifindex)));
}
int set_dis_tap_rd(int ifindex, int dis_param){
return(set_dis_tap_rd_fn(get_dev_idx_p(ifindex),dis_param));
}
int get_dis_tap_rd(int ifindex){
return(get_dis_tap_rd_fn(get_dev_idx_p(ifindex)));
}
#endif
int set_bp_disc_rd (int ifindex, int disc_mode){
return(set_disc_rd_fn(get_dev_idx_p(ifindex),disc_mode));
}
int get_bp_disc_rd (int ifindex){
return(get_disc_rd_fn(get_dev_idx_p(ifindex)));
}
int set_bp_disc_pwup_rd(int ifindex, int disc_mode){
return(set_disc_pwup_rd_fn(get_dev_idx_p(ifindex),disc_mode));
}
int get_bp_disc_pwup_rd(int ifindex){
return(get_disc_pwup_rd_fn(get_dev_idx_p(ifindex)));
}
int get_bp_disc_change_rd(int ifindex){
return(get_disc_change_rd_fn(get_dev_idx_p(ifindex)));
}
int set_bp_dis_disc_rd(int ifindex, int dis_param){
return(set_dis_disc_rd_fn(get_dev_idx_p(ifindex),dis_param));
}
int get_bp_dis_disc_rd(int ifindex){
return(get_dis_disc_rd_fn(get_dev_idx_p(ifindex)));
}
int get_wd_exp_mode_rd(int ifindex){
return(get_wd_exp_mode_rd_fn(get_dev_idx_p(ifindex)));
}
int set_wd_exp_mode_rd(int ifindex, int param){
return(set_wd_exp_mode_rd_fn(get_dev_idx_p(ifindex),param));
}
int set_tx_rd(int ifindex, int tx_state){
return(set_tx_rd_fn(get_dev_idx_p(ifindex), tx_state));
}
int set_tpl_rd(int ifindex, int tpl_state){
return(set_tpl_rd_fn(get_dev_idx_p(ifindex), tpl_state));
}
int set_bp_hw_reset_rd(int ifindex, int status){
return(set_bp_hw_reset_rd_fn(get_dev_idx_p(ifindex), status));
}
int set_wd_autoreset_rd(int ifindex, int param){
return(set_wd_autoreset_rd_fn(get_dev_idx_p(ifindex),param));
}
int get_wd_autoreset_rd(int ifindex){
return(get_wd_autoreset_rd_fn(get_dev_idx_p(ifindex)));
}
int get_bypass_caps_rd(int ifindex){
return(get_bypass_caps_rd_fn(get_dev_idx_p(ifindex)));
}
int get_bypass_slave_rd(int ifindex){
bpctl_dev_t *pbpctl_dev_out;
int ret=get_bypass_slave_rd_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out);
if (ret==1)
return(pbpctl_dev_out->ifindex) ;
return -1;
}
int get_tx_rd(int ifindex){
return(get_tx_rd_fn(get_dev_idx_p(ifindex)));
}
int get_tpl_rd(int ifindex){
return(get_tpl_rd_fn(get_dev_idx_p(ifindex)));
}
int get_bp_hw_reset_rd(int ifindex){
return(get_bp_hw_reset_rd_fn(get_dev_idx_p(ifindex)));
}
int get_bypass_info_rd(int ifindex, struct bp_info *bp_info) {
return(get_bypass_info_rd_fn(get_dev_idx_p(ifindex), bp_info->prod_name, &bp_info->fw_ver));
}
int bp_if_scan_rd(void) {
if_scan_init();
return 0;
}
EXPORT_SYMBOL_NOVERS(is_bypass_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_slave_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_caps_rd);
EXPORT_SYMBOL_NOVERS(get_wd_set_caps_rd);
EXPORT_SYMBOL_NOVERS(set_bypass_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_change_rd);
EXPORT_SYMBOL_NOVERS(set_dis_bypass_rd);
EXPORT_SYMBOL_NOVERS(get_dis_bypass_rd);
EXPORT_SYMBOL_NOVERS(set_bypass_pwoff_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_pwoff_rd);
EXPORT_SYMBOL_NOVERS(set_bypass_pwup_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_pwup_rd);
EXPORT_SYMBOL_NOVERS(set_bypass_wd_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_wd_rd);
EXPORT_SYMBOL_NOVERS(get_wd_expire_time_rd);
EXPORT_SYMBOL_NOVERS(reset_bypass_wd_timer_rd);
EXPORT_SYMBOL_NOVERS(set_std_nic_rd);
EXPORT_SYMBOL_NOVERS(get_std_nic_rd);
EXPORT_SYMBOL_NOVERS(set_tx_rd);
EXPORT_SYMBOL_NOVERS(get_tx_rd);
EXPORT_SYMBOL_NOVERS(set_tpl_rd);
EXPORT_SYMBOL_NOVERS(get_tpl_rd);
EXPORT_SYMBOL_NOVERS(set_bp_hw_reset_rd);
EXPORT_SYMBOL_NOVERS(get_bp_hw_reset_rd);
#if 0
EXPORT_SYMBOL_NOVERS(set_tap_rd);
EXPORT_SYMBOL_NOVERS(get_tap_rd);
EXPORT_SYMBOL_NOVERS(get_tap_change_rd);
EXPORT_SYMBOL_NOVERS(set_dis_tap_rd);
EXPORT_SYMBOL_NOVERS(get_dis_tap_rd);
EXPORT_SYMBOL_NOVERS(set_tap_pwup_rd);
EXPORT_SYMBOL_NOVERS(get_tap_pwup_rd);
#endif
EXPORT_SYMBOL_NOVERS(set_wd_exp_mode_rd);
EXPORT_SYMBOL_NOVERS(get_wd_exp_mode_rd);
EXPORT_SYMBOL_NOVERS(set_wd_autoreset_rd);
EXPORT_SYMBOL_NOVERS(get_wd_autoreset_rd);
EXPORT_SYMBOL_NOVERS(set_bp_disc_rd);
EXPORT_SYMBOL_NOVERS(get_bp_disc_rd);
EXPORT_SYMBOL_NOVERS(get_bp_disc_change_rd);
EXPORT_SYMBOL_NOVERS(set_bp_dis_disc_rd);
EXPORT_SYMBOL_NOVERS(get_bp_dis_disc_rd);
EXPORT_SYMBOL_NOVERS(set_bp_disc_pwup_rd);
EXPORT_SYMBOL_NOVERS(get_bp_disc_pwup_rd);
EXPORT_SYMBOL_NOVERS(get_bypass_info_rd);
EXPORT_SYMBOL_NOVERS(bp_if_scan_rd);
#ifdef BP_PROC_SUPPORT
static struct proc_dir_entry *bp_procfs_dir;
static struct proc_dir_entry *
proc_getdir(char *name, struct proc_dir_entry *proc_dir) {
struct proc_dir_entry *pde = proc_dir;
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) )
for (pde=pde->subdir; pde; pde = pde->next) {
if (pde->namelen && (strcmp(name, pde->name) == 0)) {
/* directory exists */
break;
}
}
if (pde == (struct proc_dir_entry *) 0)
#endif
{
/* create the directory */
#if (LINUX_VERSION_CODE > 0x20300)
pde = proc_mkdir(name, proc_dir);
#else
pde = create_proc_entry(name, S_IFDIR, proc_dir);
#endif
if (pde == (struct proc_dir_entry *) 0) {
return(pde);
}
}
return(pde);
}
int bp_proc_create(void)
{
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) )
bp_procfs_dir = proc_getdir(BP_PROC_DIR, proc_net);
#else
bp_procfs_dir = proc_getdir(BP_PROC_DIR, init_net.proc_net);
#endif
if (bp_procfs_dir == (struct proc_dir_entry *) 0) {
printk(KERN_DEBUG "Could not create procfs nicinfo directory %s\n", BP_PROC_DIR);
return -1;
}
return 0;
}
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) )
int
bypass_proc_create_entry_rd(struct pfs_unit_rd *pfs_unit_curr,
char* proc_name,
write_proc_t *write_proc,
read_proc_t *read_proc,
struct proc_dir_entry *parent_pfs,
void *data
)
{
strcpy(pfs_unit_curr->proc_name,proc_name);
pfs_unit_curr->proc_entry= create_proc_entry(pfs_unit_curr->proc_name,
S_IFREG|S_IRUSR|S_IWUSR|
S_IRGRP|S_IWGRP|
S_IROTH|S_IWOTH, parent_pfs);
if (pfs_unit_curr->proc_entry == 0) {
return -1;
}
pfs_unit_curr->proc_entry->read_proc = read_proc;
pfs_unit_curr->proc_entry->write_proc = write_proc;
pfs_unit_curr->proc_entry->data = data;
return 0;
}
#endif
int
get_bypass_info_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0;
len += sprintf(page, "Name\t\t\t%s\n", pbp_device_block->name);
len += sprintf(page+len, "Firmware version\t0x%x\n", pbp_device_block->bp_fw_ver);
*eof = 1;
return len;
}
int
get_bypass_slave_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * dev= (bpctl_dev_t *) data;
int len=0;
bpctl_dev_t *slave = get_status_port_rd_fn(dev);
if (!slave)
slave = dev;
if (slave) {
if (slave->ndev)
len = sprintf(page, "%s\n", slave->ndev->name);
else
len=sprintf(page, "fail\n");
}
*eof = 1;
return len;
}
int
get_bypass_caps_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bypass_caps_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "-1\n");
else
len=sprintf(page, "0x%x\n", ret);
*eof = 1;
return len;
}
int
get_wd_set_caps_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_wd_set_caps_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "-1\n");
else
len=sprintf(page, "0x%x\n", ret);
*eof = 1;
return len;
}
int
set_bypass_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int bypass_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
bypass_param=1;
else if (strcmp(kbuf,"off")==0)
bypass_param=0;
set_bypass_rd_fn (pbp_device_block, bypass_param);
return count;
}
int
set_tap_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tap_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tap_param=1;
else if (strcmp(kbuf,"off")==0)
tap_param=0;
set_tap_rd_fn(pbp_device_block, tap_param);
return count;
}
int
set_disc_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tap_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tap_param=1;
else if (strcmp(kbuf,"off")==0)
tap_param=0;
set_disc_rd_fn(pbp_device_block, tap_param);
return count;
}
int
get_bypass_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bypass_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
*eof = 1;
return len;
}
int
get_tap_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_tap_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
*eof = 1;
return len;
}
int
get_disc_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_disc_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
*eof = 1;
return len;
}
int
get_bypass_change_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bypass_change_rd_fn (pbp_device_block);
if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
else len=sprintf(page, "fail\n");
*eof = 1;
return len;
}
int
get_tap_change_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_tap_change_rd_fn (pbp_device_block);
if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
else len=sprintf(page, "fail\n");
*eof = 1;
return len;
}
int
get_disc_change_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_disc_change_rd_fn (pbp_device_block);
if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
else len=sprintf(page, "fail\n");
*eof = 1;
return len;
}
#define isdigit(c) (c >= '0' && c <= '9')
__inline static int atoi( char **s)
{
int i = 0;
while (isdigit(**s))
i = i*10 + *((*s)++) - '0';
return i;
}
int
set_bypass_wd_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
unsigned int timeout=0;
char *timeout_ptr=kbuf;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
timeout_ptr=kbuf;
timeout=atoi(&timeout_ptr);
set_bypass_wd_rd_fn(pbp_device_block, timeout) ;
return count;
}
int
get_bypass_wd_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0, timeout=0;
ret=get_bypass_wd_rd_fn (pbp_device_block, &timeout);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (timeout==-1)
len=sprintf(page, "unknown\n");
else if (timeout==0)
len=sprintf(page, "disable\n");
else
len=sprintf(page, "%d\n", timeout);
*eof = 1;
return len;
}
int
get_wd_expire_time_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0, timeout=0;
ret=get_wd_expire_time_rd_fn (pbp_device_block, &timeout);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (timeout==-1)
len=sprintf(page, "expire\n");
else if (timeout==0)
len=sprintf(page, "disable\n");
else
len=sprintf(page, "%d\n", timeout);
*eof = 1;
return len;
}
int
get_tpl_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_tpl_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
*eof = 1;
return len;
}
#ifdef PMC_FIX_FLAG
int
get_wait_at_pwup_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bp_wait_at_pwup_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
*eof = 1;
return len;
}
int
get_hw_reset_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bp_hw_reset_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==1)
len=sprintf(page, "on\n");
else if (ret==0)
len=sprintf(page, "off\n");
*eof = 1;
return len;
}
#endif /*PMC_WAIT_FLAG*/
int
reset_bypass_wd_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=reset_bypass_wd_timer_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "disable\n");
else if (ret==1)
len=sprintf(page, "success\n");
*eof = 1;
return len;
}
int
set_dis_bypass_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int bypass_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
bypass_param=1;
else if (strcmp(kbuf,"off")==0)
bypass_param=0;
set_dis_bypass_rd_fn (pbp_device_block, bypass_param);
return count;
}
int
set_dis_tap_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tap_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tap_param=1;
else if (strcmp(kbuf,"off")==0)
tap_param=0;
set_dis_tap_rd_fn (pbp_device_block, tap_param);
return count;
}
int
set_dis_disc_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tap_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tap_param=1;
else if (strcmp(kbuf,"off")==0)
tap_param=0;
set_dis_disc_rd_fn (pbp_device_block, tap_param);
return count;
}
int
get_dis_bypass_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_dis_bypass_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
get_dis_tap_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_dis_tap_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
get_dis_disc_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_dis_disc_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
set_bypass_pwup_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int bypass_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
bypass_param=1;
else if (strcmp(kbuf,"off")==0)
bypass_param=0;
set_bypass_pwup_rd_fn (pbp_device_block, bypass_param);
return count;
}
int
set_bypass_pwoff_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int bypass_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
bypass_param=1;
else if (strcmp(kbuf,"off")==0)
bypass_param=0;
set_bypass_pwoff_rd_fn (pbp_device_block, bypass_param);
return count;
}
int
set_tap_pwup_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tap_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tap_param=1;
else if (strcmp(kbuf,"off")==0)
tap_param=0;
set_tap_pwup_rd_fn (pbp_device_block, tap_param);
return count;
}
int
set_disc_pwup_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tap_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tap_param=1;
else if (strcmp(kbuf,"off")==0)
tap_param=0;
set_disc_pwup_rd_fn (pbp_device_block, tap_param);
return count;
}
int
get_bypass_pwup_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bypass_pwup_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
get_bypass_pwoff_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_bypass_pwoff_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
get_tap_pwup_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_tap_pwup_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
get_disc_pwup_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_disc_pwup_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
set_std_nic_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int bypass_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
bypass_param=1;
else if (strcmp(kbuf,"off")==0)
bypass_param=0;
set_std_nic_rd_fn (pbp_device_block, bypass_param);
return count;
}
int
get_std_nic_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_std_nic_rd_fn (pbp_device_block);
if (ret==BP_NOT_CAP)
len=sprintf(page, "fail\n");
else if (ret==0)
len=sprintf(page, "off\n");
else
len=sprintf(page, "on\n");
*eof = 1;
return len;
}
int
get_wd_exp_mode_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_wd_exp_mode_rd_fn (pbp_device_block);
if (ret==1)
len=sprintf(page, "tap\n");
else if (ret==0)
len=sprintf(page, "bypass\n");
else if (ret==2)
len=sprintf(page, "disc\n");
else len=sprintf(page, "fail\n");
*eof = 1;
return len;
}
int
set_wd_exp_mode_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int bypass_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"tap")==0)
bypass_param=1;
else if (strcmp(kbuf,"bypass")==0)
bypass_param=0;
else if (strcmp(kbuf,"disc")==0)
bypass_param=2;
set_wd_exp_mode_rd_fn(pbp_device_block, bypass_param);
return count;
}
int
get_wd_autoreset_pfs (char *page, char **start, off_t off, int count,
int *eof, void *data)
{
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int len=0, ret=0;
ret=get_wd_autoreset_rd_fn (pbp_device_block);
if (ret>=0)
len=sprintf(page, "%d\n",ret);
else len=sprintf(page, "fail\n");
*eof = 1;
return len;
}
int
set_wd_autoreset_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
u32 timeout=0;
char *timeout_ptr=kbuf;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
timeout_ptr=kbuf;
timeout=atoi(&timeout_ptr);
set_wd_autoreset_rd_fn(pbp_device_block, timeout) ;
return count;
}
int
set_tpl_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tpl_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tpl_param=1;
else if (strcmp(kbuf,"off")==0)
tpl_param=0;
set_tpl_rd_fn(pbp_device_block, tpl_param);
return count;
}
#ifdef PMC_FIX_FLAG
int
set_wait_at_pwup_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tpl_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tpl_param=1;
else if (strcmp(kbuf,"off")==0)
tpl_param=0;
set_bp_wait_at_pwup_rd_fn(pbp_device_block, tpl_param);
return count;
}
int
set_hw_reset_pfs(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char kbuf[256];
bpctl_dev_t * pbp_device_block= (bpctl_dev_t *) data;
int tpl_param=0, length=0;
if (count>(sizeof(kbuf)-1))
return -1;
if (copy_from_user(&kbuf,buffer,count)) {
return -1;
}
kbuf[count]='\0';
length=strlen(kbuf);
if (kbuf[length-1]=='\n')
kbuf[--length]='\0';
if (strcmp(kbuf,"on")==0)
tpl_param=1;
else if (strcmp(kbuf,"off")==0)
tpl_param=0;
set_bp_hw_reset_rd_fn(pbp_device_block, tpl_param);
return count;
}
#endif /*PMC_FIX_FLAG*/
#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) )
static int user_on_off(const void __user *buffer, size_t count)
{
char kbuf[256];
int length = 0;
if (count > (sizeof(kbuf) - 1))
return -1;
if (copy_from_user(&kbuf, buffer, count))
return -1;
kbuf[count] = '\0';
length = strlen(kbuf);
if (kbuf[length - 1] == '\n')
kbuf[--length] = '\0';
if (strcmp(kbuf, "on") == 0)
return 1;
if (strcmp(kbuf, "off") == 0)
return 0;
return 0;
}
#define RO_FOPS(name) \
static int name##_open(struct inode *inode, struct file *file) \
{ \
return single_open(file, show_##name, PDE_DATA(inode));\
} \
static const struct file_operations name##_ops = { \
.open = name##_open, \
.read = seq_read, \
.llseek = seq_lseek, \
.release = single_release, \
};
#define RW_FOPS(name) \
static int name##_open(struct inode *inode, struct file *file) \
{ \
return single_open(file, show_##name, PDE_DATA(inode));\
} \
static const struct file_operations name##_ops = { \
.open = name##_open, \
.read = seq_read, \
.write = name##_write, \
.llseek = seq_lseek, \
.release = single_release, \
};
static int show_bypass_info(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
seq_printf(m, "Name\t\t\t%s\n", dev->name);
seq_printf(m, "Firmware version\t0x%x\n", dev->bp_fw_ver);
return 0;
}
RO_FOPS(bypass_info)
static int show_bypass_slave(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
bpctl_dev_t *slave = get_status_port_rd_fn(dev);
if (!slave)
slave = dev;
if (!slave)
seq_printf(m, "fail\n");
else if (slave->ndev)
seq_printf(m, "%s\n", slave->ndev->name);
return 0;
}
RO_FOPS(bypass_slave)
static int show_bypass_caps(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bypass_caps_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "-1\n");
else
seq_printf(m, "0x%x\n", ret);
return 0;
}
RO_FOPS(bypass_caps)
static ssize_t std_nic_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int bypass_param = user_on_off(buffer, count);
if (bypass_param < 0)
return -EINVAL;
set_std_nic_rd_fn(PDE_DATA(file_inode(file)), bypass_param);
return count;
}
static int show_std_nic(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_std_nic_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(std_nic)
static ssize_t bypass_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int bypass_param = user_on_off(buffer, count);
if (bypass_param < 0)
return -1;
set_bypass_rd_fn(PDE_DATA(file_inode(file)), bypass_param);
return count;
}
static int show_bypass(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bypass_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
return 0;
}
RW_FOPS(bypass)
static ssize_t tap_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int tap_param = user_on_off(buffer, count);
if (tap_param < 0)
return -1;
set_tap_rd_fn(PDE_DATA(file_inode(file)), tap_param);
return count;
}
static int show_tap(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_tap_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
return 0;
}
RW_FOPS(tap)
static ssize_t disc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int tap_param = user_on_off(buffer, count);
if (tap_param < 0)
return -1;
set_disc_rd_fn(PDE_DATA(file_inode(file)), tap_param);
return count;
}
static int show_disc(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_disc_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
return 0;
}
RW_FOPS(disc)
static int show_bypass_change(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bypass_change_rd_fn(dev);
if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "fail\n");
return 0;
}
RO_FOPS(bypass_change)
static int show_tap_change(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_tap_change_rd_fn(dev);
if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "fail\n");
return 0;
}
RO_FOPS(tap_change)
static int show_disc_change(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_disc_change_rd_fn(dev);
if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "fail\n");
return 0;
}
RO_FOPS(disc_change)
static int show_tpl(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_tpl_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
return 0;
}
static ssize_t tpl_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
bpctl_dev_t *dev = PDE_DATA(file_inode(file));
int tpl_param = user_on_off(buffer, count);
if (tpl_param < 0)
return -1;
set_tpl_rd_fn(dev, tpl_param);
return count;
}
RW_FOPS(tpl)
static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
bpctl_dev_t *dev = PDE_DATA(file_inode(file));
int tpl_param = user_on_off(buffer, count);
if (tpl_param < 0)
return -1;
set_bp_wait_at_pwup_rd_fn(dev, tpl_param);
return count;
}
static int show_wait_at_pwup(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bp_wait_at_pwup_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
return 0;
}
RW_FOPS(wait_at_pwup)
static ssize_t hw_reset_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
bpctl_dev_t *dev = PDE_DATA(file_inode(file));
int tpl_param = user_on_off(buffer, count);
if (tpl_param < 0)
return -1;
set_bp_hw_reset_rd_fn(dev, tpl_param);
return count;
}
static int show_hw_reset(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bp_hw_reset_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 1)
seq_printf(m, "on\n");
else if (ret == 0)
seq_printf(m, "off\n");
return 0;
}
RW_FOPS(hw_reset)
static ssize_t dis_bypass_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int bypass_param = user_on_off(buffer, count);
if (bypass_param < 0)
return -EINVAL;
set_dis_bypass_rd_fn(PDE_DATA(file_inode(file)), bypass_param);
return count;
}
static int show_dis_bypass(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_dis_bypass_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(dis_bypass)
static ssize_t dis_tap_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int tap_param = user_on_off(buffer, count);
if (tap_param < 0)
return -EINVAL;
set_dis_tap_rd_fn(PDE_DATA(file_inode(file)), tap_param);
return count;
}
static int show_dis_tap(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_dis_tap_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(dis_tap)
static ssize_t dis_disc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int tap_param = user_on_off(buffer, count);
if (tap_param < 0)
return -EINVAL;
set_dis_disc_rd_fn(PDE_DATA(file_inode(file)), tap_param);
return count;
}
static int show_dis_disc(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_dis_disc_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(dis_disc)
static ssize_t bypass_pwup_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int bypass_param = user_on_off(buffer, count);
if (bypass_param < 0)
return -EINVAL;
set_bypass_pwup_rd_fn(PDE_DATA(file_inode(file)), bypass_param);
return count;
}
static int show_bypass_pwup(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bypass_pwup_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(bypass_pwup)
static ssize_t bypass_pwoff_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int bypass_param = user_on_off(buffer, count);
if (bypass_param < 0)
return -EINVAL;
set_bypass_pwoff_rd_fn(PDE_DATA(file_inode(file)), bypass_param);
return count;
}
static int show_bypass_pwoff(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_bypass_pwoff_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(bypass_pwoff)
static ssize_t tap_pwup_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int tap_param = user_on_off(buffer, count);
if (tap_param < 0)
return -EINVAL;
set_tap_pwup_rd_fn(PDE_DATA(file_inode(file)), tap_param);
return count;
}
static int show_tap_pwup(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_tap_pwup_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(tap_pwup)
static ssize_t disc_pwup_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int tap_param = user_on_off(buffer, count);
if (tap_param < 0)
return -EINVAL;
set_disc_pwup_rd_fn(PDE_DATA(file_inode(file)), tap_param);
return count;
}
static int show_disc_pwup(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_disc_pwup_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "off\n");
else
seq_printf(m, "on\n");
return 0;
}
RW_FOPS(disc_pwup)
static int show_reset_bypass_wd(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = reset_bypass_wd_timer_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (ret == 0)
seq_printf(m, "disable\n");
else if (ret == 1)
seq_printf(m, "success\n");
return 0;
}
RO_FOPS(reset_bypass_wd)
static ssize_t bypass_wd_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
bpctl_dev_t *dev = PDE_DATA(file_inode(file));
int timeout;
int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
if (ret)
return ret;
set_bypass_wd_rd_fn(dev, timeout);
return count;
}
static int show_bypass_wd(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = 0, timeout = 0;
ret = get_bypass_wd_rd_fn(dev, &timeout);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (timeout == -1)
seq_printf(m, "unknown\n");
else if (timeout == 0)
seq_printf(m, "disable\n");
else
seq_printf(m, "%d\n", timeout);
return 0;
}
RW_FOPS(bypass_wd)
static int show_wd_expire_time(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = 0, timeout = 0;
ret = get_wd_expire_time_rd_fn(dev, &timeout);
if (ret == BP_NOT_CAP)
seq_printf(m, "fail\n");
else if (timeout == -1)
seq_printf(m, "expire\n");
else if (timeout == 0)
seq_printf(m, "disable\n");
else
seq_printf(m, "%d\n", timeout);
return 0;
}
RO_FOPS(wd_expire_time)
static ssize_t wd_exp_mode_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
char kbuf[256];
int bypass_param = 0, length = 0;
if (count > (sizeof(kbuf) - 1))
return -1;
if (copy_from_user(&kbuf, buffer, count))
return -1;
kbuf[count] = '\0';
length = strlen(kbuf);
if (kbuf[length - 1] == '\n')
kbuf[--length] = '\0';
if (strcmp(kbuf, "tap") == 0)
bypass_param = 1;
else if (strcmp(kbuf, "bypass") == 0)
bypass_param = 0;
else if (strcmp(kbuf, "disc") == 0)
bypass_param = 2;
set_wd_exp_mode_rd_fn(PDE_DATA(file_inode(file)), bypass_param);
return count;
}
static int show_wd_exp_mode(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_wd_exp_mode_rd_fn(dev);
if (ret == 1)
seq_printf(m, "tap\n");
else if (ret == 0)
seq_printf(m, "bypass\n");
else if (ret == 2)
seq_printf(m, "disc\n");
else
seq_printf(m, "fail\n");
return 0;
}
RW_FOPS(wd_exp_mode)
static int show_wd_set_caps(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_wd_set_caps_rd_fn(dev);
if (ret == BP_NOT_CAP)
seq_printf(m, "-1\n");
else
seq_printf(m, "0x%x\n", ret);
return 0;
}
RO_FOPS(wd_set_caps)
static ssize_t wd_autoreset_write(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
int timeout;
int ret = kstrtoint_from_user(buffer, count, 10, &timeout);
if (ret)
return ret;
set_wd_autoreset_rd_fn(PDE_DATA(file_inode(file)), timeout);
return count;
}
static int show_wd_autoreset(struct seq_file *m, void *v)
{
bpctl_dev_t *dev = m->private;
int ret = get_wd_autoreset_rd_fn(dev);
if (ret >= 0)
seq_printf(m, "%d\n", ret);
else
seq_printf(m, "fail\n");
return 0;
}
RW_FOPS(wd_autoreset)
#endif
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) )
int bypass_proc_create_dev_rd(bpctl_dev_t * pbp_device_block){
struct bypass_pfs_rd *current_pfs = &(pbp_device_block->bypass_pfs_set);
static struct proc_dir_entry *procfs_dir=NULL;
int ret=0;
if (!pbp_device_block->ndev)
return -1;
sprintf(current_pfs->dir_name,"bypass_%s",pbp_device_block->ndev->name);
if (!bp_procfs_dir)
return -1;
/* create device proc dir */
procfs_dir = proc_getdir(current_pfs->dir_name,bp_procfs_dir);
if (procfs_dir == 0) {
printk(KERN_DEBUG "Could not create procfs directory %s\n",
current_pfs->dir_name);
return -1;
}
current_pfs->bypass_entry= procfs_dir;
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_info),
BYPASS_INFO_ENTRY_SD,
NULL, /* write */
get_bypass_info_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (pbp_device_block->bp_caps & SW_CTL_CAP) {
/* Create set param proc's */
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_slave),
BYPASS_SLAVE_ENTRY_SD,
NULL, /* write */
get_bypass_slave_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_caps),
BYPASS_CAPS_ENTRY_SD,
NULL, /* write */
get_bypass_caps_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->wd_set_caps),
WD_SET_CAPS_ENTRY_SD,
NULL, /* write */
get_wd_set_caps_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_wd),
BYPASS_WD_ENTRY_SD,
set_bypass_wd_pfs, /* write */
get_bypass_wd_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->wd_expire_time),
WD_EXPIRE_TIME_ENTRY_SD,
NULL, /* write */
get_wd_expire_time_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->reset_bypass_wd),
RESET_BYPASS_WD_ENTRY_SD,
NULL, /* write */
reset_bypass_wd_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->std_nic),
STD_NIC_ENTRY_SD,
set_std_nic_pfs, /* write */
get_std_nic_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (pbp_device_block->bp_caps & BP_CAP) {
if (bypass_proc_create_entry_rd(&(current_pfs->bypass),
BYPASS_ENTRY_SD,
set_bypass_pfs, /* write */
get_bypass_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->dis_bypass),
DIS_BYPASS_ENTRY_SD,
set_dis_bypass_pfs, /* write */
get_dis_bypass_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_pwup),
BYPASS_PWUP_ENTRY_SD,
set_bypass_pwup_pfs, /* write */
get_bypass_pwup_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_pwoff),
BYPASS_PWOFF_ENTRY_SD,
set_bypass_pwoff_pfs, /* write */
get_bypass_pwoff_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->bypass_change),
BYPASS_CHANGE_ENTRY_SD,
NULL, /* write */
get_bypass_change_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
}
if (pbp_device_block->bp_caps & TAP_CAP) {
if (bypass_proc_create_entry_rd(&(current_pfs->tap),
TAP_ENTRY_SD,
set_tap_pfs, /* write */
get_tap_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->dis_tap),
DIS_TAP_ENTRY_SD,
set_dis_tap_pfs, /* write */
get_dis_tap_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->tap_pwup),
TAP_PWUP_ENTRY_SD,
set_tap_pwup_pfs, /* write */
get_tap_pwup_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->tap_change),
TAP_CHANGE_ENTRY_SD,
NULL, /* write */
get_tap_change_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
}
if (pbp_device_block->bp_caps & DISC_CAP) {
if (bypass_proc_create_entry_rd(&(current_pfs->tap),
DISC_ENTRY_SD,
set_disc_pfs, /* write */
get_disc_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
#if 1
if (bypass_proc_create_entry_rd(&(current_pfs->dis_tap),
DIS_DISC_ENTRY_SD,
set_dis_disc_pfs, /* write */
get_dis_disc_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
#endif
if (bypass_proc_create_entry_rd(&(current_pfs->tap_pwup),
DISC_PWUP_ENTRY_SD,
set_disc_pwup_pfs, /* write */
get_disc_pwup_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->tap_change),
DISC_CHANGE_ENTRY_SD,
NULL, /* write */
get_disc_change_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
}
if (bypass_proc_create_entry_rd(&(current_pfs->wd_exp_mode),
WD_EXP_MODE_ENTRY_SD,
set_wd_exp_mode_pfs, /* write */
get_wd_exp_mode_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->wd_autoreset),
WD_AUTORESET_ENTRY_SD,
set_wd_autoreset_pfs, /* write */
get_wd_autoreset_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->tpl),
TPL_ENTRY_SD,
set_tpl_pfs, /* write */
get_tpl_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
#ifdef PMC_FIX_FLAG
if (bypass_proc_create_entry_rd(&(current_pfs->tpl),
WAIT_AT_PWUP_ENTRY_SD,
set_wait_at_pwup_pfs, /* write */
get_wait_at_pwup_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
if (bypass_proc_create_entry_rd(&(current_pfs->tpl),
HW_RESET_ENTRY_SD,
set_hw_reset_pfs, /* write */
get_hw_reset_pfs, /* read */
procfs_dir,
pbp_device_block))
ret= -1;
#endif
}
if (ret<0)
printk(KERN_DEBUG "Create proc entry failed\n");
return ret;
}
#else
static int procfs_add(char *proc_name, const struct file_operations *fops,
bpctl_dev_t *dev)
{
struct bypass_pfs_rd *pfs = &dev->bypass_pfs_set;
if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev))
return -1;
return 0;
}
int bypass_proc_create_dev_rd(bpctl_dev_t *pbp_device_block)
{
struct bypass_pfs_rd *current_pfs = &(pbp_device_block->bypass_pfs_set);
static struct proc_dir_entry *procfs_dir = NULL;
int ret = 0;
if (!pbp_device_block->ndev)
return -1;
sprintf(current_pfs->dir_name, "bypass_%s",
pbp_device_block->ndev->name);
if (!bp_procfs_dir)
return -1;
/* create device proc dir */
procfs_dir = proc_mkdir(current_pfs->dir_name, bp_procfs_dir);
if (!procfs_dir) {
printk(KERN_DEBUG "Could not create procfs directory %s\n",
current_pfs->dir_name);
return -1;
}
current_pfs->bypass_entry = procfs_dir;
#define ENTRY(x) ret |= procfs_add(#x, &x##_ops, pbp_device_block)
ENTRY(bypass_info);
if (pbp_device_block->bp_caps & SW_CTL_CAP) {
/* Create set param proc's */
ENTRY(bypass_slave);
ENTRY(bypass_caps);
ENTRY(wd_set_caps);
ENTRY(bypass_wd);
ENTRY(wd_expire_time);
ENTRY(reset_bypass_wd);
ENTRY(std_nic);
if (pbp_device_block->bp_caps & BP_CAP) {
ENTRY(bypass);
ENTRY(dis_bypass);
ENTRY(bypass_pwup);
ENTRY(bypass_pwoff);
ENTRY(bypass_change);
}
if (pbp_device_block->bp_caps & TAP_CAP) {
ENTRY(tap);
ENTRY(dis_tap);
ENTRY(tap_pwup);
ENTRY(tap_change);
}
if (pbp_device_block->bp_caps & DISC_CAP) {
ENTRY(disc);
ENTRY(dis_disc);
ENTRY(disc_pwup);
ENTRY(disc_change);
}
ENTRY(wd_exp_mode);
ENTRY(wd_autoreset);
ENTRY(tpl);
#ifdef PMC_FIX_FLAG
ENTRY(wait_at_pwup);
ENTRY(hw_reset);
#endif
}
#undef ENTRY
if (ret < 0)
printk(KERN_DEBUG "Create proc entry failed\n");
return ret;
}
#endif
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) )
int bypass_proc_remove_dev_rd(bpctl_dev_t * pbp_device_block){
struct bypass_pfs_rd *current_pfs = &pbp_device_block->bypass_pfs_set;
struct proc_dir_entry *pde = current_pfs->bypass_entry, *pde_curr=NULL;
char name[256];
if (!pde)
return 0;
for (pde=pde->subdir; pde; ) {
strcpy(name,pde->name);
pde_curr=pde;
pde=pde->next;
remove_proc_entry(name,current_pfs->bypass_entry);
}
if (!pde)
remove_proc_entry(current_pfs->dir_name,bp_procfs_dir);
current_pfs->bypass_entry=NULL;
return 0;
}
#else
int bypass_proc_remove_dev_rd(bpctl_dev_t *pbp_device_block)
{
struct bypass_pfs_rd *current_pfs = &pbp_device_block->bypass_pfs_set;
remove_proc_subtree(current_pfs->dir_name, bp_procfs_dir);
current_pfs->bypass_entry = NULL;
return 0;
}
#endif
#endif //BP_PROC_SUPPORT