diff options
Diffstat (limited to 'drivers/staging/silicom')
| -rw-r--r-- | drivers/staging/silicom/Kconfig | 45 | ||||
| -rw-r--r-- | drivers/staging/silicom/Makefile | 6 | ||||
| -rw-r--r-- | drivers/staging/silicom/README | 14 | ||||
| -rw-r--r-- | drivers/staging/silicom/TODO | 8 | ||||
| -rw-r--r-- | drivers/staging/silicom/bits.h | 56 | ||||
| -rw-r--r-- | drivers/staging/silicom/bp_ioctl.h | 140 | ||||
| -rw-r--r-- | drivers/staging/silicom/bp_mod.h | 711 | ||||
| -rw-r--r-- | drivers/staging/silicom/bpctl_mod.c | 7530 | ||||
| -rw-r--r-- | drivers/staging/silicom/bypass.h | 202 | ||||
| -rw-r--r-- | drivers/staging/silicom/bypasslib/Makefile | 6 | ||||
| -rw-r--r-- | drivers/staging/silicom/bypasslib/bp_ioctl.h | 198 | ||||
| -rw-r--r-- | drivers/staging/silicom/bypasslib/bplibk.h | 36 | ||||
| -rw-r--r-- | drivers/staging/silicom/bypasslib/bypass.c | 536 | ||||
| -rw-r--r-- | drivers/staging/silicom/bypasslib/libbp_sd.h | 532 | ||||
| -rw-r--r-- | drivers/staging/silicom/libbp_sd.h | 550 |
15 files changed, 10570 insertions, 0 deletions
diff --git a/drivers/staging/silicom/Kconfig b/drivers/staging/silicom/Kconfig new file mode 100644 index 00000000000..6651bd819bc --- /dev/null +++ b/drivers/staging/silicom/Kconfig @@ -0,0 +1,45 @@ +# +# Silicom device configuration +# + +config NET_VENDOR_SILICOM + bool "Silicom devices" + default y + depends on PCI && NETDEVICES + ---help--- + If you have a network card (Ethernet) belonging to this class, + say Y. + + Note that the answer to this question does not directly affect + the kernel: saying N will just case the configurator to skip all + the questions regarding Silicom chipsets. If you say Y, you will be asked + for your specific chipset/driver in the following questions. + +if NET_VENDOR_SILICOM + +config SBYPASS + tristate "Silicom BypassCTL library support" + depends on PCI + depends on m + ---help--- + If you have a network (Ethernet) controller of this type, say Y + + To compile this driver as a module, choose M here. The module + will be called bypass. + +config BPCTL + tristate "Silicom BypassCTL net support" + depends on PCI + depends on m + select SBYPASS + select MII + ---help--- + If you have a network (Ethernet) controller of this type, say Y + or M and read the Ethernet-HOWTO, available from + <http://www.tldp.org/docs.html#howto>. + + To compile this driver as a module, choose M here. The module + will be called bpctl_mod. + + +endif # NET_VENDOR_SILICOM diff --git a/drivers/staging/silicom/Makefile b/drivers/staging/silicom/Makefile new file mode 100644 index 00000000000..ca8359481c4 --- /dev/null +++ b/drivers/staging/silicom/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the Bypass network device drivers. +# + +obj-$(CONFIG_BPCTL) += bpctl_mod.o +obj-$(CONFIG_SBYPASS) += bypasslib/ diff --git a/drivers/staging/silicom/README b/drivers/staging/silicom/README new file mode 100644 index 00000000000..ae970b37fdc --- /dev/null +++ b/drivers/staging/silicom/README @@ -0,0 +1,14 @@ + +Theory of Operation: + +The Silicom Bypass Network Interface Cards (NICs) are network cards with paired ports (2 or 4). +The pairs either act as a "wire" allowing the network packets to pass or insert the device in +between the two ports. When paired with the on-board hardware watchdog or other failsafe, +they provide high availability for the network in the face of software outages or maintenance. + +The software requirements are for a kernel level driver that interfaces with the bypass and watchdog, +as well as for control software. User control can be either the provided standalone executable +(/bin/bpctl) or the API exposed by the Silicom library. + + + diff --git a/drivers/staging/silicom/TODO b/drivers/staging/silicom/TODO new file mode 100644 index 00000000000..09d07b0ea9c --- /dev/null +++ b/drivers/staging/silicom/TODO @@ -0,0 +1,8 @@ +TODO: + - checkpatch.pl cleanups + - locking audit + - single module with all functionality + - userland + - fix monolithic build. + + diff --git a/drivers/staging/silicom/bits.h b/drivers/staging/silicom/bits.h new file mode 100644 index 00000000000..8c411d0d4ec --- /dev/null +++ b/drivers/staging/silicom/bits.h @@ -0,0 +1,56 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef BITS_H +#define BITS_H + +/******************************************************************************/ +/* Bit Mask definitions */ +/******************************************************************************/ + +#define BIT_NONE 0x00 +#define BIT_0 0x01 +#define BIT_1 0x02 +#define BIT_2 0x04 +#define BIT_3 0x08 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 +#define BIT_8 0x0100 +#define BIT_9 0x0200 +#define BIT_10 0x0400 +#define BIT_11 0x0800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_16 0x010000 +#define BIT_17 0x020000 +#define BIT_18 0x040000 +#define BIT_19 0x080000 +#define BIT_20 0x100000 +#define BIT_21 0x200000 +#define BIT_22 0x400000 +#define BIT_23 0x800000 +#define BIT_24 0x01000000 +#define BIT_25 0x02000000 +#define BIT_26 0x04000000 +#define BIT_27 0x08000000 +#define BIT_28 0x10000000 +#define BIT_29 0x20000000 +#define BIT_30 0x40000000 +#define BIT_31 0x80000000 + +#endif /* BITS_H */ diff --git a/drivers/staging/silicom/bp_ioctl.h b/drivers/staging/silicom/bp_ioctl.h new file mode 100644 index 00000000000..57de34a69e8 --- /dev/null +++ b/drivers/staging/silicom/bp_ioctl.h @@ -0,0 +1,140 @@ +/******************************************************************************/ +/* */ +/* Silicom Bypass Control Utility, Copyright (c) 2005-2007 Silicom */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* */ +/******************************************************************************/ + +#ifndef BP_IOCTL_H +#define BP_IOCTL_H + +#define BP_CAP 0x01 /* BIT_0 */ +#define BP_STATUS_CAP 0x02 +#define BP_STATUS_CHANGE_CAP 0x04 +#define SW_CTL_CAP 0x08 +#define BP_DIS_CAP 0x10 +#define BP_DIS_STATUS_CAP 0x20 +#define STD_NIC_CAP 0x40 +#define BP_PWOFF_ON_CAP 0x80 +#define BP_PWOFF_OFF_CAP 0x0100 +#define BP_PWOFF_CTL_CAP 0x0200 +#define BP_PWUP_ON_CAP 0x0400 +#define BP_PWUP_OFF_CAP 0x0800 +#define BP_PWUP_CTL_CAP 0x1000 +#define WD_CTL_CAP 0x2000 +#define WD_STATUS_CAP 0x4000 +#define WD_TIMEOUT_CAP 0x8000 +#define TX_CTL_CAP 0x10000 +#define TX_STATUS_CAP 0x20000 +#define TAP_CAP 0x40000 +#define TAP_STATUS_CAP 0x80000 +#define TAP_STATUS_CHANGE_CAP 0x100000 +#define TAP_DIS_CAP 0x200000 +#define TAP_DIS_STATUS_CAP 0x400000 +#define TAP_PWUP_ON_CAP 0x800000 +#define TAP_PWUP_OFF_CAP 0x1000000 +#define TAP_PWUP_CTL_CAP 0x2000000 +#define NIC_CAP_NEG 0x4000000 +#define TPL_CAP 0x8000000 +#define DISC_CAP 0x10000000 +#define DISC_DIS_CAP 0x20000000 +#define DISC_PWUP_CTL_CAP 0x40000000 + +#define TPL2_CAP_EX 0x01 +#define DISC_PORT_CAP_EX 0x02 + +#define WD_MIN_TIME_MASK(val) (val & 0xf) +#define WD_STEP_COUNT_MASK(val) ((val & 0xf) << 5) +#define WDT_STEP_TIME 0x10 /* BIT_4 */ + +#define WD_MIN_TIME_GET(desc) (desc & 0xf) +#define WD_STEP_COUNT_GET(desc) ((desc>>5) & 0xf) + +typedef enum { + IF_SCAN, + GET_DEV_NUM, + IS_BYPASS, + GET_BYPASS_SLAVE, + GET_BYPASS_CAPS, + GET_WD_SET_CAPS, + SET_BYPASS, + GET_BYPASS, + GET_BYPASS_CHANGE, + SET_BYPASS_WD, + GET_BYPASS_WD, + GET_WD_EXPIRE_TIME, + RESET_BYPASS_WD_TIMER, + SET_DIS_BYPASS, + GET_DIS_BYPASS, + SET_BYPASS_PWOFF, + GET_BYPASS_PWOFF, + SET_BYPASS_PWUP, + GET_BYPASS_PWUP, + SET_STD_NIC, + GET_STD_NIC, + SET_TX, + GET_TX, + SET_TAP, + GET_TAP, + GET_TAP_CHANGE, + SET_DIS_TAP, + GET_DIS_TAP, + SET_TAP_PWUP, + GET_TAP_PWUP, + SET_WD_EXP_MODE, + GET_WD_EXP_MODE, + SET_WD_AUTORESET, + GET_WD_AUTORESET, + SET_TPL, + GET_TPL, + SET_DISC, + GET_DISC, + GET_DISC_CHANGE, + SET_DIS_DISC, + GET_DIS_DISC, + SET_DISC_PWUP, + GET_DISC_PWUP, + GET_BYPASS_INFO = 100, + GET_BP_WAIT_AT_PWUP, + SET_BP_WAIT_AT_PWUP, + GET_BP_HW_RESET, + SET_BP_HW_RESET, + SET_DISC_PORT, + GET_DISC_PORT, + SET_DISC_PORT_PWUP, + GET_DISC_PORT_PWUP, + SET_BP_FORCE_LINK, + GET_BP_FORCE_LINK, +#ifdef BP_SELF_TEST + SET_BP_SELF_TEST = 200, + GET_BP_SELF_TEST, +#endif + +} CMND_TYPE_SD; + +/* +* The major device number. We can't rely on dynamic +* registration any more, because ioctls need to know +* it. +*/ + +#define MAGIC_NUM 'J' + +/* for passing single values */ +struct bpctl_cmd { + int status; + int data[8]; + int in_param[8]; + int out_param[8]; +}; + +#define IOCTL_TX_MSG(cmd) _IOWR(MAGIC_NUM, cmd, struct bpctl_cmd) + +#define DEVICE_NAME "bpctl" + +#endif diff --git a/drivers/staging/silicom/bp_mod.h b/drivers/staging/silicom/bp_mod.h new file mode 100644 index 00000000000..82b4963e97b --- /dev/null +++ b/drivers/staging/silicom/bp_mod.h @@ -0,0 +1,711 @@ +/******************************************************************************/ +/* */ +/* Bypass Control utility, Copyright (c) 2005 Silicom */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* */ +/* bp_mod.h */ +/* */ +/******************************************************************************/ + +#ifndef BP_MOD_H +#define BP_MOD_H +#include "bits.h" + +#define usec_delay(x) udelay(x) +#ifndef msec_delay_bp +#define msec_delay_bp(x) \ +do { \ + int i; \ + if (1) { \ + for (i = 0; i < 1000; i++) { \ + udelay(x); \ + } \ + } else { \ + msleep(x); \ + } \ +} while (0) + +#endif + +#include <linux/param.h> + +#ifndef jiffies_to_msecs +#define jiffies_to_msecs(x) _kc_jiffies_to_msecs(x) +static inline unsigned int jiffies_to_msecs(const unsigned long j) +{ +#if HZ <= 1000 && !(1000 % HZ) + return (1000 / HZ) * j; +#elif HZ > 1000 && !(HZ % 1000) + return (j + (HZ / 1000) - 1) / (HZ / 1000); +#else + return (j * 1000) / HZ; +#endif +} +#endif + +#define SILICOM_VID 0x1374 +#define SILICOM_SVID 0x1374 + +#define SILICOM_PXG2BPFI_SSID 0x0026 +#define SILICOM_PXG2BPFILX_SSID 0x0027 +#define SILICOM_PXGBPI_SSID 0x0028 +#define SILICOM_PXGBPIG_SSID 0x0029 +#define SILICOM_PXG2TBFI_SSID 0x002a +#define SILICOM_PXG4BPI_SSID 0x002c +#define SILICOM_PXG4BPFI_SSID 0x002d +#define SILICOM_PXG4BPFILX_SSID 0x002e +#define SILICOM_PXG2BPFIL_SSID 0x002F +#define SILICOM_PXG2BPFILLX_SSID 0x0030 +#define SILICOM_PEG4BPI_SSID 0x0031 +#define SILICOM_PEG2BPI_SSID 0x0037 +#define SILICOM_PEG4BPIN_SSID 0x0038 +#define SILICOM_PEG2BPFI_SSID 0x0039 +#define SILICOM_PEG2BPFILX_SSID 0x003A +#define SILICOM_PMCXG2BPFI_SSID 0x003B +#define NOKIA_PMCXG2BPFIN_SSID 0x0510 +#define NOKIA_PMCXG2BPIN_SSID 0x0513 +#define NOKIA_PMCXG4BPIN_SSID 0x0514 +#define NOKIA_PMCXG2BPFIN_SVID 0x13B8 +#define NOKIA_PMCXG2BPIN2_SSID 0x0515 +#define NOKIA_PMCXG4BPIN2_SSID 0x0516 +#define SILICOM_PMCX2BPI_SSID 0x041 +#define SILICOM_PMCX4BPI_SSID 0x042 +#define SILICOM_PXG2BISC1_SSID 0x003d +#define SILICOM_PEG2TBFI_SSID 0x003E +#define SILICOM_PXG2TBI_SSID 0x003f +#define SILICOM_PXG4BPFID_SSID 0x0043 +#define SILICOM_PEG4BPFI_SSID 0x0040 +#define SILICOM_PEG4BPIPT_SSID 0x0044 +#define SILICOM_PXG6BPI_SSID 0x0045 +#define SILICOM_PEG4BPIL_SSID 0x0046 +#define SILICOM_PEG2BPI5_SSID 0x0052 +#define SILICOM_PEG6BPI_SSID 0x0053 +#define SILICOM_PEG4BPFI5_SSID 0x0050 +#define SILICOM_PEG4BPFI5LX_SSID 0x0051 +#define SILICOM_PEG2BISC6_SSID 0x54 + +#define SILICOM_PEG6BPIFC_SSID 0x55 + +#define SILICOM_PEG2BPFI5_SSID 0x0056 +#define SILICOM_PEG2BPFI5LX_SSID 0x0057 + +#define SILICOM_PXEG4BPFI_SSID 0x0058 + +#define SILICOM_PEG2BPFID_SSID 0x0047 +#define SILICOM_PEG2BPFIDLX_SSID 0x004C +#define SILICOM_MEG2BPFILN_SSID 0x0048 +#define SILICOM_MEG2BPFINX_SSID 0x0049 +#define SILICOM_PEG4BPFILX_SSID 0x004A +#define SILICOM_MHIO8AD_SSID 0x004F + +#define SILICOM_MEG2BPFILXLN_SSID 0x004b +#define SILICOM_PEG2BPIX1_SSID 0x004d +#define SILICOM_MEG2BPFILXNX_SSID 0x004e + +#define SILICOM_PE10G2BPISR_SSID 0x0102 +#define SILICOM_PE10G2BPILR_SSID 0x0103 +#define SILICOM_PE10G2BPICX4_SSID 0x0101 + +#define SILICOM_XE10G2BPILR_SSID 0x0163 +#define SILICOM_XE10G2BPISR_SSID 0x0162 +#define SILICOM_XE10G2BPICX4_SSID 0x0161 +#define SILICOM_XE10G2BPIT_SSID 0x0160 + +#define SILICOM_PE10GDBISR_SSID 0x0181 +#define SILICOM_PE10GDBILR_SSID 0x0182 + +#define SILICOM_PE210G2DBi9SR_SSID 0x0188 +#define SILICOM_PE210G2DBi9SRRB_SSID 0x0188 +#define SILICOM_PE210G2DBi9LR_SSID 0x0189 +#define SILICOM_PE210G2DBi9LRRB_SSID 0x0189 +#define SILICOM_PE310G4DBi940SR_SSID 0x018C + +#define SILICOM_PE310G4BPi9T_SSID 0x130 +#define SILICOM_PE310G4BPi9SR_SSID 0x132 +#define SILICOM_PE310G4BPi9LR_SSID 0x133 + +#define NOKIA_XE10G2BPIXR_SVID 0x13B8 +#define NOKIA_XE10G2BPIXR_SSID 0x051C + +#define INTEL_PEG4BPII_PID 0x10A0 +#define INTEL_PEG4BPFII_PID 0x10A1 +#define INTEL_PEG4BPII_SSID 0x11A0 +#define INTEL_PEG4BPFII_SSID 0x11A1 + +#define INTEL_PEG4BPIIO_SSID 0x10A0 +#define INTEL_PEG4BPIIO_PID 0x105e + +#define BROADCOM_VID 0x14e4 +#define BROADCOM_PE10G2_PID 0x164e + +#define SILICOM_PE10G2BPTCX4_SSID 0x0141 +#define SILICOM_PE10G2BPTSR_SSID 0x0142 +#define SILICOM_PE10G2BPTLR_SSID 0x0143 +#define SILICOM_PE10G2BPTT_SSID 0x0140 + +#define SILICOM_PEG4BPI6_SSID 0x0320 +#define SILICOM_PEG4BPFI6_SSID 0x0321 +#define SILICOM_PEG4BPFI6LX_SSID 0x0322 +#define SILICOM_PEG4BPFI6ZX_SSID 0x0323 + +#define SILICOM_PEG2BPI6_SSID 0x0300 +#define SILICOM_PEG2BPFI6_SSID 0x0301 +#define SILICOM_PEG2BPFI6LX_SSID 0x0302 +#define SILICOM_PEG2BPFI6ZX_SSID 0x0303 +#define SILICOM_PEG2BPFI6FLXM_SSID 0x0304 + +#define SILICOM_PEG2DBI6_SSID 0x0308 +#define SILICOM_PEG2DBFI6_SSID 0x0309 +#define SILICOM_PEG2DBFI6LX_SSID 0x030A +#define SILICOM_PEG2DBFI6ZX_SSID 0x030B + +#define SILICOM_MEG2BPI6_SSID 0x0310 +#define SILICOM_XEG2BPI6_SSID 0x0318 +#define SILICOM_PEG4BPI6FC_SSID 0x0328 +#define SILICOM_PEG4BPFI6FC_SSID 0x0329 +#define SILICOM_PEG4BPFI6FCLX_SSID 0x032A +#define SILICOM_PEG4BPFI6FCZX_SSID 0x032B + +#define SILICOM_PEG6BPI6_SSID 0x0340 + +#define SILICOM_PEG2BPI6SC6_SSID 0x0360 + +#define SILICOM_MEG2BPI6_SSID 0x0310 +#define SILICOM_XEG2BPI6_SSID 0x0318 +#define SILICOM_MEG4BPI6_SSID 0x0330 + +#define SILICOM_PE2G4BPi80L_SSID 0x0380 + +#define SILICOM_M6E2G8BPi80A_SSID 0x0474 + +#define SILICOM_PE2G4BPi35_SSID 0x03d8 + +#define SILICOM_PE2G4BPFi80_SSID 0x0381 +#define SILICOM_PE2G4BPFi80LX_SSID 0x0382 +#define SILICOM_PE2G4BPFi80ZX_SSID 0x0383 + +#define SILICOM_PE2G4BPi80_SSID 0x0388 + +#define SILICOM_PE2G2BPi80_SSID 0x0390 +#define SILICOM_PE2G2BPFi80_SSID 0x0391 +#define SILICOM_PE2G2BPFi80LX_SSID 0x0392 +#define SILICOM_PE2G2BPFi80ZX_SSID 0x0393 + +#define SILICOM_PE2G4BPi35L_SSID 0x03D0 +#define SILICOM_PE2G4BPFi35_SSID 0x03D1 +#define SILICOM_PE2G4BPFi35LX_SSID 0x03D2 +#define SILICOM_PE2G4BPFi35ZX_SSID 0x03D3 + +#define SILICOM_PE2G2BPi35_SSID 0x03c0 +#define SILICOM_PAC1200BPi35_SSID 0x03cc +#define SILICOM_PE2G2BPFi35_SSID 0x03C1 +#define SILICOM_PE2G2BPFi35LX_SSID 0x03C2 +#define SILICOM_PE2G2BPFi35ZX_SSID 0x03C3 + +#define SILICOM_PE2G6BPi35_SSID 0x03E0 +#define SILICOM_PE2G6BPi35CX_SSID 0x0AA0 + +#define INTEL_PE210G2SPI9_SSID 0x00C + +#define SILICOM_M1EG2BPI6_SSID 0x400 + +#define SILICOM_M1EG2BPFI6_SSID 0x0401 +#define SILICOM_M1EG2BPFI6LX_SSID 0x0402 +#define SILICOM_M1EG2BPFI6ZX_SSID 0x0403 + +#define SILICOM_M1EG4BPI6_SSID 0x0420 + +#define SILICOM_M1EG4BPFI6_SSID 0x0421 +#define SILICOM_M1EG4BPFI6LX_SSID 0x0422 +#define SILICOM_M1EG4BPFI6ZX_SSID 0x0423 + +#define SILICOM_M1EG6BPI6_SSID 0x0440 + +#define SILICOM_M1E2G4BPi80_SSID 0x0460 +#define SILICOM_M1E2G4BPFi80_SSID 0x0461 +#define SILICOM_M1E2G4BPFi80LX_SSID 0x0462 +#define SILICOM_M1E2G4BPFi80ZX_SSID 0x0463 + +#define SILICOM_M6E2G8BPi80_SSID 0x0470 +#define SILICOM_PE210G2BPi40_SSID 0x01a0 + +#define PEG540_IF_SERIES(pid) \ + ((pid == SILICOM_PE210G2BPi40_SSID)) + +#define OLD_IF_SERIES(pid)\ + ((pid == SILICOM_PXG2BPFI_SSID) || \ + (pid == SILICOM_PXG2BPFILX_SSID)) + +#define P2BPFI_IF_SERIES(pid) \ + ((pid == SILICOM_PXG2BPFI_SSID) || \ + (pid == SILICOM_PXG2BPFILX_SSID) || \ + (pid == SILICOM_PEG2BPFI_SSID) || \ + (pid == SILICOM_PEG2BPFID_SSID) || \ + (pid == SILICOM_PEG2BPFIDLX_SSID) || \ + (pid == SILICOM_MEG2BPFILN_SSID) || \ + (pid == SILICOM_MEG2BPFINX_SSID) || \ + (pid == SILICOM_PEG4BPFILX_SSID) || \ + (pid == SILICOM_PEG4BPFI_SSID) || \ + (pid == SILICOM_PXEG4BPFI_SSID) || \ + (pid == SILICOM_PXG4BPFID_SSID) || \ + (pid == SILICOM_PEG2TBFI_SSID) || \ + (pid == SILICOM_PE10G2BPISR_SSID) || \ + (pid == SILICOM_PE10G2BPILR_SSID) || \ + (pid == SILICOM_PEG2BPFILX_SSID) || \ + (pid == SILICOM_PMCXG2BPFI_SSID) || \ + (pid == SILICOM_MHIO8AD_SSID) || \ + (pid == SILICOM_PEG4BPFI5LX_SSID) || \ + (pid == SILICOM_PEG4BPFI5_SSID) || \ + (pid == SILICOM_PEG4BPFI6FC_SSID) || \ + (pid == SILICOM_PEG4BPFI6FCLX_SSID) || \ + (pid == SILICOM_PEG4BPFI6FCZX_SSID) || \ + (pid == NOKIA_PMCXG2BPFIN_SSID) || \ + (pid == SILICOM_MEG2BPFILXLN_SSID) || \ + (pid == SILICOM_MEG2BPFILXNX_SSID) || \ + (pid == SILICOM_XE10G2BPIT_SSID) || \ + (pid == SILICOM_XE10G2BPICX4_SSID) || \ + (pid == SILICOM_XE10G2BPISR_SSID) || \ + (pid == NOKIA_XE10G2BPIXR_SSID) || \ + (pid == SILICOM_PE10GDBISR_SSID) || \ + (pid == SILICOM_PE10GDBILR_SSID) || \ + (pid == SILICOM_XE10G2BPILR_SSID)) + +#define INTEL_IF_SERIES(pid) \ + ((pid == INTEL_PEG4BPII_SSID) || \ + (pid == INTEL_PEG4BPIIO_SSID) || \ + (pid == INTEL_PEG4BPFII_SSID)) + +#define NOKIA_SERIES(pid) \ + ((pid == NOKIA_PMCXG2BPIN_SSID) || \ + (pid == NOKIA_PMCXG4BPIN_SSID) || \ + (pid == SILICOM_PMCX4BPI_SSID) || \ + (pid == NOKIA_PMCXG2BPFIN_SSID) || \ + (pid == SILICOM_PMCXG2BPFI_SSID) || \ + (pid == NOKIA_PMCXG2BPIN2_SSID) || \ + (pid == NOKIA_PMCXG4BPIN2_SSID) || \ + (pid == SILICOM_PMCX2BPI_SSID)) + +#define DISCF_IF_SERIES(pid) \ + (pid == SILICOM_PEG2TBFI_SSID) + +#define PEGF_IF_SERIES(pid) \ + ((pid == SILICOM_PEG2BPFI_SSID) || \ + (pid == SILICOM_PEG2BPFID_SSID) || \ + (pid == SILICOM_PEG2BPFIDLX_SSID) || \ + (pid == SILICOM_PEG2BPFILX_SSID) || \ + (pid == SILICOM_PEG4BPFI_SSID) || \ + (pid == SILICOM_PXEG4BPFI_SSID) || \ + (pid == SILICOM_MEG2BPFILN_SSID) || \ + (pid == SILICOM_MEG2BPFINX_SSID) || \ + (pid == SILICOM_PEG4BPFILX_SSID) || \ + (pid == SILICOM_PEG2TBFI_SSID) || \ + (pid == SILICOM_MEG2BPFILXLN_SSID) || \ + (pid == SILICOM_MEG2BPFILXNX_SSID)) + +#define TPL_IF_SERIES(pid) \ + ((pid == SILICOM_PXG2BPFIL_SSID) || \ + (pid == SILICOM_PXG2BPFILLX_SSID) || \ + (pid == SILICOM_PXG2TBFI_SSID) || \ + (pid == SILICOM_PXG4BPFID_SSID) || \ + (pid == SILICOM_PXG4BPFI_SSID)) + +#define BP10G_IF_SERIES(pid) \ + ((pid == SILICOM_PE10G2BPISR_SSID) || \ + (pid == SILICOM_PE10G2BPICX4_SSID) || \ + (pid == SILICOM_PE10G2BPILR_SSID) || \ + (pid == SILICOM_XE10G2BPIT_SSID) || \ + (pid == SILICOM_XE10G2BPICX4_SSID) || \ + (pid == SILICOM_XE10G2BPISR_SSID) || \ + (pid == NOKIA_XE10G2BPIXR_SSID) || \ + (pid == SILICOM_PE10GDBISR_SSID) || \ + (pid == SILICOM_PE10GDBILR_SSID) || \ + (pid == SILICOM_XE10G2BPILR_SSID)) + +#define BP10GB_IF_SERIES(pid) \ + ((pid == SILICOM_PE10G2BPTCX4_SSID) || \ + (pid == SILICOM_PE10G2BPTSR_SSID) || \ + (pid == SILICOM_PE10G2BPTLR_SSID) || \ + (pid == SILICOM_PE10G2BPTT_SSID)) + +#define BP10G_CX4_SERIES(pid) \ + (pid == SILICOM_PE10G2BPICX4_SSID) + +#define BP10GB_CX4_SERIES(pid) \ + (pid == SILICOM_PE10G2BPTCX4_SSID) + +#define SILICOM_M2EG2BPFI6_SSID 0x0501 +#define SILICOM_M2EG2BPFI6LX_SSID 0x0502 +#define SILICOM_M2EG2BPFI6ZX_SSID 0x0503 +#define SILICOM_M2EG4BPI6_SSID 0x0520 + +#define SILICOM_M2EG4BPFI6_SSID 0x0521 +#define SILICOM_M2EG4BPFI6LX_SSID 0x0522 +#define SILICOM_M2EG4BPFI6ZX_SSID 0x0523 + +#define SILICOM_M2EG6BPI6_SSID 0x0540 + +#define SILICOM_M1E10G2BPI9CX4_SSID 0x481 +#define SILICOM_M1E10G2BPI9SR_SSID 0x482 +#define SILICOM_M1E10G2BPI9LR_SSID 0x483 +#define SILICOM_M1E10G2BPI9T_SSID 0x480 + +#define SILICOM_M2E10G2BPI9CX4_SSID 0x581 +#define SILICOM_M2E10G2BPI9SR_SSID 0x582 +#define SILICOM_M2E10G2BPI9LR_SSID 0x583 +#define SILICOM_M2E10G2BPI9T_SSID 0x580 + +#define SILICOM_PE210G2BPI9CX4_SSID 0x121 +#define SILICOM_PE210G2BPI9SR_SSID 0x122 +#define SILICOM_PE210G2BPI9LR_SSID 0x123 +#define SILICOM_PE210G2BPI9T_SSID 0x120 + +#define DBI_IF_SERIES(pid) \ + ((pid == SILICOM_PE10GDBISR_SSID) || \ + (pid == SILICOM_PE10GDBILR_SSID) || \ + (pid == SILICOM_XE10G2BPILR_SSID) || \ + (pid == SILICOM_PE210G2DBi9LR_SSID)) + +#define PEGF5_IF_SERIES(pid) \ + ((pid == SILICOM_PEG2BPFI5_SSID) || \ + (pid == SILICOM_PEG2BPFI5LX_SSID) || \ + (pid == SILICOM_PEG4BPFI6_SSID) || \ + (pid == SILICOM_PEG4BPFI6LX_SSID) || \ + (pid == SILICOM_PEG4BPFI6ZX_SSID) || \ + (pid == SILICOM_PEG2BPFI6_SSID) || \ + (pid == SILICOM_PEG2BPFI6LX_SSID) || \ + (pid == SILICOM_PEG2BPFI6ZX_SSID) || \ + (pid == SILICOM_PEG2BPFI6FLXM_SSID) || \ + (pid == SILICOM_PEG2DBFI6_SSID) || \ + (pid == SILICOM_PEG2DBFI6LX_SSID) || \ + (pid == SILICOM_PEG2DBFI6ZX_SSID) || \ + (pid == SILICOM_PEG4BPI6FC_SSID) || \ + (pid == SILICOM_PEG4BPFI6FCLX_SSID) || \ + (pid == SILICOM_PEG4BPI6FC_SSID) || \ + (pid == SILICOM_M1EG2BPFI6_SSID) || \ + (pid == SILICOM_M1EG2BPFI6LX_SSID) || \ + (pid == SILICOM_M1EG2BPFI6ZX_SSID) || \ + (pid == SILICOM_M1EG4BPFI6_SSID) || \ + (pid == SILICOM_M1EG4BPFI6LX_SSID) || \ + (pid == SILICOM_M1EG4BPFI6ZX_SSID) || \ + (pid == SILICOM_M2EG2BPFI6_SSID) || \ + (pid == SILICOM_M2EG2BPFI6LX_SSID) || \ + (pid == SILICOM_M2EG2BPFI6ZX_SSID) || \ + (pid == SILICOM_M2EG4BPFI6_SSID) || \ + (pid == SILICOM_M2EG4BPFI6LX_SSID) || \ + (pid == SILICOM_M2EG4BPFI6ZX_SSID) || \ + (pid == SILICOM_PEG4BPFI6FCZX_SSID)) + +#define PEG5_IF_SERIES(pid) \ + ((pid == SILICOM_PEG4BPI6_SSID) || \ + (pid == SILICOM_PEG2BPI6_SSID) || \ + (pid == SILICOM_PEG4BPI6FC_SSID) || \ + (pid == SILICOM_PEG6BPI6_SSID) || \ + (pid == SILICOM_PEG2BPI6SC6_SSID) || \ + (pid == SILICOM_MEG2BPI6_SSID) || \ + (pid == SILICOM_XEG2BPI6_SSID) || \ + (pid == SILICOM_MEG4BPI6_SSID) || \ + (pid == SILICOM_M1EG2BPI6_SSID) || \ + (pid == SILICOM_M1EG4BPI6_SSID) || \ + (pid == SILICOM_M1EG6BPI6_SSID) || \ + (pid == SILICOM_PEG6BPI_SSID) || \ + (pid == SILICOM_PEG4BPIL_SSID) || \ + (pid == SILICOM_PEG2BISC6_SSID) || \ + (pid == SILICOM_PEG2BPI5_SSID)) + +#define PEG80_IF_SERIES(pid) \ + ((pid == SILICOM_M1E2G4BPi80_SSID) || \ + (pid == SILICOM_M6E2G8BPi80_SSID) || \ + (pid == SILICOM_PE2G4BPi80L_SSID) || \ + (pid == SILICOM_M6E2G8BPi80A_SSID) || \ + (pid == SILICOM_PE2G2BPi35_SSID) || \ + (pid == SILICOM_PAC1200BPi35_SSID) || \ + (pid == SILICOM_PE2G4BPi35_SSID) || \ + (pid == SILICOM_PE2G4BPi35L_SSID) || \ + (pid == SILICOM_PE2G6BPi35_SSID) || \ + (pid == SILICOM_PE2G2BPi80_SSID) || \ + (pid == SILICOM_PE2G4BPi80_SSID) || \ + (pid == SILICOM_PE2G4BPFi80_SSID) || \ + (pid == SILICOM_PE2G4BPFi80LX_SSID) || \ + (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ + (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ + (pid == SILICOM_PE2G2BPFi80_SSID) || \ + (pid == SILICOM_PE2G2BPFi80LX_SSID) || \ + (pid == SILICOM_PE2G2BPFi80ZX_SSID) || \ + (pid == SILICOM_PE2G2BPFi35_SSID) || \ + (pid == SILICOM_PE2G2BPFi35LX_SSID) || \ + (pid == SILICOM_PE2G2BPFi35ZX_SSID) || \ + (pid == SILICOM_PE2G4BPFi35_SSID) || \ + (pid == SILICOM_PE2G4BPFi35LX_SSID) || \ + (pid == SILICOM_PE2G4BPFi35ZX_SSID)) + +#define PEGF80_IF_SERIES(pid) \ + ((pid == SILICOM_PE2G4BPFi80_SSID) || \ + (pid == SILICOM_PE2G4BPFi80LX_SSID) || \ + (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ + (pid == SILICOM_PE2G4BPFi80ZX_SSID) || \ + (pid == SILICOM_M1E2G4BPFi80_SSID) || \ + (pid == SILICOM_M1E2G4BPFi80LX_SSID) || \ + (pid == SILICOM_M1E2G4BPFi80ZX_SSID) || \ + (pid == SILICOM_PE2G2BPFi80_SSID) || \ + (pid == SILICOM_PE2G2BPFi80LX_SSID) || \ + (pid == SILICOM_PE2G2BPFi80ZX_SSID) || \ + (pid == SILICOM_PE2G2BPFi35_SSID) || \ + (pid == SILICOM_PE2G2BPFi35LX_SSID) || \ + (pid == SILICOM_PE2G2BPFi35ZX_SSID) || \ + (pid == SILICOM_PE2G4BPFi35_SSID) || \ + (pid == SILICOM_PE2G4BPFi35LX_SSID) || \ + (pid == SILICOM_PE2G4BPFi35ZX_SSID)) + +#define BP10G9_IF_SERIES(pid) \ + ((pid == INTEL_PE210G2SPI9_SSID) || \ + (pid == SILICOM_M1E10G2BPI9CX4_SSID) || \ + (pid == SILICOM_M1E10G2BPI9SR_SSID) || \ + (pid == SILICOM_M1E10G2BPI9LR_SSID) || \ + (pid == SILICOM_M1E10G2BPI9T_SSID) || \ + (pid == SILICOM_M2E10G2BPI9CX4_SSID) || \ + (pid == SILICOM_M2E10G2BPI9SR_SSID) || \ + (pid == SILICOM_M2E10G2BPI9LR_SSID) || \ + (pid == SILICOM_M2E10G2BPI9T_SSID) || \ + (pid == SILICOM_PE210G2BPI9CX4_SSID) || \ + (pid == SILICOM_PE210G2BPI9SR_SSID) || \ + (pid == SILICOM_PE210G2BPI9LR_SSID) || \ + (pid == SILICOM_PE210G2DBi9SR_SSID) || \ + (pid == SILICOM_PE210G2DBi9SRRB_SSID) || \ + (pid == SILICOM_PE210G2DBi9LR_SSID) || \ + (pid == SILICOM_PE210G2DBi9LRRB_SSID) || \ + (pid == SILICOM_PE310G4DBi940SR_SSID) || \ + (pid == SILICOM_PEG2BISC6_SSID) || \ + (pid == SILICOM_PE310G4BPi9T_SSID) || \ + (pid == SILICOM_PE310G4BPi9SR_SSID) || \ + (pid == SILICOM_PE310G4BPi9LR_SSID) || \ + (pid == SILICOM_PE210G2BPI9T_SSID)) + +/*******************************************************/ +/* 1G INTERFACE ****************************************/ +/*******************************************************/ + +/* Intel Registers */ +#define BPCTLI_CTRL 0x00000 +#define BPCTLI_CTRL_SWDPIO0 0x00400000 +#define BPCTLI_CTRL_SWDPIN0 0x00040000 + +#define BPCTLI_CTRL_EXT 0x00018 /* Extended Device Control - RW */ +#define BPCTLI_STATUS 0x00008 /* Device Status - RO */ + +/* HW related */ +#define BPCTLI_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW + * Defineable Pin 6 + */ +#define BPCTLI_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW + * Defineable Pin 7 + */ +#define BPCTLI_CTRL_SDP0_DATA 0x00040000 /* SWDPIN 0 value */ +#define BPCTLI_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 + * 0=in 1=out + */ +#define BPCTLI_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 + * 0=in 1=out + */ +#define BPCTLI_CTRL_SDP0_DIR 0x00400000 /* SDP0 Input or output */ +#define BPCTLI_CTRL_SWDPIN1 0x00080000 +#define BPCTLI_CTRL_SDP1_DIR 0x00800000 + +#define BPCTLI_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ + +#define BPCTLI_CTRL_SDP0_SHIFT 18 +#define BPCTLI_CTRL_EXT_SDP6_SHIFT 6 + +#define BPCTLI_STATUS_TBIMODE 0x00000020 +#define BPCTLI_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 +#define BPCTLI_CTRL_EXT_LINK_MODE_MASK 0x00C00000 + +#define BPCTLI_CTRL_EXT_MCLK_DIR BPCTLI_CTRL_EXT_SDP7_DIR +#define BPCTLI_CTRL_EXT_MCLK_DATA BPCTLI_CTRL_EXT_SDP7_DATA +#define BPCTLI_CTRL_EXT_MDIO_DIR BPCTLI_CTRL_EXT_SDP6_DIR +#define BPCTLI_CTRL_EXT_MDIO_DATA BPCTLI_CTRL_EXT_SDP6_DATA + +#define BPCTLI_CTRL_EXT_MCLK_DIR5 BPCTLI_CTRL_SDP1_DIR +#define BPCTLI_CTRL_EXT_MCLK_DATA5 BPCTLI_CTRL_SWDPIN1 +#define BPCTLI_CTRL_EXT_MCLK_DIR80 BPCTLI_CTRL_EXT_SDP6_DIR +#define BPCTLI_CTRL_EXT_MCLK_DATA80 BPCTLI_CTRL_EXT_SDP6_DATA +#define BPCTLI_CTRL_EXT_MDIO_DIR5 BPCTLI_CTRL_SWDPIO0 +#define BPCTLI_CTRL_EXT_MDIO_DATA5 BPCTLI_CTRL_SWDPIN0 +#define BPCTLI_CTRL_EXT_MDIO_DIR80 BPCTLI_CTRL_SWDPIO0 +#define BPCTLI_CTRL_EXT_MDIO_DATA80 BPCTLI_CTRL_SWDPIN0 + +#define BPCTL_WRITE_REG(a, reg, value) \ + (writel((value), (void *)(((a)->mem_map) + BPCTLI_##reg))) + +#define BPCTL_READ_REG(a, reg) ( \ + readl((void *)((a)->mem_map) + BPCTLI_##reg)) + +#define BPCTL_WRITE_FLUSH(a) BPCTL_READ_REG(a, STATUS) + +#define BPCTL_BP_WRITE_REG(a, reg, value) ({ \ + BPCTL_WRITE_REG(a, reg, value); \ + BPCTL_WRITE_FLUSH(a); }) + +/**************************************************************/ +/************** 82575 Interface********************************/ +/**************************************************************/ + +#define BPCTLI_MII_CR_POWER_DOWN 0x0800 +#define BPCTLI_PHY_CONTROL 0x00 /* Control Register */ +#define BPCTLI_MDIC 0x00020 /* MDI Control - RW */ +#define BPCTLI_IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ +#define BPCTLI_MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ + +#define BPCTLI_MDIC_DATA_MASK 0x0000FFFF +#define BPCTLI_MDIC_REG_MASK 0x001F0000 +#define BPCTLI_MDIC_REG_SHIFT 16 +#define BPCTLI_MDIC_PHY_MASK 0x03E00000 +#define BPCTLI_MDIC_PHY_SHIFT 21 +#define BPCTLI_MDIC_OP_WRITE 0x04000000 +#define BPCTLI_MDIC_OP_READ 0x08000000 +#define BPCTLI_MDIC_READY 0x10000000 +#define BPCTLI_MDIC_INT_EN 0x20000000 +#define BPCTLI_MDIC_ERROR 0x40000000 + +#define BPCTLI_SWFW_PHY0_SM 0x02 +#define BPCTLI_SWFW_PHY1_SM 0x04 + +#define BPCTLI_SW_FW_SYNC 0x05B5C /* Software-Firmware + * Synchronization - RW + */ + +#define BPCTLI_SWSM 0x05B50 /* SW Semaphore */ +#define BPCTLI_FWSM 0x05B54 /* FW Semaphore */ + +#define BPCTLI_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ +#define BPCTLI_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ +#define BPCTLI_MAX_PHY_MULTI_PAGE_REG 0xF +#define BPCTLI_GEN_POLL_TIMEOUT 640 + +/********************************************************/ + +/********************************************************/ +/* 10G INTERFACE ****************************************/ +/********************************************************/ + +#define BP10G_I2CCTL 0x28 + +/* I2CCTL Bit Masks */ +#define BP10G_I2C_CLK_IN 0x00000001 +#define BP10G_I2C_CLK_OUT 0x00000002 +#define BP10G_I2C_DATA_IN 0x00000004 +#define BP10G_I2C_DATA_OUT 0x00000008 + +#define BP10G_ESDP 0x20 + +#define BP10G_SDP0_DIR 0x100 +#define BP10G_SDP1_DIR 0x200 +#define BP10G_SDP3_DIR 0x800 +#define BP10G_SDP4_DIR BIT_12 +#define BP10G_SDP5_DIR 0x2000 +#define BP10G_SDP0_DATA 0x001 +#define BP10G_SDP1_DATA 0x002 +#define BP10G_SDP3_DATA 0x008 +#define BP10G_SDP4_DATA 0x010 +#define BP10G_SDP5_DATA 0x020 + +#define BP10G_SDP2_DIR 0x400 +#define BP10G_SDP2_DATA 0x4 + +#define BP10G_EODSDP 0x28 + +#define BP10G_SDP6_DATA_IN 0x001 +#define BP10G_SDP6_DATA_OUT 0x002 + +#define BP10G_SDP7_DATA_IN 0x004 +#define BP10G_SDP7_DATA_OUT 0x008 + +#define BP10G_MCLK_DATA_OUT BP10G_SDP7_DATA_OUT +#define BP10G_MDIO_DATA_OUT BP10G_SDP6_DATA_OUT +#define BP10G_MDIO_DATA_IN BP10G_SDP6_DATA_IN + +#define BP10G_MDIO_DATA /*BP10G_SDP5_DATA*/ BP10G_SDP3_DATA +#define BP10G_MDIO_DIR /*BP10G_SDP5_DIR*/ BP10G_SDP3_DATA + +/*#define BP10G_MCLK_DATA_OUT9 BP10G_I2C_CLK_OUT +#define BP10G_MDIO_DATA_OUT9 BP10G_I2C_DATA_OUT*/ + + /*#define BP10G_MCLK_DATA_OUT9*/ + /*BP10G_I2C_DATA_OUT */ +#define BP10G_MDIO_DATA_OUT9 BP10G_I2C_DATA_OUT /*BP10G_I2C_CLK_OUT */ + +/* VIA EOSDP ! */ +#define BP10G_MCLK_DATA_OUT9 BP10G_SDP4_DATA +#define BP10G_MCLK_DIR_OUT9 BP10G_SDP4_DIR + +/*#define BP10G_MDIO_DATA_IN9 BP10G_I2C_DATA_IN*/ + +#define BP10G_MDIO_DATA_IN9 BP10G_I2C_DATA_IN /*BP10G_I2C_CLK_IN */ + +#define BP540_MDIO_DATA /*BP10G_SDP5_DATA*/ BP10G_SDP0_DATA +#define BP540_MDIO_DIR /*BP10G_SDP5_DIR*/ BP10G_SDP0_DIR +#define BP540_MCLK_DATA BP10G_SDP2_DATA +#define BP540_MCLK_DIR BP10G_SDP2_DIR + +#define BP10G_WRITE_REG(a, reg, value) \ + (writel((value), (void *)(((a)->mem_map) + BP10G_##reg))) + +#define BP10G_READ_REG(a, reg) ( \ + readl((void *)((a)->mem_map) + BP10G_##reg)) + +/*****BROADCOM*******************************************/ + +#define BP10GB_MISC_REG_GPIO 0xa490 +#define BP10GB_GPIO3_P0 BIT_3 +#define BP10GB_GPIO3_P1 BIT_7 + +#define BP10GB_GPIO3_SET_P0 BIT_11 +#define BP10GB_GPIO3_CLR_P0 BIT_19 +#define BP10GB_GPIO3_OE_P0 BIT_27 + +#define BP10GB_GPIO3_SET_P1 BIT_15 +#define BP10GB_GPIO3_CLR_P1 BIT_23 +#define BP10GB_GPIO3_OE_P1 BIT_31 + +#define BP10GB_GPIO0_P1 0x10 +#define BP10GB_GPIO0_P0 0x1 +#define BP10GB_GPIO0_CLR_P0 0x10000 +#define BP10GB_GPIO0_CLR_P1 0x100000 +#define BP10GB_GPIO0_SET_P0 0x100 +#define BP10GB_GPIO0_SET_P1 0x1000 + +#define BP10GB_GPIO0_OE_P1 0x10000000 +#define BP10GB_GPIO0_OE_P0 0x1000000 + +#define BP10GB_MISC_REG_SPIO 0xa4fc +#define BP10GB_GPIO4_OE BIT_28 +#define BP10GB_GPIO5_OE BIT_29 +#define BP10GB_GPIO4_CLR BIT_20 +#define BP10GB_GPIO5_CLR BIT_21 +#define BP10GB_GPIO4_SET BIT_12 +#define BP10GB_GPIO5_SET BIT_13 +#define BP10GB_GPIO4 BIT_4 +#define BP10GB_GPIO5 BIT_5 + +#define BP10GB_MCLK_DIR BP10GB_GPIO5_OE +#define BP10GB_MDIO_DIR BP10GB_GPIO4_OE + +#define BP10GB_MCLK_DATA BP10GB_GPIO5 +#define BP10GB_MDIO_DATA BP10GB_GPIO4 + +#define BP10GB_MCLK_SET BP10GB_GPIO5_SET +#define BP10GB_MDIO_SET BP10GB_GPIO4_SET + +#define BP10GB_MCLK_CLR BP10GB_GPIO5_CLR +#define BP10GB_MDIO_CLR BP10GB_GPIO4_CLR + +#define BP10GB_WRITE_REG(a, reg, value) \ + (writel((value), (void *)(((a)->mem_map) + BP10GB_##reg))) + +#define BP10GB_READ_REG(a, reg) ( \ + readl((void *)((a)->mem_map) + BP10GB_##reg)) + +#endif diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c new file mode 100644 index 00000000000..765fce84d9d --- /dev/null +++ b/drivers/staging/silicom/bpctl_mod.c @@ -0,0 +1,7530 @@ +/******************************************************************************/ +/* */ +/* Bypass Control utility, Copyright (c) 2005-2011 Silicom */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* Copyright(c) 2007 - 2009, 2013 Intel Corporation. All rights reserved. */ +/* */ +/* */ +/******************************************************************************/ + +#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> +#include <linux/etherdevice.h> + +#include <linux/uaccess.h> /* for get_user and put_user */ +#include <linux/sched.h> +#include <linux/ethtool.h> +#include <linux/proc_fs.h> + +#include "bp_ioctl.h" +#include "bp_mod.h" +#include "bypass.h" +#include "libbp_sd.h" + +#define SUCCESS 0 +#define BP_MOD_VER "9.0.4" +#define BP_MOD_DESCR "Silicom Bypass-SD Control driver" +#define BP_SYNC_FLAG 1 + +static int major_num; + +MODULE_AUTHOR("Anna Lukin, annal@silicom.co.il"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(BP_MOD_DESCR); +MODULE_VERSION(BP_MOD_VER); +static spinlock_t bpvm_lock; + +#define unlock_bpctl() \ + up(&bpctl_sema); + +/* Media Types */ +enum bp_media_type { + BP_COPPER = 0, + BP_FIBER, + BP_CX4, + BP_NONE, +}; + +struct bypass_pfs_sd { + char dir_name[32]; + struct proc_dir_entry *bypass_entry; +}; + +struct bpctl_dev { + 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; + 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; + enum bp_media_type media_type; + int bp_tpl_flag; + struct timer_list bp_tpl_timer; + spinlock_t bypass_wr_lock; + int bp_10g; + int bp_10gb; + int bp_fiber5; + int bp_10g9; + int bp_i80; + int bp_540; + int (*hard_start_xmit_save) (struct sk_buff *skb, + struct net_device *dev); + const struct net_device_ops *old_ops; + struct net_device_ops new_ops; + int bp_self_test_flag; + char *bp_tx_data; + struct bypass_pfs_sd bypass_pfs_set; + +}; + +static struct bpctl_dev *bpctl_dev_arr; + +static struct semaphore bpctl_sema; +static int device_num; + +static int get_dev_idx(int ifindex); +static struct bpctl_dev *get_master_port_fn(struct bpctl_dev *pbpctl_dev); +static int disc_status(struct bpctl_dev *pbpctl_dev); +static int bypass_status(struct bpctl_dev *pbpctl_dev); +static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left); +static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev); +static void if_scan_init(void); + +static int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block); +static int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block); + +static int is_bypass_fn(struct bpctl_dev *pbpctl_dev); +static int get_dev_idx_bsf(int bus, int slot, int func); + +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 (!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_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + static struct bpctl_dev *pbpctl_dev, *pbpctl_dev_m; + int dev_num = 0, ret = 0, ret_d = 0, time_left = 0; + + /* 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; + + bypass_proc_remove_dev_sd(&bpctl_dev_arr[idx_dev]); + bypass_proc_create_dev_sd(&bpctl_dev_arr[idx_dev]); + 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) { + bypass_proc_remove_dev_sd(&bpctl_dev_arr + [idx_dev]); + 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) { + bypass_proc_remove_dev_sd(&bpctl_dev_arr + [idx_dev]); + bypass_proc_create_dev_sd(&bpctl_dev_arr + [idx_dev]); + + return NOTIFY_DONE; + + } + + } + return NOTIFY_DONE; + + } + + switch (event) { + + case NETDEV_CHANGE:{ + if (netif_carrier_ok(dev)) + return NOTIFY_DONE; + + dev_num = get_dev_idx(dev->ifindex); + if (dev_num == -1) + return NOTIFY_DONE; + + pbpctl_dev = &bpctl_dev_arr[dev_num]; + if (!pbpctl_dev) + return NOTIFY_DONE; + + if ((is_bypass_fn(pbpctl_dev)) == 1) + pbpctl_dev_m = pbpctl_dev; + else + pbpctl_dev_m = get_master_port_fn(pbpctl_dev); + if (!pbpctl_dev_m) + return NOTIFY_DONE; + ret = bypass_status(pbpctl_dev_m); + if (ret == 1) + printk("bpmod: %s is in the Bypass mode now", + dev->name); + ret_d = disc_status(pbpctl_dev_m); + if (ret_d == 1) + printk + ("bpmod: %s is in the Disconnect mode now", + dev->name); + if (ret || ret_d) { + wdt_timer(pbpctl_dev_m, &time_left); + if (time_left == -1) + printk("; WDT has expired"); + printk(".\n"); + + } + return NOTIFY_DONE; + + } + + default: + return NOTIFY_DONE; + + } + return NOTIFY_DONE; + +} + +static struct notifier_block bp_notifier_block = { + .notifier_call = bp_device_event, +}; + +static int is_bypass_fn(struct bpctl_dev *pbpctl_dev); +int wdt_time_left(struct bpctl_dev *pbpctl_dev); + +static void write_pulse(struct bpctl_dev *pbpctl_dev, + unsigned int ctrl_ext, + unsigned char value, unsigned char len) +{ + unsigned char ctrl_val = 0; + unsigned int i = len; + unsigned int ctrl = 0; + struct bpctl_dev *pbpctl_dev_c = NULL; + + if (pbpctl_dev->bp_i80) + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + if (pbpctl_dev->bp_540) + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + + if (pbpctl_dev->bp_10g9) { + pbpctl_dev_c = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_c) + return; + ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); + } + + while (i--) { + ctrl_val = (value >> i) & 0x1; + if (ctrl_val) { + if (pbpctl_dev->bp_10g9) { + + /* To start management : MCLK 1, MDIO 1, output */ + /* DATA 1 CLK 1 */ + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + ctrl_ext | + BP10G_MDIO_DATA_OUT9); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + (ctrl | BP10G_MCLK_DATA_OUT9 | + BP10G_MCLK_DIR_OUT9)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DATA5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5)); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80 + | + BPCTLI_CTRL_EXT_MDIO_DATA80)); + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, (ctrl | + BPCTLI_CTRL_EXT_MCLK_DIR80 + | + BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, (ctrl | + BP540_MDIO_DIR + | + BP540_MDIO_DATA + | + BP540_MCLK_DIR + | + BP540_MCLK_DATA)); + + } else if (pbpctl_dev->bp_10gb) { + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_SET | + BP10GB_MCLK_SET) & + ~(BP10GB_MCLK_DIR | + BP10GB_MDIO_DIR | + BP10GB_MDIO_CLR | + BP10GB_MCLK_CLR)); + + } else if (!pbpctl_dev->bp_10g) + /* To start management : MCLK 1, MDIO 1, output */ + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + (ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR | + BPCTLI_CTRL_EXT_MDIO_DIR | + BPCTLI_CTRL_EXT_MDIO_DATA | + BPCTLI_CTRL_EXT_MCLK_DATA)); + else { + + /* To start management : MCLK 1, MDIO 1, output*/ + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext | BP10G_MCLK_DATA_OUT + | BP10G_MDIO_DATA_OUT)); + + } + + usec_delay(PULSE_TIME); + if (pbpctl_dev->bp_10g9) { + + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MDIO_DATA_OUT9)&~(BP10G_MCLK_DATA_OUT9))); */ + /* DATA 1 CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + ctrl_ext | + BP10G_MDIO_DATA_OUT9); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + (ctrl | BP10G_MCLK_DIR_OUT9) & + ~BP10G_MCLK_DATA_OUT9); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 | + BPCTLI_CTRL_EXT_MDIO_DIR5 | + BPCTLI_CTRL_EXT_MDIO_DATA5) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA5))); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, (ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80 + | + BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | + BPCTLI_CTRL_EXT_MCLK_DIR80) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA80))); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + (ctrl | BP540_MDIO_DIR | + BP540_MDIO_DATA | + BP540_MCLK_DIR) & + ~(BP540_MCLK_DATA)); + + } else if (pbpctl_dev->bp_10gb) { + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_SET | + BP10GB_MCLK_CLR) & + ~(BP10GB_MCLK_DIR | + BP10GB_MDIO_DIR | + BP10GB_MDIO_CLR | + BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR | + BPCTLI_CTRL_EXT_MDIO_DIR | + BPCTLI_CTRL_EXT_MDIO_DATA) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + ((ctrl_ext | + BP10G_MDIO_DATA_OUT) & + ~(BP10G_MCLK_DATA_OUT))); + } + + usec_delay(PULSE_TIME); + + } else { + if (pbpctl_dev->bp_10g9) { + /* DATA 0 CLK 1 */ + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MCLK_DATA_OUT9)&~BP10G_MDIO_DATA_OUT9)); */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & + ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + (ctrl | BP10G_MCLK_DATA_OUT9 | + BP10G_MCLK_DIR_OUT9)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 | + BPCTLI_CTRL_EXT_MDIO_DIR5 | + BPCTLI_CTRL_EXT_MCLK_DATA5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5))); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA80))); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + (ctrl | + BPCTLI_CTRL_EXT_MCLK_DIR80 | + BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP540_MCLK_DIR | + BP540_MCLK_DATA | + BP540_MDIO_DIR) & + ~(BP540_MDIO_DATA))); + + } else if (pbpctl_dev->bp_10gb) { + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | + BP10GB_MCLK_SET) & + ~(BP10GB_MCLK_DIR | + BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | + BP10GB_MCLK_CLR)); + + } else if (!pbpctl_dev->bp_10g) + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR | + BPCTLI_CTRL_EXT_MDIO_DIR | + BPCTLI_CTRL_EXT_MCLK_DATA) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + ((ctrl_ext | + BP10G_MCLK_DATA_OUT) & + ~BP10G_MDIO_DATA_OUT)); + + } + usec_delay(PULSE_TIME); + if (pbpctl_dev->bp_10g9) { + /* DATA 0 CLK 0 */ + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & + ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~(BPCTLI_CTRL_EXT_MCLK_DATA5 + | + BPCTLI_CTRL_EXT_MDIO_DATA5))); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | + BPCTLI_CTRL_EXT_MCLK_DIR80) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA80))); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP540_MCLK_DIR | + BP540_MDIO_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + } else if (pbpctl_dev->bp_10gb) { + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | + BP10GB_MCLK_CLR) & + ~(BP10GB_MCLK_DIR | + BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | + BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR | + BPCTLI_CTRL_EXT_MDIO_DIR) & + ~(BPCTLI_CTRL_EXT_MCLK_DATA + | + BPCTLI_CTRL_EXT_MDIO_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | + BP10G_MDIO_DATA_OUT))); + } + + usec_delay(PULSE_TIME); + } + + } +} + +static int read_pulse(struct bpctl_dev *pbpctl_dev, unsigned int ctrl_ext, + unsigned char len) +{ + unsigned char ctrl_val = 0; + unsigned int i = len; + unsigned int ctrl = 0; + struct bpctl_dev *pbpctl_dev_c = NULL; + + if (pbpctl_dev->bp_i80) + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + if (pbpctl_dev->bp_540) + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + if (pbpctl_dev->bp_10g9) { + pbpctl_dev_c = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_c) + return -1; + ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); + } + + + while (i--) { + if (pbpctl_dev->bp_10g9) { + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MDIO_DATA_OUT9)&~BP10G_MCLK_DATA_OUT9)); */ + /* DATA ? CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DIR5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5))); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl_ext & + ~BPCTLI_CTRL_EXT_MDIO_DIR80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) + & ~(BPCTLI_CTRL_EXT_MCLK_DATA80))); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP540_MCLK_DIR) & + ~(BP540_MDIO_DIR | BP540_MCLK_DATA))); + + } else if (pbpctl_dev->bp_10gb) { + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_DIR | + BP10GB_MCLK_CLR) & ~(BP10GB_MCLK_DIR | + BP10GB_MDIO_CLR | + BP10GB_MDIO_SET | + BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DIR + | + BPCTLI_CTRL_EXT_MCLK_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, ((ctrl_ext | BP10G_MDIO_DATA_OUT) & ~BP10G_MCLK_DATA_OUT)); /* ? */ + /* printk("0x28=0x%x\n",BP10G_READ_REG(pbpctl_dev,EODSDP);); */ + + } + + usec_delay(PULSE_TIME); + if (pbpctl_dev->bp_10g9) { + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */ + /* DATA ? CLK 1 */ + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + (ctrl | BP10G_MCLK_DATA_OUT9 | + BP10G_MCLK_DIR_OUT9)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DIR5))); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl_ext & + ~(BPCTLI_CTRL_EXT_MDIO_DIR80))); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 | + BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP540_MCLK_DIR | + BP540_MCLK_DATA) & + ~(BP540_MDIO_DIR))); + + } else if (pbpctl_dev->bp_10gb) { + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_DIR | + BP10GB_MCLK_SET) & ~(BP10GB_MCLK_DIR | + BP10GB_MDIO_CLR | + BP10GB_MDIO_SET | + BP10GB_MCLK_CLR)); + + } else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MCLK_DATA) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DIR))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext | BP10G_MCLK_DATA_OUT | + BP10G_MDIO_DATA_OUT)); + + } + + if (pbpctl_dev->bp_10g9) + ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); + else if ((pbpctl_dev->bp_fiber5) || (pbpctl_dev->bp_i80)) + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + else if (pbpctl_dev->bp_540) + ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP); + else if (pbpctl_dev->bp_10gb) + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + else if (!pbpctl_dev->bp_10g) + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + else + ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); + + usec_delay(PULSE_TIME); + if (pbpctl_dev->bp_10g9) { + if (ctrl_ext & BP10G_MDIO_DATA_IN9) + ctrl_val |= 1 << i; + + } else if (pbpctl_dev->bp_fiber5) { + if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA5) + ctrl_val |= 1 << i; + } else if (pbpctl_dev->bp_i80) { + if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA80) + ctrl_val |= 1 << i; + } else if (pbpctl_dev->bp_540) { + if (ctrl_ext & BP540_MDIO_DATA) + ctrl_val |= 1 << i; + } else if (pbpctl_dev->bp_10gb) { + if (ctrl_ext & BP10GB_MDIO_DATA) + ctrl_val |= 1 << i; + + } else if (!pbpctl_dev->bp_10g) { + + if (ctrl_ext & BPCTLI_CTRL_EXT_MDIO_DATA) + ctrl_val |= 1 << i; + } else { + + if (ctrl_ext & BP10G_MDIO_DATA_IN) + ctrl_val |= 1 << i; + } + + } + + return ctrl_val; +} + +static void write_reg(struct bpctl_dev *pbpctl_dev, unsigned char value, + unsigned char addr) +{ + uint32_t ctrl_ext = 0, ctrl = 0; + struct bpctl_dev *pbpctl_dev_c = NULL; + unsigned long flags; + + if (pbpctl_dev->bp_10g9) { + pbpctl_dev_c = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_c) + return; + } + if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) && + (pbpctl_dev->bp_ext_ver < PXG4BPFI_VER)) + wdt_time_left(pbpctl_dev); + +#ifdef BP_SYNC_FLAG + spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 1); +#endif + if (pbpctl_dev->bp_10g9) { + + ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); + ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); + /* DATA 0 CLK 0 */ + /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5))); + } else if (pbpctl_dev->bp_i80) { + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & + ~BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + ctrl = ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | + BP540_MDIO_DIR | + BP540_MCLK_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) { + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA + | + BPCTLI_CTRL_EXT_MCLK_DATA))); + } else { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); + } + usec_delay(CMND_INTERVAL); + + /*send sync cmd */ + write_pulse(pbpctl_dev, ctrl_ext, SYNC_CMD_VAL, SYNC_CMD_LEN); + /*send wr cmd */ + write_pulse(pbpctl_dev, ctrl_ext, WR_CMD_VAL, WR_CMD_LEN); + write_pulse(pbpctl_dev, ctrl_ext, addr, ADDR_CMD_LEN); + + /*write data */ + write_pulse(pbpctl_dev, ctrl_ext, value, WR_DATA_LEN); + if (pbpctl_dev->bp_10g9) { + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + /* DATA 0 CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5))); + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & + ~BPCTLI_CTRL_EXT_MCLK_DATA80)); + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | + BP540_MDIO_DIR | + BP540_MCLK_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + } else if (pbpctl_dev->bp_10gb) { + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA + | + BPCTLI_CTRL_EXT_MCLK_DATA))); + else { + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); + + } + + usec_delay(CMND_INTERVAL * 4); + + if ((pbpctl_dev->wdt_status == WDT_STATUS_EN) && + (pbpctl_dev->bp_ext_ver < PXG4BPFI_VER) && (addr == CMND_REG_ADDR)) + pbpctl_dev->bypass_wdt_on_time = jiffies; +#ifdef BP_SYNC_FLAG + spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 0); +#endif + +} + +static void write_data(struct bpctl_dev *pbpctl_dev, unsigned char value) +{ + write_reg(pbpctl_dev, value, CMND_REG_ADDR); +} + +static int read_reg(struct bpctl_dev *pbpctl_dev, unsigned char addr) +{ + uint32_t ctrl_ext = 0, ctrl = 0, ctrl_value = 0; + struct bpctl_dev *pbpctl_dev_c = NULL; + +#ifdef BP_SYNC_FLAG + unsigned long flags; + + spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 1); +#endif + if (pbpctl_dev->bp_10g9) { + pbpctl_dev_c = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_c) + return -1; + } + + if (pbpctl_dev->bp_10g9) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); + ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); + + /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + /* DATA 0 CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5))); + } else if (pbpctl_dev->bp_i80) { + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & + ~BPCTLI_CTRL_EXT_MCLK_DATA80)); + } else if (pbpctl_dev->bp_540) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev, ESDP); + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | + BP540_MDIO_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_SET)); +#if 0 + + /*BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, (ctrl_ext | BP10GB_MCLK_DIR | BP10GB_MDIO_DIR| + BP10GB_MCLK_CLR|BP10GB_MDIO_CLR)); + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + printk("1reg=%x\n", ctrl_ext); */ + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, ((ctrl_ext | + BP10GB_MCLK_SET | + BP10GB_MDIO_CLR)) + & ~(BP10GB_MCLK_CLR | BP10GB_MDIO_SET | + BP10GB_MCLK_DIR | BP10GB_MDIO_DIR)); + + /* bnx2x_set_spio(pbpctl_dev, 5, MISC_REGISTERS_SPIO_OUTPUT_LOW); + bnx2x_set_spio(pbpctl_dev, 4, MISC_REGISTERS_SPIO_OUTPUT_LOW); + bnx2x_set_spio(pbpctl_dev, 4, MISC_REGISTERS_SPIO_INPUT_HI_Z); */ + + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + + printk("2reg=%x\n", ctrl_ext); + +#ifdef BP_SYNC_FLAG + spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 0); +#endif + + return 0; + +#endif + + } else if (!pbpctl_dev->bp_10g) { + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA + | + BPCTLI_CTRL_EXT_MCLK_DATA))); + } else { + + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); + + } + + usec_delay(CMND_INTERVAL); + + /*send sync cmd */ + write_pulse(pbpctl_dev, ctrl_ext, SYNC_CMD_VAL, SYNC_CMD_LEN); + /*send rd cmd */ + write_pulse(pbpctl_dev, ctrl_ext, RD_CMD_VAL, RD_CMD_LEN); + /*send addr */ + write_pulse(pbpctl_dev, ctrl_ext, addr, ADDR_CMD_LEN); + /*read data */ + /* zero */ + if (pbpctl_dev->bp_10g9) { + /* DATA 0 CLK 1 */ + /*BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext|BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9)); */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext | BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + (ctrl | BP10G_MCLK_DATA_OUT9 | + BP10G_MCLK_DIR_OUT9)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DATA5))); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl_ext & + ~(BPCTLI_CTRL_EXT_MDIO_DATA80 | + BPCTLI_CTRL_EXT_MDIO_DIR80))); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 | + BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + (((ctrl | BP540_MDIO_DIR | BP540_MCLK_DIR | + BP540_MCLK_DATA) & ~BP540_MDIO_DATA))); + + } else if (pbpctl_dev->bp_10gb) { + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_DIR | BP10GB_MCLK_SET) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_SET | + BP10GB_MDIO_CLR | BP10GB_MCLK_CLR)); + + } else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MCLK_DATA) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DIR + | + BPCTLI_CTRL_EXT_MDIO_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext | BP10G_MCLK_DATA_OUT | + BP10G_MDIO_DATA_OUT)); + + + } + usec_delay(PULSE_TIME); + + ctrl_value = read_pulse(pbpctl_dev, ctrl_ext, RD_DATA_LEN); + + if (pbpctl_dev->bp_10g9) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); + ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); + + /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + /* DATA 0 CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5))); + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & + ~BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | + BP540_MDIO_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA + | + BPCTLI_CTRL_EXT_MCLK_DATA))); + } else { + + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); + + } + + usec_delay(CMND_INTERVAL * 4); +#ifdef BP_SYNC_FLAG + spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 0); +#endif + + return ctrl_value; +} + +static int wdt_pulse(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0, ctrl = 0; + struct bpctl_dev *pbpctl_dev_c = NULL; + +#ifdef BP_SYNC_FLAG + unsigned long flags; + + spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); +#else + + if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) + return -1; +#endif + if (pbpctl_dev->bp_10g9) { + pbpctl_dev_c = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_c) + return -1; + } + + if (pbpctl_dev->bp_10g9) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev, I2CCTL); + ctrl = BP10G_READ_REG(pbpctl_dev_c, ESDP); + + /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + /* DATA 0 CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5))); + } else if (pbpctl_dev->bp_i80) { + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL); + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & + ~BPCTLI_CTRL_EXT_MCLK_DATA80)); + } else if (pbpctl_dev->bp_540) { + ctrl_ext = ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | + BP540_MDIO_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) { + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA + | + BPCTLI_CTRL_EXT_MCLK_DATA))); + } else { + + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + ctrl_ext = BP10G_READ_REG(pbpctl_dev, EODSDP); + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); + + } + if (pbpctl_dev->bp_10g9) { + /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, ((ctrl_ext|BP10G_MCLK_DATA_OUT9)&~BP10G_MDIO_DATA_OUT9)); */ + /* DATA 0 CLK 1 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + (ctrl | BP10G_MCLK_DATA_OUT9 | + BP10G_MCLK_DIR_OUT9)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5 + | + BPCTLI_CTRL_EXT_MCLK_DATA5) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA5))); + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + (ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80 | + BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | + BP540_MDIO_DIR | + BP540_MCLK_DIR | + BP540_MCLK_DATA) & + ~BP540_MDIO_DATA)); + + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_SET) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_CLR)); + + } else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR + | + BPCTLI_CTRL_EXT_MCLK_DATA) + & + ~ + (BPCTLI_CTRL_EXT_MDIO_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + ((ctrl_ext | BP10G_MCLK_DATA_OUT) & + ~BP10G_MDIO_DATA_OUT)); + + } + + usec_delay(WDT_INTERVAL); + if (pbpctl_dev->bp_10g9) { + /* BP10G_WRITE_REG(pbpctl_dev, I2CCTL, (ctrl_ext&~(BP10G_MCLK_DATA_OUT9|BP10G_MDIO_DATA_OUT9))); */ + /* DATA 0 CLK 0 */ + BP10G_WRITE_REG(pbpctl_dev, I2CCTL, + (ctrl_ext & ~BP10G_MDIO_DATA_OUT9)); + BP10G_WRITE_REG(pbpctl_dev_c, ESDP, + ((ctrl | BP10G_MCLK_DIR_OUT9) & + ~(BP10G_MCLK_DATA_OUT9))); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR5 + | + BPCTLI_CTRL_EXT_MDIO_DIR5) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA5 + | + BPCTLI_CTRL_EXT_MDIO_DATA5))); + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, ((ctrl_ext | + BPCTLI_CTRL_EXT_MDIO_DIR80) + & + ~BPCTLI_CTRL_EXT_MDIO_DATA80)); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | BPCTLI_CTRL_EXT_MCLK_DIR80) & + ~BPCTLI_CTRL_EXT_MCLK_DATA80)); + + } else if (pbpctl_dev->bp_540) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, ((ctrl | BP540_MCLK_DIR | + BP540_MDIO_DIR) & + ~(BP540_MDIO_DATA | + BP540_MCLK_DATA))); + + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = BP10GB_READ_REG(pbpctl_dev, MISC_REG_SPIO); + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_SPIO, + (ctrl_ext | BP10GB_MDIO_CLR | BP10GB_MCLK_CLR) + & ~(BP10GB_MCLK_DIR | BP10GB_MDIO_DIR | + BP10GB_MDIO_SET | BP10GB_MCLK_SET)); + + } else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR + | + BPCTLI_CTRL_EXT_MDIO_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA + | + BPCTLI_CTRL_EXT_MDIO_DATA))); + else { + + BP10G_WRITE_REG(pbpctl_dev, EODSDP, + (ctrl_ext & + ~(BP10G_MCLK_DATA_OUT | BP10G_MDIO_DATA_OUT))); + } + if ((pbpctl_dev->wdt_status == WDT_STATUS_EN)) + /*&& (pbpctl_dev->bp_ext_ver<PXG4BPFI_VER) */ + pbpctl_dev->bypass_wdt_on_time = jiffies; +#ifdef BP_SYNC_FLAG + spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); +#endif + usec_delay(CMND_INTERVAL * 4); + return 0; +} + +static void data_pulse(struct bpctl_dev *pbpctl_dev, unsigned char value) +{ + + uint32_t ctrl_ext = 0; +#ifdef BP_SYNC_FLAG + unsigned long flags; +#endif + wdt_time_left(pbpctl_dev); +#ifdef BP_SYNC_FLAG + spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 1); +#endif + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP7_DIR) & + ~(BPCTLI_CTRL_EXT_SDP6_DATA | + BPCTLI_CTRL_EXT_SDP7_DATA))); + + usec_delay(INIT_CMND_INTERVAL); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP7_DIR | + BPCTLI_CTRL_EXT_SDP6_DATA) & + ~ + (BPCTLI_CTRL_EXT_SDP7_DATA))); + usec_delay(INIT_CMND_INTERVAL); + + while (value) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP7_DIR | + BPCTLI_CTRL_EXT_SDP6_DATA | + BPCTLI_CTRL_EXT_SDP7_DATA); + usec_delay(PULSE_INTERVAL); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR + | + BPCTLI_CTRL_EXT_SDP7_DIR + | + BPCTLI_CTRL_EXT_SDP6_DATA) + & + ~BPCTLI_CTRL_EXT_SDP7_DATA)); + usec_delay(PULSE_INTERVAL); + value--; + + } + usec_delay(INIT_CMND_INTERVAL - PULSE_INTERVAL); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP7_DIR) & + ~(BPCTLI_CTRL_EXT_SDP6_DATA | + BPCTLI_CTRL_EXT_SDP7_DATA))); + usec_delay(WDT_TIME_CNT); + if (pbpctl_dev->wdt_status == WDT_STATUS_EN) + pbpctl_dev->bypass_wdt_on_time = jiffies; +#ifdef BP_SYNC_FLAG + spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); +#else + atomic_set(&pbpctl_dev->wdt_busy, 0); +#endif + +} + +static int send_wdt_pulse(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + +#ifdef BP_SYNC_FLAG + unsigned long flags; + + spin_lock_irqsave(&pbpctl_dev->bypass_wr_lock, flags); +#else + + if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) + return -1; +#endif + wdt_time_left(pbpctl_dev); + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | /* 1 */ + BPCTLI_CTRL_EXT_SDP7_DIR | + BPCTLI_CTRL_EXT_SDP7_DATA); + usec_delay(PULSE_INTERVAL); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | /* 0 */ + BPCTLI_CTRL_EXT_SDP7_DIR) & + ~BPCTLI_CTRL_EXT_SDP7_DATA)); + + usec_delay(PULSE_INTERVAL); + if (pbpctl_dev->wdt_status == WDT_STATUS_EN) + pbpctl_dev->bypass_wdt_on_time = jiffies; +#ifdef BP_SYNC_FLAG + spin_unlock_irqrestore(&pbpctl_dev->bypass_wr_lock, flags); +#endif + + return 0; +} + +static void send_bypass_clear_pulse(struct bpctl_dev *pbpctl_dev, + unsigned int value) +{ + uint32_t ctrl_ext = 0; + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | /* 0 */ + BPCTLI_CTRL_EXT_SDP6_DIR) & + ~BPCTLI_CTRL_EXT_SDP6_DATA)); + + usec_delay(PULSE_INTERVAL); + while (value) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | /* 1 */ + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP6_DATA); + usec_delay(PULSE_INTERVAL); + value--; + } + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | /* 0 */ + BPCTLI_CTRL_EXT_SDP6_DIR) & + ~BPCTLI_CTRL_EXT_SDP6_DATA)); + usec_delay(PULSE_INTERVAL); +} + +/* #endif OLD_FW */ +#ifdef BYPASS_DEBUG + +int pulse_set_fn(struct bpctl_dev *pbpctl_dev, unsigned int counter) +{ + uint32_t ctrl_ext = 0; + + if (!pbpctl_dev) + return -1; + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + write_pulse_1(pbpctl_dev, ctrl_ext, counter, counter); + + pbpctl_dev->bypass_wdt_status = 0; + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + write_pulse_1(pbpctl_dev, ctrl_ext, counter, counter); + } else { + wdt_time_left(pbpctl_dev); + if (pbpctl_dev->wdt_status == WDT_STATUS_EN) { + pbpctl_dev->wdt_status = 0; + data_pulse(pbpctl_dev, counter); + pbpctl_dev->wdt_status = WDT_STATUS_EN; + pbpctl_dev->bypass_wdt_on_time = jiffies; + + } else + data_pulse(pbpctl_dev, counter); + } + + return 0; +} + +int zero_set_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + printk("zero_set"); + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_MCLK_DIR) + & + ~ + (BPCTLI_CTRL_EXT_MCLK_DATA + | + BPCTLI_CTRL_EXT_MDIO_DIR + | + BPCTLI_CTRL_EXT_MDIO_DATA))); + + } + return 0; +} + +int pulse_get2_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0, ctrl_value = 0; + + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + printk("pulse_get_fn\n"); + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + ctrl_value = read_pulse_2(pbpctl_dev, ctrl_ext); + printk("read:%d\n", ctrl_value); + } + return ctrl_value; +} + +int pulse_get1_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0, ctrl_value = 0; + + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + + printk("pulse_get_fn\n"); + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + ctrl_value = read_pulse_1(pbpctl_dev, ctrl_ext); + printk("read:%d\n", ctrl_value); + } + return ctrl_value; +} + +int gpio6_set_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP6_DATA); + return 0; +} + +int gpio7_set_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ctrl_ext | + BPCTLI_CTRL_EXT_SDP7_DIR | + BPCTLI_CTRL_EXT_SDP7_DATA); + return 0; +} + +int gpio7_clear_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_SDP7_DIR) & + ~BPCTLI_CTRL_EXT_SDP7_DATA)); + return 0; +} + +int gpio6_clear_fn(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, ((ctrl_ext | + BPCTLI_CTRL_EXT_SDP6_DIR) & + ~BPCTLI_CTRL_EXT_SDP6_DATA)); + return 0; +} +#endif /*BYPASS_DEBUG */ + +static struct bpctl_dev *lookup_port(struct bpctl_dev *dev) +{ + struct bpctl_dev *p; + int n; + + for (n = 0, p = bpctl_dev_arr; n < device_num && p->pdev; n++) { + if (p->bus == dev->bus + && p->slot == dev->slot + && p->func == (dev->func ^ 1)) + return p; + } + return NULL; +} + +static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev) { + if (pbpctl_dev->func == 0 || pbpctl_dev->func == 2) + return lookup_port(pbpctl_dev); + } + return NULL; +} + +static struct bpctl_dev *get_master_port_fn(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev) { + if (pbpctl_dev->func == 1 || pbpctl_dev->func == 3) + return lookup_port(pbpctl_dev); + } + return NULL; +} + +/**************************************/ +/**************INTEL API***************/ +/**************************************/ + +static void write_data_port_int(struct bpctl_dev *pbpctl_dev, + unsigned char ctrl_value) +{ + uint32_t value; + + value = BPCTL_READ_REG(pbpctl_dev, CTRL); +/* Make SDP0 Pin Directonality to Output */ + value |= BPCTLI_CTRL_SDP0_DIR; + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, value); + + value &= ~BPCTLI_CTRL_SDP0_DATA; + value |= ((ctrl_value & 0x1) << BPCTLI_CTRL_SDP0_SHIFT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, value); + + value = (BPCTL_READ_REG(pbpctl_dev, CTRL_EXT)); +/* Make SDP2 Pin Directonality to Output */ + value |= BPCTLI_CTRL_EXT_SDP6_DIR; + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, value); + + value &= ~BPCTLI_CTRL_EXT_SDP6_DATA; + value |= (((ctrl_value & 0x2) >> 1) << BPCTLI_CTRL_EXT_SDP6_SHIFT); + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, value); + +} + +static int write_data_int(struct bpctl_dev *pbpctl_dev, unsigned char value) +{ + struct bpctl_dev *pbpctl_dev_b = NULL; + + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return -1; + atomic_set(&pbpctl_dev->wdt_busy, 1); + write_data_port_int(pbpctl_dev, value & 0x3); + write_data_port_int(pbpctl_dev_b, ((value & 0xc) >> 2)); + atomic_set(&pbpctl_dev->wdt_busy, 0); + + return 0; +} + +static int wdt_pulse_int(struct bpctl_dev *pbpctl_dev) +{ + + if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) + return -1; + + if ((write_data_int(pbpctl_dev, RESET_WDT_INT)) < 0) + return -1; + msec_delay_bp(CMND_INTERVAL_INT); + if ((write_data_int(pbpctl_dev, CMND_OFF_INT)) < 0) + return -1; + msec_delay_bp(CMND_INTERVAL_INT); + + if (pbpctl_dev->wdt_status == WDT_STATUS_EN) + pbpctl_dev->bypass_wdt_on_time = jiffies; + + return 0; +} + +/*************************************/ +/************* COMMANDS **************/ +/*************************************/ + +/* CMND_ON 0x4 (100)*/ +static int cmnd_on(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + return 0; + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) + write_data(pbpctl_dev, CMND_ON); + else + data_pulse(pbpctl_dev, CMND_ON); + ret = 0; + } + return ret; +} + +/* CMND_OFF 0x2 (10)*/ +static int cmnd_off(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, CMND_OFF_INT); + msec_delay_bp(CMND_INTERVAL_INT); + } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) + write_data(pbpctl_dev, CMND_OFF); + else + data_pulse(pbpctl_dev, CMND_OFF); + ret = 0; + } + return ret; +} + +/* BYPASS_ON (0xa)*/ +static int bypass_on(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & BP_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, BYPASS_ON_INT); + msec_delay_bp(BYPASS_DELAY_INT); + pbpctl_dev->bp_status_un = 0; + } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + write_data(pbpctl_dev, BYPASS_ON); + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) + msec_delay_bp(LATCH_DELAY); + } else + data_pulse(pbpctl_dev, BYPASS_ON); + ret = 0; + } + return ret; +} + +/* BYPASS_OFF (0x8 111)*/ +static int bypass_off(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & BP_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); + msec_delay_bp(BYPASS_DELAY_INT); + write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT); + msec_delay_bp(BYPASS_DELAY_INT); + pbpctl_dev->bp_status_un = 0; + } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + write_data(pbpctl_dev, BYPASS_OFF); + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) + msec_delay_bp(LATCH_DELAY); + } else + data_pulse(pbpctl_dev, BYPASS_OFF); + ret = 0; + } + return ret; +} + +/* TAP_OFF (0x9)*/ +static int tap_off(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if ((pbpctl_dev->bp_caps & TAP_CAP) + && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) { + write_data(pbpctl_dev, TAP_OFF); + msec_delay_bp(LATCH_DELAY); + ret = 0; + } + return ret; +} + +/* TAP_ON (0xb)*/ +static int tap_on(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if ((pbpctl_dev->bp_caps & TAP_CAP) + && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) { + write_data(pbpctl_dev, TAP_ON); + msec_delay_bp(LATCH_DELAY); + ret = 0; + } + return ret; +} + +/* DISC_OFF (0x9)*/ +static int disc_off(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) { + write_data(pbpctl_dev, DISC_OFF); + msec_delay_bp(LATCH_DELAY); + } else + ret = BP_NOT_CAP; + return ret; +} + +/* DISC_ON (0xb)*/ +static int disc_on(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) { + write_data(pbpctl_dev, /*DISC_ON */ 0x85); + msec_delay_bp(LATCH_DELAY); + } else + ret = BP_NOT_CAP; + return ret; +} + +/*TWO_PORT_LINK_HW_EN (0xe)*/ +static int tpl_hw_on(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0, ctrl = 0; + struct bpctl_dev *pbpctl_dev_b = NULL; + + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + + if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { + cmnd_on(pbpctl_dev); + write_data(pbpctl_dev, TPL2_ON); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + cmnd_off(pbpctl_dev); + return ret; + } + + if (TPL_IF_SERIES(pbpctl_dev->subdevice)) { + ctrl = BPCTL_READ_REG(pbpctl_dev_b, CTRL); + BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL, + ((ctrl | BPCTLI_CTRL_SWDPIO0) & + ~BPCTLI_CTRL_SWDPIN0)); + } else + ret = BP_NOT_CAP; + return ret; +} + +/*TWO_PORT_LINK_HW_DIS (0xc)*/ +static int tpl_hw_off(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0, ctrl = 0; + struct bpctl_dev *pbpctl_dev_b = NULL; + + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { + cmnd_on(pbpctl_dev); + write_data(pbpctl_dev, TPL2_OFF); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + cmnd_off(pbpctl_dev); + return ret; + } + if (TPL_IF_SERIES(pbpctl_dev->subdevice)) { + ctrl = BPCTL_READ_REG(pbpctl_dev_b, CTRL); + BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL, + (ctrl | BPCTLI_CTRL_SWDPIO0 | + BPCTLI_CTRL_SWDPIN0)); + } else + ret = BP_NOT_CAP; + return ret; +} + +/* WDT_OFF (0x6 110)*/ +static int wdt_off(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + bypass_off(pbpctl_dev); + else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) + write_data(pbpctl_dev, WDT_OFF); + else + data_pulse(pbpctl_dev, WDT_OFF); + pbpctl_dev->wdt_status = WDT_STATUS_DIS; + ret = 0; + } + return ret; +} + +/* WDT_ON (0x10)*/ + +/***Global***/ +static unsigned int + wdt_val_array[] = { 1000, 1500, 2000, 3000, 4000, 8000, 16000, 32000, 0 }; + +static int wdt_on(struct bpctl_dev *pbpctl_dev, unsigned int timeout) +{ + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + unsigned int pulse = 0, temp_value = 0, temp_cnt = 0; + pbpctl_dev->wdt_status = 0; + + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + for (; wdt_val_array[temp_cnt]; temp_cnt++) + if (timeout <= wdt_val_array[temp_cnt]) + break; + + if (!wdt_val_array[temp_cnt]) + temp_cnt--; + + timeout = wdt_val_array[temp_cnt]; + temp_cnt += 0x7; + + write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); + msec_delay_bp(BYPASS_DELAY_INT); + pbpctl_dev->bp_status_un = 0; + write_data_int(pbpctl_dev, temp_cnt); + pbpctl_dev->bypass_wdt_on_time = jiffies; + msec_delay_bp(CMND_INTERVAL_INT); + pbpctl_dev->bypass_timer_interval = timeout; + } else { + timeout = + (timeout < + TIMEOUT_UNIT ? TIMEOUT_UNIT : (timeout > + WDT_TIMEOUT_MAX ? + WDT_TIMEOUT_MAX : + timeout)); + temp_value = timeout / 100; + while ((temp_value >>= 1)) + temp_cnt++; + if (timeout > ((1 << temp_cnt) * 100)) + temp_cnt++; + pbpctl_dev->bypass_wdt_on_time = jiffies; + pulse = (WDT_ON | temp_cnt); + if (pbpctl_dev->bp_ext_ver == OLD_IF_VER) + data_pulse(pbpctl_dev, pulse); + else + write_data(pbpctl_dev, pulse); + pbpctl_dev->bypass_timer_interval = + (1 << temp_cnt) * 100; + } + pbpctl_dev->wdt_status = WDT_STATUS_EN; + return 0; + } + return BP_NOT_CAP; +} + +static void bp75_put_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev) +{ + u32 swsm; + + swsm = BPCTL_READ_REG(pbpctl_dev, SWSM); + + swsm &= ~(BPCTLI_SWSM_SMBI | BPCTLI_SWSM_SWESMBI); + + BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm); +} + +static s32 bp75_get_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev) +{ + u32 swsm; + s32 ret_val = 0; + s32 timeout = 8192 + 1; + s32 i = 0; + + /* Get the SW semaphore */ + while (i < timeout) { + swsm = BPCTL_READ_REG(pbpctl_dev, SWSM); + if (!(swsm & BPCTLI_SWSM_SMBI)) + break; + + usec_delay(50); + i++; + } + + if (i == timeout) { + printk + ("bpctl_mod: Driver can't access device - SMBI bit is set.\n"); + ret_val = -1; + goto out; + } + + /* Get the FW semaphore. */ + for (i = 0; i < timeout; i++) { + swsm = BPCTL_READ_REG(pbpctl_dev, SWSM); + BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm | BPCTLI_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ + if (BPCTL_READ_REG(pbpctl_dev, SWSM) & BPCTLI_SWSM_SWESMBI) + break; + + usec_delay(50); + } + + if (i == timeout) { + /* Release semaphores */ + bp75_put_hw_semaphore_generic(pbpctl_dev); + printk("bpctl_mod: Driver can't access the NVM\n"); + ret_val = -1; + goto out; + } + + out: + return ret_val; +} + +static void bp75_release_phy(struct bpctl_dev *pbpctl_dev) +{ + u16 mask = BPCTLI_SWFW_PHY0_SM; + u32 swfw_sync; + s32 ret_val; + + if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) + mask = BPCTLI_SWFW_PHY1_SM; + + do + ret_val = bp75_get_hw_semaphore_generic(pbpctl_dev); + while (ret_val != 0); + + swfw_sync = BPCTL_READ_REG(pbpctl_dev, SW_FW_SYNC); + swfw_sync &= ~mask; + BPCTL_WRITE_REG(pbpctl_dev, SW_FW_SYNC, swfw_sync); + + bp75_put_hw_semaphore_generic(pbpctl_dev); +} + +static s32 bp75_acquire_phy(struct bpctl_dev *pbpctl_dev) +{ + u16 mask = BPCTLI_SWFW_PHY0_SM; + u32 swfw_sync; + u32 swmask; + u32 fwmask; + s32 ret_val = 0; + s32 i = 0, timeout = 200; + + if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) + mask = BPCTLI_SWFW_PHY1_SM; + + swmask = mask; + fwmask = mask << 16; + + while (i < timeout) { + if (bp75_get_hw_semaphore_generic(pbpctl_dev)) { + ret_val = -1; + goto out; + } + + swfw_sync = BPCTL_READ_REG(pbpctl_dev, SW_FW_SYNC); + if (!(swfw_sync & (fwmask | swmask))) + break; + + bp75_put_hw_semaphore_generic(pbpctl_dev); + mdelay(5); + i++; + } + + if (i == timeout) { + printk + ("bpctl_mod: Driver can't access resource, SW_FW_SYNC timeout.\n"); + ret_val = -1; + goto out; + } + + swfw_sync |= swmask; + BPCTL_WRITE_REG(pbpctl_dev, SW_FW_SYNC, swfw_sync); + + bp75_put_hw_semaphore_generic(pbpctl_dev); + + out: + return ret_val; +} + +static s32 bp75_read_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, + u16 *data) +{ + u32 i, mdic = 0; + s32 ret_val = 0; + u32 phy_addr = 1; + + mdic = ((offset << BPCTLI_MDIC_REG_SHIFT) | + (phy_addr << BPCTLI_MDIC_PHY_SHIFT) | (BPCTLI_MDIC_OP_READ)); + + BPCTL_WRITE_REG(pbpctl_dev, MDIC, mdic); + + for (i = 0; i < (BPCTLI_GEN_POLL_TIMEOUT * 3); i++) { + usec_delay(50); + mdic = BPCTL_READ_REG(pbpctl_dev, MDIC); + if (mdic & BPCTLI_MDIC_READY) + break; + } + if (!(mdic & BPCTLI_MDIC_READY)) { + printk("bpctl_mod: MDI Read did not complete\n"); + ret_val = -1; + goto out; + } + if (mdic & BPCTLI_MDIC_ERROR) { + printk("bpctl_mod: MDI Error\n"); + ret_val = -1; + goto out; + } + *data = (u16) mdic; + + out: + return ret_val; +} + +static s32 bp75_write_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, + u16 data) +{ + u32 i, mdic = 0; + s32 ret_val = 0; + u32 phy_addr = 1; + + mdic = (((u32) data) | + (offset << BPCTLI_MDIC_REG_SHIFT) | + (phy_addr << BPCTLI_MDIC_PHY_SHIFT) | (BPCTLI_MDIC_OP_WRITE)); + + BPCTL_WRITE_REG(pbpctl_dev, MDIC, mdic); + + for (i = 0; i < (BPCTLI_GEN_POLL_TIMEOUT * 3); i++) { + usec_delay(50); + mdic = BPCTL_READ_REG(pbpctl_dev, MDIC); + if (mdic & BPCTLI_MDIC_READY) + break; + } + if (!(mdic & BPCTLI_MDIC_READY)) { + printk("bpctl_mod: MDI Write did not complete\n"); + ret_val = -1; + goto out; + } + if (mdic & BPCTLI_MDIC_ERROR) { + printk("bpctl_mod: MDI Error\n"); + ret_val = -1; + goto out; + } + + out: + return ret_val; +} + +static s32 bp75_read_phy_reg(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data) +{ + s32 ret_val = 0; + + ret_val = bp75_acquire_phy(pbpctl_dev); + if (ret_val) + goto out; + + if (offset > BPCTLI_MAX_PHY_MULTI_PAGE_REG) { + ret_val = bp75_write_phy_reg_mdic(pbpctl_dev, + BPCTLI_IGP01E1000_PHY_PAGE_SELECT, + (u16) offset); + if (ret_val) + goto release; + } + + ret_val = + bp75_read_phy_reg_mdic(pbpctl_dev, + BPCTLI_MAX_PHY_REG_ADDRESS & offset, data); + + release: + bp75_release_phy(pbpctl_dev); + out: + return ret_val; +} + +static s32 bp75_write_phy_reg(struct bpctl_dev *pbpctl_dev, u32 offset, u16 data) +{ + s32 ret_val = 0; + + ret_val = bp75_acquire_phy(pbpctl_dev); + if (ret_val) + goto out; + + if (offset > BPCTLI_MAX_PHY_MULTI_PAGE_REG) { + ret_val = bp75_write_phy_reg_mdic(pbpctl_dev, + BPCTLI_IGP01E1000_PHY_PAGE_SELECT, + (u16) offset); + if (ret_val) + goto release; + } + + ret_val = + bp75_write_phy_reg_mdic(pbpctl_dev, + BPCTLI_MAX_PHY_REG_ADDRESS & offset, data); + + release: + bp75_release_phy(pbpctl_dev); + + out: + return ret_val; +} + +/* SET_TX (non-Bypass command :)) */ +static int set_tx(struct bpctl_dev *pbpctl_dev, int tx_state) +{ + int ret = 0, ctrl = 0; + struct bpctl_dev *pbpctl_dev_m; + + if ((is_bypass_fn(pbpctl_dev)) == 1) + pbpctl_dev_m = pbpctl_dev; + else + pbpctl_dev_m = get_master_port_fn(pbpctl_dev); + if (pbpctl_dev_m == NULL) + return BP_NOT_CAP; + if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); + if (!tx_state) { + if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, + (ctrl | BP10G_SDP1_DIR | + BP10G_SDP1_DATA)); + + } else { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl | BPCTLI_CTRL_SDP1_DIR + | BPCTLI_CTRL_SWDPIN1)); + } + } else { + if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP10G_SDP1_DIR) & + ~BP10G_SDP1_DATA)); + } else { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl | + BPCTLI_CTRL_SDP1_DIR) & + ~BPCTLI_CTRL_SWDPIN1)); + } + return ret; + + } + } else if (pbpctl_dev->bp_caps & TX_CTL_CAP) { + if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) { + if (tx_state) { + uint16_t mii_reg; + ret = bp75_read_phy_reg(pbpctl_dev, + BPCTLI_PHY_CONTROL, + &mii_reg); + if (!ret) { + if (mii_reg & BPCTLI_MII_CR_POWER_DOWN) { + ret = + bp75_write_phy_reg + (pbpctl_dev, + BPCTLI_PHY_CONTROL, + mii_reg & + ~BPCTLI_MII_CR_POWER_DOWN); + } + } + } else { + uint16_t mii_reg; + ret = bp75_read_phy_reg(pbpctl_dev, + BPCTLI_PHY_CONTROL, + &mii_reg); + if (!ret) { + + mii_reg |= BPCTLI_MII_CR_POWER_DOWN; + ret = bp75_write_phy_reg(pbpctl_dev, + BPCTLI_PHY_CONTROL, + mii_reg); + } + } + + } + if (pbpctl_dev->bp_fiber5) + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + else if (pbpctl_dev->bp_10gb) + ctrl = BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); + else if (!pbpctl_dev->bp_10g) + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); + else + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + + if (!tx_state) + if (pbpctl_dev->bp_10g9) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + (ctrl | BP10G_SDP3_DATA | + BP10G_SDP3_DIR)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + (ctrl | + BPCTLI_CTRL_EXT_SDP6_DIR | + BPCTLI_CTRL_EXT_SDP6_DATA)); + + } else if (pbpctl_dev->bp_10gb) { + if ((pbpctl_dev->func == 1) + || (pbpctl_dev->func == 3)) + BP10GB_WRITE_REG(pbpctl_dev, + MISC_REG_GPIO, + (ctrl | + BP10GB_GPIO0_SET_P1) & + ~(BP10GB_GPIO0_CLR_P1 | + BP10GB_GPIO0_OE_P1)); + else + BP10GB_WRITE_REG(pbpctl_dev, + MISC_REG_GPIO, + (ctrl | + BP10GB_GPIO0_OE_P0 | + BP10GB_GPIO0_SET_P0)); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl | BPCTLI_CTRL_SDP1_DIR + | BPCTLI_CTRL_SWDPIN1)); + + } else if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, + (ctrl | BP10G_SDP1_DIR | + BP10G_SDP1_DATA)); + + } + + else if (!pbpctl_dev->bp_10g) + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl | BPCTLI_CTRL_SWDPIO0 | + BPCTLI_CTRL_SWDPIN0)); + + else + BP10G_WRITE_REG(pbpctl_dev, ESDP, + (ctrl | BP10G_SDP0_DATA | + BP10G_SDP0_DIR)); + + else { + if (pbpctl_dev->bp_10g9) { + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP10G_SDP3_DIR) & + ~BP10G_SDP3_DATA)); + + } else if (pbpctl_dev->bp_fiber5) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL_EXT, + ((ctrl | + BPCTLI_CTRL_EXT_SDP6_DIR) & + ~BPCTLI_CTRL_EXT_SDP6_DATA)); + + } else if (pbpctl_dev->bp_10gb) { + if ((bpctl_dev_arr->func == 1) + || (bpctl_dev_arr->func == 3)) + BP10GB_WRITE_REG(pbpctl_dev, + MISC_REG_GPIO, + (ctrl | + BP10GB_GPIO0_CLR_P1) & + ~(BP10GB_GPIO0_SET_P1 | + BP10GB_GPIO0_OE_P1)); + else + BP10GB_WRITE_REG(pbpctl_dev, + MISC_REG_GPIO, + (ctrl | + BP10GB_GPIO0_OE_P0 | + BP10GB_GPIO0_CLR_P0)); + + } else if (pbpctl_dev->bp_i80) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl | + BPCTLI_CTRL_SDP1_DIR) & + ~BPCTLI_CTRL_SWDPIN1)); + } else if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP10G_SDP1_DIR) & + ~BP10G_SDP1_DATA)); + } + + else if (!pbpctl_dev->bp_10g) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + ((ctrl | BPCTLI_CTRL_SWDPIO0) + & ~BPCTLI_CTRL_SWDPIN0)); + if (!PEGF_IF_SERIES(pbpctl_dev->subdevice)) { + BPCTL_BP_WRITE_REG(pbpctl_dev, CTRL, + (ctrl & + ~ + (BPCTLI_CTRL_SDP0_DATA + | + BPCTLI_CTRL_SDP0_DIR))); + } + } else + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP10G_SDP0_DIR) & + ~BP10G_SDP0_DATA)); + + } + + } else + ret = BP_NOT_CAP; + return ret; + +} + +/* SET_FORCE_LINK (non-Bypass command :)) */ +static int set_bp_force_link(struct bpctl_dev *pbpctl_dev, int tx_state) +{ + int ret = 0, ctrl = 0; + + if (DBI_IF_SERIES(pbpctl_dev->subdevice)) { + + if ((pbpctl_dev->bp_10g) || (pbpctl_dev->bp_10g9)) { + + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); + if (!tx_state) + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ctrl & ~BP10G_SDP1_DIR); + else + BP10G_WRITE_REG(pbpctl_dev, ESDP, + ((ctrl | BP10G_SDP1_DIR) & + ~BP10G_SDP1_DATA)); + return ret; + } + + } + return BP_NOT_CAP; +} + +/*RESET_CONT 0x20 */ +static int reset_cont(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + return BP_NOT_CAP; + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) + write_data(pbpctl_dev, RESET_CONT); + else + data_pulse(pbpctl_dev, RESET_CONT); + ret = 0; + } + return ret; +} + +/*DIS_BYPASS_CAP 0x22 */ +static int dis_bypass_cap(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & BP_DIS_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); + msec_delay_bp(BYPASS_DELAY_INT); + } else { + write_data(pbpctl_dev, BYPASS_OFF); + msec_delay_bp(LATCH_DELAY); + write_data(pbpctl_dev, DIS_BYPASS_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + } + return 0; + } + return BP_NOT_CAP; +} + +/*EN_BYPASS_CAP 0x24 */ +static int en_bypass_cap(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & BP_DIS_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT); + msec_delay_bp(BYPASS_DELAY_INT); + } else { + write_data(pbpctl_dev, EN_BYPASS_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + } + return 0; + } + return BP_NOT_CAP; +} + +/* BYPASS_STATE_PWRON 0x26*/ +static int bypass_state_pwron(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { + write_data(pbpctl_dev, BYPASS_STATE_PWRON); + if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) + msec_delay_bp(DFLT_PWRON_DELAY); + else + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/* NORMAL_STATE_PWRON 0x28*/ +static int normal_state_pwron(struct bpctl_dev *pbpctl_dev) +{ + if ((pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) + || (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)) { + write_data(pbpctl_dev, NORMAL_STATE_PWRON); + if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) + msec_delay_bp(DFLT_PWRON_DELAY); + else + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/* BYPASS_STATE_PWROFF 0x27*/ +static int bypass_state_pwroff(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP) { + write_data(pbpctl_dev, BYPASS_STATE_PWROFF); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/* NORMAL_STATE_PWROFF 0x29*/ +static int normal_state_pwroff(struct bpctl_dev *pbpctl_dev) +{ + if ((pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) { + write_data(pbpctl_dev, NORMAL_STATE_PWROFF); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/*TAP_STATE_PWRON 0x2a*/ +static int tap_state_pwron(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { + write_data(pbpctl_dev, TAP_STATE_PWRON); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/*DIS_TAP_CAP 0x2c*/ +static int dis_tap_cap(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { + write_data(pbpctl_dev, DIS_TAP_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/*EN_TAP_CAP 0x2e*/ +static int en_tap_cap(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { + write_data(pbpctl_dev, EN_TAP_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + return 0; + } + return BP_NOT_CAP; +} + +/*DISC_STATE_PWRON 0x2a*/ +static int disc_state_pwron(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + write_data(pbpctl_dev, DISC_STATE_PWRON); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + return BP_OK; + } + } + return BP_NOT_CAP; +} + +/*DIS_DISC_CAP 0x2c*/ +static int dis_disc_cap(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + write_data(pbpctl_dev, DIS_DISC_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + return BP_OK; + } + } + return BP_NOT_CAP; +} + +/*EN_TAP_CAP 0x2e*/ +static int en_disc_cap(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + write_data(pbpctl_dev, EN_DISC_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + return BP_OK; + } + } + return BP_NOT_CAP; +} + +static int std_nic_on(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & STD_NIC_CAP) { + + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, DIS_BYPASS_CAP_INT); + msec_delay_bp(BYPASS_DELAY_INT); + pbpctl_dev->bp_status_un = 0; + return BP_OK; + } + + if (pbpctl_dev->bp_ext_ver >= 0x8) { + write_data(pbpctl_dev, STD_NIC_ON); + msec_delay_bp(BYPASS_CAP_DELAY); + return BP_OK; + + } + + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + wdt_off(pbpctl_dev); + + if (pbpctl_dev->bp_caps & BP_CAP) { + write_data(pbpctl_dev, BYPASS_OFF); + msec_delay_bp(LATCH_DELAY); + } + + if (pbpctl_dev->bp_caps & TAP_CAP) { + write_data(pbpctl_dev, TAP_OFF); + msec_delay_bp(LATCH_DELAY); + } + + write_data(pbpctl_dev, NORMAL_STATE_PWRON); + if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) + msec_delay_bp(DFLT_PWRON_DELAY); + else + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + + if (pbpctl_dev->bp_caps & BP_DIS_CAP) { + write_data(pbpctl_dev, DIS_BYPASS_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + } + + if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { + write_data(pbpctl_dev, DIS_TAP_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + + } + return 0; + } + } + return BP_NOT_CAP; +} + +static int std_nic_off(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & STD_NIC_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + write_data_int(pbpctl_dev, PWROFF_BYPASS_ON_INT); + msec_delay_bp(BYPASS_DELAY_INT); + return BP_OK; + } + if (pbpctl_dev->bp_ext_ver >= 0x8) { + write_data(pbpctl_dev, STD_NIC_OFF); + msec_delay_bp(BYPASS_CAP_DELAY); + return BP_OK; + + } + + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + + if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { + write_data(pbpctl_dev, TAP_STATE_PWRON); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + } + + if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { + write_data(pbpctl_dev, BYPASS_STATE_PWRON); + if (pbpctl_dev->bp_ext_ver > PXG2BPI_VER) + msec_delay_bp(LATCH_DELAY + + EEPROM_WR_DELAY); + else + msec_delay_bp(DFLT_PWRON_DELAY); + } + + if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { + write_data(pbpctl_dev, EN_TAP_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + } + if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { + write_data(pbpctl_dev, EN_DISC_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + } + + if (pbpctl_dev->bp_caps & BP_DIS_CAP) { + write_data(pbpctl_dev, EN_BYPASS_CAP); + msec_delay_bp(BYPASS_CAP_DELAY); + } + + return 0; + } + } + return BP_NOT_CAP; +} + +int wdt_time_left(struct bpctl_dev *pbpctl_dev) +{ + + /* unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; */ + unsigned long curr_time = jiffies, delta_time = 0, wdt_on_time = + pbpctl_dev->bypass_wdt_on_time, delta_time_msec = 0; + int time_left = 0; + + switch (pbpctl_dev->wdt_status) { + case WDT_STATUS_DIS: + time_left = 0; + break; + case WDT_STATUS_EN: + delta_time = + (curr_time >= + wdt_on_time) ? (curr_time - wdt_on_time) : (~wdt_on_time + + curr_time); + delta_time_msec = jiffies_to_msecs(delta_time); + time_left = pbpctl_dev->bypass_timer_interval - delta_time_msec; + if (time_left < 0) { + time_left = -1; + pbpctl_dev->wdt_status = WDT_STATUS_EXP; + } + break; + case WDT_STATUS_EXP: + time_left = -1; + break; + } + + return time_left; +} + +static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left) +{ + int ret = 0; + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + { + if (pbpctl_dev->wdt_status == WDT_STATUS_UNKNOWN) + ret = BP_NOT_CAP; + else + *time_left = wdt_time_left(pbpctl_dev); + } + + } else + ret = BP_NOT_CAP; + return ret; +} + +static int wdt_timer_reload(struct bpctl_dev *pbpctl_dev) +{ + + int ret = 0; + + if ((pbpctl_dev->bp_caps & WD_CTL_CAP) && + (pbpctl_dev->wdt_status != WDT_STATUS_UNKNOWN)) { + if (pbpctl_dev->wdt_status == WDT_STATUS_DIS) + return 0; + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) + ret = wdt_pulse(pbpctl_dev); + else if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + ret = wdt_pulse_int(pbpctl_dev); + else + ret = send_wdt_pulse(pbpctl_dev); + /* if (ret==-1) + mod_timer(&pbpctl_dev->bp_timer, jiffies+1);*/ + return 1; + } + return BP_NOT_CAP; +} + +static void wd_reset_timer(unsigned long param) +{ + struct bpctl_dev *pbpctl_dev = (struct bpctl_dev *) param; +#ifdef BP_SELF_TEST + struct sk_buff *skb_tmp; +#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; + } +#ifdef BP_SELF_TEST + + if (pbpctl_dev->bp_self_test_flag == 1) { + skb_tmp = dev_alloc_skb(BPTEST_DATA_LEN + 2); + if ((skb_tmp) && (pbpctl_dev->ndev) && (pbpctl_dev->bp_tx_data)) { + memcpy(skb_put(skb_tmp, BPTEST_DATA_LEN), + pbpctl_dev->bp_tx_data, BPTEST_DATA_LEN); + skb_tmp->dev = pbpctl_dev->ndev; + skb_tmp->protocol = + eth_type_trans(skb_tmp, pbpctl_dev->ndev); + skb_tmp->ip_summed = CHECKSUM_UNNECESSARY; + netif_receive_skb(skb_tmp); + goto bp_timer_reload; + return; + } + } +#endif + + wdt_timer_reload(pbpctl_dev); +#ifdef BP_SELF_TEST + bp_timer_reload: +#endif + if (pbpctl_dev->reset_time) { + mod_timer(&pbpctl_dev->bp_timer, + jiffies + (HZ * pbpctl_dev->reset_time) / 1000); + } +} + +/*WAIT_AT_PWRUP 0x80 */ +static int bp_wait_at_pwup_en(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { + write_data(pbpctl_dev, BP_WAIT_AT_PWUP_EN); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + + return BP_OK; + } + } + return BP_NOT_CAP; +} + +/*DIS_WAIT_AT_PWRUP 0x81 */ +static int bp_wait_at_pwup_dis(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { + write_data(pbpctl_dev, BP_WAIT_AT_PWUP_DIS); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + + return BP_OK; + } + } + return BP_NOT_CAP; +} + +/*EN_HW_RESET 0x82 */ + +static int bp_hw_reset_en(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { + write_data(pbpctl_dev, BP_HW_RESET_EN); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + + return BP_OK; + } + } + return BP_NOT_CAP; +} + +/*DIS_HW_RESET 0x83 */ + +static int bp_hw_reset_dis(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { + write_data(pbpctl_dev, BP_HW_RESET_DIS); + msec_delay_bp(LATCH_DELAY + EEPROM_WR_DELAY); + + return BP_OK; + } + } + return BP_NOT_CAP; +} + + +static int wdt_exp_mode(struct bpctl_dev *pbpctl_dev, int mode) +{ + uint32_t status_reg = 0, status_reg1 = 0; + + if ((pbpctl_dev->bp_caps & (TAP_STATUS_CAP | DISC_CAP)) && + (pbpctl_dev->bp_caps & BP_CAP)) { + if (pbpctl_dev->bp_ext_ver >= PXE2TBPI_VER) { + + if ((pbpctl_dev->bp_ext_ver >= 0x8) && + (mode == 2) && (pbpctl_dev->bp_caps & DISC_CAP)) { + status_reg1 = + read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR); + if (!(status_reg1 & WDTE_DISC_BPN_MASK)) + write_reg(pbpctl_dev, + status_reg1 | + WDTE_DISC_BPN_MASK, + STATUS_DISC_REG_ADDR); + return BP_OK; + } + } + status_reg = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); + + if ((mode == 0) && (pbpctl_dev->bp_caps & BP_CAP)) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + status_reg1 = + read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR); + if (status_reg1 & WDTE_DISC_BPN_MASK) + write_reg(pbpctl_dev, + status_reg1 & + ~WDTE_DISC_BPN_MASK, + STATUS_DISC_REG_ADDR); + } + if (status_reg & WDTE_TAP_BPN_MASK) + write_reg(pbpctl_dev, + status_reg & ~WDTE_TAP_BPN_MASK, + STATUS_TAP_REG_ADDR); + return BP_OK; + + } else if ((mode == 1) && (pbpctl_dev->bp_caps & TAP_CAP)) { + if (!(status_reg & WDTE_TAP_BPN_MASK)) + write_reg(pbpctl_dev, + status_reg | WDTE_TAP_BPN_MASK, + STATUS_TAP_REG_ADDR); + /*else return BP_NOT_CAP; */ + return BP_OK; + } + + } + return BP_NOT_CAP; +} + +static int bypass_fw_ver(struct bpctl_dev *pbpctl_dev) +{ + if (is_bypass_fn(pbpctl_dev)) + return read_reg(pbpctl_dev, VER_REG_ADDR); + else + return BP_NOT_CAP; +} + +static int bypass_sign_check(struct bpctl_dev *pbpctl_dev) +{ + + if (is_bypass_fn(pbpctl_dev)) + return (((read_reg(pbpctl_dev, PIC_SIGN_REG_ADDR)) == + PIC_SIGN_VALUE) ? 1 : 0); + else + return BP_NOT_CAP; +} + +static int tx_status(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl = 0; + struct bpctl_dev *pbpctl_dev_m; + + if ((is_bypass_fn(pbpctl_dev)) == 1) + pbpctl_dev_m = pbpctl_dev; + else + pbpctl_dev_m = get_master_port_fn(pbpctl_dev); + if (pbpctl_dev_m == NULL) + return BP_NOT_CAP; + if (pbpctl_dev_m->bp_caps_ex & DISC_PORT_CAP_EX) { + + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); + if (pbpctl_dev->bp_i80) + return ((ctrl & BPCTLI_CTRL_SWDPIN1) != 0 ? 0 : 1); + if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + + return ((ctrl & BP10G_SDP1_DATA) != 0 ? 0 : 1); + } + + } + + if (pbpctl_dev->bp_caps & TX_CTL_CAP) { + if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) { + uint16_t mii_reg; + if (! + (bp75_read_phy_reg + (pbpctl_dev, BPCTLI_PHY_CONTROL, &mii_reg))) { + if (mii_reg & BPCTLI_MII_CR_POWER_DOWN) + return 0; + + else + return 1; + } + return -1; + } + + if (pbpctl_dev->bp_10g9) { + return ((BP10G_READ_REG(pbpctl_dev, ESDP) & + BP10G_SDP3_DATA) != 0 ? 0 : 1); + + } else if (pbpctl_dev->bp_fiber5) { + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + if (ctrl & BPCTLI_CTRL_EXT_SDP6_DATA) + return 0; + return 1; + } else if (pbpctl_dev->bp_10gb) { + ctrl = BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO, + (ctrl | BP10GB_GPIO0_OE_P1) & + ~(BP10GB_GPIO0_SET_P1 | + BP10GB_GPIO0_CLR_P1)); + + if ((pbpctl_dev->func == 1) || (pbpctl_dev->func == 3)) + return (((BP10GB_READ_REG + (pbpctl_dev, + MISC_REG_GPIO)) & BP10GB_GPIO0_P1) != + 0 ? 0 : 1); + else + return (((BP10GB_READ_REG + (pbpctl_dev, + MISC_REG_GPIO)) & BP10GB_GPIO0_P0) != + 0 ? 0 : 1); + } + + if (!pbpctl_dev->bp_10g) { + + ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL); + if (pbpctl_dev->bp_i80) + return ((ctrl & BPCTLI_CTRL_SWDPIN1) != + 0 ? 0 : 1); + if (pbpctl_dev->bp_540) { + ctrl = BP10G_READ_REG(pbpctl_dev, ESDP); + + return ((ctrl & BP10G_SDP1_DATA) != 0 ? 0 : 1); + } + + return ((ctrl & BPCTLI_CTRL_SWDPIN0) != 0 ? 0 : 1); + } else + return ((BP10G_READ_REG(pbpctl_dev, ESDP) & + BP10G_SDP0_DATA) != 0 ? 0 : 1); + + } + return BP_NOT_CAP; +} + +static int bp_force_link_status(struct bpctl_dev *pbpctl_dev) +{ + + if (DBI_IF_SERIES(pbpctl_dev->subdevice)) { + + if ((pbpctl_dev->bp_10g) || (pbpctl_dev->bp_10g9)) { + return ((BP10G_READ_REG(pbpctl_dev, ESDP) & + BP10G_SDP1_DIR) != 0 ? 1 : 0); + + } + } + return BP_NOT_CAP; +} + +static int bypass_from_last_read(struct bpctl_dev *pbpctl_dev) +{ + uint32_t ctrl_ext = 0; + struct bpctl_dev *pbpctl_dev_b = NULL; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + ctrl_ext = BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT); + BPCTL_BP_WRITE_REG(pbpctl_dev_b, CTRL_EXT, + (ctrl_ext & ~BPCTLI_CTRL_EXT_SDP7_DIR)); + ctrl_ext = BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT); + if (ctrl_ext & BPCTLI_CTRL_EXT_SDP7_DATA) + return 0; + return 1; + } else + return BP_NOT_CAP; +} + +static int bypass_status_clear(struct bpctl_dev *pbpctl_dev) +{ + struct bpctl_dev *pbpctl_dev_b = NULL; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + send_bypass_clear_pulse(pbpctl_dev_b, 1); + return 0; + } else + return BP_NOT_CAP; +} + +static int bypass_flag_status(struct bpctl_dev *pbpctl_dev) +{ + + if ((pbpctl_dev->bp_caps & BP_CAP)) { + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & + BYPASS_FLAG_MASK) == + BYPASS_FLAG_MASK) ? 1 : 0); + } + } + return BP_NOT_CAP; +} + +static int bypass_flag_status_clear(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & BP_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + uint32_t status_reg = 0; + status_reg = read_reg(pbpctl_dev, STATUS_REG_ADDR); + write_reg(pbpctl_dev, status_reg & ~BYPASS_FLAG_MASK, + STATUS_REG_ADDR); + return 0; + } + } + return BP_NOT_CAP; +} + +static int bypass_change_status(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & BP_STATUS_CHANGE_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + ret = bypass_flag_status(pbpctl_dev); + bypass_flag_status_clear(pbpctl_dev); + } else if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + ret = bypass_flag_status(pbpctl_dev); + bypass_flag_status_clear(pbpctl_dev); + } else { + ret = bypass_from_last_read(pbpctl_dev); + bypass_status_clear(pbpctl_dev); + } + } + return ret; +} + +static int bypass_status(struct bpctl_dev *pbpctl_dev) +{ + u32 ctrl_ext = 0; + + if (pbpctl_dev->bp_caps & BP_CAP) { + + struct bpctl_dev *pbpctl_dev_b = NULL; + + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + + if (!pbpctl_dev->bp_status_un) + return (((BPCTL_READ_REG + (pbpctl_dev_b, + CTRL_EXT)) & + BPCTLI_CTRL_EXT_SDP7_DATA) != + 0 ? 1 : 0); + else + return BP_NOT_CAP; + } + if (pbpctl_dev->bp_ext_ver >= 0x8) { + + if (pbpctl_dev->bp_10g9) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL); + BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL, + (ctrl_ext | BP10G_I2C_CLK_OUT)); + return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) & + BP10G_I2C_CLK_IN) != 0 ? 0 : 1); + + } else if (pbpctl_dev->bp_540) { + return (((BP10G_READ_REG(pbpctl_dev_b, ESDP)) & + BP10G_SDP0_DATA) != 0 ? 0 : 1); + } + + else if ((pbpctl_dev->bp_fiber5) + || (pbpctl_dev->bp_i80)) { + return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & + BPCTLI_CTRL_SWDPIN0) != 0 ? 0 : 1); + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = + BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO, + (ctrl_ext | BP10GB_GPIO3_OE_P0) + & ~(BP10GB_GPIO3_SET_P0 | + BP10GB_GPIO3_CLR_P0)); + + return (((BP10GB_READ_REG + (pbpctl_dev, + MISC_REG_GPIO)) & BP10GB_GPIO3_P0) != + 0 ? 0 : 1); + } + + else if (!pbpctl_dev->bp_10g) + return (((BPCTL_READ_REG + (pbpctl_dev_b, + CTRL_EXT)) & + BPCTLI_CTRL_EXT_SDP7_DATA) != + 0 ? 0 : 1); + + else { + ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP); + BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, + (ctrl_ext | + BP10G_SDP7_DATA_OUT)); + return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) & + BP10G_SDP7_DATA_IN) != 0 ? 0 : 1); + } + + } else if (pbpctl_dev->media_type == BP_COPPER) { + + return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & + BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); + } else { + if ((bypass_status_clear(pbpctl_dev)) >= 0) + return bypass_from_last_read(pbpctl_dev); + } + + } + return BP_NOT_CAP; +} + +static int default_pwron_status(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + return ((((read_reg + (pbpctl_dev, + STATUS_REG_ADDR)) & DFLT_PWRON_MASK) + == DFLT_PWRON_MASK) ? 0 : 1); + } + } /*else if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&& + (pbpctl_dev->bp_caps&BP_PWUP_ON_CAP)) + return 1; */ + } + return BP_NOT_CAP; +} + +static int default_pwroff_status(struct bpctl_dev *pbpctl_dev) +{ + + /*if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&& + (pbpctl_dev->bp_caps&BP_PWOFF_ON_CAP)) + return 1; */ + if ((pbpctl_dev->bp_caps & SW_CTL_CAP) + && (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) { + return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & + DFLT_PWROFF_MASK) == DFLT_PWROFF_MASK) ? 0 : 1); + } + return BP_NOT_CAP; +} + +static int dis_bypass_cap_status(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & BP_DIS_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + return ((((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & + DIS_BYPASS_CAP_MASK) == + DIS_BYPASS_CAP_MASK) ? 1 : 0); + } + } + return BP_NOT_CAP; +} + +static int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout) +{ + int ret = 0; + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + if ((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & + WDT_EN_MASK) { + u8 wdt_val; + wdt_val = read_reg(pbpctl_dev, WDT_REG_ADDR); + *timeout = (1 << wdt_val) * 100; + } else + *timeout = 0; + } else { + int curr_wdt_status = pbpctl_dev->wdt_status; + if (curr_wdt_status == WDT_STATUS_UNKNOWN) + *timeout = -1; + else + *timeout = + curr_wdt_status == + 0 ? 0 : pbpctl_dev->bypass_timer_interval; + } + } else + ret = BP_NOT_CAP; + return ret; +} + +static int normal_support(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { + ret = + ((((read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR)) & + NORMAL_UNSUPPORT_MASK) == + NORMAL_UNSUPPORT_MASK) ? 0 : 1); + } else + ret = 1; + } + return ret; +} + +static int get_bp_prod_caps(struct bpctl_dev *pbpctl_dev) +{ + if ((pbpctl_dev->bp_caps & SW_CTL_CAP) && + (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) + return read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR); + return BP_NOT_CAP; + +} + +static int tap_flag_status(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) + return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & + TAP_FLAG_MASK) == TAP_FLAG_MASK) ? 1 : 0); + + } + return BP_NOT_CAP; +} + +static int tap_flag_status_clear(struct bpctl_dev *pbpctl_dev) +{ + uint32_t status_reg = 0; + + if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { + status_reg = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); + write_reg(pbpctl_dev, status_reg & ~TAP_FLAG_MASK, + STATUS_TAP_REG_ADDR); + return 0; + } + } + return BP_NOT_CAP; +} + +static int tap_change_status(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { + if (pbpctl_dev->bp_caps & TAP_CAP) { + if (pbpctl_dev->bp_caps & BP_CAP) { + ret = tap_flag_status(pbpctl_dev); + tap_flag_status_clear(pbpctl_dev); + } else { + ret = bypass_from_last_read(pbpctl_dev); + bypass_status_clear(pbpctl_dev); + } + } + } + return ret; +} + +static int tap_status(struct bpctl_dev *pbpctl_dev) +{ + u32 ctrl_ext = 0; + + if (pbpctl_dev->bp_caps & TAP_CAP) { + struct bpctl_dev *pbpctl_dev_b = NULL; + + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + + if (pbpctl_dev->bp_ext_ver >= 0x8) { + if (!pbpctl_dev->bp_10g) + return (((BPCTL_READ_REG + (pbpctl_dev_b, + CTRL_EXT)) & + BPCTLI_CTRL_EXT_SDP6_DATA) != + 0 ? 0 : 1); + else { + ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP); + BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, + (ctrl_ext | + BP10G_SDP6_DATA_OUT)); + return ((BP10G_READ_REG(pbpctl_dev_b, EODSDP) & + BP10G_SDP6_DATA_IN) != 0 ? 0 : 1); + } + + } else if (pbpctl_dev->media_type == BP_COPPER) + return (((BPCTL_READ_REG(pbpctl_dev, CTRL)) & + BPCTLI_CTRL_SWDPIN0) != 0 ? 1 : 0); + else { + if ((bypass_status_clear(pbpctl_dev)) >= 0) + return bypass_from_last_read(pbpctl_dev); + } + + } + return BP_NOT_CAP; +} + +static int default_pwron_tap_status(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) + return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & + DFLT_PWRON_TAP_MASK) == + DFLT_PWRON_TAP_MASK) ? 1 : 0); + } + return BP_NOT_CAP; +} + +static int dis_tap_cap_status(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) + return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & + DIS_TAP_CAP_MASK) == + DIS_TAP_CAP_MASK) ? 1 : 0); + } + return BP_NOT_CAP; +} + +static int disc_flag_status(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & DISC_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + DISC_FLAG_MASK) == DISC_FLAG_MASK) ? 1 : 0); + + } + return BP_NOT_CAP; +} + +static int disc_flag_status_clear(struct bpctl_dev *pbpctl_dev) +{ + uint32_t status_reg = 0; + + if (pbpctl_dev->bp_caps & DISC_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + status_reg = read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR); + write_reg(pbpctl_dev, status_reg & ~DISC_FLAG_MASK, + STATUS_DISC_REG_ADDR); + return BP_OK; + } + } + return BP_NOT_CAP; +} + +static int disc_change_status(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (pbpctl_dev->bp_caps & DISC_CAP) { + ret = disc_flag_status(pbpctl_dev); + disc_flag_status_clear(pbpctl_dev); + return ret; + } + return BP_NOT_CAP; +} + +static int disc_off_status(struct bpctl_dev *pbpctl_dev) +{ + struct bpctl_dev *pbpctl_dev_b = NULL; + u32 ctrl_ext = 0; + + if (pbpctl_dev->bp_caps & DISC_CAP) { + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return BP_NOT_CAP; + if (DISCF_IF_SERIES(pbpctl_dev->subdevice)) + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0); + + if (pbpctl_dev->bp_i80) { + return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL_EXT)) & + BPCTLI_CTRL_EXT_SDP6_DATA) != 0 ? 1 : 0); + + } + if (pbpctl_dev->bp_540) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, ESDP); + return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) & + BP10G_SDP2_DATA) != 0 ? 1 : 0); + + } + if (pbpctl_dev->media_type == BP_COPPER) { + +#if 0 + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + DISC_OFF_MASK) == DISC_OFF_MASK) ? 1 : 0); +#endif + if (!pbpctl_dev->bp_10g) + return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & + BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); + else + return ((BP10G_READ_REG(pbpctl_dev_b, ESDP) & + BP10G_SDP1_DATA) != 0 ? 1 : 0); + + } else { + + if (pbpctl_dev->bp_10g9) { + ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, I2CCTL); + BP10G_WRITE_REG(pbpctl_dev_b, I2CCTL, + (ctrl_ext | + BP10G_I2C_DATA_OUT)); + return ((BP10G_READ_REG(pbpctl_dev_b, I2CCTL) & + BP10G_I2C_DATA_IN) != 0 ? 1 : 0); + + } else if (pbpctl_dev->bp_fiber5) { + return (((BPCTL_READ_REG(pbpctl_dev_b, CTRL)) & + BPCTLI_CTRL_SWDPIN1) != 0 ? 1 : 0); + } else if (pbpctl_dev->bp_10gb) { + ctrl_ext = + BP10GB_READ_REG(pbpctl_dev, MISC_REG_GPIO); + BP10GB_WRITE_REG(pbpctl_dev, MISC_REG_GPIO, + (ctrl_ext | BP10GB_GPIO3_OE_P1) + & ~(BP10GB_GPIO3_SET_P1 | + BP10GB_GPIO3_CLR_P1)); + + return (((BP10GB_READ_REG + (pbpctl_dev, + MISC_REG_GPIO)) & BP10GB_GPIO3_P1) != + 0 ? 1 : 0); + } + if (!pbpctl_dev->bp_10g) { + + return (((BPCTL_READ_REG + (pbpctl_dev_b, + CTRL_EXT)) & + BPCTLI_CTRL_EXT_SDP6_DATA) != + 0 ? 1 : 0); + } else { + ctrl_ext = BP10G_READ_REG(pbpctl_dev_b, EODSDP); + BP10G_WRITE_REG(pbpctl_dev_b, EODSDP, + (ctrl_ext | + BP10G_SDP6_DATA_OUT)); + return (((BP10G_READ_REG(pbpctl_dev_b, EODSDP)) + & BP10G_SDP6_DATA_IN) != 0 ? 1 : 0); + } + + } + } + return BP_NOT_CAP; +} + +static int disc_status(struct bpctl_dev *pbpctl_dev) +{ + int ctrl = 0; + + if (pbpctl_dev->bp_caps & DISC_CAP) { + ctrl = disc_off_status(pbpctl_dev); + if (ctrl < 0) + return ctrl; + return ((ctrl == 0) ? 1 : 0); + } + return BP_NOT_CAP; +} + +static int default_pwron_disc_status(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + DFLT_PWRON_DISC_MASK) == + DFLT_PWRON_DISC_MASK) ? 1 : 0); + } + return BP_NOT_CAP; +} + +static int dis_disc_cap_status(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & DIS_DISC_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + DIS_DISC_CAP_MASK) == + DIS_DISC_CAP_MASK) ? 1 : 0); + } + return BP_NOT_CAP; +} + +static int wdt_exp_mode_status(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver <= PXG2BPI_VER) + return 0; /* bypass mode */ + else if (pbpctl_dev->bp_ext_ver == PXG2TBPI_VER) + return 1; /* tap mode */ + else if (pbpctl_dev->bp_ext_ver >= PXE2TBPI_VER) { + if (pbpctl_dev->bp_ext_ver >= 0x8) { + if (((read_reg + (pbpctl_dev, + STATUS_DISC_REG_ADDR)) & + WDTE_DISC_BPN_MASK) == WDTE_DISC_BPN_MASK) + return 2; + } + return ((((read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR)) & + WDTE_TAP_BPN_MASK) == + WDTE_TAP_BPN_MASK) ? 1 : 0); + } + } + return BP_NOT_CAP; +} + +static int tpl2_flag_status(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + TPL2_FLAG_MASK) == TPL2_FLAG_MASK) ? 1 : 0); + + } + return BP_NOT_CAP; +} + +static int bp_wait_at_pwup_status(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + if (pbpctl_dev->bp_ext_ver >= 0x8) + return ((((read_reg(pbpctl_dev, CONT_CONFIG_REG_ADDR)) & + WAIT_AT_PWUP_MASK) == + WAIT_AT_PWUP_MASK) ? 1 : 0); + } + return BP_NOT_CAP; +} + +static int bp_hw_reset_status(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + + if (pbpctl_dev->bp_ext_ver >= 0x8) + return ((((read_reg(pbpctl_dev, CONT_CONFIG_REG_ADDR)) & + EN_HW_RESET_MASK) == + EN_HW_RESET_MASK) ? 1 : 0); + } + return BP_NOT_CAP; +} + + +static int std_nic_status(struct bpctl_dev *pbpctl_dev) +{ + int status_val = 0; + + if (pbpctl_dev->bp_caps & STD_NIC_CAP) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + return BP_NOT_CAP; + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { + return ((((read_reg(pbpctl_dev, STATUS_DISC_REG_ADDR)) & + STD_NIC_ON_MASK) == STD_NIC_ON_MASK) ? 1 : 0); + } + + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + if (pbpctl_dev->bp_caps & BP_CAP) { + status_val = + read_reg(pbpctl_dev, STATUS_REG_ADDR); + if (((!(status_val & WDT_EN_MASK)) + && ((status_val & STD_NIC_MASK) == + STD_NIC_MASK))) + status_val = 1; + else + return 0; + } + if (pbpctl_dev->bp_caps & TAP_CAP) { + status_val = + read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); + if ((status_val & STD_NIC_TAP_MASK) == + STD_NIC_TAP_MASK) + status_val = 1; + else + return 0; + } + if (pbpctl_dev->bp_caps & TAP_CAP) { + if ((disc_off_status(pbpctl_dev))) + status_val = 1; + else + return 0; + } + + return status_val; + } + } + return BP_NOT_CAP; +} + +/******************************************************/ +/**************SW_INIT*********************************/ +/******************************************************/ +static void bypass_caps_init(struct bpctl_dev *pbpctl_dev) +{ + u_int32_t ctrl_ext = 0; + struct bpctl_dev *pbpctl_dev_m = NULL; + +#ifdef BYPASS_DEBUG + int ret = 0; + + if (!(INTEL_IF_SERIES(adapter->bp_device_block.subdevice))) { + ret = read_reg(pbpctl_dev, VER_REG_ADDR); + printk("VER_REG reg1=%x\n", ret); + ret = read_reg(pbpctl_dev, PRODUCT_CAP_REG_ADDR); + printk("PRODUCT_CAP reg=%x\n", ret); + ret = read_reg(pbpctl_dev, STATUS_TAP_REG_ADDR); + printk("STATUS_TAP reg1=%x\n", ret); + ret = read_reg(pbpctl_dev, 0x7); + printk("SIG_REG reg1=%x\n", ret); + ret = read_reg(pbpctl_dev, STATUS_REG_ADDR); + printk("STATUS_REG_ADDR=%x\n", ret); + ret = read_reg(pbpctl_dev, WDT_REG_ADDR); + printk("WDT_REG_ADDR=%x\n", ret); + ret = read_reg(pbpctl_dev, TMRL_REG_ADDR); + printk("TMRL_REG_ADDR=%x\n", ret); + ret = read_reg(pbpctl_dev, TMRH_REG_ADDR); + printk("TMRH_REG_ADDR=%x\n", ret); + } +#endif + if ((pbpctl_dev->bp_fiber5) || (pbpctl_dev->bp_10g9)) { + pbpctl_dev->media_type = BP_FIBER; + } else if (pbpctl_dev->bp_10gb) { + if (BP10GB_CX4_SERIES(pbpctl_dev->subdevice)) + pbpctl_dev->media_type = BP_CX4; + else + pbpctl_dev->media_type = BP_FIBER; + + } + + else if (pbpctl_dev->bp_540) + pbpctl_dev->media_type = BP_NONE; + else if (!pbpctl_dev->bp_10g) { + + ctrl_ext = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); + if ((ctrl_ext & BPCTLI_CTRL_EXT_LINK_MODE_MASK) == 0x0) + pbpctl_dev->media_type = BP_COPPER; + else + pbpctl_dev->media_type = BP_FIBER; + + } else { + if (BP10G_CX4_SERIES(pbpctl_dev->subdevice)) + pbpctl_dev->media_type = BP_CX4; + else + pbpctl_dev->media_type = BP_FIBER; + } + + if (is_bypass_fn(pbpctl_dev)) { + + pbpctl_dev->bp_caps |= BP_PWOFF_ON_CAP; + if (pbpctl_dev->media_type == BP_FIBER) + pbpctl_dev->bp_caps |= + (TX_CTL_CAP | TX_STATUS_CAP | TPL_CAP); + + if (TPL_IF_SERIES(pbpctl_dev->subdevice)) + pbpctl_dev->bp_caps |= TPL_CAP; + + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { + pbpctl_dev->bp_caps |= + (BP_CAP | BP_STATUS_CAP | SW_CTL_CAP | + BP_PWUP_ON_CAP | BP_PWUP_OFF_CAP | BP_PWOFF_OFF_CAP + | WD_CTL_CAP | WD_STATUS_CAP | STD_NIC_CAP | + WD_TIMEOUT_CAP); + + pbpctl_dev->bp_ext_ver = OLD_IF_VER; + return; + } + + if ((pbpctl_dev->bp_fw_ver == 0xff) && + OLD_IF_SERIES(pbpctl_dev->subdevice)) { + + pbpctl_dev->bp_caps |= + (BP_CAP | BP_STATUS_CAP | BP_STATUS_CHANGE_CAP | + SW_CTL_CAP | BP_PWUP_ON_CAP | WD_CTL_CAP | + WD_STATUS_CAP | WD_TIMEOUT_CAP); + + pbpctl_dev->bp_ext_ver = OLD_IF_VER; + return; + } + + else { + switch (pbpctl_dev->bp_fw_ver) { + case BP_FW_VER_A0: + case BP_FW_VER_A1:{ + pbpctl_dev->bp_ext_ver = + (pbpctl_dev-> + bp_fw_ver & EXT_VER_MASK); + break; + } + default:{ + if ((bypass_sign_check(pbpctl_dev)) != + 1) { + pbpctl_dev->bp_caps = 0; + return; + } + pbpctl_dev->bp_ext_ver = + (pbpctl_dev-> + bp_fw_ver & EXT_VER_MASK); + } + } + } + + if (pbpctl_dev->bp_ext_ver == PXG2BPI_VER) + pbpctl_dev->bp_caps |= + (BP_CAP | BP_STATUS_CAP | BP_STATUS_CHANGE_CAP | + SW_CTL_CAP | BP_DIS_CAP | BP_DIS_STATUS_CAP | + BP_PWUP_ON_CAP | BP_PWUP_OFF_CAP | BP_PWUP_CTL_CAP + | WD_CTL_CAP | STD_NIC_CAP | WD_STATUS_CAP | + WD_TIMEOUT_CAP); + else if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { + int cap_reg; + + pbpctl_dev->bp_caps |= + (SW_CTL_CAP | WD_CTL_CAP | WD_STATUS_CAP | + WD_TIMEOUT_CAP); + cap_reg = get_bp_prod_caps(pbpctl_dev); + + if ((cap_reg & NORMAL_UNSUPPORT_MASK) == + NORMAL_UNSUPPORT_MASK) + pbpctl_dev->bp_caps |= NIC_CAP_NEG; + else + pbpctl_dev->bp_caps |= STD_NIC_CAP; + + if ((normal_support(pbpctl_dev)) == 1) + + pbpctl_dev->bp_caps |= STD_NIC_CAP; + + else + pbpctl_dev->bp_caps |= NIC_CAP_NEG; + if ((cap_reg & BYPASS_SUPPORT_MASK) == + BYPASS_SUPPORT_MASK) { + pbpctl_dev->bp_caps |= + (BP_CAP | BP_STATUS_CAP | + BP_STATUS_CHANGE_CAP | BP_DIS_CAP | + BP_DIS_STATUS_CAP | BP_PWUP_ON_CAP | + BP_PWUP_OFF_CAP | BP_PWUP_CTL_CAP); + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER7) + pbpctl_dev->bp_caps |= + BP_PWOFF_ON_CAP | BP_PWOFF_OFF_CAP | + BP_PWOFF_CTL_CAP; + } + if ((cap_reg & TAP_SUPPORT_MASK) == TAP_SUPPORT_MASK) { + pbpctl_dev->bp_caps |= + (TAP_CAP | TAP_STATUS_CAP | + TAP_STATUS_CHANGE_CAP | TAP_DIS_CAP | + TAP_DIS_STATUS_CAP | TAP_PWUP_ON_CAP | + TAP_PWUP_OFF_CAP | TAP_PWUP_CTL_CAP); + } + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER8) { + if ((cap_reg & DISC_SUPPORT_MASK) == + DISC_SUPPORT_MASK) + pbpctl_dev->bp_caps |= + (DISC_CAP | DISC_DIS_CAP | + DISC_PWUP_CTL_CAP); + if ((cap_reg & TPL2_SUPPORT_MASK) == + TPL2_SUPPORT_MASK) { + pbpctl_dev->bp_caps_ex |= TPL2_CAP_EX; + pbpctl_dev->bp_caps |= TPL_CAP; + pbpctl_dev->bp_tpl_flag = + tpl2_flag_status(pbpctl_dev); + } + + } + + if (pbpctl_dev->bp_ext_ver >= BP_FW_EXT_VER9) { + if ((cap_reg & DISC_PORT_SUPPORT_MASK) == + DISC_PORT_SUPPORT_MASK) { + pbpctl_dev->bp_caps_ex |= + DISC_PORT_CAP_EX; + pbpctl_dev->bp_caps |= + (TX_CTL_CAP | TX_STATUS_CAP); + } + + } + + } + if (pbpctl_dev->bp_ext_ver >= PXG2BPI_VER) { + if ((read_reg(pbpctl_dev, STATUS_REG_ADDR)) & + WDT_EN_MASK) + pbpctl_dev->wdt_status = WDT_STATUS_EN; + else + pbpctl_dev->wdt_status = WDT_STATUS_DIS; + } + + } else if ((P2BPFI_IF_SERIES(pbpctl_dev->subdevice)) || + (PEGF5_IF_SERIES(pbpctl_dev->subdevice)) || + (PEGF80_IF_SERIES(pbpctl_dev->subdevice)) || + (BP10G9_IF_SERIES(pbpctl_dev->subdevice))) { + pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP); + } + if ((pbpctl_dev->subdevice & 0xa00) == 0xa00) + pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP); + if (PEG5_IF_SERIES(pbpctl_dev->subdevice)) + pbpctl_dev->bp_caps |= (TX_CTL_CAP | TX_STATUS_CAP); + + if (BP10GB_IF_SERIES(pbpctl_dev->subdevice)) + pbpctl_dev->bp_caps &= ~(TX_CTL_CAP | TX_STATUS_CAP); + + pbpctl_dev_m = get_master_port_fn(pbpctl_dev); + if (pbpctl_dev_m != NULL) { + int cap_reg = 0; + if (pbpctl_dev_m->bp_ext_ver >= 0x9) { + cap_reg = get_bp_prod_caps(pbpctl_dev_m); + if ((cap_reg & DISC_PORT_SUPPORT_MASK) == + DISC_PORT_SUPPORT_MASK) + pbpctl_dev->bp_caps |= + (TX_CTL_CAP | TX_STATUS_CAP); + pbpctl_dev->bp_caps_ex |= DISC_PORT_CAP_EX; + } + } +} + +static void remove_bypass_wd_auto(struct bpctl_dev *pbpctl_dev) +{ +#ifdef BP_SELF_TEST + struct bpctl_dev *pbpctl_dev_sl = NULL; +#endif + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + + del_timer_sync(&pbpctl_dev->bp_timer); +#ifdef BP_SELF_TEST + pbpctl_dev_sl = get_status_port_fn(pbpctl_dev); + if (pbpctl_dev_sl && (pbpctl_dev_sl->ndev)) { + if ((pbpctl_dev_sl->ndev->netdev_ops) + && (pbpctl_dev_sl->old_ops)) { + rtnl_lock(); + pbpctl_dev_sl->ndev->netdev_ops = + pbpctl_dev_sl->old_ops; + pbpctl_dev_sl->old_ops = NULL; + + rtnl_unlock(); + + } + + } +#endif + } + +} + +static int init_bypass_wd_auto(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + init_timer(&pbpctl_dev->bp_timer); + pbpctl_dev->bp_timer.function = &wd_reset_timer; + pbpctl_dev->bp_timer.data = (unsigned long)pbpctl_dev; + return 1; + } + return BP_NOT_CAP; +} + +#ifdef BP_SELF_TEST +int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bpctl_dev *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; + int idx_dev = 0; + struct ethhdr *eth = (struct ethhdr *)skb->data; + + for (idx_dev = 0; + ((bpctl_dev_arr[idx_dev].ndev != NULL) && (idx_dev < device_num)); + idx_dev++) { + if (bpctl_dev_arr[idx_dev].ndev == dev) { + pbpctl_dev = &bpctl_dev_arr[idx_dev]; + break; + } + } + if (!pbpctl_dev) + return 1; + if ((htons(ETH_P_BPTEST) == eth->h_proto)) { + + pbpctl_dev_m = get_master_port_fn(pbpctl_dev); + if (pbpctl_dev_m) { + + if (bypass_status(pbpctl_dev_m)) { + cmnd_on(pbpctl_dev_m); + bypass_off(pbpctl_dev_m); + cmnd_off(pbpctl_dev_m); + } + wdt_timer_reload(pbpctl_dev_m); + } + dev_kfree_skb_irq(skb); + return 0; + } + return pbpctl_dev->hard_start_xmit_save(skb, dev); +} +#endif + +static int set_bypass_wd_auto(struct bpctl_dev *pbpctl_dev, unsigned int param) +{ + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + if (pbpctl_dev->reset_time != param) { + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + pbpctl_dev->reset_time = + (param < + WDT_AUTO_MIN_INT) ? WDT_AUTO_MIN_INT : + param; + else + pbpctl_dev->reset_time = param; + if (param) + mod_timer(&pbpctl_dev->bp_timer, jiffies); + } + return 0; + } + return BP_NOT_CAP; +} + +static int get_bypass_wd_auto(struct bpctl_dev *pbpctl_dev) +{ + if (pbpctl_dev->bp_caps & WD_CTL_CAP) + return pbpctl_dev->reset_time; + + return BP_NOT_CAP; +} + +#ifdef BP_SELF_TEST + +int set_bp_self_test(struct bpctl_dev *pbpctl_dev, unsigned int param) +{ + struct bpctl_dev *pbpctl_dev_sl = NULL; + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + pbpctl_dev->bp_self_test_flag = param == 0 ? 0 : 1; + pbpctl_dev_sl = get_status_port_fn(pbpctl_dev); + + if ((pbpctl_dev_sl->ndev) && (pbpctl_dev_sl->ndev->netdev_ops)) { + rtnl_lock(); + if (pbpctl_dev->bp_self_test_flag == 1) { + + pbpctl_dev_sl->old_ops = + pbpctl_dev_sl->ndev->netdev_ops; + pbpctl_dev_sl->new_ops = + *pbpctl_dev_sl->old_ops; + pbpctl_dev_sl->new_ops.ndo_start_xmit = + bp_hard_start_xmit; + pbpctl_dev_sl->ndev->netdev_ops = + &pbpctl_dev_sl->new_ops; + + } else if (pbpctl_dev_sl->old_ops) { + pbpctl_dev_sl->ndev->netdev_ops = + pbpctl_dev_sl->old_ops; + pbpctl_dev_sl->old_ops = NULL; + } + rtnl_unlock(); + } + + set_bypass_wd_auto(pbpctl_dev, param); + return 0; + } + return BP_NOT_CAP; +} + +int get_bp_self_test(struct bpctl_dev *pbpctl_dev) +{ + + if (pbpctl_dev->bp_caps & WD_CTL_CAP) { + if (pbpctl_dev->bp_self_test_flag == 1) + return pbpctl_dev->reset_time; + else + return 0; + } + return BP_NOT_CAP; +} + +#endif + +/**************************************************************/ +/************************* API ********************************/ +/**************************************************************/ + +int is_bypass_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return (((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) ? 1 : 0); +} + +static int set_bypass_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode) +{ + int ret = 0; + + if (!(pbpctl_dev->bp_caps & BP_CAP)) + return BP_NOT_CAP; + ret = cmnd_on(pbpctl_dev); + if (ret < 0) + return ret; + if (!bypass_mode) + ret = bypass_off(pbpctl_dev); + else + ret = bypass_on(pbpctl_dev); + cmnd_off(pbpctl_dev); + + return ret; +} + +static int get_bypass_fn(struct bpctl_dev *pbpctl_dev) +{ + return bypass_status(pbpctl_dev); +} + +static int get_bypass_change_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return bypass_change_status(pbpctl_dev); +} + +static int set_dis_bypass_fn(struct bpctl_dev *pbpctl_dev, int dis_param) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if (!(pbpctl_dev->bp_caps & BP_DIS_CAP)) + return BP_NOT_CAP; + ret = cmnd_on(pbpctl_dev); + if (ret < 0) + return ret; + if (dis_param) + ret = dis_bypass_cap(pbpctl_dev); + else + ret = en_bypass_cap(pbpctl_dev); + cmnd_off(pbpctl_dev); + return ret; +} + +static int get_dis_bypass_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return dis_bypass_cap_status(pbpctl_dev); +} + +static int set_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if (!(pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) + return BP_NOT_CAP; + ret = cmnd_on(pbpctl_dev); + if (ret < 0) + return ret; + if (bypass_mode) + ret = bypass_state_pwroff(pbpctl_dev); + else + ret = normal_state_pwroff(pbpctl_dev); + cmnd_off(pbpctl_dev); + return ret; +} + +static int get_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return default_pwroff_status(pbpctl_dev); +} + +static int set_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if (!(pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP)) + return BP_NOT_CAP; + ret = cmnd_on(pbpctl_dev); + if (ret < 0) + return ret; + if (bypass_mode) + ret = bypass_state_pwron(pbpctl_dev); + else + ret = normal_state_pwron(pbpctl_dev); + cmnd_off(pbpctl_dev); + return ret; +} + +static int get_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return default_pwron_status(pbpctl_dev); +} + +static int set_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int timeout) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if (!(pbpctl_dev->bp_caps & WD_CTL_CAP)) + return BP_NOT_CAP; + + ret = cmnd_on(pbpctl_dev); + if (ret < 0) + return ret; + if (!timeout) + ret = wdt_off(pbpctl_dev); + else { + wdt_on(pbpctl_dev, timeout); + ret = pbpctl_dev->bypass_timer_interval; + } + cmnd_off(pbpctl_dev); + return ret; +} + +static int get_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int *timeout) +{ + if (!pbpctl_dev) + return -1; + + return wdt_programmed(pbpctl_dev, timeout); +} + +static int get_wd_expire_time_fn(struct bpctl_dev *pbpctl_dev, int *time_left) +{ + if (!pbpctl_dev) + return -1; + + return wdt_timer(pbpctl_dev, time_left); +} + +static int reset_bypass_wd_timer_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return wdt_timer_reload(pbpctl_dev); +} + +static int get_wd_set_caps_fn(struct bpctl_dev *pbpctl_dev) +{ + int bp_status = 0; + unsigned int step_value = TIMEOUT_MAX_STEP + 1, bit_cnt = 0; + + if (!pbpctl_dev) + return -1; + + if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) + return BP_NOT_CAP; + + while ((step_value >>= 1)) + bit_cnt++; + + if (is_bypass_fn(pbpctl_dev)) { + bp_status = + WD_STEP_COUNT_MASK(bit_cnt) | WDT_STEP_TIME | + WD_MIN_TIME_MASK(TIMEOUT_UNIT / 100); + } else + return -1; + + return bp_status; +} + +static int set_std_nic_fn(struct bpctl_dev *pbpctl_dev, int nic_mode) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if (!(pbpctl_dev->bp_caps & STD_NIC_CAP)) + return BP_NOT_CAP; + + ret = cmnd_on(pbpctl_dev); + if (ret < 0) + return ret; + if (nic_mode) + ret = std_nic_on(pbpctl_dev); + else + ret = std_nic_off(pbpctl_dev); + cmnd_off(pbpctl_dev); + return ret; +} + +static int get_std_nic_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return std_nic_status(pbpctl_dev); +} + +static int set_tap_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) +{ + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & TAP_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) { + if (!tap_mode) + tap_off(pbpctl_dev); + else + tap_on(pbpctl_dev); + cmnd_off(pbpctl_dev); + return 0; + } + return BP_NOT_CAP; +} + +static int get_tap_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return tap_status(pbpctl_dev); +} + +static int set_tap_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) + && ((cmnd_on(pbpctl_dev)) >= 0)) { + if (tap_mode) + ret = tap_state_pwron(pbpctl_dev); + else + ret = normal_state_pwron(pbpctl_dev); + cmnd_off(pbpctl_dev); + } else + ret = BP_NOT_CAP; + return ret; +} + +static int get_tap_pwup_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + ret = default_pwron_tap_status(pbpctl_dev); + if (ret < 0) + return ret; + return ((ret == 0) ? 1 : 0); +} + +static int get_tap_change_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return tap_change_status(pbpctl_dev); +} + +static int set_dis_tap_fn(struct bpctl_dev *pbpctl_dev, int dis_param) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & TAP_DIS_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) { + if (dis_param) + ret = dis_tap_cap(pbpctl_dev); + else + ret = en_tap_cap(pbpctl_dev); + cmnd_off(pbpctl_dev); + return ret; + } else + return BP_NOT_CAP; +} + +static int get_dis_tap_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return dis_tap_cap_status(pbpctl_dev); +} + +static int set_disc_fn(struct bpctl_dev *pbpctl_dev, int disc_mode) +{ + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & DISC_CAP) && ((cmnd_on(pbpctl_dev)) >= 0)) { + if (!disc_mode) + disc_off(pbpctl_dev); + else + disc_on(pbpctl_dev); + cmnd_off(pbpctl_dev); + + return BP_OK; + } + return BP_NOT_CAP; +} + +static int get_disc_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + ret = disc_status(pbpctl_dev); + + return ret; +} + +static int set_disc_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) + && ((cmnd_on(pbpctl_dev)) >= 0)) { + if (disc_mode) + ret = disc_state_pwron(pbpctl_dev); + else + ret = normal_state_pwron(pbpctl_dev); + cmnd_off(pbpctl_dev); + } else + ret = BP_NOT_CAP; + return ret; +} + +static int get_disc_pwup_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + ret = default_pwron_disc_status(pbpctl_dev); + return (ret == 0 ? 1 : (ret < 0 ? BP_NOT_CAP : 0)); +} + +static int get_disc_change_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + ret = disc_change_status(pbpctl_dev); + return ret; +} + +static int set_dis_disc_fn(struct bpctl_dev *pbpctl_dev, int dis_param) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & DISC_DIS_CAP) + && ((cmnd_on(pbpctl_dev)) >= 0)) { + if (dis_param) + ret = dis_disc_cap(pbpctl_dev); + else + ret = en_disc_cap(pbpctl_dev); + cmnd_off(pbpctl_dev); + return ret; + } else + return BP_NOT_CAP; +} + +static int get_dis_disc_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + ret = dis_disc_cap_status(pbpctl_dev); + + return ret; +} + +static int get_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return wdt_exp_mode_status(pbpctl_dev); +} + +static int set_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev, int param) +{ + if (!pbpctl_dev) + return -1; + + return wdt_exp_mode(pbpctl_dev, param); +} + +static int set_tx_fn(struct bpctl_dev *pbpctl_dev, int tx_state) +{ + struct bpctl_dev *pbpctl_dev_b = NULL; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & TPL_CAP) && + (pbpctl_dev->bp_caps & SW_CTL_CAP)) { + if ((pbpctl_dev->bp_tpl_flag)) + return BP_NOT_CAP; + } else { + pbpctl_dev_b = get_master_port_fn(pbpctl_dev); + if (pbpctl_dev_b && + (pbpctl_dev_b->bp_caps & TPL_CAP) && + (pbpctl_dev_b->bp_tpl_flag)) + return BP_NOT_CAP; + } + return set_tx(pbpctl_dev, tx_state); +} + +static int set_bp_force_link_fn(int dev_num, int tx_state) +{ + static struct bpctl_dev *bpctl_dev_curr; + + if ((dev_num < 0) || (dev_num > device_num) + || (bpctl_dev_arr[dev_num].pdev == NULL)) + return -1; + bpctl_dev_curr = &bpctl_dev_arr[dev_num]; + + return set_bp_force_link(bpctl_dev_curr, tx_state); +} + +static int set_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev, int param) +{ + if (!pbpctl_dev) + return -1; + + return set_bypass_wd_auto(pbpctl_dev, param); +} + +static int get_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return get_bypass_wd_auto(pbpctl_dev); +} + +#ifdef BP_SELF_TEST +int set_bp_self_test_fn(struct bpctl_dev *pbpctl_dev, int param) +{ + if (!pbpctl_dev) + return -1; + + return set_bp_self_test(pbpctl_dev, param); +} + +int get_bp_self_test_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return get_bp_self_test(pbpctl_dev); +} + +#endif + +static int get_bypass_caps_fn(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + return pbpctl_dev->bp_caps; + +} + +static int get_bypass_slave_fn(struct bpctl_dev *pbpctl_dev, + struct bpctl_dev **pbpctl_dev_out) +{ + int idx_dev = 0; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) { + for (idx_dev = 0; + ((bpctl_dev_arr[idx_dev].pdev != NULL) + && (idx_dev < device_num)); idx_dev++) { + if ((bpctl_dev_arr[idx_dev].bus == pbpctl_dev->bus) + && (bpctl_dev_arr[idx_dev].slot == + pbpctl_dev->slot)) { + if ((pbpctl_dev->func == 0) + && (bpctl_dev_arr[idx_dev].func == 1)) { + *pbpctl_dev_out = + &bpctl_dev_arr[idx_dev]; + return 1; + } + if ((pbpctl_dev->func == 2) && + (bpctl_dev_arr[idx_dev].func == 3)) { + *pbpctl_dev_out = + &bpctl_dev_arr[idx_dev]; + return 1; + } + } + } + return -1; + } else + return 0; +} + +static int is_bypass(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) + return 1; + else + return 0; +} + +static int get_tx_fn(struct bpctl_dev *pbpctl_dev) +{ + struct bpctl_dev *pbpctl_dev_b = NULL; + + if (!pbpctl_dev) + return -1; + + if ((pbpctl_dev->bp_caps & TPL_CAP) && + (pbpctl_dev->bp_caps & SW_CTL_CAP)) { + if ((pbpctl_dev->bp_tpl_flag)) + return BP_NOT_CAP; + } else { + pbpctl_dev_b = get_master_port_fn(pbpctl_dev); + if (pbpctl_dev_b && + (pbpctl_dev_b->bp_caps & TPL_CAP) && + (pbpctl_dev_b->bp_tpl_flag)) + return BP_NOT_CAP; + } + return tx_status(pbpctl_dev); +} + +static int get_bp_force_link_fn(int dev_num) +{ + static struct bpctl_dev *bpctl_dev_curr; + + if ((dev_num < 0) || (dev_num > device_num) + || (bpctl_dev_arr[dev_num].pdev == NULL)) + return -1; + bpctl_dev_curr = &bpctl_dev_arr[dev_num]; + + return bp_force_link_status(bpctl_dev_curr); +} + +static int get_bypass_link_status(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->media_type == BP_FIBER) + return ((BPCTL_READ_REG(pbpctl_dev, CTRL) & + BPCTLI_CTRL_SWDPIN1)); + else + return ((BPCTL_READ_REG(pbpctl_dev, STATUS) & + BPCTLI_STATUS_LU)); + +} + +static void bp_tpl_timer_fn(unsigned long param) +{ + struct bpctl_dev *pbpctl_dev = (struct bpctl_dev *) param; + uint32_t link1, link2; + struct bpctl_dev *pbpctl_dev_b = NULL; + + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (!pbpctl_dev_b) + return; + + if (!pbpctl_dev->bp_tpl_flag) { + set_tx(pbpctl_dev_b, 1); + set_tx(pbpctl_dev, 1); + return; + } + link1 = get_bypass_link_status(pbpctl_dev); + + link2 = get_bypass_link_status(pbpctl_dev_b); + if ((link1) && (tx_status(pbpctl_dev))) { + if ((!link2) && (tx_status(pbpctl_dev_b))) + set_tx(pbpctl_dev, 0); + else if (!tx_status(pbpctl_dev_b)) + set_tx(pbpctl_dev_b, 1); + } else if ((!link1) && (tx_status(pbpctl_dev))) { + if ((link2) && (tx_status(pbpctl_dev_b))) + set_tx(pbpctl_dev_b, 0); + } else if ((link1) && (!tx_status(pbpctl_dev))) { + if ((link2) && (tx_status(pbpctl_dev_b))) + set_tx(pbpctl_dev, 1); + } else if ((!link1) && (!tx_status(pbpctl_dev))) { + if ((link2) && (tx_status(pbpctl_dev_b))) + set_tx(pbpctl_dev, 1); + } + + mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + BP_LINK_MON_DELAY * HZ); +} + +static void remove_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev) +{ + struct bpctl_dev *pbpctl_dev_b; + if (!pbpctl_dev) + return; + + if (pbpctl_dev->bp_caps & TPL_CAP) { + del_timer_sync(&pbpctl_dev->bp_tpl_timer); + pbpctl_dev->bp_tpl_flag = 0; + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (pbpctl_dev_b) + set_tx(pbpctl_dev_b, 1); + set_tx(pbpctl_dev, 1); + } + return; +} + +static int init_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev) +{ + if (!pbpctl_dev) + return -1; + if (pbpctl_dev->bp_caps & TPL_CAP) { + 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; + return BP_OK; + } + return BP_NOT_CAP; +} + +static int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param) +{ + if (!pbpctl_dev) + return -1; + if (pbpctl_dev->bp_caps & TPL_CAP) { + if ((param) && (!pbpctl_dev->bp_tpl_flag)) { + pbpctl_dev->bp_tpl_flag = param; + mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + 1); + return BP_OK; + } + if ((!param) && (pbpctl_dev->bp_tpl_flag)) + remove_bypass_tpl_auto(pbpctl_dev); + + return BP_OK; + } + return BP_NOT_CAP; +} + +static int set_tpl_fn(struct bpctl_dev *pbpctl_dev, int tpl_mode) +{ + + struct bpctl_dev *pbpctl_dev_b; + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_caps & TPL_CAP) { + if (tpl_mode) { + pbpctl_dev_b = get_status_port_fn(pbpctl_dev); + if (pbpctl_dev_b) + set_tx(pbpctl_dev_b, 1); + set_tx(pbpctl_dev, 1); + } + if ((TPL_IF_SERIES(pbpctl_dev->subdevice)) || + (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX)) { + pbpctl_dev->bp_tpl_flag = tpl_mode; + if (!tpl_mode) + tpl_hw_off(pbpctl_dev); + else + tpl_hw_on(pbpctl_dev); + } else + set_bypass_tpl_auto(pbpctl_dev, tpl_mode); + return 0; + } + return BP_NOT_CAP; +} + +static int get_tpl_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = BP_NOT_CAP; + + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_caps & TPL_CAP) { + if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) + return tpl2_flag_status(pbpctl_dev); + ret = pbpctl_dev->bp_tpl_flag; + } + return ret; +} + +static int set_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) +{ + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + /* bp_lock(pbp_device_block); */ + cmnd_on(pbpctl_dev); + if (!tap_mode) + bp_wait_at_pwup_dis(pbpctl_dev); + else + bp_wait_at_pwup_en(pbpctl_dev); + cmnd_off(pbpctl_dev); + + /* bp_unlock(pbp_device_block); */ + return BP_OK; + } + return BP_NOT_CAP; +} + +static int get_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + /* bp_lock(pbp_device_block); */ + ret = bp_wait_at_pwup_status(pbpctl_dev); + /* bp_unlock(pbp_device_block); */ + + return ret; +} + +static int set_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) +{ + if (!pbpctl_dev) + return -1; + + if (pbpctl_dev->bp_caps & SW_CTL_CAP) { + /* bp_lock(pbp_device_block); */ + cmnd_on(pbpctl_dev); + + if (!tap_mode) + bp_hw_reset_dis(pbpctl_dev); + else + bp_hw_reset_en(pbpctl_dev); + cmnd_off(pbpctl_dev); + /* bp_unlock(pbp_device_block); */ + return BP_OK; + } + return BP_NOT_CAP; +} + +static int get_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev) +{ + int ret = 0; + + if (!pbpctl_dev) + return -1; + + /* bp_lock(pbp_device_block); */ + ret = bp_hw_reset_status(pbpctl_dev); + + /* bp_unlock(pbp_device_block); */ + + return ret; +} + + +static int get_bypass_info_fn(struct bpctl_dev *pbpctl_dev, char *dev_name, + char *add_param) +{ + if (!pbpctl_dev) + return -1; + if (!is_bypass_fn(pbpctl_dev)) + return -1; + strcpy(dev_name, pbpctl_dev->name); + *add_param = pbpctl_dev->bp_fw_ver; + return 0; +} + +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_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 struct bpctl_dev *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 void if_scan_init(void) +{ + struct net_device *dev; + + /* rcu_read_lock(); */ + /* rtnl_lock(); */ + /* rcu_read_lock(); */ + + for_each_netdev(&init_net, dev) { + 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; + } + /* rtnl_unlock(); */ + /* rcu_read_unlock(); */ +} + +static long device_ioctl(struct file *file, /* see include/linux/fs.h */ + unsigned int ioctl_num, /* number and param for ioctl */ + unsigned long ioctl_param) +{ + struct bpctl_cmd bpctl_cmd; + int dev_idx = 0; + struct bpctl_dev *pbpctl_dev_out; + void __user *argp = (void __user *)ioctl_param; + int ret = 0; + unsigned long flags; + + static struct bpctl_dev *pbpctl_dev; + + /* lock_kernel(); */ + if (down_interruptible(&bpctl_sema)) + return -ERESTARTSYS; + /* local_irq_save(flags); */ + /* if(!spin_trylock_irqsave(&bpvm_lock)){ + local_irq_restore(flags); + unlock_bpctl(); + unlock_kernel(); + return -1; + } */ + /* spin_lock_irqsave(&bpvm_lock, flags); */ + +/* +* 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; + + } + /* lock_bpctl(); */ + /* preempt_disable(); */ + local_irq_save(flags); + if (!spin_trylock(&bpvm_lock)) { + local_irq_restore(flags); + unlock_bpctl(); + return -1; + } + +/* preempt_disable(); + rcu_read_lock(); + spin_lock_irqsave(&bpvm_lock, flags); +*/ + 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) { + /* unlock_bpctl(); + preempt_enable(); */ + ret = -EOPNOTSUPP; + /* preempt_enable(); + rcu_read_unlock(); */ + spin_unlock_irqrestore(&bpvm_lock, flags); + 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 ((bpctl_dev_arr[dev_idx].bp_10gb) + && (!(bpctl_dev_arr[dev_idx].ifindex))) { + printk("Please load network driver for %s adapter!\n", + bpctl_dev_arr[dev_idx].name); + bpctl_cmd.status = -1; + ret = SUCCESS; + /* preempt_enable(); */ + /* rcu_read_unlock(); */ + spin_unlock_irqrestore(&bpvm_lock, flags); + goto bp_exit; + + } + if ((bpctl_dev_arr[dev_idx].bp_10gb) && (bpctl_dev_arr[dev_idx].ndev)) { + if (!(bpctl_dev_arr[dev_idx].ndev->flags & IFF_UP)) { + if (!(bpctl_dev_arr[dev_idx].ndev->flags & IFF_UP)) { + printk + ("Please bring up network interfaces for %s adapter!\n", + bpctl_dev_arr[dev_idx].name); + bpctl_cmd.status = -1; + ret = SUCCESS; + /* preempt_enable(); */ + /* rcu_read_unlock(); */ + spin_unlock_irqrestore(&bpvm_lock, flags); + goto bp_exit; + } + + } + } + + 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_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BYPASS_PWOFF): + bpctl_cmd.status = get_bypass_pwoff_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_BYPASS_PWUP): + bpctl_cmd.status = + set_bypass_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BYPASS_PWUP): + bpctl_cmd.status = get_bypass_pwup_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_BYPASS_WD): + bpctl_cmd.status = + set_bypass_wd_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BYPASS_WD): + bpctl_cmd.status = + get_bypass_wd_fn(pbpctl_dev, (int *)&(bpctl_cmd.data[0])); + break; + + case IOCTL_TX_MSG(GET_WD_EXPIRE_TIME): + bpctl_cmd.status = + get_wd_expire_time_fn(pbpctl_dev, + (int *)&(bpctl_cmd.data[0])); + break; + + case IOCTL_TX_MSG(RESET_BYPASS_WD_TIMER): + bpctl_cmd.status = reset_bypass_wd_timer_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(GET_WD_SET_CAPS): + bpctl_cmd.status = get_wd_set_caps_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_STD_NIC): + bpctl_cmd.status = + set_std_nic_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_STD_NIC): + bpctl_cmd.status = get_std_nic_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_TAP): + bpctl_cmd.status = + set_tap_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_TAP): + bpctl_cmd.status = get_tap_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(GET_TAP_CHANGE): + bpctl_cmd.status = get_tap_change_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_DIS_TAP): + bpctl_cmd.status = + set_dis_tap_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_DIS_TAP): + bpctl_cmd.status = get_dis_tap_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_TAP_PWUP): + bpctl_cmd.status = + set_tap_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_TAP_PWUP): + bpctl_cmd.status = get_tap_pwup_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_WD_EXP_MODE): + bpctl_cmd.status = + set_wd_exp_mode_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_WD_EXP_MODE): + bpctl_cmd.status = get_wd_exp_mode_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(GET_DIS_BYPASS): + bpctl_cmd.status = get_dis_bypass_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_DIS_BYPASS): + bpctl_cmd.status = + set_dis_bypass_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BYPASS_CHANGE): + bpctl_cmd.status = get_bypass_change_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(GET_BYPASS): + bpctl_cmd.status = get_bypass_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_BYPASS): + bpctl_cmd.status = + set_bypass_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BYPASS_CAPS): + bpctl_cmd.status = get_bypass_caps_fn(pbpctl_dev); + /*preempt_enable(); */ + /*rcu_read_unlock();*/ + spin_unlock_irqrestore(&bpvm_lock, flags); + if (copy_to_user + (argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) { + /*unlock_bpctl(); */ + /*preempt_enable(); */ + ret = -EFAULT; + goto bp_exit; + } + goto bp_exit; + + case IOCTL_TX_MSG(GET_BYPASS_SLAVE): + bpctl_cmd.status = + get_bypass_slave_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(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_TX): + bpctl_cmd.status = set_tx_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + case IOCTL_TX_MSG(GET_TX): + bpctl_cmd.status = get_tx_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_WD_AUTORESET): + bpctl_cmd.status = + set_wd_autoreset_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + + break; + case IOCTL_TX_MSG(GET_WD_AUTORESET): + + bpctl_cmd.status = get_wd_autoreset_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_DISC): + bpctl_cmd.status = + set_disc_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + case IOCTL_TX_MSG(GET_DISC): + bpctl_cmd.status = get_disc_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(GET_DISC_CHANGE): + bpctl_cmd.status = get_disc_change_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_DIS_DISC): + bpctl_cmd.status = + set_dis_disc_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + case IOCTL_TX_MSG(GET_DIS_DISC): + bpctl_cmd.status = get_dis_disc_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_DISC_PWUP): + bpctl_cmd.status = + set_disc_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + case IOCTL_TX_MSG(GET_DISC_PWUP): + bpctl_cmd.status = get_disc_pwup_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(GET_BYPASS_INFO): + + bpctl_cmd.status = + get_bypass_info_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_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_TPL): + bpctl_cmd.status = get_tpl_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_BP_WAIT_AT_PWUP): + bpctl_cmd.status = + set_bp_wait_at_pwup_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_fn(pbpctl_dev); + break; + case IOCTL_TX_MSG(SET_BP_HW_RESET): + bpctl_cmd.status = + set_bp_hw_reset_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BP_HW_RESET): + bpctl_cmd.status = get_bp_hw_reset_fn(pbpctl_dev); + break; +#ifdef BP_SELF_TEST + case IOCTL_TX_MSG(SET_BP_SELF_TEST): + bpctl_cmd.status = + set_bp_self_test_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + + break; + case IOCTL_TX_MSG(GET_BP_SELF_TEST): + bpctl_cmd.status = get_bp_self_test_fn(pbpctl_dev); + break; + +#endif +#if 0 + case IOCTL_TX_MSG(SET_DISC_PORT): + bpctl_cmd.status = + set_disc_port_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_DISC_PORT): + bpctl_cmd.status = get_disc_port_fn(pbpctl_dev); + break; + + case IOCTL_TX_MSG(SET_DISC_PORT_PWUP): + bpctl_cmd.status = + set_disc_port_pwup_fn(pbpctl_dev, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_DISC_PORT_PWUP): + bpctl_cmd.status = get_disc_port_pwup_fn(pbpctl_dev); + break; +#endif + case IOCTL_TX_MSG(SET_BP_FORCE_LINK): + bpctl_cmd.status = + set_bp_force_link_fn(dev_idx, bpctl_cmd.in_param[2]); + break; + + case IOCTL_TX_MSG(GET_BP_FORCE_LINK): + bpctl_cmd.status = get_bp_force_link_fn(dev_idx); + break; + + default: + /* unlock_bpctl(); */ + + ret = -EOPNOTSUPP; + /* preempt_enable(); */ + /* rcu_read_unlock();*/ + spin_unlock_irqrestore(&bpvm_lock, flags); + goto bp_exit; + } + /* unlock_bpctl(); */ + /* preempt_enable(); */ + bpcmd_exit: + /* rcu_read_unlock(); */ + spin_unlock_irqrestore(&bpvm_lock, flags); + if (copy_to_user(argp, (void *)&bpctl_cmd, sizeof(struct bpctl_cmd))) + ret = -EFAULT; + ret = SUCCESS; + bp_exit: + /* unlock_kernel(); */ + /* spin_unlock_irqrestore(&bpvm_lock, flags); */ + unlock_bpctl(); + /* unlock_kernel(); */ + return ret; +} + +static const struct file_operations Fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = device_ioctl, +}; + +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend, dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif + +#define SILICOM_E1000BP_ETHERNET_DEVICE(device_id) {\ + PCI_DEVICE(SILICOM_VID, device_id)} + +enum board_type { + PXG2BPFI, + PXG2BPFIL, + PXG2BPFILX, + PXG2BPFILLX, + PXGBPI, + PXGBPIG, + PXG2TBFI, + PXG4BPI, + PXG4BPFI, + PEG4BPI, + PEG2BPI, + PEG4BPIN, + PEG2BPFI, + PEG2BPFILX, + PMCXG2BPFI, + PMCXG2BPFIN, + PEG4BPII, + PEG4BPFII, + PXG4BPFILX, + PMCXG2BPIN, + PMCXG4BPIN, + PXG2BISC1, + PEG2TBFI, + PXG2TBI, + PXG4BPFID, + PEG4BPFI, + PEG4BPIPT, + PXG6BPI, + PEG4BPIL, + PMCXG2BPIN2, + PMCXG4BPIN2, + PMCX2BPI, + PEG2BPFID, + PEG2BPFIDLX, + PMCX4BPI, + MEG2BPFILN, + MEG2BPFINX, + PEG4BPFILX, + PE10G2BPISR, + PE10G2BPILR, + MHIO8AD, + PE10G2BPICX4, + PEG2BPI5, + PEG6BPI, + PEG4BPFI5, + PEG4BPFI5LX, + MEG2BPFILXLN, + PEG2BPIX1, + MEG2BPFILXNX, + XE10G2BPIT, + XE10G2BPICX4, + XE10G2BPISR, + XE10G2BPILR, + PEG4BPIIO, + XE10G2BPIXR, + PE10GDBISR, + PE10GDBILR, + PEG2BISC6, + PEG6BPIFC, + PE10G2BPTCX4, + PE10G2BPTSR, + PE10G2BPTLR, + PE10G2BPTT, + PEG4BPI6, + PEG4BPFI6, + PEG4BPFI6LX, + PEG4BPFI6ZX, + PEG2BPI6, + PEG2BPFI6, + PEG2BPFI6LX, + PEG2BPFI6ZX, + PEG2BPFI6FLXM, + PEG4BPI6FC, + PEG4BPFI6FC, + PEG4BPFI6FCLX, + PEG4BPFI6FCZX, + PEG6BPI6, + PEG2BPI6SC6, + MEG2BPI6, + XEG2BPI6, + MEG4BPI6, + PEG2BPFI5, + PEG2BPFI5LX, + PXEG4BPFI, + M1EG2BPI6, + M1EG2BPFI6, + M1EG2BPFI6LX, + M1EG2BPFI6ZX, + M1EG4BPI6, + M1EG4BPFI6, + M1EG4BPFI6LX, + M1EG4BPFI6ZX, + M1EG6BPI6, + M1E2G4BPi80, + M1E2G4BPFi80, + M1E2G4BPFi80LX, + M1E2G4BPFi80ZX, + PE210G2SPI9, + M1E10G2BPI9CX4, + M1E10G2BPI9SR, + M1E10G2BPI9LR, + M1E10G2BPI9T, + PE210G2BPI9CX4, + PE210G2BPI9SR, + PE210G2BPI9LR, + PE210G2BPI9T, + M2EG2BPFI6, + M2EG2BPFI6LX, + M2EG2BPFI6ZX, + M2EG4BPI6, + M2EG4BPFI6, + M2EG4BPFI6LX, + M2EG4BPFI6ZX, + M2EG6BPI6, + PEG2DBI6, + PEG2DBFI6, + PEG2DBFI6LX, + PEG2DBFI6ZX, + PE2G4BPi80, + PE2G4BPFi80, + PE2G4BPFi80LX, + PE2G4BPFi80ZX, + PE2G4BPi80L, + M6E2G8BPi80A, + + PE2G2BPi35, + PAC1200BPi35, + PE2G2BPFi35, + PE2G2BPFi35LX, + PE2G2BPFi35ZX, + PE2G4BPi35, + PE2G4BPi35L, + PE2G4BPFi35, + PE2G4BPFi35LX, + PE2G4BPFi35ZX, + + PE2G6BPi35, + PE2G6BPi35CX, + + PE2G2BPi80, + PE2G2BPFi80, + PE2G2BPFi80LX, + PE2G2BPFi80ZX, + M2E10G2BPI9CX4, + M2E10G2BPI9SR, + M2E10G2BPI9LR, + M2E10G2BPI9T, + M6E2G8BPi80, + PE210G2DBi9SR, + PE210G2DBi9SRRB, + PE210G2DBi9LR, + PE210G2DBi9LRRB, + PE310G4DBi940SR, + PE310G4BPi9T, + PE310G4BPi9SR, + PE310G4BPi9LR, + PE210G2BPi40, +}; + +struct bpmod_info { + unsigned int vendor; + unsigned int device; + unsigned int subvendor; + unsigned int subdevice; + unsigned int index; + char *bp_name; + +}; + +struct { + char *name; +} dev_desc[] = { + {"Silicom Bypass PXG2BPFI-SD series adapter"}, + {"Silicom Bypass PXG2BPFIL-SD series adapter"}, + {"Silicom Bypass PXG2BPFILX-SD series adapter"}, + {"Silicom Bypass PXG2BPFILLX-SD series adapter"}, + {"Silicom Bypass PXG2BPI-SD series adapter"}, + {"Silicom Bypass PXG2BPIG-SD series adapter"}, + {"Silicom Bypass PXG2TBFI-SD series adapter"}, + {"Silicom Bypass PXG4BPI-SD series adapter"}, + {"Silicom Bypass PXG4BPFI-SD series adapter"}, + {"Silicom Bypass PEG4BPI-SD series adapter"}, + {"Silicom Bypass PEG2BPI-SD series adapter"}, + {"Silicom Bypass PEG4BPIN-SD series adapter"}, + {"Silicom Bypass PEG2BPFI-SD series adapter"}, + {"Silicom Bypass PEG2BPFI-LX-SD series adapter"}, + {"Silicom Bypass PMCX2BPFI-SD series adapter"}, + {"Silicom Bypass PMCX2BPFI-N series adapter"}, + {"Intel Bypass PEG2BPII series adapter"}, + {"Intel Bypass PEG2BPFII series adapter"}, + {"Silicom Bypass PXG4BPFILX-SD series adapter"}, + {"Silicom Bypass PMCX2BPI-N series adapter"}, + {"Silicom Bypass PMCX4BPI-N series adapter"}, + {"Silicom Bypass PXG2BISC1-SD series adapter"}, + {"Silicom Bypass PEG2TBFI-SD series adapter"}, + {"Silicom Bypass PXG2TBI-SD series adapter"}, + {"Silicom Bypass PXG4BPFID-SD series adapter"}, + {"Silicom Bypass PEG4BPFI-SD series adapter"}, + {"Silicom Bypass PEG4BPIPT-SD series adapter"}, + {"Silicom Bypass PXG6BPI-SD series adapter"}, + {"Silicom Bypass PEG4BPIL-SD series adapter"}, + {"Silicom Bypass PMCX2BPI-N2 series adapter"}, + {"Silicom Bypass PMCX4BPI-N2 series adapter"}, + {"Silicom Bypass PMCX2BPI-SD series adapter"}, + {"Silicom Bypass PEG2BPFID-SD series adapter"}, + {"Silicom Bypass PEG2BPFIDLX-SD series adapter"}, + {"Silicom Bypass PMCX4BPI-SD series adapter"}, + {"Silicom Bypass MEG2BPFILN-SD series adapter"}, + {"Silicom Bypass MEG2BPFINX-SD series adapter"}, + {"Silicom Bypass PEG4BPFILX-SD series adapter"}, + {"Silicom Bypass PE10G2BPISR-SD series adapter"}, + {"Silicom Bypass PE10G2BPILR-SD series adapter"}, + {"Silicom Bypass MHIO8AD-SD series adapter"}, + {"Silicom Bypass PE10G2BPICX4-SD series adapter"}, + {"Silicom Bypass PEG2BPI5-SD series adapter"}, + {"Silicom Bypass PEG6BPI5-SD series adapter"}, + {"Silicom Bypass PEG4BPFI5-SD series adapter"}, + {"Silicom Bypass PEG4BPFI5LX-SD series adapter"}, + {"Silicom Bypass MEG2BPFILXLN-SD series adapter"}, + {"Silicom Bypass PEG2BPIX1-SD series adapter"}, + {"Silicom Bypass MEG2BPFILXNX-SD series adapter"}, + {"Silicom Bypass XE10G2BPIT-SD series adapter"}, + {"Silicom Bypass XE10G2BPICX4-SD series adapter"}, + {"Silicom Bypass XE10G2BPISR-SD series adapter"}, + {"Silicom Bypass XE10G2BPILR-SD series adapter"}, + {"Intel Bypass PEG2BPFII0 series adapter"}, + {"Silicom Bypass XE10G2BPIXR series adapter"}, + {"Silicom Bypass PE10G2DBISR series adapter"}, + {"Silicom Bypass PEG2BI5SC6 series adapter"}, + {"Silicom Bypass PEG6BPI5FC series adapter"}, + + {"Silicom Bypass PE10G2BPTCX4 series adapter"}, + {"Silicom Bypass PE10G2BPTSR series adapter"}, + {"Silicom Bypass PE10G2BPTLR series adapter"}, + {"Silicom Bypass PE10G2BPTT series adapter"}, + {"Silicom Bypass PEG4BPI6 series adapter"}, + {"Silicom Bypass PEG4BPFI6 series adapter"}, + {"Silicom Bypass PEG4BPFI6LX series adapter"}, + {"Silicom Bypass PEG4BPFI6ZX series adapter"}, + {"Silicom Bypass PEG2BPI6 series adapter"}, + {"Silicom Bypass PEG2BPFI6 series adapter"}, + {"Silicom Bypass PEG2BPFI6LX series adapter"}, + {"Silicom Bypass PEG2BPFI6ZX series adapter"}, + {"Silicom Bypass PEG2BPFI6FLXM series adapter"}, + {"Silicom Bypass PEG4BPI6FC series adapter"}, + {"Silicom Bypass PEG4BPFI6FC series adapter"}, + {"Silicom Bypass PEG4BPFI6FCLX series adapter"}, + {"Silicom Bypass PEG4BPFI6FCZX series adapter"}, + {"Silicom Bypass PEG6BPI6 series adapter"}, + {"Silicom Bypass PEG2BPI6SC6 series adapter"}, + {"Silicom Bypass MEG2BPI6 series adapter"}, + {"Silicom Bypass XEG2BPI6 series adapter"}, + {"Silicom Bypass MEG4BPI6 series adapter"}, + {"Silicom Bypass PEG2BPFI5-SD series adapter"}, + {"Silicom Bypass PEG2BPFI5LX-SD series adapter"}, + {"Silicom Bypass PXEG4BPFI-SD series adapter"}, + {"Silicom Bypass MxEG2BPI6 series adapter"}, + {"Silicom Bypass MxEG2BPFI6 series adapter"}, + {"Silicom Bypass MxEG2BPFI6LX series adapter"}, + {"Silicom Bypass MxEG2BPFI6ZX series adapter"}, + {"Silicom Bypass MxEG4BPI6 series adapter"}, + {"Silicom Bypass MxEG4BPFI6 series adapter"}, + {"Silicom Bypass MxEG4BPFI6LX series adapter"}, + {"Silicom Bypass MxEG4BPFI6ZX series adapter"}, + {"Silicom Bypass MxEG6BPI6 series adapter"}, + {"Silicom Bypass MxE2G4BPi80 series adapter"}, + {"Silicom Bypass MxE2G4BPFi80 series adapter"}, + {"Silicom Bypass MxE2G4BPFi80LX series adapter"}, + {"Silicom Bypass MxE2G4BPFi80ZX series adapter"}, + + {"Silicom Bypass PE210G2SPI9 series adapter"}, + + {"Silicom Bypass MxE210G2BPI9CX4 series adapter"}, + {"Silicom Bypass MxE210G2BPI9SR series adapter"}, + {"Silicom Bypass MxE210G2BPI9LR series adapter"}, + {"Silicom Bypass MxE210G2BPI9T series adapter"}, + + {"Silicom Bypass PE210G2BPI9CX4 series adapter"}, + {"Silicom Bypass PE210G2BPI9SR series adapter"}, + {"Silicom Bypass PE210G2BPI9LR series adapter"}, + {"Silicom Bypass PE210G2BPI9T series adapter"}, + + {"Silicom Bypass M2EG2BPFI6 series adapter"}, + {"Silicom Bypass M2EG2BPFI6LX series adapter"}, + {"Silicom Bypass M2EG2BPFI6ZX series adapter"}, + {"Silicom Bypass M2EG4BPI6 series adapter"}, + {"Silicom Bypass M2EG4BPFI6 series adapter"}, + {"Silicom Bypass M2EG4BPFI6LX series adapter"}, + {"Silicom Bypass M2EG4BPFI6ZX series adapter"}, + {"Silicom Bypass M2EG6BPI6 series adapter"}, + + {"Silicom Bypass PEG2DBI6 series adapter"}, + {"Silicom Bypass PEG2DBFI6 series adapter"}, + {"Silicom Bypass PEG2DBFI6LX series adapter"}, + {"Silicom Bypass PEG2DBFI6ZX series adapter"}, + + {"Silicom Bypass PE2G4BPi80 series adapter"}, + {"Silicom Bypass PE2G4BPFi80 series adapter"}, + {"Silicom Bypass PE2G4BPFi80LX series adapter"}, + {"Silicom Bypass PE2G4BPFi80ZX series adapter"}, + + {"Silicom Bypass PE2G4BPi80L series adapter"}, + {"Silicom Bypass MxE2G8BPi80A series adapter"}, + + {"Silicom Bypass PE2G2BPi35 series adapter"}, + {"Silicom Bypass PAC1200BPi35 series adapter"}, + {"Silicom Bypass PE2G2BPFi35 series adapter"}, + {"Silicom Bypass PE2G2BPFi35LX series adapter"}, + {"Silicom Bypass PE2G2BPFi35ZX series adapter"}, + + {"Silicom Bypass PE2G4BPi35 series adapter"}, + {"Silicom Bypass PE2G4BPi35L series adapter"}, + {"Silicom Bypass PE2G4BPFi35 series adapter"}, + {"Silicom Bypass PE2G4BPFi35LX series adapter"}, + {"Silicom Bypass PE2G4BPFi35ZX series adapter"}, + + {"Silicom Bypass PE2G6BPi35 series adapter"}, + {"Silicom Bypass PE2G6BPi35CX series adapter"}, + + {"Silicom Bypass PE2G2BPi80 series adapter"}, + {"Silicom Bypass PE2G2BPFi80 series adapter"}, + {"Silicom Bypass PE2G2BPFi80LX series adapter"}, + {"Silicom Bypass PE2G2BPFi80ZX series adapter"}, + + {"Silicom Bypass M2E10G2BPI9CX4 series adapter"}, + {"Silicom Bypass M2E10G2BPI9SR series adapter"}, + {"Silicom Bypass M2E10G2BPI9LR series adapter"}, + {"Silicom Bypass M2E10G2BPI9T series adapter"}, + {"Silicom Bypass MxE2G8BPi80 series adapter"}, + {"Silicom Bypass PE210G2DBi9SR series adapter"}, + {"Silicom Bypass PE210G2DBi9SRRB series adapter"}, + {"Silicom Bypass PE210G2DBi9LR series adapter"}, + {"Silicom Bypass PE210G2DBi9LRRB series adapter"}, + {"Silicom Bypass PE310G4DBi9-SR series adapter"}, + {"Silicom Bypass PE310G4BPi9T series adapter"}, + {"Silicom Bypass PE310G4BPi9SR series adapter"}, + {"Silicom Bypass PE310G4BPi9LR series adapter"}, + {"Silicom Bypass PE210G2BPi40T series adapter"}, + {0}, +}; + +static struct bpmod_info tx_ctl_pci_tbl[] = { + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFI_SSID, PXG2BPFI, + "PXG2BPFI-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFIL_SSID, PXG2BPFIL, + "PXG2BPFIL-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFILX_SSID, PXG2BPFILX, + "PXG2BPFILX-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFILLX_SSID, PXG2BPFILLX, + "PXG2BPFILLXSD"}, + {0x8086, 0x1010, SILICOM_SVID, SILICOM_PXGBPI_SSID, PXGBPI, + "PXG2BPI-SD"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXGBPIG_SSID, PXGBPIG, + "PXG2BPIG-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2TBFI_SSID, PXG2TBFI, + "PXG2TBFI-SD"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG4BPI_SSID, PXG4BPI, + "PXG4BPI-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFI_SSID, PXG4BPFI, + "PXG4BPFI-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFILX_SSID, PXG4BPFILX, + "PXG4BPFILX-SD"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PEG4BPI_SSID, PEG4BPI, + "PEXG4BPI-SD"}, + {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG2BPI_SSID, PEG2BPI, + "PEG2BPI-SD"}, + {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG4BPIN_SSID, PEG4BPIN, + "PEG4BPI-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFI_SSID, PEG2BPFI, + "PEG2BPFI-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFILX_SSID, PEG2BPFILX, + "PEG2BPFILX-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PMCXG2BPFI_SSID, PMCXG2BPFI, + "PMCX2BPFI-SD"}, + {0x8086, 0x107a, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPFIN_SSID, + PMCXG2BPFIN, "PMCX2BPFI-N"}, + {0x8086, INTEL_PEG4BPII_PID, 0x8086, INTEL_PEG4BPII_SSID, PEG4BPII, + "PEG4BPII"}, + {0x8086, INTEL_PEG4BPIIO_PID, 0x8086, INTEL_PEG4BPIIO_SSID, PEG4BPIIO, + "PEG4BPII0"}, + {0x8086, INTEL_PEG4BPFII_PID, 0x8086, INTEL_PEG4BPFII_SSID, PEG4BPFII, + "PEG4BPFII"}, + {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPIN_SSID, + PMCXG2BPIN, "PMCX2BPI-N"}, + {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG4BPIN_SSID, + PMCXG4BPIN, "PMCX4BPI-N"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG2BISC1_SSID, PXG2BISC1, + "PXG2BISC1-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2TBFI_SSID, PEG2TBFI, + "PEG2TBFI-SD"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG2TBI_SSID, PXG2TBI, + "PXG2TBI-SD"}, + {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG4BPFID_SSID, PXG4BPFID, + "PXG4BPFID-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG4BPFI_SSID, PEG4BPFI, + "PEG4BPFI-SD"}, + {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG4BPIPT_SSID, PEG4BPIPT, + "PEG4BPIPT-SD"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PXG6BPI_SSID, PXG6BPI, + "PXG6BPI-SD"}, + {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPIL_SSID /*PCI_ANY_ID */ , PEG4BPIL, "PEG4BPIL-SD"}, + {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG2BPIN2_SSID, + PMCXG2BPIN2, "PMCX2BPI-N2"}, + {0x8086, 0x1079, NOKIA_PMCXG2BPFIN_SVID, NOKIA_PMCXG4BPIN2_SSID, + PMCXG4BPIN2, "PMCX4BPI-N2"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PMCX2BPI_SSID, PMCX2BPI, + "PMCX2BPI-SD"}, + {0x8086, 0x1079, SILICOM_SVID, SILICOM_PMCX4BPI_SSID, PMCX4BPI, + "PMCX4BPI-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFID_SSID, PEG2BPFID, + "PEG2BPFID-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG2BPFIDLX_SSID, PEG2BPFIDLX, + "PEG2BPFIDLXSD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILN_SSID, MEG2BPFILN, + "MEG2BPFILN-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFINX_SSID, MEG2BPFINX, + "MEG2BPFINX-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PEG4BPFILX_SSID, PEG4BPFILX, + "PEG4BPFILX-SD"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPISR_SSID, + PE10G2BPISR, "PE10G2BPISR"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPILR_SSID, + PE10G2BPILR, "PE10G2BPILR"}, + {0x8086, 0x10a9, SILICOM_SVID, SILICOM_MHIO8AD_SSID, MHIO8AD, + "MHIO8AD-SD"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_PE10G2BPICX4_SSID, + PE10G2BPISR, "PE10G2BPICX4"}, + {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPI5_SSID /*PCI_ANY_ID */ , PEG2BPI5, "PEG2BPI5-SD"}, + {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG6BPI_SSID /*PCI_ANY_ID */ , PEG6BPI, "PEG6BPI5"}, + {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG4BPFI5_SSID, + PEG4BPFI5, "PEG4BPFI5"}, + {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI5LX_SSID, PEG4BPFI5LX, "PEG4BPFI5LX"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILXLN_SSID, MEG2BPFILXLN, + "MEG2BPFILXLN"}, + {0x8086, 0x105e, SILICOM_SVID, SILICOM_PEG2BPIX1_SSID, PEG2BPIX1, + "PEG2BPIX1-SD"}, + {0x8086, 0x105f, SILICOM_SVID, SILICOM_MEG2BPFILXNX_SSID, MEG2BPFILXNX, + "MEG2BPFILXNX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_XE10G2BPIT_SSID, XE10G2BPIT, + "XE10G2BPIT"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID, SILICOM_XE10G2BPICX4_SSID, + XE10G2BPICX4, "XE10G2BPICX4"}, + {0x8086, 0x10C6, SILICOM_SVID, SILICOM_XE10G2BPISR_SSID, XE10G2BPISR, + "XE10G2BPISR"}, + {0x8086, 0x10C6, SILICOM_SVID, SILICOM_XE10G2BPILR_SSID, XE10G2BPILR, + "XE10G2BPILR"}, + {0x8086, 0x10C6, NOKIA_XE10G2BPIXR_SVID, NOKIA_XE10G2BPIXR_SSID, + XE10G2BPIXR, "XE10G2BPIXR"}, + {0x8086, 0x10C6, SILICOM_SVID, SILICOM_PE10GDBISR_SSID, PE10GDBISR, + "PE10G2DBISR"}, + {0x8086, 0x10C6, SILICOM_SVID, SILICOM_PE10GDBILR_SSID, PE10GDBILR, + "PE10G2DBILR"}, + {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BISC6_SSID /*PCI_ANY_ID */ , PEG2BISC6, "PEG2BI5SC6"}, + {0x8086, 0x10a7, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG6BPIFC_SSID /*PCI_ANY_ID */ , PEG6BPIFC, "PEG6BPI5FC"}, + + {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, + SILICOM_PE10G2BPTCX4_SSID, PE10G2BPTCX4, "PE10G2BPTCX4"}, + {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, + SILICOM_PE10G2BPTSR_SSID, PE10G2BPTSR, "PE10G2BPTSR"}, + {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, + SILICOM_PE10G2BPTLR_SSID, PE10G2BPTLR, "PE10G2BPTLR"}, + {BROADCOM_VID, BROADCOM_PE10G2_PID, SILICOM_SVID, + SILICOM_PE10G2BPTT_SSID, PE10G2BPTT, "PE10G2BPTT"}, + + /* {BROADCOM_VID, BROADCOM_PE10G2_PID, PCI_ANY_ID, PCI_ANY_ID, PE10G2BPTCX4, "PE10G2BPTCX4"}, */ + + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPI6_SSID /*PCI_ANY_ID */ , PEG4BPI6, "PEG4BPI6"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI6_SSID /*PCI_ANY_ID */ , PEG4BPFI6, "PEG4BPFI6"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI6LX_SSID /*PCI_ANY_ID */ , PEG4BPFI6LX, "PEG4BPFI6LX"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI6ZX_SSID /*PCI_ANY_ID */ , PEG4BPFI6ZX, "PEG4BPFI6ZX"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPI6_SSID /*PCI_ANY_ID */ , PEG2BPI6, "PEG2BPI6"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPFI6_SSID /*PCI_ANY_ID */ , PEG2BPFI6, "PEG2BPFI6"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPFI6LX_SSID /*PCI_ANY_ID */ , PEG2BPFI6LX, "PEG2BPFI6LX"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPFI6ZX_SSID /*PCI_ANY_ID */ , PEG2BPFI6ZX, "PEG2BPFI6ZX"}, + {0x8086, 0x10e7, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPFI6FLXM_SSID /*PCI_ANY_ID */ , PEG2BPFI6FLXM, + "PEG2BPFI6FLXM"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPI6FC_SSID /*PCI_ANY_ID */ , PEG4BPI6FC, "PEG4BPI6FC"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI6FC_SSID /*PCI_ANY_ID */ , PEG4BPFI6FC, "PEG4BPFI6FC"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI6FCLX_SSID /*PCI_ANY_ID */ , PEG4BPFI6FCLX, + "PEG4BPFI6FCLX"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG4BPFI6FCZX_SSID /*PCI_ANY_ID */ , PEG4BPFI6FCZX, + "PEG4BPFI6FCZX"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG6BPI6_SSID /*PCI_ANY_ID */ , PEG6BPI6, "PEG6BPI6"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPI6SC6_SSID /*PCI_ANY_ID */ , PEG2BPI6SC6, + "PEG6BPI62SC6"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_MEG2BPI6_SSID /*PCI_ANY_ID */ , MEG2BPI6, "MEG2BPI6"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_XEG2BPI6_SSID /*PCI_ANY_ID */ , XEG2BPI6, "XEG2BPI6"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_MEG4BPI6_SSID /*PCI_ANY_ID */ , MEG4BPI6, "MEG4BPI6"}, + + {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , SILICOM_PEG2BPFI5_SSID, + PEG2BPFI5, "PEG2BPFI5"}, + {0x8086, 0x10a9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2BPFI5LX_SSID, PEG2BPFI5LX, "PEG2BPFI5LX"}, + + {0x8086, 0x105f, SILICOM_SVID, SILICOM_PXEG4BPFI_SSID, PXEG4BPFI, + "PXEG4BPFI-SD"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG2BPI6_SSID /*PCI_ANY_ID */ , M1EG2BPI6, "MxEG2BPI6"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG2BPFI6_SSID /*PCI_ANY_ID */ , M1EG2BPFI6, "MxEG2BPFI6"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG2BPFI6LX_SSID /*PCI_ANY_ID */ , M1EG2BPFI6LX, + "MxEG2BPFI6LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG2BPFI6ZX_SSID /*PCI_ANY_ID */ , M1EG2BPFI6ZX, + "MxEG2BPFI6ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG4BPI6_SSID /*PCI_ANY_ID */ , M1EG4BPI6, "MxEG4BPI6"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG4BPFI6_SSID /*PCI_ANY_ID */ , M1EG4BPFI6, "MxEG4BPFI6"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG4BPFI6LX_SSID /*PCI_ANY_ID */ , M1EG4BPFI6LX, + "MxEG4BPFI6LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG4BPFI6ZX_SSID /*PCI_ANY_ID */ , M1EG4BPFI6ZX, + "MxEG4BPFI6ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1EG6BPI6_SSID /*PCI_ANY_ID */ , M1EG6BPI6, "MxEG6BPI6"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E2G4BPi80_SSID /*PCI_ANY_ID */ , M1E2G4BPi80, "MxE2G4BPi80"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E2G4BPFi80_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80, + "MxE2G4BPFi80"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E2G4BPFi80LX_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80LX, + "MxE2G4BPFi80LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E2G4BPFi80ZX_SSID /*PCI_ANY_ID */ , M1E2G4BPFi80ZX, + "MxE2G4BPFi80ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG2BPFI6_SSID /*PCI_ANY_ID */ , M2EG2BPFI6, "M2EG2BPFI6"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG2BPFI6LX_SSID /*PCI_ANY_ID */ , M2EG2BPFI6LX, + "M2EG2BPFI6LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG2BPFI6ZX_SSID /*PCI_ANY_ID */ , M2EG2BPFI6ZX, + "M2EG2BPFI6ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG4BPI6_SSID /*PCI_ANY_ID */ , M2EG4BPI6, "M2EG4BPI6"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG4BPFI6_SSID /*PCI_ANY_ID */ , M2EG4BPFI6, "M2EG4BPFI6"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG4BPFI6LX_SSID /*PCI_ANY_ID */ , M2EG4BPFI6LX, + "M2EG4BPFI6LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG4BPFI6ZX_SSID /*PCI_ANY_ID */ , M2EG4BPFI6ZX, + "M2EG4BPFI6ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2EG6BPI6_SSID /*PCI_ANY_ID */ , M2EG6BPI6, "M2EG6BPI6"}, + + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2DBI6_SSID /*PCI_ANY_ID */ , PEG2DBI6, "PEG2DBI6"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2DBFI6_SSID /*PCI_ANY_ID */ , PEG2DBFI6, "PEG2DBFI6"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2DBFI6LX_SSID /*PCI_ANY_ID */ , PEG2DBFI6LX, "PEG2DBFI6LX"}, + {0x8086, 0x10e6, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PEG2DBFI6ZX_SSID /*PCI_ANY_ID */ , PEG2DBFI6ZX, "PEG2DBFI6ZX"}, + + {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE210G2DBi9SR_SSID, PE210G2DBi9SR, "PE210G2DBi9SR"}, + {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE210G2DBi9LR_SSID, PE210G2DBi9LR, "PE210G2DBi9LR"}, + {0x8086, 0x10F9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE310G4DBi940SR_SSID, PE310G4DBi940SR, "PE310G4DBi9SR"}, + + {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE310G4BPi9T_SSID, PE310G4BPi9T, "PE310G4BPi9T"}, + {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE310G4BPi9SR_SSID, PE310G4BPi9SR, "PE310G4BPi9SR"}, + {0x8086, 0x10Fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE310G4BPi9LR_SSID, PE310G4BPi9LR, "PE310G4BPi9LR"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPi80_SSID /*PCI_ANY_ID */ , PE2G4BPi80, "PE2G4BPi80"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPFi80_SSID /*PCI_ANY_ID */ , PE2G4BPFi80, "PE2G4BPFi80"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPFi80LX_SSID /*PCI_ANY_ID */ , PE2G4BPFi80LX, + "PE2G4BPFi80LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPFi80ZX_SSID /*PCI_ANY_ID */ , PE2G4BPFi80ZX, + "PE2G4BPFi80ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPi80L_SSID /*PCI_ANY_ID */ , PE2G4BPi80L, "PE2G4BPi80L"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M6E2G8BPi80A_SSID /*PCI_ANY_ID */ , M6E2G8BPi80A, + "MxE2G8BPi80A"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPi35_SSID /*PCI_ANY_ID */ , PE2G2BPi35, "PE2G2BPi35"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PAC1200BPi35_SSID /*PCI_ANY_ID */ , PAC1200BPi35, + "PAC1200BPi35"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPFi35_SSID /*PCI_ANY_ID */ , PE2G2BPFi35, "PE2G2BPFi35"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPFi35LX_SSID /*PCI_ANY_ID */ , PE2G2BPFi35LX, + "PE2G2BPFi35LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPFi35ZX_SSID /*PCI_ANY_ID */ , PE2G2BPFi35ZX, + "PE2G2BPFi35ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPi35_SSID /*PCI_ANY_ID */ , PE2G4BPi35, "PE2G4BPi35"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPi35L_SSID /*PCI_ANY_ID */ , PE2G4BPi35L, "PE2G4BPi35L"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPFi35_SSID /*PCI_ANY_ID */ , PE2G4BPFi35, "PE2G4BPFi35"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPFi35LX_SSID /*PCI_ANY_ID */ , PE2G4BPFi35LX, + "PE2G4BPFi35LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G4BPFi35ZX_SSID /*PCI_ANY_ID */ , PE2G4BPFi35ZX, + "PE2G4BPFi35ZX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G6BPi35_SSID /*PCI_ANY_ID */ , PE2G6BPi35, "PE2G6BPi35"}, + + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa0, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa1, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa2, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa3, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa4, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa5, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa6, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa7, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa8, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaa9, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaaa, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaab, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaac, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaad, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaae, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaaf, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab0, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab1, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab2, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab3, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab4, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab5, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab6, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab7, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab8, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xab9, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xaba, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabb, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabc, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabd, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabe, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , 0xabf, PE2G6BPi35CX, + "PE2G6BPi35CX"}, + + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPi80_SSID /*PCI_ANY_ID */ , PE2G2BPi80, "PE2G2BPi80"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPFi80_SSID /*PCI_ANY_ID */ , PE2G2BPFi80, "PE2G2BPFi80"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPFi80LX_SSID /*PCI_ANY_ID */ , PE2G2BPFi80LX, + "PE2G2BPFi80LX"}, + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE2G2BPFi80ZX_SSID /*PCI_ANY_ID */ , PE2G2BPFi80ZX, + "PE2G2BPFi80ZX"}, + + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_MEG2BPI6_SSID /*PCI_ANY_ID */ , MEG2BPI6, "MEG2BPI6"}, + {0x8086, 0x10c9, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_XEG2BPI6_SSID /*PCI_ANY_ID */ , XEG2BPI6, "XEG2BPI6"}, + +#if 0 + {0x8086, 0x10fb, 0x8086, INTEL_PE210G2SPI9_SSID, PE210G2SPI9, + "PE210G2SPI9"}, +#endif + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E10G2BPI9CX4_SSID /*PCI_ANY_ID */ , M1E10G2BPI9CX4, + "MxE210G2BPI9CX4"}, + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E10G2BPI9SR_SSID /*PCI_ANY_ID */ , M1E10G2BPI9SR, + "MxE210G2BPI9SR"}, + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E10G2BPI9LR_SSID /*PCI_ANY_ID */ , M1E10G2BPI9LR, + "MxE210G2BPI9LR"}, + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M1E10G2BPI9T_SSID /*PCI_ANY_ID */ , M1E10G2BPI9T, + "MxE210G2BPI9T"}, + + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2E10G2BPI9CX4_SSID /*PCI_ANY_ID */ , M2E10G2BPI9CX4, + "M2E10G2BPI9CX4"}, + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2E10G2BPI9SR_SSID /*PCI_ANY_ID */ , M2E10G2BPI9SR, + "M2E10G2BPI9SR"}, + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2E10G2BPI9LR_SSID /*PCI_ANY_ID */ , M2E10G2BPI9LR, + "M2E10G2BPI9LR"}, + {0x8086, 0x10fb, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M2E10G2BPI9T_SSID /*PCI_ANY_ID */ , M2E10G2BPI9T, + "M2E10G2BPI9T"}, + + {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9CX4_SSID, + PE210G2BPI9CX4, "PE210G2BPI9CX4"}, + {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9SR_SSID, + PE210G2BPI9SR, "PE210G2BPI9SR"}, + {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9LR_SSID, + PE210G2BPI9LR, "PE210G2BPI9LR"}, + {0x8086, 0x10fb, SILICOM_SVID, SILICOM_PE210G2BPI9T_SSID, PE210G2BPI9T, + "PE210G2BPI9T"}, + +#if 0 + {0x1374, 0x2c, SILICOM_SVID, SILICOM_PXG4BPI_SSID, PXG4BPI, + "PXG4BPI-SD"}, + + {0x1374, 0x2d, SILICOM_SVID, SILICOM_PXG4BPFI_SSID, PXG4BPFI, + "PXG4BPFI-SD"}, + + {0x1374, 0x3f, SILICOM_SVID, SILICOM_PXG2TBI_SSID, PXG2TBI, + "PXG2TBI-SD"}, + + {0x1374, 0x3d, SILICOM_SVID, SILICOM_PXG2BISC1_SSID, PXG2BISC1, + "PXG2BISC1-SD"}, + + {0x1374, 0x40, SILICOM_SVID, SILICOM_PEG4BPFI_SSID, PEG4BPFI, + "PEG4BPFI-SD"}, + +#ifdef BP_SELF_TEST + {0x1374, 0x28, SILICOM_SVID, 0x28, PXGBPI, "PXG2BPI-SD"}, +#endif +#endif + {0x8086, PCI_ANY_ID, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_M6E2G8BPi80_SSID /*PCI_ANY_ID */ , M6E2G8BPi80, "MxE2G8BPi80"}, + {0x8086, 0x1528, SILICOM_SVID /*PCI_ANY_ID */ , + SILICOM_PE210G2BPi40_SSID /*PCI_ANY_ID */ , PE210G2BPi40, + "PE210G2BPi40T"}, + + /* required last entry */ + {0,} +}; + +static void find_fw(struct bpctl_dev *dev) +{ + unsigned long mmio_start, mmio_len; + struct pci_dev *pdev1 = dev->pdev; + + if ((OLD_IF_SERIES(dev->subdevice)) || + (INTEL_IF_SERIES(dev->subdevice))) + dev->bp_fw_ver = 0xff; + else + dev->bp_fw_ver = bypass_fw_ver(dev); + + if (dev->bp_10gb == 1 && dev->bp_fw_ver == 0xff) { + int cnt = 100; + while (cnt--) { + iounmap((void *)dev->mem_map); + mmio_start = pci_resource_start(pdev1, 0); + mmio_len = pci_resource_len(pdev1, 0); + + dev->mem_map = (unsigned long) + ioremap(mmio_start, mmio_len); + + dev->bp_fw_ver = bypass_fw_ver(dev); + if (dev->bp_fw_ver == 0xa8) + break; + } + } + /* dev->bp_fw_ver=0xa8; */ + printk("firmware version: 0x%x\n", dev->bp_fw_ver); +} + +static int init_one(struct bpctl_dev *dev, struct bpmod_info *info, struct pci_dev *pdev1) +{ + unsigned long mmio_start, mmio_len; + + dev->pdev = pdev1; + mmio_start = pci_resource_start(pdev1, 0); + mmio_len = pci_resource_len(pdev1, 0); + + dev->desc = dev_desc[info->index].name; + dev->name = info->bp_name; + dev->device = info->device; + dev->vendor = info->vendor; + dev->subdevice = info->subdevice; + dev->subvendor = info->subvendor; + dev->func = PCI_FUNC(pdev1->devfn); + dev->slot = PCI_SLOT(pdev1->devfn); + dev->bus = pdev1->bus->number; + dev->mem_map = (unsigned long)ioremap(mmio_start, mmio_len); +#ifdef BP_SYNC_FLAG + spin_lock_init(&dev->bypass_wr_lock); +#endif + if (BP10G9_IF_SERIES(dev->subdevice)) + dev->bp_10g9 = 1; + if (BP10G_IF_SERIES(dev->subdevice)) + dev->bp_10g = 1; + if (PEG540_IF_SERIES(dev->subdevice)) + dev->bp_540 = 1; + if (PEGF5_IF_SERIES(dev->subdevice)) + dev->bp_fiber5 = 1; + if (PEG80_IF_SERIES(dev->subdevice)) + dev->bp_i80 = 1; + if (PEGF80_IF_SERIES(dev->subdevice)) + dev->bp_i80 = 1; + if ((dev->subdevice & 0xa00) == 0xa00) + dev->bp_i80 = 1; + if (BP10GB_IF_SERIES(dev->subdevice)) { + if (dev->ifindex == 0) { + unregister_chrdev(major_num, DEVICE_NAME); + printk("Please load network driver for %s adapter!\n", + dev->name); + return -1; + } + + if (dev->ndev && !(dev->ndev->flags & IFF_UP)) { + unregister_chrdev(major_num, DEVICE_NAME); + printk("Please bring up network interfaces for %s adapter!\n", + dev->name); + return -1; + } + dev->bp_10gb = 1; + } + + if (!dev->bp_10g9) { + if (is_bypass_fn(dev)) { + printk(KERN_INFO "%s found, ", + dev->name); + find_fw(dev); + } + dev->wdt_status = WDT_STATUS_UNKNOWN; + dev->reset_time = 0; + atomic_set(&dev->wdt_busy, 0); + dev->bp_status_un = 1; + + bypass_caps_init(dev); + + init_bypass_wd_auto(dev); + init_bypass_tpl_auto(dev); + if (NOKIA_SERIES(dev->subdevice)) + reset_cont(dev); + } +#ifdef BP_SELF_TEST + dev->bp_tx_data = kzalloc(BPTEST_DATA_LEN, GFP_KERNEL); + if (dev->bp_tx_data) { + memset(dev->bp_tx_data, 0xff, 6); + memset(dev->bp_tx_data + 6, 0x0, 1); + memset(dev->bp_tx_data + 7, 0xaa, 5); + *(__be16 *)(dev->bp_tx_data + 12) = htons(ETH_P_BPTEST); + } else + printk("bp_ctl: Memory allocation error!\n"); +#endif + return 0; +} + +/* +* Initialize the module - Register the character device +*/ + +static int __init bypass_init_module(void) +{ + int ret_val, idx, idx_dev = 0; + struct pci_dev *pdev1 = NULL; + struct bpctl_dev *dev; + + printk(BP_MOD_DESCR " v" BP_MOD_VER "\n"); + 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))) { + + 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(struct bpctl_dev), GFP_KERNEL); + + if (!bpctl_dev_arr) { + printk("Allocation error\n"); + unregister_chrdev(major_num, DEVICE_NAME); + return -1; + } + memset(bpctl_dev_arr, 0, ((device_num) * sizeof(struct bpctl_dev))); + + pdev1 = NULL; + dev = bpctl_dev_arr; + 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))) { + if (init_one(dev, &tx_ctl_pci_tbl[idx], pdev1) < 0) + return -1; + dev++; + } + } + if_scan_init(); + + sema_init(&bpctl_sema, 1); + spin_lock_init(&bpvm_lock); + + for (idx_dev = 0, dev = bpctl_dev_arr; + idx_dev < device_num && dev->pdev; + idx_dev++, dev++) { + if (dev->bp_10g9) { + if (is_bypass_fn(dev)) { + printk(KERN_INFO "%s found, ", dev->name); + dev->bp_fw_ver = bypass_fw_ver(dev); + printk("firmware version: 0x%x\n", + dev->bp_fw_ver); + } + dev->wdt_status = WDT_STATUS_UNKNOWN; + dev->reset_time = 0; + atomic_set(&dev->wdt_busy, 0); + dev->bp_status_un = 1; + + bypass_caps_init(dev); + + init_bypass_wd_auto(dev); + init_bypass_tpl_auto(dev); + } + } + + register_netdevice_notifier(&bp_notifier_block); + return 0; +} + +/* +* Cleanup - unregister the appropriate file from /proc +*/ +static void __exit bypass_cleanup_module(void) +{ + int i; + + unregister_netdevice_notifier(&bp_notifier_block); + + for (i = 0; i < device_num; i++) { + /* unsigned long flags; */ + remove_bypass_wd_auto(&bpctl_dev_arr[i]); + bpctl_dev_arr[i].reset_time = 0; + + remove_bypass_tpl_auto(&bpctl_dev_arr[i]); + } + + /* unmap all devices */ + for (i = 0; i < device_num; i++) { +#ifdef BP_SELF_TEST + kfree(bpctl_dev_arr[i].bp_tx_data); +#endif + iounmap((void *)(bpctl_dev_arr[i].mem_map)); + } + + /* free all devices space */ + kfree(bpctl_dev_arr); + +/* +* Unregister the device +*/ + unregister_chrdev(major_num, DEVICE_NAME); +} + +module_init(bypass_init_module); +module_exit(bypass_cleanup_module); + +int is_bypass_sd(int ifindex) +{ + return is_bypass(get_dev_idx_p(ifindex)); +} +EXPORT_SYMBOL(is_bypass_sd); + +int set_bypass_sd(int ifindex, int bypass_mode) +{ + + return set_bypass_fn(get_dev_idx_p(ifindex), bypass_mode); +} +EXPORT_SYMBOL(set_bypass_sd); + +int get_bypass_sd(int ifindex) +{ + + return get_bypass_fn(get_dev_idx_p(ifindex)); +} +EXPORT_SYMBOL(get_bypass_sd); + +int get_bypass_change_sd(int ifindex) +{ + + return get_bypass_change_fn(get_dev_idx_p(ifindex)); +} +EXPORT_SYMBOL(get_bypass_change_sd); + +int set_dis_bypass_sd(int ifindex, int dis_param) +{ + return set_dis_bypass_fn(get_dev_idx_p(ifindex), dis_param); +} +EXPORT_SYMBOL(set_dis_bypass_sd); + +int get_dis_bypass_sd(int ifindex) +{ + + return get_dis_bypass_fn(get_dev_idx_p(ifindex)); +} +EXPORT_SYMBOL(get_dis_bypass_sd); + +int set_bypass_pwoff_sd(int ifindex, int bypass_mode) +{ + return set_bypass_pwoff_fn(get_dev_idx_p(ifindex), bypass_mode); + +} +EXPORT_SYMBOL(set_bypass_pwoff_sd); + +int get_bypass_pwoff_sd(int ifindex) +{ + return get_bypass_pwoff_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bypass_pwoff_sd); + +int set_bypass_pwup_sd(int ifindex, int bypass_mode) +{ + return set_bypass_pwup_fn(get_dev_idx_p(ifindex), bypass_mode); + +} +EXPORT_SYMBOL(set_bypass_pwup_sd); + +int get_bypass_pwup_sd(int ifindex) +{ + return get_bypass_pwup_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bypass_pwup_sd); + +int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set) +{ + if ((is_bypass(get_dev_idx_p(if_index))) <= 0) + return BP_NOT_CAP; + *ms_timeout_set = set_bypass_wd_fn(get_dev_idx_p(if_index), ms_timeout); + return 0; +} +EXPORT_SYMBOL(set_bypass_wd_sd); + +int get_bypass_wd_sd(int ifindex, int *timeout) +{ + return get_bypass_wd_fn(get_dev_idx_p(ifindex), timeout); + +} +EXPORT_SYMBOL(get_bypass_wd_sd); + +int get_wd_expire_time_sd(int ifindex, int *time_left) +{ + return get_wd_expire_time_fn(get_dev_idx_p(ifindex), time_left); +} +EXPORT_SYMBOL(get_wd_expire_time_sd); + +int reset_bypass_wd_timer_sd(int ifindex) +{ + return reset_bypass_wd_timer_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(reset_bypass_wd_timer_sd); + +int get_wd_set_caps_sd(int ifindex) +{ + return get_wd_set_caps_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_wd_set_caps_sd); + +int set_std_nic_sd(int ifindex, int nic_mode) +{ + return set_std_nic_fn(get_dev_idx_p(ifindex), nic_mode); + +} +EXPORT_SYMBOL(set_std_nic_sd); + +int get_std_nic_sd(int ifindex) +{ + return get_std_nic_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_std_nic_sd); + +int set_tap_sd(int ifindex, int tap_mode) +{ + return set_tap_fn(get_dev_idx_p(ifindex), tap_mode); + +} +EXPORT_SYMBOL(set_tap_sd); + +int get_tap_sd(int ifindex) +{ + return get_tap_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_tap_sd); + +int set_tap_pwup_sd(int ifindex, int tap_mode) +{ + return set_tap_pwup_fn(get_dev_idx_p(ifindex), tap_mode); + +} +EXPORT_SYMBOL(set_tap_pwup_sd); + +int get_tap_pwup_sd(int ifindex) +{ + return get_tap_pwup_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_tap_pwup_sd); + +int get_tap_change_sd(int ifindex) +{ + return get_tap_change_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_tap_change_sd); + +int set_dis_tap_sd(int ifindex, int dis_param) +{ + return set_dis_tap_fn(get_dev_idx_p(ifindex), dis_param); + +} +EXPORT_SYMBOL(set_dis_tap_sd); + +int get_dis_tap_sd(int ifindex) +{ + return get_dis_tap_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_dis_tap_sd); + +int set_bp_disc_sd(int ifindex, int disc_mode) +{ + return set_disc_fn(get_dev_idx_p(ifindex), disc_mode); + +} +EXPORT_SYMBOL(set_bp_disc_sd); + +int get_bp_disc_sd(int ifindex) +{ + return get_disc_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bp_disc_sd); + +int set_bp_disc_pwup_sd(int ifindex, int disc_mode) +{ + return set_disc_pwup_fn(get_dev_idx_p(ifindex), disc_mode); + +} +EXPORT_SYMBOL(set_bp_disc_pwup_sd); + +int get_bp_disc_pwup_sd(int ifindex) +{ + return get_disc_pwup_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bp_disc_pwup_sd); + +int get_bp_disc_change_sd(int ifindex) +{ + return get_disc_change_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bp_disc_change_sd); + +int set_bp_dis_disc_sd(int ifindex, int dis_param) +{ + return set_dis_disc_fn(get_dev_idx_p(ifindex), dis_param); + +} +EXPORT_SYMBOL(set_bp_dis_disc_sd); + +int get_bp_dis_disc_sd(int ifindex) +{ + return get_dis_disc_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bp_dis_disc_sd); + +int get_wd_exp_mode_sd(int ifindex) +{ + return get_wd_exp_mode_fn(get_dev_idx_p(ifindex)); +} +EXPORT_SYMBOL(get_wd_exp_mode_sd); + +int set_wd_exp_mode_sd(int ifindex, int param) +{ + return set_wd_exp_mode_fn(get_dev_idx_p(ifindex), param); + +} +EXPORT_SYMBOL(set_wd_exp_mode_sd); + +int set_tx_sd(int ifindex, int tx_state) +{ + return set_tx_fn(get_dev_idx_p(ifindex), tx_state); + +} +EXPORT_SYMBOL(set_tx_sd); + +int set_tpl_sd(int ifindex, int tpl_state) +{ + return set_tpl_fn(get_dev_idx_p(ifindex), tpl_state); + +} +EXPORT_SYMBOL(set_tpl_sd); + +int set_bp_hw_reset_sd(int ifindex, int status) +{ + return set_bp_hw_reset_fn(get_dev_idx_p(ifindex), status); + +} +EXPORT_SYMBOL(set_bp_hw_reset_sd); + +int set_wd_autoreset_sd(int ifindex, int param) +{ + return set_wd_autoreset_fn(get_dev_idx_p(ifindex), param); + +} +EXPORT_SYMBOL(set_wd_autoreset_sd); + +int get_wd_autoreset_sd(int ifindex) +{ + return get_wd_autoreset_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_wd_autoreset_sd); + +int get_bypass_caps_sd(int ifindex) +{ + return get_bypass_caps_fn(get_dev_idx_p(ifindex)); +} +EXPORT_SYMBOL(get_bypass_caps_sd); + +int get_bypass_slave_sd(int ifindex) +{ + struct bpctl_dev *pbpctl_dev_out; + int ret = get_bypass_slave_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out); + + if (ret == 1) + return pbpctl_dev_out->ifindex; + return -1; + +} +EXPORT_SYMBOL(get_bypass_slave_sd); + +int get_tx_sd(int ifindex) +{ + return get_tx_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_tx_sd); + +int get_tpl_sd(int ifindex) +{ + return get_tpl_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_tpl_sd); + +int get_bp_hw_reset_sd(int ifindex) +{ + return get_bp_hw_reset_fn(get_dev_idx_p(ifindex)); + +} +EXPORT_SYMBOL(get_bp_hw_reset_sd); + +int get_bypass_info_sd(int ifindex, struct bp_info *bp_info) +{ + return get_bypass_info_fn(get_dev_idx_p(ifindex), bp_info->prod_name, &bp_info->fw_ver); +} +EXPORT_SYMBOL(get_bypass_info_sd); + +int bp_if_scan_sd(void) +{ + if_scan_init(); + return 0; +} +EXPORT_SYMBOL(bp_if_scan_sd); + +#define BP_PROC_DIR "bypass" + +static struct proc_dir_entry *bp_procfs_dir; + +static int procfs_add(char *proc_name, const struct file_operations *fops, + struct bpctl_dev *dev) +{ + struct bypass_pfs_sd *pfs = &dev->bypass_pfs_set; + + if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev)) + return -1; + 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) +{ + struct bpctl_dev *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) +{ + struct bpctl_dev *dev = m->private; + struct bpctl_dev *slave = get_status_port_fn(dev); + + if (!slave) + slave = dev; + if (!slave) + seq_puts(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) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bypass_caps_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "-1\n"); + else + seq_printf(m, "0x%x\n", ret); + return 0; +} +RO_FOPS(bypass_caps) + +static int show_wd_set_caps(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_wd_set_caps_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "-1\n"); + else + seq_printf(m, "0x%x\n", ret); + return 0; +} +RO_FOPS(wd_set_caps) + +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; +} + +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_fn(PDE_DATA(file_inode(file)), bypass_param); + return count; +} +static int show_bypass(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bypass_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(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_fn(PDE_DATA(file_inode(file)), tap_param); + return count; +} +static int show_tap(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_tap_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(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_fn(PDE_DATA(file_inode(file)), tap_param); + return count; +} +static int show_disc(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_disc_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + return 0; +} +RW_FOPS(disc) + +static int show_bypass_change(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bypass_change_fn(dev); + + if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(m, "fail\n"); + return 0; +} +RO_FOPS(bypass_change) + +static int show_tap_change(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_tap_change_fn(dev); + + if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(m, "fail\n"); + return 0; +} +RO_FOPS(tap_change) + +static int show_disc_change(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_disc_change_fn(dev); + + if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(m, "fail\n"); + return 0; +} +RO_FOPS(disc_change) + +static ssize_t bypass_wd_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); + int timeout; + int ret = kstrtoint_from_user(buffer, count, 10, &timeout); + + if (ret) + return ret; + set_bypass_wd_fn(dev, timeout); + return count; +} +static int show_bypass_wd(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = 0, timeout = 0; + + ret = get_bypass_wd_fn(dev, &timeout); + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (timeout == -1) + seq_puts(m, "unknown\n"); + else if (timeout == 0) + seq_puts(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) +{ + struct bpctl_dev *dev = m->private; + int ret = 0, timeout = 0; + + ret = get_wd_expire_time_fn(dev, &timeout); + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (timeout == -1) + seq_puts(m, "expire\n"); + else if (timeout == 0) + seq_puts(m, "disable\n"); + else + seq_printf(m, "%d\n", timeout); + return 0; +} +RO_FOPS(wd_expire_time) + +static ssize_t tpl_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); + int tpl_param = user_on_off(buffer, count); + + if (tpl_param < 0) + return -1; + + set_tpl_fn(dev, tpl_param); + return count; +} +static int show_tpl(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_tpl_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + return 0; +} +RW_FOPS(tpl) + +#ifdef PMC_FIX_FLAG +static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + struct bpctl_dev *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_fn(dev, tpl_param); + return count; +} +static int show_wait_at_pwup(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bp_wait_at_pwup_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(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) +{ + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); + int tpl_param = user_on_off(buffer, count); + + if (tpl_param < 0) + return -1; + + set_bp_hw_reset_fn(dev, tpl_param); + return count; +} +static int show_hw_reset(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bp_hw_reset_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 1) + seq_puts(m, "on\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + return 0; +} +RW_FOPS(hw_reset) + +#endif /*PMC_WAIT_FLAG */ + +static int show_reset_bypass_wd(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = reset_bypass_wd_timer_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "disable\n"); + else if (ret == 1) + seq_puts(m, "success\n"); + return 0; +} +RO_FOPS(reset_bypass_wd) + +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_fn(PDE_DATA(file_inode(file)), bypass_param); + return count; +} +static int show_dis_bypass(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_dis_bypass_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(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_fn(PDE_DATA(file_inode(file)), tap_param); + return count; +} +static int show_dis_tap(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_dis_tap_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(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_fn(PDE_DATA(file_inode(file)), tap_param); + return count; +} +static int show_dis_disc(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_dis_disc_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(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_fn(PDE_DATA(file_inode(file)), bypass_param); + return count; +} +static int show_bypass_pwup(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bypass_pwup_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(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_fn(PDE_DATA(file_inode(file)), bypass_param); + return count; +} +static int show_bypass_pwoff(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_bypass_pwoff_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(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_fn(PDE_DATA(file_inode(file)), tap_param); + return count; +} +static int show_tap_pwup(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_tap_pwup_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(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_fn(PDE_DATA(file_inode(file)), tap_param); + return count; +} +static int show_disc_pwup(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_disc_pwup_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(m, "on\n"); + return 0; +} +RW_FOPS(disc_pwup) + +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_fn(PDE_DATA(file_inode(file)), bypass_param); + return count; +} +static int show_std_nic(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_std_nic_fn(dev); + + if (ret == BP_NOT_CAP) + seq_puts(m, "fail\n"); + else if (ret == 0) + seq_puts(m, "off\n"); + else + seq_puts(m, "on\n"); + return 0; +} +RW_FOPS(std_nic) + +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_fn(PDE_DATA(file_inode(file)), bypass_param); + + return count; +} +static int show_wd_exp_mode(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_wd_exp_mode_fn(dev); + + if (ret == 1) + seq_puts(m, "tap\n"); + else if (ret == 0) + seq_puts(m, "bypass\n"); + else if (ret == 2) + seq_puts(m, "disc\n"); + else + seq_puts(m, "fail\n"); + return 0; +} +RW_FOPS(wd_exp_mode) + +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_fn(PDE_DATA(file_inode(file)), timeout); + return count; +} +static int show_wd_autoreset(struct seq_file *m, void *v) +{ + struct bpctl_dev *dev = m->private; + int ret = get_wd_autoreset_fn(dev); + + if (ret >= 0) + seq_printf(m, "%d\n", ret); + else + seq_puts(m, "fail\n"); + return 0; +} +RW_FOPS(wd_autoreset) + +static int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block) +{ + struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set); + static struct proc_dir_entry *procfs_dir; + 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; +} + +static int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block) +{ + struct bypass_pfs_sd *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; +} diff --git a/drivers/staging/silicom/bypass.h b/drivers/staging/silicom/bypass.h new file mode 100644 index 00000000000..08fa7a0fc8d --- /dev/null +++ b/drivers/staging/silicom/bypass.h @@ -0,0 +1,202 @@ +/******************************************************************************/ +/* */ +/* Bypass Control utility, Copyright (c) 2005 Silicom */ +/* All rights reserved. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* */ +/******************************************************************************/ + +#ifndef BYPASS_H +#define BYPASS_H + +/* Bypass related */ + +#define SYNC_CMD_VAL 2 /* 10b */ +#define SYNC_CMD_LEN 2 + +#define WR_CMD_VAL 2 /* 10b */ +#define WR_CMD_LEN 2 + +#define RD_CMD_VAL 1 /* 10b */ +#define RD_CMD_LEN 2 + +#define ADDR_CMD_LEN 4 + +#define WR_DATA_LEN 8 +#define RD_DATA_LEN 8 + +#define PIC_SIGN_REG_ADDR 0x7 +#define PIC_SIGN_VALUE 0xcd + +#define STATUS_REG_ADDR 0 +#define WDT_EN_MASK 0x01 /* BIT_0 */ +#define CMND_EN_MASK 0x02 /* BIT_1 */ +#define DIS_BYPASS_CAP_MASK 0x04 /* BIT_2 Bypass Cap is disable*/ +#define DFLT_PWRON_MASK 0x08 /* BIT_3 */ +#define BYPASS_OFF_MASK 0x10 /* BIT_4 */ +#define BYPASS_FLAG_MASK 0x20 /* BIT_5 */ +#define STD_NIC_MASK (DIS_BYPASS_CAP_MASK | BYPASS_OFF_MASK | DFLT_PWRON_MASK) +#define WD_EXP_FLAG_MASK 0x40 /* BIT_6 */ +#define DFLT_PWROFF_MASK 0x80 /* BIT_7 */ +#define STD_NIC_PWOFF_MASK (DIS_BYPASS_CAP_MASK | BYPASS_OFF_MASK | DFLT_PWRON_MASK | DFLT_PWROFF_MASK) + +#define PRODUCT_CAP_REG_ADDR 0x5 +#define BYPASS_SUPPORT_MASK 0x01 /* BIT_0 */ +#define TAP_SUPPORT_MASK 0x02 /* BIT_1 */ +#define NORMAL_UNSUPPORT_MASK 0x04 /* BIT_2 */ +#define DISC_SUPPORT_MASK 0x08 /* BIT_3 */ +#define TPL2_SUPPORT_MASK 0x10 /* BIT_4 */ +#define DISC_PORT_SUPPORT_MASK 0x20 /* BIT_5 */ + +#define STATUS_TAP_REG_ADDR 0x6 +#define WDTE_TAP_BPN_MASK 0x01 /* BIT_1 1 when wdt expired -> TAP, 0 - Bypass */ +#define DIS_TAP_CAP_MASK 0x04 /* BIT_2 TAP Cap is disable*/ +#define DFLT_PWRON_TAP_MASK 0x08 /* BIT_3 */ +#define TAP_OFF_MASK 0x10 /* BIT_4 */ +#define TAP_FLAG_MASK 0x20 /* BIT_5 */ +#define TX_DISA_MASK 0x40 +#define TX_DISB_MASK 0x80 + +#define STD_NIC_TAP_MASK (DIS_TAP_CAP_MASK | TAP_OFF_MASK | DFLT_PWRON_TAP_MASK) + +#define STATUS_DISC_REG_ADDR 13 +#define WDTE_DISC_BPN_MASK 0x01 /* BIT_0 1 when wdt expired -> TAP, 0 - Bypass */ +#define STD_NIC_ON_MASK 0x02 /* BIT_1 */ +#define DIS_DISC_CAP_MASK 0x04 /* BIT_2 TAP Cap is disable*/ +#define DFLT_PWRON_DISC_MASK 0x08 /* BIT_3 */ +#define DISC_OFF_MASK 0x10 /* BIT_4 */ +#define DISC_FLAG_MASK 0x20 /* BIT_5 */ +#define TPL2_FLAG_MASK 0x40 /* BIT_6 */ +#define STD_NIC_DISC_MASK DIS_DISC_CAP_MASK + +#define CONT_CONFIG_REG_ADDR 12 +#define EN_HW_RESET_MASK 0x2 /* BIT_1 */ +#define WAIT_AT_PWUP_MASK 0x1 /* BIT_0 */ + +#define VER_REG_ADDR 0x1 +#define BP_FW_VER_A0 0xa0 +#define BP_FW_VER_A1 0xa1 + +#define INT_VER_MASK 0xf0 +#define EXT_VER_MASK 0xf +/* */ +#define PXG2BPI_VER 0x0 +#define PXG2TBPI_VER 0x1 +#define PXE2TBPI_VER 0x2 +#define PXG4BPFI_VER 0x4 +#define BP_FW_EXT_VER7 0x6 +#define BP_FW_EXT_VER8 0x8 +#define BP_FW_EXT_VER9 0x9 + +#define OLD_IF_VER -1 + +#define CMND_REG_ADDR 10 /* 1010b */ +#define WDT_REG_ADDR 4 +#define TMRL_REG_ADDR 2 +#define TMRH_REG_ADDR 3 + +/* NEW_FW */ +#define WDT_INTERVAL 1 /* 5 //8 */ +#define WDT_CMND_INTERVAL 200 /* 50 */ +#define CMND_INTERVAL 200 /* 100 usec */ +#define PULSE_TIME 100 + +/* OLD_FW */ +#define INIT_CMND_INTERVAL 40 +#define PULSE_INTERVAL 5 +#define WDT_TIME_CNT 3 + +/* Intel Commands */ + +#define CMND_OFF_INT 0xf +#define PWROFF_BYPASS_ON_INT 0x5 +#define BYPASS_ON_INT 0x6 +#define DIS_BYPASS_CAP_INT 0x4 +#define RESET_WDT_INT 0x1 + +/* Intel timing */ + +#define BYPASS_DELAY_INT 4 /* msec */ +#define CMND_INTERVAL_INT 2 /* msec */ + +/* Silicom Commands */ +#define CMND_ON 0x4 +#define CMND_OFF 0x2 +#define BYPASS_ON 0xa +#define BYPASS_OFF 0x8 +#define PORT_LINK_EN 0xe +#define PORT_LINK_DIS 0xc +#define WDT_ON 0x10 /* 0x1f (11111) - max */ +#define TIMEOUT_UNIT 100 +#define TIMEOUT_MAX_STEP 15 +#define WDT_TIMEOUT_MIN 100 /* msec */ +#define WDT_TIMEOUT_MAX 3276800 /* msec */ +#define WDT_AUTO_MIN_INT 500 +#define WDT_TIMEOUT_DEF WDT_TIMEOUT_MIN +#define WDT_OFF 0x6 +#define WDT_RELOAD 0x9 +#define RESET_CONT 0x20 +#define DIS_BYPASS_CAP 0x22 +#define EN_BYPASS_CAP 0x24 +#define BYPASS_STATE_PWRON 0x26 +#define NORMAL_STATE_PWRON 0x28 +#define BYPASS_STATE_PWROFF 0x27 +#define NORMAL_STATE_PWROFF 0x29 +#define TAP_ON 0xb +#define TAP_OFF 0x9 +#define TAP_STATE_PWRON 0x2a +#define DIS_TAP_CAP 0x2c +#define EN_TAP_CAP 0x2e +#define STD_NIC_OFF 0x86 +#define STD_NIC_ON 0x84 +#define DISC_ON 0x85 +#define DISC_OFF 0x8a +#define DISC_STATE_PWRON 0x87 +#define DIS_DISC_CAP 0x88 +#define EN_DISC_CAP 0x89 +#define TPL2_ON 0x8c +#define TPL2_OFF 0x8b +#define BP_WAIT_AT_PWUP_EN 0x80 +#define BP_WAIT_AT_PWUP_DIS 0x81 +#define BP_HW_RESET_EN 0x82 +#define BP_HW_RESET_DIS 0x83 + +#define TX_DISA 0x8d +#define TX_DISB 0x8e +#define TX_ENA 0xA0 +#define TX_ENB 0xA1 + +#define TX_DISA_PWRUP 0xA2 +#define TX_DISB_PWRUP 0xA3 +#define TX_ENA_PWRUP 0xA4 +#define TX_ENB_PWRUP 0xA5 + +#define BYPASS_CAP_DELAY 21 /* msec */ +#define DFLT_PWRON_DELAY 10 /* msec */ +#define LATCH_DELAY 13 /* msec */ +#define EEPROM_WR_DELAY 8 /* msec */ + +#define BP_LINK_MON_DELAY 4 /* sec */ + +#define BP_FW_EXT_VER0 0xa0 +#define BP_FW_EXT_VER1 0xa1 +#define BP_FW_EXT_VER2 0xb1 + +#define BP_OK 0 +#define BP_NOT_CAP -1 +#define WDT_STATUS_EXP -2 +#define WDT_STATUS_UNKNOWN -1 +#define WDT_STATUS_EN 1 +#define WDT_STATUS_DIS 0 + +#ifdef BP_SELF_TEST +#define ETH_P_BPTEST 0xabba + +#define BPTEST_DATA_LEN 60 +#endif + +#endif /* BYPASS_H */ diff --git a/drivers/staging/silicom/bypasslib/Makefile b/drivers/staging/silicom/bypasslib/Makefile new file mode 100644 index 00000000000..80e8b9bc935 --- /dev/null +++ b/drivers/staging/silicom/bypasslib/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the Bypass network device drivers. +# + +obj-$(CONFIG_SBYPASS) += bypass.o + diff --git a/drivers/staging/silicom/bypasslib/bp_ioctl.h b/drivers/staging/silicom/bypasslib/bp_ioctl.h new file mode 100644 index 00000000000..a13932af733 --- /dev/null +++ b/drivers/staging/silicom/bypasslib/bp_ioctl.h @@ -0,0 +1,198 @@ +/******************************************************************************/ +/* */ +/* bypass library, Copyright (c) 2004-2006 Silicom, Ltd */ +/* Corporation. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* */ +/* */ +/******************************************************************************/ + +#ifndef BP_IOCTL_H +#define BP_IOCTL_H + +#define BP_CAP 0x01 /* BIT_0 */ +#define BP_STATUS_CAP 0x02 /* BIT_1 */ +#define BP_STATUS_CHANGE_CAP 0x04 /* BIT_2 */ +#define SW_CTL_CAP 0x08 /* BIT_3 */ +#define BP_DIS_CAP 0x10 /* BIT_4 */ +#define BP_DIS_STATUS_CAP 0x20 /* BIT_5 */ +#define STD_NIC_CAP 0x40 /* BIT_6 */ +#define BP_PWOFF_ON_CAP 0x80 /* BIT_7 */ +#define BP_PWOFF_OFF_CAP 0x0100 /* BIT_8 */ +#define BP_PWOFF_CTL_CAP 0x0200 /* BIT_9 */ +#define BP_PWUP_ON_CAP 0x0400 /* BIT_10 */ +#define BP_PWUP_OFF_CAP 0x0800 /* BIT_11 */ +#define BP_PWUP_CTL_CAP 0x1000 /* BIT_12 */ +#define WD_CTL_CAP 0x2000 /* BIT_13 */ +#define WD_STATUS_CAP 0x4000 /* BIT_14 */ +#define WD_TIMEOUT_CAP 0x8000 /* BIT_15 */ +#define TX_CTL_CAP 0x10000 /* BIT_16 */ +#define TX_STATUS_CAP 0x20000 /* BIT_17 */ +#define TAP_CAP 0x40000 /* BIT_18 */ +#define TAP_STATUS_CAP 0x80000 /* BIT_19 */ +#define TAP_STATUS_CHANGE_CAP 0x100000 /* BIT_20 */ +#define TAP_DIS_CAP 0x200000 /* BIT_21 */ +#define TAP_DIS_STATUS_CAP 0x400000 /* BIT_22 */ +#define TAP_PWUP_ON_CAP 0x800000 /* BIT_23 */ +#define TAP_PWUP_OFF_CAP 0x1000000 /* BIT 24 */ +#define TAP_PWUP_CTL_CAP 0x2000000 /* BIT 25 */ +#define NIC_CAP_NEG 0x4000000 /* BIT 26 */ +#define TPL_CAP 0x8000000 /* BIT 27 */ +#define DISC_CAP 0x10000000 /* BIT 28 */ +#define DISC_DIS_CAP 0x20000000 /* BIT 29 */ +#define DISC_PWUP_CTL_CAP 0x40000000 /* BIT 30 */ + +#define WD_MIN_TIME_MASK(val) (val & 0xf) +#define WD_STEP_COUNT_MASK(val) ((val & 0xf) << 5) +#define WDT_STEP_TIME 0x10 /* BIT_4 */ + +#define WD_MIN_TIME_GET(desc) (desc & 0xf) +#define WD_STEP_COUNT_GET(desc) ((desc>>5) & 0xf) + +enum { + IS_BYPASS = 1, + GET_BYPASS_SLAVE, + GET_BYPASS_CAPS, + GET_WD_SET_CAPS, + SET_BYPASS, + GET_BYPASS, + GET_BYPASS_CHANGE, + SET_BYPASS_WD, + GET_BYPASS_WD, + GET_WD_EXPIRE_TIME, + RESET_BYPASS_WD_TIMER, + SET_DIS_BYPASS, + GET_DIS_BYPASS, + SET_BYPASS_PWOFF, + GET_BYPASS_PWOFF, + SET_BYPASS_PWUP, + GET_BYPASS_PWUP, + SET_STD_NIC, + GET_STD_NIC, + SET_TX, + GET_TX, + SET_TAP, + GET_TAP, + GET_TAP_CHANGE, + SET_DIS_TAP, + GET_DIS_TAP, + SET_TAP_PWUP, + GET_TAP_PWUP, + SET_WD_EXP_MODE, + GET_WD_EXP_MODE, + SET_WD_AUTORESET, + GET_WD_AUTORESET, + SET_TPL, + GET_TPL, + SET_DISC, + GET_DISC, + GET_DISC_CHANGE, + SET_DIS_DISC, + GET_DIS_DISC, + SET_DISC_PWUP, + GET_DISC_PWUP, + + GET_BYPASS_INFO = 100, + GET_BP_WAIT_AT_PWUP, + SET_BP_WAIT_AT_PWUP, + GET_BP_HW_RESET, + SET_BP_HW_RESET, +}; + +enum { + IF_SCAN_SD, + GET_DEV_NUM_SD, + IS_BYPASS_SD, + GET_BYPASS_SLAVE_SD, + GET_BYPASS_CAPS_SD, + GET_WD_SET_CAPS_SD, + SET_BYPASS_SD, + GET_BYPASS_SD, + GET_BYPASS_CHANGE_SD, + SET_BYPASS_WD_SD, + GET_BYPASS_WD_SD, + GET_WD_EXPIRE_TIME_SD, + RESET_BYPASS_WD_TIMER_SD, + SET_DIS_BYPASS_SD, + GET_DIS_BYPASS_SD, + SET_BYPASS_PWOFF_SD, + GET_BYPASS_PWOFF_SD, + SET_BYPASS_PWUP_SD, + GET_BYPASS_PWUP_SD, + SET_STD_NIC_SD, + GET_STD_NIC_SD, + SET_TX_SD, + GET_TX_SD, + SET_TAP_SD, + GET_TAP_SD, + GET_TAP_CHANGE_SD, + SET_DIS_TAP_SD, + GET_DIS_TAP_SD, + SET_TAP_PWUP_SD, + GET_TAP_PWUP_SD, + SET_WD_EXP_MODE_SD, + GET_WD_EXP_MODE_SD, + SET_WD_AUTORESET_SD, + GET_WD_AUTORESET_SD, + SET_TPL_SD, + GET_TPL_SD, + SET_DISC_SD, + GET_DISC_SD, + GET_DISC_CHANGE_SD, + SET_DIS_DISC_SD, + GET_DIS_DISC_SD, + SET_DISC_PWUP_SD, + GET_DISC_PWUP_SD, + + GET_BYPASS_INFO_SD = 100, + GET_BP_WAIT_AT_PWUP_SD, + SET_BP_WAIT_AT_PWUP_SD, + GET_BP_HW_RESET_SD, + SET_BP_HW_RESET_SD, + +}; + +#define SIOCGIFBYPASS (SIOCDEVPRIVATE+10) + +struct bp_info { + char prod_name[14]; + unsigned char fw_ver; +}; + +/* for passing single values */ +struct if_bypass { + char if_name[IFNAMSIZ]; + int cmd; + int data; +}; +struct if_bypass_info { + char if_name[IFNAMSIZ]; + char cmd; + struct bp_info bp_info; +}; + +/* +* The major device number. We can't rely on dynamic +* registration any more, because ioctls need to know +* it. +*/ + +#define MAGIC_NUM 'J' + +/* for passing single values */ +struct bpctl_cmd { + int status; + int data[8]; + int in_param[8]; + int out_param[8]; +}; + +#define IOCTL_TX_MSG(cmd) _IOWR(MAGIC_NUM, cmd, struct bpctl_cmd) + +#define DEVICE_NAME "bpctl" + +#endif diff --git a/drivers/staging/silicom/bypasslib/bplibk.h b/drivers/staging/silicom/bypasslib/bplibk.h new file mode 100644 index 00000000000..c5c75c4fe05 --- /dev/null +++ b/drivers/staging/silicom/bypasslib/bplibk.h @@ -0,0 +1,36 @@ +/******************************************************************************/ +/* */ +/* bypass library, Copyright (c) 2004 Silicom, Ltd */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* */ +/* bplib.h */ +/* */ +/******************************************************************************/ +#ifndef BYPASS_H +#define BYPASS_H + +#include "bp_ioctl.h" +#include "libbp_sd.h" + +#define IF_NAME "eth" +#define SILICOM_VID 0x1374 +#define SILICOM_BP_PID_MIN 0x24 +#define SILICOM_BP_PID_MAX 0x5f +#define INTEL_PEG4BPII_PID 0x10a0 +#define INTEL_PEG4BPFII_PID 0x10a1 + +#define PEGII_IF_SERIES(vid, pid) \ + ((vid == 0x8086) && \ + ((pid == INTEL_PEG4BPII_PID) || \ + (pid == INTEL_PEG4BPFII_PID))) + +#ifdef BP_VENDOR_SUPPORT +char *bp_desc_array[] = { "e1000bp", "e1000bpe", "slcm5700", + "bnx2xbp", "ixgbp", "ixgbpe", NULL }; +#endif + +#endif diff --git a/drivers/staging/silicom/bypasslib/bypass.c b/drivers/staging/silicom/bypasslib/bypass.c new file mode 100644 index 00000000000..8e714a8ea3a --- /dev/null +++ b/drivers/staging/silicom/bypasslib/bypass.c @@ -0,0 +1,536 @@ +/******************************************************************************/ +/* */ +/* bypass library, Copyright (c) 2004-2007 Silicom, Ltd */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* */ +/* bypass.c */ +/* */ +/******************************************************************************/ + +#if defined(CONFIG_SMP) && !defined(__SMP__) +#define __SMP__ +#endif + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> + +#include <linux/sched.h> +#include <linux/wait.h> + +#include <linux/netdevice.h> /* struct device, and other headers */ +#include <linux/kernel_stat.h> +#include <linux/pci.h> +#include <linux/rtnetlink.h> +#include <linux/ethtool.h> + +#include <net/net_namespace.h> + +#include "bplibk.h" + +#define MOD_NAME "bypass" + +#define VERSION "\n"MOD_NAME" version 9.0.4\n" + +MODULE_AUTHOR("www.silicom.co.il"); + +MODULE_LICENSE("GPL"); + +static int do_cmd(struct net_device *dev, struct ifreq *ifr, int cmd, int *data) +{ + int ret = -1; + struct if_bypass *bypass_cb; + + bypass_cb = (struct if_bypass *)ifr; + bypass_cb->cmd = cmd; + bypass_cb->data = *data; + + if (dev->netdev_ops && dev->netdev_ops->ndo_do_ioctl) { + ret = dev->netdev_ops->ndo_do_ioctl(dev, ifr, SIOCGIFBYPASS); + *data = bypass_cb->data; + } + + return ret; +} + +static int doit(int cmd, int if_index, int *data) +{ + struct ifreq ifr; + int ret = -1; + struct net_device *dev; + struct net_device *n; + + for_each_netdev_safe(&init_net, dev, n) { + if (dev->ifindex == if_index) { + ret = do_cmd(dev, &ifr, cmd, data); + if (ret < 0) + ret = -1; + } + } + + return ret; +} + +#define bp_symbol_get(fn_name) symbol_get(fn_name) +#define bp_symbol_put(fn_name) symbol_put(fn_name) + +#define SET_BPLIB_INT_FN(fn_name, arg_type, arg, ret) \ +({ int (*fn_ex)(arg_type) = NULL; \ + fn_ex = bp_symbol_get(fn_name##_sd); \ + if (fn_ex) { \ + ret = fn_ex(arg); \ + bp_symbol_put(fn_name##_sd); \ + } else { \ + ret = -1; \ + } \ +}) + +#define SET_BPLIB_INT_FN2(fn_name, arg_type, arg, arg_type1, arg1, ret)\ +({ int (*fn_ex)(arg_type, arg_type1) = NULL; \ + fn_ex = bp_symbol_get(fn_name##_sd); \ + if (fn_ex) { \ + ret = fn_ex(arg, arg1); \ + bp_symbol_put(fn_name##_sd); \ + } else { \ + ret = -1; \ + } \ +}) + +#define SET_BPLIB_INT_FN3(fn_name, arg_type, arg, arg_type1, arg1, \ + arg_type2, arg2, ret) \ +({ int (*fn_ex)(arg_type, arg_type1, arg_type2) = NULL; \ + fn_ex = bp_symbol_get(fn_name##_sd); \ + if (fn_ex) { \ + ret = fn_ex(arg, arg1, arg2); \ + bp_symbol_put(fn_name##_sd); \ + } else { \ + ret = -1; \ + } \ +}) + +#define DO_BPLIB_GET_ARG_FN(fn_name, ioctl_val, if_index) \ +({ int data, ret = 0; \ + if (is_dev_sd(if_index)) { \ + SET_BPLIB_INT_FN(fn_name, int, if_index, ret); \ + return ret; \ + } \ + return doit(ioctl_val, if_index, &data); \ +}) + +#define DO_BPLIB_SET_ARG_FN(fn_name, ioctl_val, if_index, arg) \ +({ int data, ret = 0; \ + if (is_dev_sd(if_index)) { \ + SET_BPLIB_INT_FN2(fn_name, int, if_index, int, \ + arg, ret); \ + return ret; \ + } \ + data = arg; \ + return doit(ioctl_val, if_index, &data); \ +}) + +static int is_dev_sd(int if_index) +{ + int ret = 0; + + SET_BPLIB_INT_FN(is_bypass, int, if_index, ret); + return ret >= 0 ? 1 : 0; +} + +static int is_bypass_dev(int if_index) +{ + struct pci_dev *pdev = NULL; + struct net_device *dev = NULL; + struct ifreq ifr; + int ret = 0; + int data = 0; + + while ((pdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) { + dev = pci_get_drvdata(pdev); + if ((dev != NULL) && (dev->ifindex == if_index)) { + if ((pdev->vendor == SILICOM_VID) && + (pdev->device >= SILICOM_BP_PID_MIN) && + (pdev->device <= SILICOM_BP_PID_MAX)) { + goto send_cmd; + } +#if defined(BP_VENDOR_SUPPORT) && defined(ETHTOOL_GDRVINFO) + else { + struct ethtool_drvinfo info; + const struct ethtool_ops *ops = + dev->ethtool_ops; + int k = 0; + + if (ops->get_drvinfo) { + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GDRVINFO; + ops->get_drvinfo(dev, &info); + for (; bp_desc_array[k]; k++) + if (!(strcmp(bp_desc_array[k], + info.driver))) + goto send_cmd; + + } + + } +#endif + return -1; + } + } + send_cmd: + ret = do_cmd(dev, &ifr, IS_BYPASS, &data); + return ret < 0 ? -1 : ret; +} + +static int is_bypass(int if_index) +{ + int ret = 0; + + SET_BPLIB_INT_FN(is_bypass, int, if_index, ret); + + if (ret < 0) + return is_bypass_dev(if_index); + return ret; +} +EXPORT_SYMBOL(is_bypass); + +static int get_bypass_slave(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bypass_slave, GET_BYPASS_SLAVE, if_index); +} +EXPORT_SYMBOL(get_bypass_slave); + +static int get_bypass_caps(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bypass_caps, GET_BYPASS_CAPS, if_index); +} +EXPORT_SYMBOL(get_bypass_caps); + +static int get_wd_set_caps(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_wd_set_caps, GET_WD_SET_CAPS, if_index); +} +EXPORT_SYMBOL(get_wd_set_caps); + +static int set_bypass(int if_index, int bypass_mode) +{ + DO_BPLIB_SET_ARG_FN(set_bypass, SET_BYPASS, if_index, bypass_mode); +} +EXPORT_SYMBOL(set_bypass); + +static int get_bypass(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bypass, GET_BYPASS, if_index); +} +EXPORT_SYMBOL(get_bypass); + +static int get_bypass_change(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bypass_change, GET_BYPASS_CHANGE, if_index); +} +EXPORT_SYMBOL(get_bypass_change); + +static int set_dis_bypass(int if_index, int dis_bypass) +{ + DO_BPLIB_SET_ARG_FN(set_dis_bypass, SET_DIS_BYPASS, if_index, + dis_bypass); +} +EXPORT_SYMBOL(set_dis_bypass); + +static int get_dis_bypass(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_dis_bypass, GET_DIS_BYPASS, if_index); +} +EXPORT_SYMBOL(get_dis_bypass); + +static int set_bypass_pwoff(int if_index, int bypass_mode) +{ + DO_BPLIB_SET_ARG_FN(set_bypass_pwoff, SET_BYPASS_PWOFF, if_index, + bypass_mode); +} +EXPORT_SYMBOL(set_bypass_pwoff); + +static int get_bypass_pwoff(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bypass_pwoff, GET_BYPASS_PWOFF, if_index); +} +EXPORT_SYMBOL(get_bypass_pwoff); + +static int set_bypass_pwup(int if_index, int bypass_mode) +{ + DO_BPLIB_SET_ARG_FN(set_bypass_pwup, SET_BYPASS_PWUP, if_index, + bypass_mode); +} +EXPORT_SYMBOL(set_bypass_pwup); + +static int get_bypass_pwup(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bypass_pwup, GET_BYPASS_PWUP, if_index); +} +EXPORT_SYMBOL(get_bypass_pwup); + +static int set_bypass_wd(int if_index, int ms_timeout, int *ms_timeout_set) +{ + int data = ms_timeout; + int ret = 0; + + if (is_dev_sd(if_index)) { + SET_BPLIB_INT_FN3(set_bypass_wd, int, if_index, int, ms_timeout, + int *, ms_timeout_set, ret); + } else { + ret = doit(SET_BYPASS_WD, if_index, &data); + if (ret > 0) { + *ms_timeout_set = ret; + ret = 0; + } + } + return ret; +} +EXPORT_SYMBOL(set_bypass_wd); + +static int get_bypass_wd(int if_index, int *ms_timeout_set) +{ + int *data = ms_timeout_set; + int ret = 0; + + if (is_dev_sd(if_index)) + SET_BPLIB_INT_FN2(get_bypass_wd, int, if_index, int *, + ms_timeout_set, ret); + else + ret = doit(GET_BYPASS_WD, if_index, data); + return ret; +} +EXPORT_SYMBOL(get_bypass_wd); + +static int get_wd_expire_time(int if_index, int *ms_time_left) +{ + int *data = ms_time_left, ret = 0; + + if (is_dev_sd(if_index)) { + SET_BPLIB_INT_FN2(get_wd_expire_time, int, if_index, int *, + ms_time_left, ret); + } else { + ret = doit(GET_WD_EXPIRE_TIME, if_index, data); + if ((ret == 0) && (*data != 0)) + ret = 1; + } + return ret; +} +EXPORT_SYMBOL(get_wd_expire_time); + +static int reset_bypass_wd_timer(int if_index) +{ + DO_BPLIB_GET_ARG_FN(reset_bypass_wd_timer, RESET_BYPASS_WD_TIMER, + if_index); +} +EXPORT_SYMBOL(reset_bypass_wd_timer); + +static int set_std_nic(int if_index, int bypass_mode) +{ + DO_BPLIB_SET_ARG_FN(set_std_nic, SET_STD_NIC, if_index, bypass_mode); +} +EXPORT_SYMBOL(set_std_nic); + +static int get_std_nic(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_std_nic, GET_STD_NIC, if_index); +} +EXPORT_SYMBOL(get_std_nic); + +static int set_tx(int if_index, int tx_state) +{ + DO_BPLIB_SET_ARG_FN(set_tx, SET_TX, if_index, tx_state); +} +EXPORT_SYMBOL(set_tx); + +static int get_tx(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_tx, GET_TX, if_index); +} +EXPORT_SYMBOL(get_tx); + +static int set_tap(int if_index, int tap_mode) +{ + DO_BPLIB_SET_ARG_FN(set_tap, SET_TAP, if_index, tap_mode); +} +EXPORT_SYMBOL(set_tap); + +static int get_tap(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_tap, GET_TAP, if_index); +} +EXPORT_SYMBOL(get_tap); + +static int get_tap_change(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_tap_change, GET_TAP_CHANGE, if_index); +} +EXPORT_SYMBOL(get_tap_change); + +static int set_dis_tap(int if_index, int dis_tap) +{ + DO_BPLIB_SET_ARG_FN(set_dis_tap, SET_DIS_TAP, if_index, dis_tap); +} +EXPORT_SYMBOL(set_dis_tap); + +static int get_dis_tap(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_dis_tap, GET_DIS_TAP, if_index); +} +EXPORT_SYMBOL(get_dis_tap); + +static int set_tap_pwup(int if_index, int tap_mode) +{ + DO_BPLIB_SET_ARG_FN(set_tap_pwup, SET_TAP_PWUP, if_index, tap_mode); +} +EXPORT_SYMBOL(set_tap_pwup); + +static int get_tap_pwup(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_tap_pwup, GET_TAP_PWUP, if_index); +} +EXPORT_SYMBOL(get_tap_pwup); + +static int set_bp_disc(int if_index, int disc_mode) +{ + DO_BPLIB_SET_ARG_FN(set_bp_disc, SET_DISC, if_index, disc_mode); +} +EXPORT_SYMBOL(set_bp_disc); + +static int get_bp_disc(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bp_disc, GET_DISC, if_index); +} +EXPORT_SYMBOL(get_bp_disc); + +static int get_bp_disc_change(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bp_disc_change, GET_DISC_CHANGE, if_index); +} +EXPORT_SYMBOL(get_bp_disc_change); + +static int set_bp_dis_disc(int if_index, int dis_disc) +{ + DO_BPLIB_SET_ARG_FN(set_bp_dis_disc, SET_DIS_DISC, if_index, dis_disc); +} +EXPORT_SYMBOL(set_bp_dis_disc); + +static int get_bp_dis_disc(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bp_dis_disc, GET_DIS_DISC, if_index); +} +EXPORT_SYMBOL(get_bp_dis_disc); + +static int set_bp_disc_pwup(int if_index, int disc_mode) +{ + DO_BPLIB_SET_ARG_FN(set_bp_disc_pwup, SET_DISC_PWUP, if_index, + disc_mode); +} +EXPORT_SYMBOL(set_bp_disc_pwup); + +static int get_bp_disc_pwup(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_bp_disc_pwup, GET_DISC_PWUP, if_index); +} +EXPORT_SYMBOL(get_bp_disc_pwup); + +static int set_wd_exp_mode(int if_index, int mode) +{ + DO_BPLIB_SET_ARG_FN(set_wd_exp_mode, SET_WD_EXP_MODE, if_index, mode); +} +EXPORT_SYMBOL(set_wd_exp_mode); + +static int get_wd_exp_mode(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_wd_exp_mode, GET_WD_EXP_MODE, if_index); +} +EXPORT_SYMBOL(get_wd_exp_mode); + +static int set_wd_autoreset(int if_index, int time) +{ + DO_BPLIB_SET_ARG_FN(set_wd_autoreset, SET_WD_AUTORESET, if_index, time); +} +EXPORT_SYMBOL(set_wd_autoreset); + +static int get_wd_autoreset(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_wd_autoreset, GET_WD_AUTORESET, if_index); +} +EXPORT_SYMBOL(get_wd_autoreset); + +static int set_tpl(int if_index, int tpl_mode) +{ + DO_BPLIB_SET_ARG_FN(set_tpl, SET_TPL, if_index, tpl_mode); +} +EXPORT_SYMBOL(set_tpl); + +static int get_tpl(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_tpl, GET_TPL, if_index); +} +EXPORT_SYMBOL(get_tpl); + +static int set_bp_hw_reset(int if_index, int mode) +{ + DO_BPLIB_SET_ARG_FN(set_tpl, SET_BP_HW_RESET, if_index, mode); +} +EXPORT_SYMBOL(set_bp_hw_reset); + +static int get_bp_hw_reset(int if_index) +{ + DO_BPLIB_GET_ARG_FN(get_tpl, GET_BP_HW_RESET, if_index); +} +EXPORT_SYMBOL(get_bp_hw_reset); + +static int get_bypass_info(int if_index, struct bp_info *bp_info) +{ + int ret = 0; + + if (is_dev_sd(if_index)) { + SET_BPLIB_INT_FN2(get_bypass_info, int, if_index, + struct bp_info *, bp_info, ret); + } else { + struct net_device *dev; + struct net_device *n; + + for_each_netdev_safe(&init_net, dev, n) { + if (dev->ifindex == if_index) { + struct if_bypass_info *bypass_cb; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + bypass_cb = (struct if_bypass_info *)𝔦 + bypass_cb->cmd = GET_BYPASS_INFO; + + if (dev->netdev_ops && + dev->netdev_ops->ndo_do_ioctl) + ret = dev->netdev_ops->ndo_do_ioctl(dev, + &ifr, SIOCGIFBYPASS); + else + ret = -1; + if (ret == 0) + memcpy(bp_info, &bypass_cb->bp_info, + sizeof(struct bp_info)); + ret = ret < 0 ? -1 : 0; + break; + } + } + } + return ret; +} +EXPORT_SYMBOL(get_bypass_info); + +static int __init init_lib_module(void) +{ + printk(VERSION); + return 0; +} + +static void __exit cleanup_lib_module(void) +{ +} + +module_init(init_lib_module); +module_exit(cleanup_lib_module); diff --git a/drivers/staging/silicom/bypasslib/libbp_sd.h b/drivers/staging/silicom/bypasslib/libbp_sd.h new file mode 100644 index 00000000000..cac4b0b2ed7 --- /dev/null +++ b/drivers/staging/silicom/bypasslib/libbp_sd.h @@ -0,0 +1,532 @@ +/******************************************************************************/ +/* */ +/* bypass library, Copyright (c) 2004 Silicom, Ltd */ +/* Corporation. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* Ver 1.0.0 */ +/* */ +/* libbypass.h */ +/* */ +/******************************************************************************/ + +/** + * is_bypass - check if device is a Bypass controlling device + * @if_index: network device index + * + * Output: + * 1 - if device is bypass controlling device, + * 0 - if device is bypass slave device + * -1 - device not support Bypass + **/ +int is_bypass_sd(int if_index); + +/** + * get_bypass_slave - get second port participate in the Bypass pair + * @if_index: network device index + * + * Output: + * network device index of the slave device + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_bypass_slave_sd(int if_index); + +/** + * get_bypass_caps - get second port participate in the Bypass pair + * @if_index: network device index + * + * Output: + * flags word on success;flag word is a 32-bit mask word with each bit defines + * different capability as described bellow. + * Value of 1 for supporting this feature. 0 for not supporting this feature. + * -1 - on failure (if the device is not capable of the operation or not a + * Bypass device) + * Bit feature description + * + * 0 BP_CAP The interface is Bypass capable in general + * + * 1 BP_STATUS_CAP The interface can report of the current Bypass + * mode + * + * 2 BP_STATUS_CHANGE_CAP The interface can report on a change to bypass + * mode from the last time the mode was defined + * + * 3 SW_CTL_CAP The interface is Software controlled capable for + * bypass/non bypass modes. + * + * 4 BP_DIS_CAP The interface is capable of disabling the Bypass + * mode at all times. This mode will retain its + * mode even during power loss and also after power + * recovery. This will overcome on any bypass + * operation due to watchdog timeout or set bypass + * command. + * + * 5 BP_DIS_STATUS_CAP The interface can report of the current + * DIS_BP_CAP + * + * 6 STD_NIC_CAP The interface is capable to be configured to + * operate as standard, non Bypass, NIC interface + * (have direct connection to interfaces at all + * power modes) + * + * 7 BP_PWOFF_NO_CAP The interface can be in Bypass mode at power off + * state + * + * 8 BP_PWOFF_OFF_CAP The interface can disconnect the Bypass mode at + * power off state without effecting all the other + * states of operation + * + * 9 BP_PWOFF_CTL_CAP The behavior of the Bypass mode at Power-off + * state can be controlled by software without + * effecting any other state + * + *10 BP_PWUP_ON_CAP The interface can be in Bypass mode when power + * is turned on (until the system take control of + * the bypass functionality) + * + *11 BP_PWUP_OFF_CAP The interface can disconnect from Bypass mode + * when power is turned on (until the system take + * control of the bypass functionality) + * + *12 BP_PWUP_CTL_CAP The behavior of the Bypass mode at Power-up can + * be controlled by software + * + *13 WD_CTL_CAP The interface has watchdog capabilities to turn + * to Bypass mode when not reset for defined period + * of time. + * + *14 WD_STATUS_CAP The interface can report on the watchdog status + * (Active/inactive) + * + *15 WD_TIMEOUT_CAP The interface can report the time left till + * watchdog triggers to Bypass mode. + * + *16-31 RESERVED + * + * **/ +int get_bypass_caps_sd(int if_index); + +/** + * get_wd_set_caps - Obtain watchdog timer setting capabilities + * @if_index: network device index + * + * Output: + * + * Set of numbers defining the various parameters of the watchdog capable + * to be set to as described bellow. + * -1 - on failure (device not support Bypass or it's a slave device) + * + * Bit feature description + * + * 0-3 WD_MIN_TIME The interface WD minimal time period in 100mS units + * + * 4 WD_STEP_TIME The steps of the WD timer in + * 0 - for linear steps (WD_MIN_TIME * X) + * 1 - for multiply by 2 from previous step + * (WD_MIN_TIME * 2^X) + * + * 5-8 WD_STEP_COUNT Number of steps the WD timer supports in 2^X + * (X bit available for defining the value) + * + * + * + **/ +int get_wd_set_caps_sd(int if_index); + +/** + * set_bypass - set Bypass state + * @if_index: network device index of the controlling device + * @bypass_mode: bypass mode (1=on, 0=off) + * Output: + * 0 - on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int set_bypass_sd(int if_index, int bypass_mode); + +/** + * get_bypass - Get Bypass mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_bypass_sd(int if_index); + +/** + * get_bypass_change - Get change of Bypass mode state from last status check + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_bypass_change_sd(int if_index); + +/** + * set_dis_bypass - Set Disable Bypass mode + * @if_index: network device index of the controlling device + * @dis_bypass: disable bypass(1=dis, 0=en) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int set_dis_bypass_sd(int if_index, int dis_bypass); + +/** + * get_dis_bypass - Get Disable Bypass mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (normal Bypass mode/ Disable bypass) + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int get_dis_bypass_sd(int if_index); + +/** + * set_bypass_pwoff - Set Bypass mode at power-off state + * @if_index: network device index of the controlling device + * @bypass_mode: bypass mode setting at power off state (1=BP en, 0=BP Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int set_bypass_pwoff_sd(int if_index, int bypass_mode); + +/** + * get_bypass_pwoff - Get Bypass mode state at power-off state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable bypass at power off state / normal Bypass mode) + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int get_bypass_pwoff_sd(int if_index); + +/** + * set_bypass_pwup - Set Bypass mode at power-up state + * @if_index: network device index of the controlling device + * @bypass_mode: bypass mode setting at power up state (1=BP en, 0=BP Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int set_bypass_pwup_sd(int if_index, int bypass_mode); + +/** + * get_bypass_pwup - Get Bypass mode state at power-up state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable bypass at power up state / normal Bypass mode) + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int get_bypass_pwup_sd(int if_index); + +/** + * set_bypass_wd - Set watchdog state + * @if_index: network device index of the controlling device + * @ms_timeout: requested timeout (in ms units), 0 for disabling the watchdog + * timer + * @ms_timeout_set(output): requested timeout (in ms units), that the adapter + * supports and will be used by the watchdog + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set); + +/** + * get_bypass_wd - Get watchdog state + * @if_index: network device index of the controlling device + * @ms_timeout (output): WDT timeout (in ms units), + * -1 for unknown wdt status + * 0 if WDT is disabled + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int get_bypass_wd_sd(int if_index, int *ms_timeout_set); + +/** + * get_wd_expire_time - Get watchdog expire + * @if_index: network device index of the controlling device + * @ms_time_left (output): time left till watchdog time expire, + * -1 if WDT has expired + * 0 if WDT is disabled + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device or unknown wdt status) + **/ +int get_wd_expire_time_sd(int if_index, int *ms_time_left); + +/** + * reset_bypass_wd_timer - Reset watchdog timer + * @if_index: network device index of the controlling device + * + * Output: + * 1 - on success + * 0 - watchdog is not configured + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device or unknown wdt status) + **/ +int reset_bypass_wd_timer_sd(int if_index); + +/** + * set_std_nic - Standard NIC mode of operation + * @if_index: network device index of the controlling device + * @nic_mode: 0/1 (Default Bypass mode / Standard NIC mode) + * + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int set_std_nic_sd(int if_index, int nic_mode); + +/** + * get_std_nic - Get Standard NIC mode setting + * @if_index: network device index of the controlling device + * + * Output: + * 0/1 (Default Bypass mode / Standard NIC mode) on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass or it's a slave device) + **/ +int get_std_nic_sd(int if_index); + +/** + * set_tx - set transmitter enable/disable + * @if_index: network device index of the controlling device + * @tx_state: 0/1 (Transmit Disable / Transmit Enable) + * + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ) + **/ +int set_tx_sd(int if_index, int tx_state); + +/** + * get_std_nic - get transmitter state (disable / enable) + * @if_index: network device index of the controlling device + * + * Output: + * 0/1 (ransmit Disable / Transmit Enable) on success + * -1 - on failure (device is not capable of the operation or device not support + * Bypass) + **/ +int get_tx_sd(int if_index); + +/** + * set_tap - set TAP state + * @if_index: network device index of the controlling device + * @tap_mode: 1 tap mode , 0 normal nic mode + * Output: + * 0 - on success + * -1 - on failure (device not support TAP or it's a slave device) + **/ +int set_tap_sd(int if_index, int tap_mode); + +/** + * get_tap - Get TAP mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support TAP or it's a slave device) + **/ +int get_tap_sd(int if_index); + +/** + * get_tap_change - Get change of TAP mode state from last status check + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support TAP or it's a slave device) + **/ +int get_tap_change_sd(int if_index); + +/** + * set_dis_tap - Set Disable TAP mode + * @if_index: network device index of the controlling device + * @dis_tap: disable tap(1=dis, 0=en) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not support + * TAP or it's a slave device) + **/ +int set_dis_tap_sd(int if_index, int dis_tap); + +/** + * get_dis_tap - Get Disable TAP mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (normal TAP mode/ Disable TAP) + * -1 - on failure (device is not capable of the operation or device not support + * TAP or it's a slave device) + **/ +int get_dis_tap_sd(int if_index); + +/** + * set_tap_pwup - Set TAP mode at power-up state + * @if_index: network device index of the controlling device + * @bypass_mode: tap mode setting at power up state (1=TAP en, 0=TAP Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not + * support TAP or it's a slave device) + **/ +int set_tap_pwup_sd(int if_index, int tap_mode); + +/** + * get_tap_pwup - Get TAP mode state at power-up state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable TAP at power up state / normal TAP mode) + * -1 - on failure (device is not capable of the operation or device not + * support TAP or it's a slave device) + **/ +int get_tap_pwup_sd(int if_index); + +/** + * set_bp_disc - set Disconnect state + * @if_index: network device index of the controlling device + * @tap_mode: 1 disc mode , 0 non-disc mode + * Output: + * 0 - on success + * -1 - on failure (device not support Disconnect or it's a slave device) + **/ +int set_bp_disc_sd(int if_index, int disc_mode); + +/** + * get_bp_disc - Get Disconnect mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support Disconnect or it's a slave device) + **/ +int get_bp_disc_sd(int if_index); + +/** + * get_bp_disc_change - Get change of Disconnect mode state from last status check + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support Disconnect or it's a slave device) + **/ +int get_bp_disc_change_sd(int if_index); + +/** + * set_bp_dis_disc - Set Disable Disconnect mode + * @if_index: network device index of the controlling device + * @dis_tap: disable tap(1=dis, 0=en) + * Output: + * 0 - on success + * -1 - on failure (device is not capable ofthe operation or device not + * support Disconnect or it's a slave device) + **/ +int set_bp_dis_disc_sd(int if_index, int dis_disc); + +/** + * get_dis_tap - Get Disable Disconnect mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (normal Disconnect mode/ Disable Disconnect) + * -1 - on failure (device is not capable of the operation or device not + * support Disconnect or it's a slave device) + **/ +int get_bp_dis_disc_sd(int if_index); + +/** + * set_bp_disc_pwup - Set Disconnect mode at power-up state + * @if_index: network device index of the controlling device + * @disc_mode: tap mode setting at power up state (1=Disc en, 0=Disc Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation or device not + * support Disconnect or it's a slave device) + **/ +int set_bp_disc_pwup_sd(int if_index, int disc_mode); + +/** + * get_bp_disc_pwup - Get Disconnect mode state at power-up state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable Disconnect at power up state / normal Disconnect + * mode) + * -1 - on failure (device is not capable of the operation or device not + * support TAP or it's a slave device) + **/ +int get_bp_disc_pwup_sd(int if_index); + +/** + * set_wd_exp_mode - Set adapter state when WDT expired. + * @if_index: network device index of the controlling device + * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) + * Output: + * 0 - on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int set_wd_exp_mode_sd(int if_index, int bypass_mode); + +/** + * get_wd_exp_mode - Get adapter state when WDT expired. + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (bypass/tap) on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_wd_exp_mode_sd(int if_index); + +/** + * set_wd_autoreset - reset WDT periodically. + * @if_index: network device index of the controlling device + * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) + * Output: + * 1 - on success + * -1 - on failure (device is not capable of the operation or device not + * support Bypass or it's a slave device or unknown wdt + * status) + **/ +int set_wd_autoreset_sd(int if_index, int time); + +/** + * set_wd_autoreset - reset WDT periodically. + * @if_index: network device index of the controlling device + * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) + * Output: + * 1 - on success + * -1 - on failure (device is not capable of the operation or device not + * support Bypass or it's a slave device or unknown wdt + * status) + **/ +int get_wd_autoreset_sd(int if_index); + +/** + * set_tpl - set TPL state + * @if_index: network device index of the controlling device + * @tpl_mode: 1 tpl mode , 0 normal nic mode + * Output: + * 0 - on success + * -1 - on failure (device not support TPL) + **/ +int set_tpl_sd(int if_index, int tpl_mode); + +/** + * get_tpl - Get TPL mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support TPL or it's a slave device) + **/ +int get_tpl_sd(int if_index); + +int get_bypass_info_sd(int if_index, struct bp_info *bp_info); +int bp_if_scan_sd(void); +/*int get_dev_num_sd(void);*/ diff --git a/drivers/staging/silicom/libbp_sd.h b/drivers/staging/silicom/libbp_sd.h new file mode 100644 index 00000000000..065277f81c7 --- /dev/null +++ b/drivers/staging/silicom/libbp_sd.h @@ -0,0 +1,550 @@ +/******************************************************************************/ +/* */ +/* bypass library, Copyright (c) 2004 Silicom, Ltd */ +/* Corporation. */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, located in the file LICENSE. */ +/* */ +/* Ver 1.0.0 */ +/* */ +/* libbypass.h */ +/* */ +/******************************************************************************/ + +#define BP_CAP 0x01 /* BIT_0 */ +#define BP_STATUS_CAP 0x02 +#define BP_STATUS_CHANGE_CAP 0x04 +#define SW_CTL_CAP 0x08 +#define BP_DIS_CAP 0x10 +#define BP_DIS_STATUS_CAP 0x20 +#define STD_NIC_CAP 0x40 +#define BP_PWOFF_ON_CAP 0x80 +#define BP_PWOFF_OFF_CAP 0x0100 +#define BP_PWOFF_CTL_CAP 0x0200 +#define BP_PWUP_ON_CAP 0x0400 +#define BP_PWUP_OFF_CAP 0x0800 +#define BP_PWUP_CTL_CAP 0x1000 +#define WD_CTL_CAP 0x2000 +#define WD_STATUS_CAP 0x4000 +#define WD_TIMEOUT_CAP 0x8000 +#define TX_CTL_CAP 0x10000 +#define TX_STATUS_CAP 0x20000 +#define TAP_CAP 0x40000 +#define TAP_STATUS_CAP 0x80000 +#define TAP_STATUS_CHANGE_CAP 0x100000 +#define TAP_DIS_CAP 0x200000 +#define TAP_DIS_STATUS_CAP 0x400000 +#define TAP_PWUP_ON_CAP 0x800000 +#define TAP_PWUP_OFF_CAP 0x1000000 +#define TAP_PWUP_CTL_CAP 0x2000000 +#define NIC_CAP_NEG 0x4000000 /* BIT 26 */ + +#define WD_MIN_TIME_GET(desc) (desc & 0xf) +#define WDT_STEP_TIME 0x10 + +struct bp_info { + char prod_name[14]; + unsigned char fw_ver; +}; + +/** + * is_bypass - check if device is a Bypass controlling device + * @if_index: network device index + * + * Output: + * 1 - if device is bypass controlling device, + * 0 - if device is bypass slave device + * -1 - device not support Bypass + **/ +int is_bypass_sd(int if_index); + +/** + * get_bypass_slave - get second port participate in the Bypass pair + * @if_index: network device index + * + * Output: + * network device index of the slave device + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_bypass_slave_sd(int if_index); + +/** + * get_bypass_caps - get second port participate in the Bypass pair + * @if_index: network device index + * + * Output: + * flags word on success;flag word is a 32-bit mask word with each bit defines different + * capability as described bellow. + * Value of 1 for supporting this feature. 0 for not supporting this feature. + * -1 - on failure (if the device is not capable of the operation or not a Bypass device) + * Bit feature description + * + * 0 BP_CAP The interface is Bypass capable in general + * + * 1 BP_STATUS_CAP The interface can report of the current Bypass mode + * + * 2 BP_STATUS_CHANGE_CAP The interface can report on a change to bypass mode from + * the last time the mode was defined + * + * 3 SW_CTL_CAP The interface is Software controlled capable for bypass/non bypass modes. + * + * 4 BP_DIS_CAP The interface is capable of disabling the Bypass mode at all times. + * This mode will retain its mode even during power loss and also after + * power recovery. This will overcome on any bypass operation due to + * watchdog timeout or set bypass command. + * + * 5 BP_DIS_STATUS_CAP The interface can report of the current DIS_BP_CAP + * + * 6 STD_NIC_CAP The interface is capable to be configured to operate as standard, non Bypass, + * NIC interface (have direct connection to interfaces at all power modes) + * + * 7 BP_PWOFF_NO_CAP The interface can be in Bypass mode at power off state + * + * 8 BP_PWOFF_OFF_CAP The interface can disconnect the Bypass mode at power off state without + * effecting all the other states of operation + * + * 9 BP_PWOFF_CTL_CAP The behavior of the Bypass mode at Power-off state can be controlled by + * software without effecting any other state + * + *10 BP_PWUP_ON_CAP The interface can be in Bypass mode when power is turned on + * (until the system take control of the bypass functionality) + * + *11 BP_PWUP_OFF_CAP The interface can disconnect from Bypass mode when power is turned on + * (until the system take control of the bypass functionality) + * + *12 BP_PWUP_CTL_CAP The behavior of the Bypass mode at Power-up can be controlled by software + * + *13 WD_CTL_CAP The interface has watchdog capabilities to turn to Bypass mode when not reset + * for defined period of time. + * + *14 WD_STATUS_CAP The interface can report on the watchdog status (Active/inactive) + * + *15 WD_TIMEOUT_CAP The interface can report the time left till watchdog triggers to Bypass mode. + * + *16-31 RESERVED + * + * **/ +int get_bypass_caps_sd(int if_index); + +/** + * get_wd_set_caps - Obtain watchdog timer setting capabilities + * @if_index: network device index + * + * Output: + * + * Set of numbers defining the various parameters of the watchdog capable + * to be set to as described bellow. + * -1 - on failure (device not support Bypass or it's a slave device) + * + * Bit feature description + * + * 0-3 WD_MIN_TIME The interface WD minimal time period in 100mS units + * + * 4 WD_STEP_TIME The steps of the WD timer in + * 0 - for linear steps (WD_MIN_TIME * X) + * 1 - for multiply by 2 from previous step (WD_MIN_TIME * 2^X) + * + * 5-8 WD_STEP_COUNT Number of steps the WD timer supports in 2^X + * (X bit available for defining the value) + * + * + * + **/ +int get_wd_set_caps_sd(int if_index); + +/** + * set_bypass - set Bypass state + * @if_index: network device index of the controlling device + * @bypass_mode: bypass mode (1=on, 0=off) + * Output: + * 0 - on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int set_bypass_sd(int if_index, int bypass_mode); + +/** + * get_bypass - Get Bypass mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_bypass_sd(int if_index); + +/** + * get_bypass_change - Get change of Bypass mode state from last status check + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_bypass_change_sd(int if_index); + +/** + * set_dis_bypass - Set Disable Bypass mode + * @if_index: network device index of the controlling device + * @dis_bypass: disable bypass(1=dis, 0=en) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int set_dis_bypass_sd(int if_index, int dis_bypass); + +/** + * get_dis_bypass - Get Disable Bypass mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (normal Bypass mode/ Disable bypass) + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int get_dis_bypass_sd(int if_index); + +/** + * set_bypass_pwoff - Set Bypass mode at power-off state + * @if_index: network device index of the controlling device + * @bypass_mode: bypass mode setting at power off state (1=BP en, 0=BP Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int set_bypass_pwoff_sd(int if_index, int bypass_mode); + +/** + * get_bypass_pwoff - Get Bypass mode state at power-off state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable bypass at power off state / normal Bypass mode) + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int get_bypass_pwoff_sd(int if_index); + +/** + * set_bypass_pwup - Set Bypass mode at power-up state + * @if_index: network device index of the controlling device + * @bypass_mode: bypass mode setting at power up state (1=BP en, 0=BP Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int set_bypass_pwup_sd(int if_index, int bypass_mode); + +/** + * get_bypass_pwup - Get Bypass mode state at power-up state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable bypass at power up state / normal Bypass mode) + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int get_bypass_pwup_sd(int if_index); + +/** + * set_bypass_wd - Set watchdog state + * @if_index: network device index of the controlling device + * @ms_timeout: requested timeout (in ms units), 0 for disabling the watchdog timer + * @ms_timeout_set(output): requested timeout (in ms units), + * that the adapter supports and will be used by the watchdog + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int set_bypass_wd_sd(int if_index, int ms_timeout, int *ms_timeout_set); + +/** + * get_bypass_wd - Get watchdog state + * @if_index: network device index of the controlling device + * @ms_timeout (output): WDT timeout (in ms units), + * -1 for unknown wdt status + * 0 if WDT is disabled + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int get_bypass_wd_sd(int if_index, int *ms_timeout_set); + +/** + * get_wd_expire_time - Get watchdog expire + * @if_index: network device index of the controlling device + * @ms_time_left (output): time left till watchdog time expire, + * -1 if WDT has expired + * 0 if WDT is disabled + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device or unknown wdt status) + **/ +int get_wd_expire_time_sd(int if_index, int *ms_time_left); + +/** + * reset_bypass_wd_timer - Reset watchdog timer + * @if_index: network device index of the controlling device + * + * Output: + * 1 - on success + * 0 - watchdog is not configured + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device or unknown wdt status) + **/ +int reset_bypass_wd_timer_sd(int if_index); + +/** + * set_std_nic - Standard NIC mode of operation + * @if_index: network device index of the controlling device + * @nic_mode: 0/1 (Default Bypass mode / Standard NIC mode) + * + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int set_std_nic_sd(int if_index, int nic_mode); + +/** + * get_std_nic - Get Standard NIC mode setting + * @if_index: network device index of the controlling device + * + * Output: + * 0/1 (Default Bypass mode / Standard NIC mode) on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device) + **/ +int get_std_nic_sd(int if_index); + +/** + * set_tx - set transmitter enable/disable + * @if_index: network device index of the controlling device + * @tx_state: 0/1 (Transmit Disable / Transmit Enable) + * + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ) + **/ +int set_tx_sd(int if_index, int tx_state); + +/** + * get_tx - get transmitter state (disable / enable) + * @if_index: network device index of the controlling device + * + * Output: + * 0/1 (ransmit Disable / Transmit Enable) on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass) + **/ +int get_tx_sd(int if_index); + +/** + * set_tpl - set TPL enable/disable + * @if_index: network device index of the controlling device + * @tx_state: 0/1 (TPL Disable / TPL Enable) + * + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ) + **/ +int set_tpl_sd(int if_index, int tpl_state); + +/** + * get_tpl - get TPL state (disable / enable) + * @if_index: network device index of the controlling device + * + * Output: + * 0/1 (TPL Disable / TPL Enable) on success + * -1 - on failure (device is not capable of the operation) + **/ +int get_tpl_sd(int if_index); + +int get_bp_hw_reset_sd(int if_index); + +int set_bp_hw_reset_sd(int if_index, int status); + +/** + * set_tap - set TAP state + * @if_index: network device index of the controlling device + * @tap_mode: 1 tap mode , 0 normal nic mode + * Output: + * 0 - on success + * -1 - on failure (device not support TAP or it's a slave device) + **/ +int set_tap_sd(int if_index, int tap_mode); + +/** + * get_tap - Get TAP mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support TAP or it's a slave device) + **/ +int get_tap_sd(int if_index); + +/** + * get_tap_change - Get change of TAP mode state from last status check + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support TAP or it's a slave device) + **/ +int get_tap_change_sd(int if_index); + +/** + * set_dis_tap - Set Disable TAP mode + * @if_index: network device index of the controlling device + * @dis_tap: disable tap(1=dis, 0=en) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support TAP + * or it's a slave device) + **/ +int set_dis_tap_sd(int if_index, int dis_tap); + +/** + * get_dis_tap - Get Disable TAP mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (normal TAP mode/ Disable TAP) + * -1 - on failure (device is not capable of the operation ordevice not support TAP + * or it's a slave device) + **/ +int get_dis_tap_sd(int if_index); + +/** + * set_tap_pwup - Set TAP mode at power-up state + * @if_index: network device index of the controlling device + * @bypass_mode: tap mode setting at power up state (1=TAP en, 0=TAP Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support TAP + * or it's a slave device) + **/ +int set_tap_pwup_sd(int if_index, int tap_mode); + +/** + * get_tap_pwup - Get TAP mode state at power-up state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable TAP at power up state / normal TAP mode) + * -1 - on failure (device is not capable of the operation ordevice not support TAP + * or it's a slave device) + **/ +int get_tap_pwup_sd(int if_index); + +/** + * set_wd_exp_mode - Set adapter state when WDT expired. + * @if_index: network device index of the controlling device + * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) + * Output: + * 0 - on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int set_wd_exp_mode_sd(int if_index, int bypass_mode); + +/** + * get_wd_exp_mode - Get adapter state when WDT expired. + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (bypass/tap) on success + * -1 - on failure (device not support Bypass or it's a slave device) + **/ +int get_wd_exp_mode_sd(int if_index); + +/** + * set_wd_autoreset - reset WDT periodically. + * @if_index: network device index of the controlling device + * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) + * Output: + * 1 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device or unknown wdt status) + **/ +int set_wd_autoreset_sd(int if_index, int time); + +/** + * set_wd_autoreset - reset WDT periodically. + * @if_index: network device index of the controlling device + * @bypass_mode: adapter mode (1=tap mode, 0=bypass mode) + * Output: + * 1 - on success + * -1 - on failure (device is not capable of the operation ordevice not support Bypass + * or it's a slave device or unknown wdt status) + **/ +int get_wd_autoreset_sd(int if_index); +/** + * set_disc - set DISC state + * @if_index: network device index of the controlling device + * @tap_mode: 1 DISC mode , 0 normal nic mode + * Output: + * 0 - on success + * -1 - on failure (device not support disconnect or it's a slave device) + **/ +int set_bp_disc_sd(int if_index, int disc_mode); + +/** + * get_disc - Get disc mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support disconnect or it's a slave device) + **/ +int get_bp_disc_sd(int if_index); + +/** + * get_disc_change - Get change of DISC mode state from last status check + * @if_index: network device index of the controlling device + * Output: + * 0/1 - (off/on) on success + * -1 - on failure (device not support disconnect or it's a slave device) + **/ +int get_bp_disc_change_sd(int if_index); + +/** + * set_dis_disc - Set Disable DISC mode + * @if_index: network device index of the controlling device + * @dis_disc: disable disconnect(1=dis, 0=en) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support DISC + * or it's a slave device) + **/ +int set_bp_dis_disc_sd(int if_index, int dis_disc); + +/** + * get_dis_disc - Get Disable DISC mode state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (normal DISC mode/ Disable DISC) + * -1 - on failure (device is not capable of the operation ordevice not support TAP + * or it's a slave device) + **/ +int get_bp_dis_disc_sd(int if_index); + +/** + * set_disc_pwup - Set DISC mode at power-up state + * @if_index: network device index of the controlling device + * @disc_mode: DISC mode setting at power up state (1= en, 0= Dis) + * Output: + * 0 - on success + * -1 - on failure (device is not capable of the operation ordevice not support DISC + * or it's a slave device) + **/ +int set_bp_disc_pwup_sd(int if_index, int disc_mode); + +/** + * get_disc_pwup - Get DISC mode state at power-up state + * @if_index: network device index of the controlling device + * Output: + * 0/1 - on success (Disable DISC at power up state / normal DISC mode) + * -1 - on failure (device is not capable of the operation ordevice not support DISC + * or it's a slave device) + **/ +int get_bp_disc_pwup_sd(int if_index); + +int get_bypass_info_sd(int if_index, struct bp_info *bp_info); +int bp_if_scan_sd(void); +/*int get_dev_num_sd(void);*/ |
