/drivers/net/ethernet/micrel/ksz884x.c
http://github.com/mirrors/linux · C · 7258 lines · 4600 code · 1016 blank · 1642 comment · 551 complexity · 7327a5821464bade45f1b97a615821cb MD5 · raw file
Large files are truncated click here to view the full file
- // SPDX-License-Identifier: GPL-2.0-only
- /**
- * drivers/net/ethernet/micrel/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver
- *
- * Copyright (c) 2009-2010 Micrel, Inc.
- * Tristram Ha <Tristram.Ha@micrel.com>
- */
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/ioport.h>
- #include <linux/pci.h>
- #include <linux/proc_fs.h>
- #include <linux/mii.h>
- #include <linux/platform_device.h>
- #include <linux/ethtool.h>
- #include <linux/etherdevice.h>
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <linux/if_vlan.h>
- #include <linux/crc32.h>
- #include <linux/sched.h>
- #include <linux/slab.h>
- /* DMA Registers */
- #define KS_DMA_TX_CTRL 0x0000
- #define DMA_TX_ENABLE 0x00000001
- #define DMA_TX_CRC_ENABLE 0x00000002
- #define DMA_TX_PAD_ENABLE 0x00000004
- #define DMA_TX_LOOPBACK 0x00000100
- #define DMA_TX_FLOW_ENABLE 0x00000200
- #define DMA_TX_CSUM_IP 0x00010000
- #define DMA_TX_CSUM_TCP 0x00020000
- #define DMA_TX_CSUM_UDP 0x00040000
- #define DMA_TX_BURST_SIZE 0x3F000000
- #define KS_DMA_RX_CTRL 0x0004
- #define DMA_RX_ENABLE 0x00000001
- #define KS884X_DMA_RX_MULTICAST 0x00000002
- #define DMA_RX_PROMISCUOUS 0x00000004
- #define DMA_RX_ERROR 0x00000008
- #define DMA_RX_UNICAST 0x00000010
- #define DMA_RX_ALL_MULTICAST 0x00000020
- #define DMA_RX_BROADCAST 0x00000040
- #define DMA_RX_FLOW_ENABLE 0x00000200
- #define DMA_RX_CSUM_IP 0x00010000
- #define DMA_RX_CSUM_TCP 0x00020000
- #define DMA_RX_CSUM_UDP 0x00040000
- #define DMA_RX_BURST_SIZE 0x3F000000
- #define DMA_BURST_SHIFT 24
- #define DMA_BURST_DEFAULT 8
- #define KS_DMA_TX_START 0x0008
- #define KS_DMA_RX_START 0x000C
- #define DMA_START 0x00000001
- #define KS_DMA_TX_ADDR 0x0010
- #define KS_DMA_RX_ADDR 0x0014
- #define DMA_ADDR_LIST_MASK 0xFFFFFFFC
- #define DMA_ADDR_LIST_SHIFT 2
- /* MTR0 */
- #define KS884X_MULTICAST_0_OFFSET 0x0020
- #define KS884X_MULTICAST_1_OFFSET 0x0021
- #define KS884X_MULTICAST_2_OFFSET 0x0022
- #define KS884x_MULTICAST_3_OFFSET 0x0023
- /* MTR1 */
- #define KS884X_MULTICAST_4_OFFSET 0x0024
- #define KS884X_MULTICAST_5_OFFSET 0x0025
- #define KS884X_MULTICAST_6_OFFSET 0x0026
- #define KS884X_MULTICAST_7_OFFSET 0x0027
- /* Interrupt Registers */
- /* INTEN */
- #define KS884X_INTERRUPTS_ENABLE 0x0028
- /* INTST */
- #define KS884X_INTERRUPTS_STATUS 0x002C
- #define KS884X_INT_RX_STOPPED 0x02000000
- #define KS884X_INT_TX_STOPPED 0x04000000
- #define KS884X_INT_RX_OVERRUN 0x08000000
- #define KS884X_INT_TX_EMPTY 0x10000000
- #define KS884X_INT_RX 0x20000000
- #define KS884X_INT_TX 0x40000000
- #define KS884X_INT_PHY 0x80000000
- #define KS884X_INT_RX_MASK \
- (KS884X_INT_RX | KS884X_INT_RX_OVERRUN)
- #define KS884X_INT_TX_MASK \
- (KS884X_INT_TX | KS884X_INT_TX_EMPTY)
- #define KS884X_INT_MASK (KS884X_INT_RX | KS884X_INT_TX | KS884X_INT_PHY)
- /* MAC Additional Station Address */
- /* MAAL0 */
- #define KS_ADD_ADDR_0_LO 0x0080
- /* MAAH0 */
- #define KS_ADD_ADDR_0_HI 0x0084
- /* MAAL1 */
- #define KS_ADD_ADDR_1_LO 0x0088
- /* MAAH1 */
- #define KS_ADD_ADDR_1_HI 0x008C
- /* MAAL2 */
- #define KS_ADD_ADDR_2_LO 0x0090
- /* MAAH2 */
- #define KS_ADD_ADDR_2_HI 0x0094
- /* MAAL3 */
- #define KS_ADD_ADDR_3_LO 0x0098
- /* MAAH3 */
- #define KS_ADD_ADDR_3_HI 0x009C
- /* MAAL4 */
- #define KS_ADD_ADDR_4_LO 0x00A0
- /* MAAH4 */
- #define KS_ADD_ADDR_4_HI 0x00A4
- /* MAAL5 */
- #define KS_ADD_ADDR_5_LO 0x00A8
- /* MAAH5 */
- #define KS_ADD_ADDR_5_HI 0x00AC
- /* MAAL6 */
- #define KS_ADD_ADDR_6_LO 0x00B0
- /* MAAH6 */
- #define KS_ADD_ADDR_6_HI 0x00B4
- /* MAAL7 */
- #define KS_ADD_ADDR_7_LO 0x00B8
- /* MAAH7 */
- #define KS_ADD_ADDR_7_HI 0x00BC
- /* MAAL8 */
- #define KS_ADD_ADDR_8_LO 0x00C0
- /* MAAH8 */
- #define KS_ADD_ADDR_8_HI 0x00C4
- /* MAAL9 */
- #define KS_ADD_ADDR_9_LO 0x00C8
- /* MAAH9 */
- #define KS_ADD_ADDR_9_HI 0x00CC
- /* MAAL10 */
- #define KS_ADD_ADDR_A_LO 0x00D0
- /* MAAH10 */
- #define KS_ADD_ADDR_A_HI 0x00D4
- /* MAAL11 */
- #define KS_ADD_ADDR_B_LO 0x00D8
- /* MAAH11 */
- #define KS_ADD_ADDR_B_HI 0x00DC
- /* MAAL12 */
- #define KS_ADD_ADDR_C_LO 0x00E0
- /* MAAH12 */
- #define KS_ADD_ADDR_C_HI 0x00E4
- /* MAAL13 */
- #define KS_ADD_ADDR_D_LO 0x00E8
- /* MAAH13 */
- #define KS_ADD_ADDR_D_HI 0x00EC
- /* MAAL14 */
- #define KS_ADD_ADDR_E_LO 0x00F0
- /* MAAH14 */
- #define KS_ADD_ADDR_E_HI 0x00F4
- /* MAAL15 */
- #define KS_ADD_ADDR_F_LO 0x00F8
- /* MAAH15 */
- #define KS_ADD_ADDR_F_HI 0x00FC
- #define ADD_ADDR_HI_MASK 0x0000FFFF
- #define ADD_ADDR_ENABLE 0x80000000
- #define ADD_ADDR_INCR 8
- /* Miscellaneous Registers */
- /* MARL */
- #define KS884X_ADDR_0_OFFSET 0x0200
- #define KS884X_ADDR_1_OFFSET 0x0201
- /* MARM */
- #define KS884X_ADDR_2_OFFSET 0x0202
- #define KS884X_ADDR_3_OFFSET 0x0203
- /* MARH */
- #define KS884X_ADDR_4_OFFSET 0x0204
- #define KS884X_ADDR_5_OFFSET 0x0205
- /* OBCR */
- #define KS884X_BUS_CTRL_OFFSET 0x0210
- #define BUS_SPEED_125_MHZ 0x0000
- #define BUS_SPEED_62_5_MHZ 0x0001
- #define BUS_SPEED_41_66_MHZ 0x0002
- #define BUS_SPEED_25_MHZ 0x0003
- /* EEPCR */
- #define KS884X_EEPROM_CTRL_OFFSET 0x0212
- #define EEPROM_CHIP_SELECT 0x0001
- #define EEPROM_SERIAL_CLOCK 0x0002
- #define EEPROM_DATA_OUT 0x0004
- #define EEPROM_DATA_IN 0x0008
- #define EEPROM_ACCESS_ENABLE 0x0010
- /* MBIR */
- #define KS884X_MEM_INFO_OFFSET 0x0214
- #define RX_MEM_TEST_FAILED 0x0008
- #define RX_MEM_TEST_FINISHED 0x0010
- #define TX_MEM_TEST_FAILED 0x0800
- #define TX_MEM_TEST_FINISHED 0x1000
- /* GCR */
- #define KS884X_GLOBAL_CTRL_OFFSET 0x0216
- #define GLOBAL_SOFTWARE_RESET 0x0001
- #define KS8841_POWER_MANAGE_OFFSET 0x0218
- /* WFCR */
- #define KS8841_WOL_CTRL_OFFSET 0x021A
- #define KS8841_WOL_MAGIC_ENABLE 0x0080
- #define KS8841_WOL_FRAME3_ENABLE 0x0008
- #define KS8841_WOL_FRAME2_ENABLE 0x0004
- #define KS8841_WOL_FRAME1_ENABLE 0x0002
- #define KS8841_WOL_FRAME0_ENABLE 0x0001
- /* WF0 */
- #define KS8841_WOL_FRAME_CRC_OFFSET 0x0220
- #define KS8841_WOL_FRAME_BYTE0_OFFSET 0x0224
- #define KS8841_WOL_FRAME_BYTE2_OFFSET 0x0228
- /* IACR */
- #define KS884X_IACR_P 0x04A0
- #define KS884X_IACR_OFFSET KS884X_IACR_P
- /* IADR1 */
- #define KS884X_IADR1_P 0x04A2
- #define KS884X_IADR2_P 0x04A4
- #define KS884X_IADR3_P 0x04A6
- #define KS884X_IADR4_P 0x04A8
- #define KS884X_IADR5_P 0x04AA
- #define KS884X_ACC_CTRL_SEL_OFFSET KS884X_IACR_P
- #define KS884X_ACC_CTRL_INDEX_OFFSET (KS884X_ACC_CTRL_SEL_OFFSET + 1)
- #define KS884X_ACC_DATA_0_OFFSET KS884X_IADR4_P
- #define KS884X_ACC_DATA_1_OFFSET (KS884X_ACC_DATA_0_OFFSET + 1)
- #define KS884X_ACC_DATA_2_OFFSET KS884X_IADR5_P
- #define KS884X_ACC_DATA_3_OFFSET (KS884X_ACC_DATA_2_OFFSET + 1)
- #define KS884X_ACC_DATA_4_OFFSET KS884X_IADR2_P
- #define KS884X_ACC_DATA_5_OFFSET (KS884X_ACC_DATA_4_OFFSET + 1)
- #define KS884X_ACC_DATA_6_OFFSET KS884X_IADR3_P
- #define KS884X_ACC_DATA_7_OFFSET (KS884X_ACC_DATA_6_OFFSET + 1)
- #define KS884X_ACC_DATA_8_OFFSET KS884X_IADR1_P
- /* P1MBCR */
- #define KS884X_P1MBCR_P 0x04D0
- #define KS884X_P1MBSR_P 0x04D2
- #define KS884X_PHY1ILR_P 0x04D4
- #define KS884X_PHY1IHR_P 0x04D6
- #define KS884X_P1ANAR_P 0x04D8
- #define KS884X_P1ANLPR_P 0x04DA
- /* P2MBCR */
- #define KS884X_P2MBCR_P 0x04E0
- #define KS884X_P2MBSR_P 0x04E2
- #define KS884X_PHY2ILR_P 0x04E4
- #define KS884X_PHY2IHR_P 0x04E6
- #define KS884X_P2ANAR_P 0x04E8
- #define KS884X_P2ANLPR_P 0x04EA
- #define KS884X_PHY_1_CTRL_OFFSET KS884X_P1MBCR_P
- #define PHY_CTRL_INTERVAL (KS884X_P2MBCR_P - KS884X_P1MBCR_P)
- #define KS884X_PHY_CTRL_OFFSET 0x00
- /* Mode Control Register */
- #define PHY_REG_CTRL 0
- #define PHY_RESET 0x8000
- #define PHY_LOOPBACK 0x4000
- #define PHY_SPEED_100MBIT 0x2000
- #define PHY_AUTO_NEG_ENABLE 0x1000
- #define PHY_POWER_DOWN 0x0800
- #define PHY_MII_DISABLE 0x0400
- #define PHY_AUTO_NEG_RESTART 0x0200
- #define PHY_FULL_DUPLEX 0x0100
- #define PHY_COLLISION_TEST 0x0080
- #define PHY_HP_MDIX 0x0020
- #define PHY_FORCE_MDIX 0x0010
- #define PHY_AUTO_MDIX_DISABLE 0x0008
- #define PHY_REMOTE_FAULT_DISABLE 0x0004
- #define PHY_TRANSMIT_DISABLE 0x0002
- #define PHY_LED_DISABLE 0x0001
- #define KS884X_PHY_STATUS_OFFSET 0x02
- /* Mode Status Register */
- #define PHY_REG_STATUS 1
- #define PHY_100BT4_CAPABLE 0x8000
- #define PHY_100BTX_FD_CAPABLE 0x4000
- #define PHY_100BTX_CAPABLE 0x2000
- #define PHY_10BT_FD_CAPABLE 0x1000
- #define PHY_10BT_CAPABLE 0x0800
- #define PHY_MII_SUPPRESS_CAPABLE 0x0040
- #define PHY_AUTO_NEG_ACKNOWLEDGE 0x0020
- #define PHY_REMOTE_FAULT 0x0010
- #define PHY_AUTO_NEG_CAPABLE 0x0008
- #define PHY_LINK_STATUS 0x0004
- #define PHY_JABBER_DETECT 0x0002
- #define PHY_EXTENDED_CAPABILITY 0x0001
- #define KS884X_PHY_ID_1_OFFSET 0x04
- #define KS884X_PHY_ID_2_OFFSET 0x06
- /* PHY Identifier Registers */
- #define PHY_REG_ID_1 2
- #define PHY_REG_ID_2 3
- #define KS884X_PHY_AUTO_NEG_OFFSET 0x08
- /* Auto-Negotiation Advertisement Register */
- #define PHY_REG_AUTO_NEGOTIATION 4
- #define PHY_AUTO_NEG_NEXT_PAGE 0x8000
- #define PHY_AUTO_NEG_REMOTE_FAULT 0x2000
- /* Not supported. */
- #define PHY_AUTO_NEG_ASYM_PAUSE 0x0800
- #define PHY_AUTO_NEG_SYM_PAUSE 0x0400
- #define PHY_AUTO_NEG_100BT4 0x0200
- #define PHY_AUTO_NEG_100BTX_FD 0x0100
- #define PHY_AUTO_NEG_100BTX 0x0080
- #define PHY_AUTO_NEG_10BT_FD 0x0040
- #define PHY_AUTO_NEG_10BT 0x0020
- #define PHY_AUTO_NEG_SELECTOR 0x001F
- #define PHY_AUTO_NEG_802_3 0x0001
- #define PHY_AUTO_NEG_PAUSE (PHY_AUTO_NEG_SYM_PAUSE | PHY_AUTO_NEG_ASYM_PAUSE)
- #define KS884X_PHY_REMOTE_CAP_OFFSET 0x0A
- /* Auto-Negotiation Link Partner Ability Register */
- #define PHY_REG_REMOTE_CAPABILITY 5
- #define PHY_REMOTE_NEXT_PAGE 0x8000
- #define PHY_REMOTE_ACKNOWLEDGE 0x4000
- #define PHY_REMOTE_REMOTE_FAULT 0x2000
- #define PHY_REMOTE_SYM_PAUSE 0x0400
- #define PHY_REMOTE_100BTX_FD 0x0100
- #define PHY_REMOTE_100BTX 0x0080
- #define PHY_REMOTE_10BT_FD 0x0040
- #define PHY_REMOTE_10BT 0x0020
- /* P1VCT */
- #define KS884X_P1VCT_P 0x04F0
- #define KS884X_P1PHYCTRL_P 0x04F2
- /* P2VCT */
- #define KS884X_P2VCT_P 0x04F4
- #define KS884X_P2PHYCTRL_P 0x04F6
- #define KS884X_PHY_SPECIAL_OFFSET KS884X_P1VCT_P
- #define PHY_SPECIAL_INTERVAL (KS884X_P2VCT_P - KS884X_P1VCT_P)
- #define KS884X_PHY_LINK_MD_OFFSET 0x00
- #define PHY_START_CABLE_DIAG 0x8000
- #define PHY_CABLE_DIAG_RESULT 0x6000
- #define PHY_CABLE_STAT_NORMAL 0x0000
- #define PHY_CABLE_STAT_OPEN 0x2000
- #define PHY_CABLE_STAT_SHORT 0x4000
- #define PHY_CABLE_STAT_FAILED 0x6000
- #define PHY_CABLE_10M_SHORT 0x1000
- #define PHY_CABLE_FAULT_COUNTER 0x01FF
- #define KS884X_PHY_PHY_CTRL_OFFSET 0x02
- #define PHY_STAT_REVERSED_POLARITY 0x0020
- #define PHY_STAT_MDIX 0x0010
- #define PHY_FORCE_LINK 0x0008
- #define PHY_POWER_SAVING_DISABLE 0x0004
- #define PHY_REMOTE_LOOPBACK 0x0002
- /* SIDER */
- #define KS884X_SIDER_P 0x0400
- #define KS884X_CHIP_ID_OFFSET KS884X_SIDER_P
- #define KS884X_FAMILY_ID_OFFSET (KS884X_CHIP_ID_OFFSET + 1)
- #define REG_FAMILY_ID 0x88
- #define REG_CHIP_ID_41 0x8810
- #define REG_CHIP_ID_42 0x8800
- #define KS884X_CHIP_ID_MASK_41 0xFF10
- #define KS884X_CHIP_ID_MASK 0xFFF0
- #define KS884X_CHIP_ID_SHIFT 4
- #define KS884X_REVISION_MASK 0x000E
- #define KS884X_REVISION_SHIFT 1
- #define KS8842_START 0x0001
- #define CHIP_IP_41_M 0x8810
- #define CHIP_IP_42_M 0x8800
- #define CHIP_IP_61_M 0x8890
- #define CHIP_IP_62_M 0x8880
- #define CHIP_IP_41_P 0x8850
- #define CHIP_IP_42_P 0x8840
- #define CHIP_IP_61_P 0x88D0
- #define CHIP_IP_62_P 0x88C0
- /* SGCR1 */
- #define KS8842_SGCR1_P 0x0402
- #define KS8842_SWITCH_CTRL_1_OFFSET KS8842_SGCR1_P
- #define SWITCH_PASS_ALL 0x8000
- #define SWITCH_TX_FLOW_CTRL 0x2000
- #define SWITCH_RX_FLOW_CTRL 0x1000
- #define SWITCH_CHECK_LENGTH 0x0800
- #define SWITCH_AGING_ENABLE 0x0400
- #define SWITCH_FAST_AGING 0x0200
- #define SWITCH_AGGR_BACKOFF 0x0100
- #define SWITCH_PASS_PAUSE 0x0008
- #define SWITCH_LINK_AUTO_AGING 0x0001
- /* SGCR2 */
- #define KS8842_SGCR2_P 0x0404
- #define KS8842_SWITCH_CTRL_2_OFFSET KS8842_SGCR2_P
- #define SWITCH_VLAN_ENABLE 0x8000
- #define SWITCH_IGMP_SNOOP 0x4000
- #define IPV6_MLD_SNOOP_ENABLE 0x2000
- #define IPV6_MLD_SNOOP_OPTION 0x1000
- #define PRIORITY_SCHEME_SELECT 0x0800
- #define SWITCH_MIRROR_RX_TX 0x0100
- #define UNICAST_VLAN_BOUNDARY 0x0080
- #define MULTICAST_STORM_DISABLE 0x0040
- #define SWITCH_BACK_PRESSURE 0x0020
- #define FAIR_FLOW_CTRL 0x0010
- #define NO_EXC_COLLISION_DROP 0x0008
- #define SWITCH_HUGE_PACKET 0x0004
- #define SWITCH_LEGAL_PACKET 0x0002
- #define SWITCH_BUF_RESERVE 0x0001
- /* SGCR3 */
- #define KS8842_SGCR3_P 0x0406
- #define KS8842_SWITCH_CTRL_3_OFFSET KS8842_SGCR3_P
- #define BROADCAST_STORM_RATE_LO 0xFF00
- #define SWITCH_REPEATER 0x0080
- #define SWITCH_HALF_DUPLEX 0x0040
- #define SWITCH_FLOW_CTRL 0x0020
- #define SWITCH_10_MBIT 0x0010
- #define SWITCH_REPLACE_NULL_VID 0x0008
- #define BROADCAST_STORM_RATE_HI 0x0007
- #define BROADCAST_STORM_RATE 0x07FF
- /* SGCR4 */
- #define KS8842_SGCR4_P 0x0408
- /* SGCR5 */
- #define KS8842_SGCR5_P 0x040A
- #define KS8842_SWITCH_CTRL_5_OFFSET KS8842_SGCR5_P
- #define LED_MODE 0x8200
- #define LED_SPEED_DUPLEX_ACT 0x0000
- #define LED_SPEED_DUPLEX_LINK_ACT 0x8000
- #define LED_DUPLEX_10_100 0x0200
- /* SGCR6 */
- #define KS8842_SGCR6_P 0x0410
- #define KS8842_SWITCH_CTRL_6_OFFSET KS8842_SGCR6_P
- #define KS8842_PRIORITY_MASK 3
- #define KS8842_PRIORITY_SHIFT 2
- /* SGCR7 */
- #define KS8842_SGCR7_P 0x0412
- #define KS8842_SWITCH_CTRL_7_OFFSET KS8842_SGCR7_P
- #define SWITCH_UNK_DEF_PORT_ENABLE 0x0008
- #define SWITCH_UNK_DEF_PORT_3 0x0004
- #define SWITCH_UNK_DEF_PORT_2 0x0002
- #define SWITCH_UNK_DEF_PORT_1 0x0001
- /* MACAR1 */
- #define KS8842_MACAR1_P 0x0470
- #define KS8842_MACAR2_P 0x0472
- #define KS8842_MACAR3_P 0x0474
- #define KS8842_MAC_ADDR_1_OFFSET KS8842_MACAR1_P
- #define KS8842_MAC_ADDR_0_OFFSET (KS8842_MAC_ADDR_1_OFFSET + 1)
- #define KS8842_MAC_ADDR_3_OFFSET KS8842_MACAR2_P
- #define KS8842_MAC_ADDR_2_OFFSET (KS8842_MAC_ADDR_3_OFFSET + 1)
- #define KS8842_MAC_ADDR_5_OFFSET KS8842_MACAR3_P
- #define KS8842_MAC_ADDR_4_OFFSET (KS8842_MAC_ADDR_5_OFFSET + 1)
- /* TOSR1 */
- #define KS8842_TOSR1_P 0x0480
- #define KS8842_TOSR2_P 0x0482
- #define KS8842_TOSR3_P 0x0484
- #define KS8842_TOSR4_P 0x0486
- #define KS8842_TOSR5_P 0x0488
- #define KS8842_TOSR6_P 0x048A
- #define KS8842_TOSR7_P 0x0490
- #define KS8842_TOSR8_P 0x0492
- #define KS8842_TOS_1_OFFSET KS8842_TOSR1_P
- #define KS8842_TOS_2_OFFSET KS8842_TOSR2_P
- #define KS8842_TOS_3_OFFSET KS8842_TOSR3_P
- #define KS8842_TOS_4_OFFSET KS8842_TOSR4_P
- #define KS8842_TOS_5_OFFSET KS8842_TOSR5_P
- #define KS8842_TOS_6_OFFSET KS8842_TOSR6_P
- #define KS8842_TOS_7_OFFSET KS8842_TOSR7_P
- #define KS8842_TOS_8_OFFSET KS8842_TOSR8_P
- /* P1CR1 */
- #define KS8842_P1CR1_P 0x0500
- #define KS8842_P1CR2_P 0x0502
- #define KS8842_P1VIDR_P 0x0504
- #define KS8842_P1CR3_P 0x0506
- #define KS8842_P1IRCR_P 0x0508
- #define KS8842_P1ERCR_P 0x050A
- #define KS884X_P1SCSLMD_P 0x0510
- #define KS884X_P1CR4_P 0x0512
- #define KS884X_P1SR_P 0x0514
- /* P2CR1 */
- #define KS8842_P2CR1_P 0x0520
- #define KS8842_P2CR2_P 0x0522
- #define KS8842_P2VIDR_P 0x0524
- #define KS8842_P2CR3_P 0x0526
- #define KS8842_P2IRCR_P 0x0528
- #define KS8842_P2ERCR_P 0x052A
- #define KS884X_P2SCSLMD_P 0x0530
- #define KS884X_P2CR4_P 0x0532
- #define KS884X_P2SR_P 0x0534
- /* P3CR1 */
- #define KS8842_P3CR1_P 0x0540
- #define KS8842_P3CR2_P 0x0542
- #define KS8842_P3VIDR_P 0x0544
- #define KS8842_P3CR3_P 0x0546
- #define KS8842_P3IRCR_P 0x0548
- #define KS8842_P3ERCR_P 0x054A
- #define KS8842_PORT_1_CTRL_1 KS8842_P1CR1_P
- #define KS8842_PORT_2_CTRL_1 KS8842_P2CR1_P
- #define KS8842_PORT_3_CTRL_1 KS8842_P3CR1_P
- #define PORT_CTRL_ADDR(port, addr) \
- (addr = KS8842_PORT_1_CTRL_1 + (port) * \
- (KS8842_PORT_2_CTRL_1 - KS8842_PORT_1_CTRL_1))
- #define KS8842_PORT_CTRL_1_OFFSET 0x00
- #define PORT_BROADCAST_STORM 0x0080
- #define PORT_DIFFSERV_ENABLE 0x0040
- #define PORT_802_1P_ENABLE 0x0020
- #define PORT_BASED_PRIORITY_MASK 0x0018
- #define PORT_BASED_PRIORITY_BASE 0x0003
- #define PORT_BASED_PRIORITY_SHIFT 3
- #define PORT_BASED_PRIORITY_0 0x0000
- #define PORT_BASED_PRIORITY_1 0x0008
- #define PORT_BASED_PRIORITY_2 0x0010
- #define PORT_BASED_PRIORITY_3 0x0018
- #define PORT_INSERT_TAG 0x0004
- #define PORT_REMOVE_TAG 0x0002
- #define PORT_PRIO_QUEUE_ENABLE 0x0001
- #define KS8842_PORT_CTRL_2_OFFSET 0x02
- #define PORT_INGRESS_VLAN_FILTER 0x4000
- #define PORT_DISCARD_NON_VID 0x2000
- #define PORT_FORCE_FLOW_CTRL 0x1000
- #define PORT_BACK_PRESSURE 0x0800
- #define PORT_TX_ENABLE 0x0400
- #define PORT_RX_ENABLE 0x0200
- #define PORT_LEARN_DISABLE 0x0100
- #define PORT_MIRROR_SNIFFER 0x0080
- #define PORT_MIRROR_RX 0x0040
- #define PORT_MIRROR_TX 0x0020
- #define PORT_USER_PRIORITY_CEILING 0x0008
- #define PORT_VLAN_MEMBERSHIP 0x0007
- #define KS8842_PORT_CTRL_VID_OFFSET 0x04
- #define PORT_DEFAULT_VID 0x0001
- #define KS8842_PORT_CTRL_3_OFFSET 0x06
- #define PORT_INGRESS_LIMIT_MODE 0x000C
- #define PORT_INGRESS_ALL 0x0000
- #define PORT_INGRESS_UNICAST 0x0004
- #define PORT_INGRESS_MULTICAST 0x0008
- #define PORT_INGRESS_BROADCAST 0x000C
- #define PORT_COUNT_IFG 0x0002
- #define PORT_COUNT_PREAMBLE 0x0001
- #define KS8842_PORT_IN_RATE_OFFSET 0x08
- #define KS8842_PORT_OUT_RATE_OFFSET 0x0A
- #define PORT_PRIORITY_RATE 0x0F
- #define PORT_PRIORITY_RATE_SHIFT 4
- #define KS884X_PORT_LINK_MD 0x10
- #define PORT_CABLE_10M_SHORT 0x8000
- #define PORT_CABLE_DIAG_RESULT 0x6000
- #define PORT_CABLE_STAT_NORMAL 0x0000
- #define PORT_CABLE_STAT_OPEN 0x2000
- #define PORT_CABLE_STAT_SHORT 0x4000
- #define PORT_CABLE_STAT_FAILED 0x6000
- #define PORT_START_CABLE_DIAG 0x1000
- #define PORT_FORCE_LINK 0x0800
- #define PORT_POWER_SAVING_DISABLE 0x0400
- #define PORT_PHY_REMOTE_LOOPBACK 0x0200
- #define PORT_CABLE_FAULT_COUNTER 0x01FF
- #define KS884X_PORT_CTRL_4_OFFSET 0x12
- #define PORT_LED_OFF 0x8000
- #define PORT_TX_DISABLE 0x4000
- #define PORT_AUTO_NEG_RESTART 0x2000
- #define PORT_REMOTE_FAULT_DISABLE 0x1000
- #define PORT_POWER_DOWN 0x0800
- #define PORT_AUTO_MDIX_DISABLE 0x0400
- #define PORT_FORCE_MDIX 0x0200
- #define PORT_LOOPBACK 0x0100
- #define PORT_AUTO_NEG_ENABLE 0x0080
- #define PORT_FORCE_100_MBIT 0x0040
- #define PORT_FORCE_FULL_DUPLEX 0x0020
- #define PORT_AUTO_NEG_SYM_PAUSE 0x0010
- #define PORT_AUTO_NEG_100BTX_FD 0x0008
- #define PORT_AUTO_NEG_100BTX 0x0004
- #define PORT_AUTO_NEG_10BT_FD 0x0002
- #define PORT_AUTO_NEG_10BT 0x0001
- #define KS884X_PORT_STATUS_OFFSET 0x14
- #define PORT_HP_MDIX 0x8000
- #define PORT_REVERSED_POLARITY 0x2000
- #define PORT_RX_FLOW_CTRL 0x0800
- #define PORT_TX_FLOW_CTRL 0x1000
- #define PORT_STATUS_SPEED_100MBIT 0x0400
- #define PORT_STATUS_FULL_DUPLEX 0x0200
- #define PORT_REMOTE_FAULT 0x0100
- #define PORT_MDIX_STATUS 0x0080
- #define PORT_AUTO_NEG_COMPLETE 0x0040
- #define PORT_STATUS_LINK_GOOD 0x0020
- #define PORT_REMOTE_SYM_PAUSE 0x0010
- #define PORT_REMOTE_100BTX_FD 0x0008
- #define PORT_REMOTE_100BTX 0x0004
- #define PORT_REMOTE_10BT_FD 0x0002
- #define PORT_REMOTE_10BT 0x0001
- /*
- #define STATIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF
- #define STATIC_MAC_TABLE_FWD_PORTS 00-00070000-00000000
- #define STATIC_MAC_TABLE_VALID 00-00080000-00000000
- #define STATIC_MAC_TABLE_OVERRIDE 00-00100000-00000000
- #define STATIC_MAC_TABLE_USE_FID 00-00200000-00000000
- #define STATIC_MAC_TABLE_FID 00-03C00000-00000000
- */
- #define STATIC_MAC_TABLE_ADDR 0x0000FFFF
- #define STATIC_MAC_TABLE_FWD_PORTS 0x00070000
- #define STATIC_MAC_TABLE_VALID 0x00080000
- #define STATIC_MAC_TABLE_OVERRIDE 0x00100000
- #define STATIC_MAC_TABLE_USE_FID 0x00200000
- #define STATIC_MAC_TABLE_FID 0x03C00000
- #define STATIC_MAC_FWD_PORTS_SHIFT 16
- #define STATIC_MAC_FID_SHIFT 22
- /*
- #define VLAN_TABLE_VID 00-00000000-00000FFF
- #define VLAN_TABLE_FID 00-00000000-0000F000
- #define VLAN_TABLE_MEMBERSHIP 00-00000000-00070000
- #define VLAN_TABLE_VALID 00-00000000-00080000
- */
- #define VLAN_TABLE_VID 0x00000FFF
- #define VLAN_TABLE_FID 0x0000F000
- #define VLAN_TABLE_MEMBERSHIP 0x00070000
- #define VLAN_TABLE_VALID 0x00080000
- #define VLAN_TABLE_FID_SHIFT 12
- #define VLAN_TABLE_MEMBERSHIP_SHIFT 16
- /*
- #define DYNAMIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF
- #define DYNAMIC_MAC_TABLE_FID 00-000F0000-00000000
- #define DYNAMIC_MAC_TABLE_SRC_PORT 00-00300000-00000000
- #define DYNAMIC_MAC_TABLE_TIMESTAMP 00-00C00000-00000000
- #define DYNAMIC_MAC_TABLE_ENTRIES 03-FF000000-00000000
- #define DYNAMIC_MAC_TABLE_MAC_EMPTY 04-00000000-00000000
- #define DYNAMIC_MAC_TABLE_RESERVED 78-00000000-00000000
- #define DYNAMIC_MAC_TABLE_NOT_READY 80-00000000-00000000
- */
- #define DYNAMIC_MAC_TABLE_ADDR 0x0000FFFF
- #define DYNAMIC_MAC_TABLE_FID 0x000F0000
- #define DYNAMIC_MAC_TABLE_SRC_PORT 0x00300000
- #define DYNAMIC_MAC_TABLE_TIMESTAMP 0x00C00000
- #define DYNAMIC_MAC_TABLE_ENTRIES 0xFF000000
- #define DYNAMIC_MAC_TABLE_ENTRIES_H 0x03
- #define DYNAMIC_MAC_TABLE_MAC_EMPTY 0x04
- #define DYNAMIC_MAC_TABLE_RESERVED 0x78
- #define DYNAMIC_MAC_TABLE_NOT_READY 0x80
- #define DYNAMIC_MAC_FID_SHIFT 16
- #define DYNAMIC_MAC_SRC_PORT_SHIFT 20
- #define DYNAMIC_MAC_TIMESTAMP_SHIFT 22
- #define DYNAMIC_MAC_ENTRIES_SHIFT 24
- #define DYNAMIC_MAC_ENTRIES_H_SHIFT 8
- /*
- #define MIB_COUNTER_VALUE 00-00000000-3FFFFFFF
- #define MIB_COUNTER_VALID 00-00000000-40000000
- #define MIB_COUNTER_OVERFLOW 00-00000000-80000000
- */
- #define MIB_COUNTER_VALUE 0x3FFFFFFF
- #define MIB_COUNTER_VALID 0x40000000
- #define MIB_COUNTER_OVERFLOW 0x80000000
- #define MIB_PACKET_DROPPED 0x0000FFFF
- #define KS_MIB_PACKET_DROPPED_TX_0 0x100
- #define KS_MIB_PACKET_DROPPED_TX_1 0x101
- #define KS_MIB_PACKET_DROPPED_TX 0x102
- #define KS_MIB_PACKET_DROPPED_RX_0 0x103
- #define KS_MIB_PACKET_DROPPED_RX_1 0x104
- #define KS_MIB_PACKET_DROPPED_RX 0x105
- /* Change default LED mode. */
- #define SET_DEFAULT_LED LED_SPEED_DUPLEX_ACT
- #define MAC_ADDR_ORDER(i) (ETH_ALEN - 1 - (i))
- #define MAX_ETHERNET_BODY_SIZE 1500
- #define ETHERNET_HEADER_SIZE (14 + VLAN_HLEN)
- #define MAX_ETHERNET_PACKET_SIZE \
- (MAX_ETHERNET_BODY_SIZE + ETHERNET_HEADER_SIZE)
- #define REGULAR_RX_BUF_SIZE (MAX_ETHERNET_PACKET_SIZE + 4)
- #define MAX_RX_BUF_SIZE (1912 + 4)
- #define ADDITIONAL_ENTRIES 16
- #define MAX_MULTICAST_LIST 32
- #define HW_MULTICAST_SIZE 8
- #define HW_TO_DEV_PORT(port) (port - 1)
- enum {
- media_connected,
- media_disconnected
- };
- enum {
- OID_COUNTER_UNKOWN,
- OID_COUNTER_FIRST,
- /* total transmit errors */
- OID_COUNTER_XMIT_ERROR,
- /* total receive errors */
- OID_COUNTER_RCV_ERROR,
- OID_COUNTER_LAST
- };
- /*
- * Hardware descriptor definitions
- */
- #define DESC_ALIGNMENT 16
- #define BUFFER_ALIGNMENT 8
- #define NUM_OF_RX_DESC 64
- #define NUM_OF_TX_DESC 64
- #define KS_DESC_RX_FRAME_LEN 0x000007FF
- #define KS_DESC_RX_FRAME_TYPE 0x00008000
- #define KS_DESC_RX_ERROR_CRC 0x00010000
- #define KS_DESC_RX_ERROR_RUNT 0x00020000
- #define KS_DESC_RX_ERROR_TOO_LONG 0x00040000
- #define KS_DESC_RX_ERROR_PHY 0x00080000
- #define KS884X_DESC_RX_PORT_MASK 0x00300000
- #define KS_DESC_RX_MULTICAST 0x01000000
- #define KS_DESC_RX_ERROR 0x02000000
- #define KS_DESC_RX_ERROR_CSUM_UDP 0x04000000
- #define KS_DESC_RX_ERROR_CSUM_TCP 0x08000000
- #define KS_DESC_RX_ERROR_CSUM_IP 0x10000000
- #define KS_DESC_RX_LAST 0x20000000
- #define KS_DESC_RX_FIRST 0x40000000
- #define KS_DESC_RX_ERROR_COND \
- (KS_DESC_RX_ERROR_CRC | \
- KS_DESC_RX_ERROR_RUNT | \
- KS_DESC_RX_ERROR_PHY | \
- KS_DESC_RX_ERROR_TOO_LONG)
- #define KS_DESC_HW_OWNED 0x80000000
- #define KS_DESC_BUF_SIZE 0x000007FF
- #define KS884X_DESC_TX_PORT_MASK 0x00300000
- #define KS_DESC_END_OF_RING 0x02000000
- #define KS_DESC_TX_CSUM_GEN_UDP 0x04000000
- #define KS_DESC_TX_CSUM_GEN_TCP 0x08000000
- #define KS_DESC_TX_CSUM_GEN_IP 0x10000000
- #define KS_DESC_TX_LAST 0x20000000
- #define KS_DESC_TX_FIRST 0x40000000
- #define KS_DESC_TX_INTERRUPT 0x80000000
- #define KS_DESC_PORT_SHIFT 20
- #define KS_DESC_RX_MASK (KS_DESC_BUF_SIZE)
- #define KS_DESC_TX_MASK \
- (KS_DESC_TX_INTERRUPT | \
- KS_DESC_TX_FIRST | \
- KS_DESC_TX_LAST | \
- KS_DESC_TX_CSUM_GEN_IP | \
- KS_DESC_TX_CSUM_GEN_TCP | \
- KS_DESC_TX_CSUM_GEN_UDP | \
- KS_DESC_BUF_SIZE)
- struct ksz_desc_rx_stat {
- #ifdef __BIG_ENDIAN_BITFIELD
- u32 hw_owned:1;
- u32 first_desc:1;
- u32 last_desc:1;
- u32 csum_err_ip:1;
- u32 csum_err_tcp:1;
- u32 csum_err_udp:1;
- u32 error:1;
- u32 multicast:1;
- u32 src_port:4;
- u32 err_phy:1;
- u32 err_too_long:1;
- u32 err_runt:1;
- u32 err_crc:1;
- u32 frame_type:1;
- u32 reserved1:4;
- u32 frame_len:11;
- #else
- u32 frame_len:11;
- u32 reserved1:4;
- u32 frame_type:1;
- u32 err_crc:1;
- u32 err_runt:1;
- u32 err_too_long:1;
- u32 err_phy:1;
- u32 src_port:4;
- u32 multicast:1;
- u32 error:1;
- u32 csum_err_udp:1;
- u32 csum_err_tcp:1;
- u32 csum_err_ip:1;
- u32 last_desc:1;
- u32 first_desc:1;
- u32 hw_owned:1;
- #endif
- };
- struct ksz_desc_tx_stat {
- #ifdef __BIG_ENDIAN_BITFIELD
- u32 hw_owned:1;
- u32 reserved1:31;
- #else
- u32 reserved1:31;
- u32 hw_owned:1;
- #endif
- };
- struct ksz_desc_rx_buf {
- #ifdef __BIG_ENDIAN_BITFIELD
- u32 reserved4:6;
- u32 end_of_ring:1;
- u32 reserved3:14;
- u32 buf_size:11;
- #else
- u32 buf_size:11;
- u32 reserved3:14;
- u32 end_of_ring:1;
- u32 reserved4:6;
- #endif
- };
- struct ksz_desc_tx_buf {
- #ifdef __BIG_ENDIAN_BITFIELD
- u32 intr:1;
- u32 first_seg:1;
- u32 last_seg:1;
- u32 csum_gen_ip:1;
- u32 csum_gen_tcp:1;
- u32 csum_gen_udp:1;
- u32 end_of_ring:1;
- u32 reserved4:1;
- u32 dest_port:4;
- u32 reserved3:9;
- u32 buf_size:11;
- #else
- u32 buf_size:11;
- u32 reserved3:9;
- u32 dest_port:4;
- u32 reserved4:1;
- u32 end_of_ring:1;
- u32 csum_gen_udp:1;
- u32 csum_gen_tcp:1;
- u32 csum_gen_ip:1;
- u32 last_seg:1;
- u32 first_seg:1;
- u32 intr:1;
- #endif
- };
- union desc_stat {
- struct ksz_desc_rx_stat rx;
- struct ksz_desc_tx_stat tx;
- u32 data;
- };
- union desc_buf {
- struct ksz_desc_rx_buf rx;
- struct ksz_desc_tx_buf tx;
- u32 data;
- };
- /**
- * struct ksz_hw_desc - Hardware descriptor data structure
- * @ctrl: Descriptor control value.
- * @buf: Descriptor buffer value.
- * @addr: Physical address of memory buffer.
- * @next: Pointer to next hardware descriptor.
- */
- struct ksz_hw_desc {
- union desc_stat ctrl;
- union desc_buf buf;
- u32 addr;
- u32 next;
- };
- /**
- * struct ksz_sw_desc - Software descriptor data structure
- * @ctrl: Descriptor control value.
- * @buf: Descriptor buffer value.
- * @buf_size: Current buffers size value in hardware descriptor.
- */
- struct ksz_sw_desc {
- union desc_stat ctrl;
- union desc_buf buf;
- u32 buf_size;
- };
- /**
- * struct ksz_dma_buf - OS dependent DMA buffer data structure
- * @skb: Associated socket buffer.
- * @dma: Associated physical DMA address.
- * len: Actual len used.
- */
- struct ksz_dma_buf {
- struct sk_buff *skb;
- dma_addr_t dma;
- int len;
- };
- /**
- * struct ksz_desc - Descriptor structure
- * @phw: Hardware descriptor pointer to uncached physical memory.
- * @sw: Cached memory to hold hardware descriptor values for
- * manipulation.
- * @dma_buf: Operating system dependent data structure to hold physical
- * memory buffer allocation information.
- */
- struct ksz_desc {
- struct ksz_hw_desc *phw;
- struct ksz_sw_desc sw;
- struct ksz_dma_buf dma_buf;
- };
- #define DMA_BUFFER(desc) ((struct ksz_dma_buf *)(&(desc)->dma_buf))
- /**
- * struct ksz_desc_info - Descriptor information data structure
- * @ring: First descriptor in the ring.
- * @cur: Current descriptor being manipulated.
- * @ring_virt: First hardware descriptor in the ring.
- * @ring_phys: The physical address of the first descriptor of the ring.
- * @size: Size of hardware descriptor.
- * @alloc: Number of descriptors allocated.
- * @avail: Number of descriptors available for use.
- * @last: Index for last descriptor released to hardware.
- * @next: Index for next descriptor available for use.
- * @mask: Mask for index wrapping.
- */
- struct ksz_desc_info {
- struct ksz_desc *ring;
- struct ksz_desc *cur;
- struct ksz_hw_desc *ring_virt;
- u32 ring_phys;
- int size;
- int alloc;
- int avail;
- int last;
- int next;
- int mask;
- };
- /*
- * KSZ8842 switch definitions
- */
- enum {
- TABLE_STATIC_MAC = 0,
- TABLE_VLAN,
- TABLE_DYNAMIC_MAC,
- TABLE_MIB
- };
- #define LEARNED_MAC_TABLE_ENTRIES 1024
- #define STATIC_MAC_TABLE_ENTRIES 8
- /**
- * struct ksz_mac_table - Static MAC table data structure
- * @mac_addr: MAC address to filter.
- * @vid: VID value.
- * @fid: FID value.
- * @ports: Port membership.
- * @override: Override setting.
- * @use_fid: FID use setting.
- * @valid: Valid setting indicating the entry is being used.
- */
- struct ksz_mac_table {
- u8 mac_addr[ETH_ALEN];
- u16 vid;
- u8 fid;
- u8 ports;
- u8 override:1;
- u8 use_fid:1;
- u8 valid:1;
- };
- #define VLAN_TABLE_ENTRIES 16
- /**
- * struct ksz_vlan_table - VLAN table data structure
- * @vid: VID value.
- * @fid: FID value.
- * @member: Port membership.
- */
- struct ksz_vlan_table {
- u16 vid;
- u8 fid;
- u8 member;
- };
- #define DIFFSERV_ENTRIES 64
- #define PRIO_802_1P_ENTRIES 8
- #define PRIO_QUEUES 4
- #define SWITCH_PORT_NUM 2
- #define TOTAL_PORT_NUM (SWITCH_PORT_NUM + 1)
- #define HOST_MASK (1 << SWITCH_PORT_NUM)
- #define PORT_MASK 7
- #define MAIN_PORT 0
- #define OTHER_PORT 1
- #define HOST_PORT SWITCH_PORT_NUM
- #define PORT_COUNTER_NUM 0x20
- #define TOTAL_PORT_COUNTER_NUM (PORT_COUNTER_NUM + 2)
- #define MIB_COUNTER_RX_LO_PRIORITY 0x00
- #define MIB_COUNTER_RX_HI_PRIORITY 0x01
- #define MIB_COUNTER_RX_UNDERSIZE 0x02
- #define MIB_COUNTER_RX_FRAGMENT 0x03
- #define MIB_COUNTER_RX_OVERSIZE 0x04
- #define MIB_COUNTER_RX_JABBER 0x05
- #define MIB_COUNTER_RX_SYMBOL_ERR 0x06
- #define MIB_COUNTER_RX_CRC_ERR 0x07
- #define MIB_COUNTER_RX_ALIGNMENT_ERR 0x08
- #define MIB_COUNTER_RX_CTRL_8808 0x09
- #define MIB_COUNTER_RX_PAUSE 0x0A
- #define MIB_COUNTER_RX_BROADCAST 0x0B
- #define MIB_COUNTER_RX_MULTICAST 0x0C
- #define MIB_COUNTER_RX_UNICAST 0x0D
- #define MIB_COUNTER_RX_OCTET_64 0x0E
- #define MIB_COUNTER_RX_OCTET_65_127 0x0F
- #define MIB_COUNTER_RX_OCTET_128_255 0x10
- #define MIB_COUNTER_RX_OCTET_256_511 0x11
- #define MIB_COUNTER_RX_OCTET_512_1023 0x12
- #define MIB_COUNTER_RX_OCTET_1024_1522 0x13
- #define MIB_COUNTER_TX_LO_PRIORITY 0x14
- #define MIB_COUNTER_TX_HI_PRIORITY 0x15
- #define MIB_COUNTER_TX_LATE_COLLISION 0x16
- #define MIB_COUNTER_TX_PAUSE 0x17
- #define MIB_COUNTER_TX_BROADCAST 0x18
- #define MIB_COUNTER_TX_MULTICAST 0x19
- #define MIB_COUNTER_TX_UNICAST 0x1A
- #define MIB_COUNTER_TX_DEFERRED 0x1B
- #define MIB_COUNTER_TX_TOTAL_COLLISION 0x1C
- #define MIB_COUNTER_TX_EXCESS_COLLISION 0x1D
- #define MIB_COUNTER_TX_SINGLE_COLLISION 0x1E
- #define MIB_COUNTER_TX_MULTI_COLLISION 0x1F
- #define MIB_COUNTER_RX_DROPPED_PACKET 0x20
- #define MIB_COUNTER_TX_DROPPED_PACKET 0x21
- /**
- * struct ksz_port_mib - Port MIB data structure
- * @cnt_ptr: Current pointer to MIB counter index.
- * @link_down: Indication the link has just gone down.
- * @state: Connection status of the port.
- * @mib_start: The starting counter index. Some ports do not start at 0.
- * @counter: 64-bit MIB counter value.
- * @dropped: Temporary buffer to remember last read packet dropped values.
- *
- * MIB counters needs to be read periodically so that counters do not get
- * overflowed and give incorrect values. A right balance is needed to
- * satisfy this condition and not waste too much CPU time.
- *
- * It is pointless to read MIB counters when the port is disconnected. The
- * @state provides the connection status so that MIB counters are read only
- * when the port is connected. The @link_down indicates the port is just
- * disconnected so that all MIB counters are read one last time to update the
- * information.
- */
- struct ksz_port_mib {
- u8 cnt_ptr;
- u8 link_down;
- u8 state;
- u8 mib_start;
- u64 counter[TOTAL_PORT_COUNTER_NUM];
- u32 dropped[2];
- };
- /**
- * struct ksz_port_cfg - Port configuration data structure
- * @vid: VID value.
- * @member: Port membership.
- * @port_prio: Port priority.
- * @rx_rate: Receive priority rate.
- * @tx_rate: Transmit priority rate.
- * @stp_state: Current Spanning Tree Protocol state.
- */
- struct ksz_port_cfg {
- u16 vid;
- u8 member;
- u8 port_prio;
- u32 rx_rate[PRIO_QUEUES];
- u32 tx_rate[PRIO_QUEUES];
- int stp_state;
- };
- /**
- * struct ksz_switch - KSZ8842 switch data structure
- * @mac_table: MAC table entries information.
- * @vlan_table: VLAN table entries information.
- * @port_cfg: Port configuration information.
- * @diffserv: DiffServ priority settings. Possible values from 6-bit of ToS
- * (bit7 ~ bit2) field.
- * @p_802_1p: 802.1P priority settings. Possible values from 3-bit of 802.1p
- * Tag priority field.
- * @br_addr: Bridge address. Used for STP.
- * @other_addr: Other MAC address. Used for multiple network device mode.
- * @broad_per: Broadcast storm percentage.
- * @member: Current port membership. Used for STP.
- */
- struct ksz_switch {
- struct ksz_mac_table mac_table[STATIC_MAC_TABLE_ENTRIES];
- struct ksz_vlan_table vlan_table[VLAN_TABLE_ENTRIES];
- struct ksz_port_cfg port_cfg[TOTAL_PORT_NUM];
- u8 diffserv[DIFFSERV_ENTRIES];
- u8 p_802_1p[PRIO_802_1P_ENTRIES];
- u8 br_addr[ETH_ALEN];
- u8 other_addr[ETH_ALEN];
- u8 broad_per;
- u8 member;
- };
- #define TX_RATE_UNIT 10000
- /**
- * struct ksz_port_info - Port information data structure
- * @state: Connection status of the port.
- * @tx_rate: Transmit rate divided by 10000 to get Mbit.
- * @duplex: Duplex mode.
- * @advertised: Advertised auto-negotiation setting. Used to determine link.
- * @partner: Auto-negotiation partner setting. Used to determine link.
- * @port_id: Port index to access actual hardware register.
- * @pdev: Pointer to OS dependent network device.
- */
- struct ksz_port_info {
- uint state;
- uint tx_rate;
- u8 duplex;
- u8 advertised;
- u8 partner;
- u8 port_id;
- void *pdev;
- };
- #define MAX_TX_HELD_SIZE 52000
- /* Hardware features and bug fixes. */
- #define LINK_INT_WORKING (1 << 0)
- #define SMALL_PACKET_TX_BUG (1 << 1)
- #define HALF_DUPLEX_SIGNAL_BUG (1 << 2)
- #define RX_HUGE_FRAME (1 << 4)
- #define STP_SUPPORT (1 << 8)
- /* Software overrides. */
- #define PAUSE_FLOW_CTRL (1 << 0)
- #define FAST_AGING (1 << 1)
- /**
- * struct ksz_hw - KSZ884X hardware data structure
- * @io: Virtual address assigned.
- * @ksz_switch: Pointer to KSZ8842 switch.
- * @port_info: Port information.
- * @port_mib: Port MIB information.
- * @dev_count: Number of network devices this hardware supports.
- * @dst_ports: Destination ports in switch for transmission.
- * @id: Hardware ID. Used for display only.
- * @mib_cnt: Number of MIB counters this hardware has.
- * @mib_port_cnt: Number of ports with MIB counters.
- * @tx_cfg: Cached transmit control settings.
- * @rx_cfg: Cached receive control settings.
- * @intr_mask: Current interrupt mask.
- * @intr_set: Current interrup set.
- * @intr_blocked: Interrupt blocked.
- * @rx_desc_info: Receive descriptor information.
- * @tx_desc_info: Transmit descriptor information.
- * @tx_int_cnt: Transmit interrupt count. Used for TX optimization.
- * @tx_int_mask: Transmit interrupt mask. Used for TX optimization.
- * @tx_size: Transmit data size. Used for TX optimization.
- * The maximum is defined by MAX_TX_HELD_SIZE.
- * @perm_addr: Permanent MAC address.
- * @override_addr: Overridden MAC address.
- * @address: Additional MAC address entries.
- * @addr_list_size: Additional MAC address list size.
- * @mac_override: Indication of MAC address overridden.
- * @promiscuous: Counter to keep track of promiscuous mode set.
- * @all_multi: Counter to keep track of all multicast mode set.
- * @multi_list: Multicast address entries.
- * @multi_bits: Cached multicast hash table settings.
- * @multi_list_size: Multicast address list size.
- * @enabled: Indication of hardware enabled.
- * @rx_stop: Indication of receive process stop.
- * @features: Hardware features to enable.
- * @overrides: Hardware features to override.
- * @parent: Pointer to parent, network device private structure.
- */
- struct ksz_hw {
- void __iomem *io;
- struct ksz_switch *ksz_switch;
- struct ksz_port_info port_info[SWITCH_PORT_NUM];
- struct ksz_port_mib port_mib[TOTAL_PORT_NUM];
- int dev_count;
- int dst_ports;
- int id;
- int mib_cnt;
- int mib_port_cnt;
- u32 tx_cfg;
- u32 rx_cfg;
- u32 intr_mask;
- u32 intr_set;
- uint intr_blocked;
- struct ksz_desc_info rx_desc_info;
- struct ksz_desc_info tx_desc_info;
- int tx_int_cnt;
- int tx_int_mask;
- int tx_size;
- u8 perm_addr[ETH_ALEN];
- u8 override_addr[ETH_ALEN];
- u8 address[ADDITIONAL_ENTRIES][ETH_ALEN];
- u8 addr_list_size;
- u8 mac_override;
- u8 promiscuous;
- u8 all_multi;
- u8 multi_list[MAX_MULTICAST_LIST][ETH_ALEN];
- u8 multi_bits[HW_MULTICAST_SIZE];
- u8 multi_list_size;
- u8 enabled;
- u8 rx_stop;
- u8 reserved2[1];
- uint features;
- uint overrides;
- void *parent;
- };
- enum {
- PHY_NO_FLOW_CTRL,
- PHY_FLOW_CTRL,
- PHY_TX_ONLY,
- PHY_RX_ONLY
- };
- /**
- * struct ksz_port - Virtual port data structure
- * @duplex: Duplex mode setting. 1 for half duplex, 2 for full
- * duplex, and 0 for auto, which normally results in full
- * duplex.
- * @speed: Speed setting. 10 for 10 Mbit, 100 for 100 Mbit, and
- * 0 for auto, which normally results in 100 Mbit.
- * @force_link: Force link setting. 0 for auto-negotiation, and 1 for
- * force.
- * @flow_ctrl: Flow control setting. PHY_NO_FLOW_CTRL for no flow
- * control, and PHY_FLOW_CTRL for flow control.
- * PHY_TX_ONLY and PHY_RX_ONLY are not supported for 100
- * Mbit PHY.
- * @first_port: Index of first port this port supports.
- * @mib_port_cnt: Number of ports with MIB counters.
- * @port_cnt: Number of ports this port supports.
- * @counter: Port statistics counter.
- * @hw: Pointer to hardware structure.
- * @linked: Pointer to port information linked to this port.
- */
- struct ksz_port {
- u8 duplex;
- u8 speed;
- u8 force_link;
- u8 flow_ctrl;
- int first_port;
- int mib_port_cnt;
- int port_cnt;
- u64 counter[OID_COUNTER_LAST];
- struct ksz_hw *hw;
- struct ksz_port_info *linked;
- };
- /**
- * struct ksz_timer_info - Timer information data structure
- * @timer: Kernel timer.
- * @cnt: Running timer counter.
- * @max: Number of times to run timer; -1 for infinity.
- * @period: Timer period in jiffies.
- */
- struct ksz_timer_info {
- struct timer_list timer;
- int cnt;
- int max;
- int period;
- };
- /**
- * struct ksz_shared_mem - OS dependent shared memory data structure
- * @dma_addr: Physical DMA address allocated.
- * @alloc_size: Allocation size.
- * @phys: Actual physical address used.
- * @alloc_virt: Virtual address allocated.
- * @virt: Actual virtual address used.
- */
- struct ksz_shared_mem {
- dma_addr_t dma_addr;
- uint alloc_size;
- uint phys;
- u8 *alloc_virt;
- u8 *virt;
- };
- /**
- * struct ksz_counter_info - OS dependent counter information data structure
- * @counter: Wait queue to wakeup after counters are read.
- * @time: Next time in jiffies to read counter.
- * @read: Indication of counters read in full or not.
- */
- struct ksz_counter_info {
- wait_queue_head_t counter;
- unsigned long time;
- int read;
- };
- /**
- * struct dev_info - Network device information data structure
- * @dev: Pointer to network device.
- * @pdev: Pointer to PCI device.
- * @hw: Hardware structure.
- * @desc_pool: Physical memory used for descriptor pool.
- * @hwlock: Spinlock to prevent hardware from accessing.
- * @lock: Mutex lock to prevent device from accessing.
- * @dev_rcv: Receive process function used.
- * @last_skb: Socket buffer allocated for descriptor rx fragments.
- * @skb_index: Buffer index for receiving fragments.
- * @skb_len: Buffer length for receiving fragments.
- * @mib_read: Workqueue to read MIB counters.
- * @mib_timer_info: Timer to read MIB counters.
- * @counter: Used for MIB reading.
- * @mtu: Current MTU used. The default is REGULAR_RX_BUF_SIZE;
- * the maximum is MAX_RX_BUF_SIZE.
- * @opened: Counter to keep track of device open.
- * @rx_tasklet: Receive processing tasklet.
- * @tx_tasklet: Transmit processing tasklet.
- * @wol_enable: Wake-on-LAN enable set by ethtool.
- * @wol_support: Wake-on-LAN support used by ethtool.
- * @pme_wait: Used for KSZ8841 power management.
- */
- struct dev_info {
- struct net_device *dev;
- struct pci_dev *pdev;
- struct ksz_hw hw;
- struct ksz_shared_mem desc_pool;
- spinlock_t hwlock;
- struct mutex lock;
- int (*dev_rcv)(struct dev_info *);
- struct sk_buff *last_skb;
- int skb_index;
- int skb_len;
- struct work_struct mib_read;
- struct ksz_timer_info mib_timer_info;
- struct ksz_counter_info counter[TOTAL_PORT_NUM];
- int mtu;
- int opened;
- struct tasklet_struct rx_tasklet;
- struct tasklet_struct tx_tasklet;
- int wol_enable;
- int wol_support;
- unsigned long pme_wait;
- };
- /**
- * struct dev_priv - Network device private data structure
- * @adapter: Adapter device information.
- * @port: Port information.
- * @monitor_time_info: Timer to monitor ports.
- * @proc_sem: Semaphore for proc accessing.
- * @id: Device ID.
- * @mii_if: MII interface information.
- * @advertising: Temporary variable to store advertised settings.
- * @msg_enable: The message flags controlling driver output.
- * @media_state: The connection status of the device.
- * @multicast: The all multicast state of the device.
- * @promiscuous: The promiscuous state of the device.
- */
- struct dev_priv {
- struct dev_info *adapter;
- struct ksz_port port;
- struct ksz_timer_info monitor_timer_info;
- struct semaphore proc_sem;
- int id;
- struct mii_if_info mii_if;
- u32 advertising;
- u32 msg_enable;
- int media_state;
- int multicast;
- int promiscuous;
- };
- #define DRV_NAME "KSZ884X PCI"
- #define DEVICE_NAME "KSZ884x PCI"
- #define DRV_VERSION "1.0.0"
- #define DRV_RELDATE "Feb 8, 2010"
- static char version[] =
- "Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")";
- static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 };
- /*
- * Interrupt processing primary routines
- */
- static inline void hw_ack_intr(struct ksz_hw *hw, uint interrupt)
- {
- writel(interrupt, hw->io + KS884X_INTERRUPTS_STATUS);
- }
- static inline void hw_dis_intr(struct ksz_hw *hw)
- {
- hw->intr_blocked = hw->intr_mask;
- writel(0, hw->io + KS884X_INTERRUPTS_ENABLE);
- hw->intr_set = readl(hw->io + KS884X_INTERRUPTS_ENABLE);
- }
- static inline void hw_set_intr(struct ksz_hw *hw, uint interrupt)
- {
- hw->intr_set = interrupt;
- writel(interrupt, hw->io + KS884X_INTERRUPTS_ENABLE);
- }
- static inline void hw_ena_intr(struct ksz_hw *hw)
- {
- hw->intr_blocked = 0;
- hw_set_intr(hw, hw->intr_mask);
- }
- static inline void hw_dis_intr_bit(struct ksz_hw *hw, uint bit)
- {
- hw->intr_mask &= ~(bit);
- }
- static inline void hw_turn_off_intr(struct ksz_hw *hw, uint interrupt)
- {
- u32 read_intr;
- read_intr = readl(hw->io + KS884X_INTERRUPTS_ENABLE);
- hw->intr_set = read_intr & ~interrupt;
- writel(hw->intr_set, hw->io + KS884X_INTERRUPTS_ENABLE);
- hw_dis_intr_bit(hw, interrupt);
- }
- /**
- * hw_turn_on_intr - turn on specified interrupts
- * @hw: The hardware instance.
- * @bit: The interrupt bits to be on.
- *
- * This routine turns on the specified interrupts in the interrupt mask so that
- * those interrupts will be enabled.
- */
- static void hw_turn_on_intr(struct ksz_hw *hw, u32 bit)
- {
- hw->intr_mask |= bit;
- if (!hw->intr_blocked)
- hw_set_intr(hw, hw->intr_mask);
- }
- static inline void hw_ena_intr_bit(struct ksz_hw *hw, uint interrupt)
- {
- u32 read_intr;
- read_intr = readl(hw->io + KS884X_INTERRUPTS_ENABLE);
- hw->intr_set = read_intr | interrupt;
- writel(hw->intr_set, hw->io + KS884X_INTERRUPTS_ENABLE);
- }
- static inline void hw_read_intr(struct ksz_hw *hw, uint *status)
- {
- *status = readl(hw->io + KS884X_INTERRUPTS_STATUS);
- *status = *status & hw->intr_set;
- }
- static inline void hw_restore_intr(struct ksz_hw *hw, uint interrupt)
- {
- if (interrupt)
- hw_ena_intr(hw);
- }
- /**
- * hw_block_intr - block hardware interrupts
- *
- * This function blocks all interrupts of the hardware and returns the current
- * interrupt enable mask so that interrupts can be restored later.
- *
- * Return the current interrupt enable mask.
- */
- static uint hw_block_intr(struct ksz_hw *hw)
- {
- uint interrupt = 0;
- if (!hw->intr_blocked) {
- hw_dis_intr(hw);
- interrupt = hw->intr_blocked;
- }
- return interrupt;
- }
- /*
- * Hardware descriptor routines
- */
- static inline void reset_desc(struct ksz_desc *desc, union desc_stat status)
- {
- status.rx.hw_owned = 0;
- desc->phw->ctrl.data = cpu_to_le32(status.data);
- }
- static inline void release_desc(struct ksz_desc *desc)
- {
- desc->sw.ctrl.tx.hw_owned = 1;
- if (desc->sw.buf_size != desc->sw.buf.data) {
- desc->sw.buf_size = desc->sw.buf.data;
- desc->phw->buf.data = cpu_to_le32(desc->sw.buf.data);
- }
- desc->phw->ctrl.data = cpu_to_le32(desc->sw.ctrl.data);
- }
- static void get_rx_pkt(struct ksz_desc_info *info, struct ksz_desc **desc)
- {
- *desc = &info->ring[info->last];
- info->last++;
- info->last &= info->mask;
- info->avail--;
- (*desc)->sw.buf.data &= ~KS_DESC_RX_MASK;
- }
- static inline void set_rx_buf(struct ksz_desc *desc, u32 addr)
- {
- desc->phw->addr = cpu_to_le32(addr);
- }
- static inline void set_rx_len(struct ksz_desc *desc, u32 len)
- {
- desc->sw.buf.rx.buf_size = len;
- }
- static inline void get_tx_pkt(struct ksz_desc_info *info,
- struct ksz_desc **desc)
- {
- *desc = &info->ring[info->next];
- info->next++;
- info->next &= info->mask;
- info->avail--;
- (*desc)->sw.buf.data &= ~KS_DESC_TX_MASK;
- }
- static inline void set_tx_buf(struct ksz_desc *desc, u32 addr)
- {
- desc->phw->addr = cpu_to_le32(addr);
- }
- static inline void set_tx_len(struct ksz_desc *desc, u32 len)
- {
- desc->sw.buf.tx.buf_size = len;
- }
- /* Switch functions */
- #define TABLE_READ 0x10
- #define TABLE_SEL_SHIFT 2
- #define HW_DELAY(hw, reg) \
- do { \
- u16 dummy; \
- dummy = readw(hw->io + reg); \
- } while (0)
- /**
- * sw_r_table - read 4 bytes of data from switch table
- * @hw: The hardware instance.
- * @table: The table selector.
- * @addr: The address of the table entry.
- * @data: Buffer to store the read data.
- *
- * This routine reads 4 bytes of data from the table of the switch.
- * Hardware interrupts are disabled to minimize corruption of read data.
- */
- static void sw_r_table(struct ksz_hw *hw, int table, u16 addr, u32 *data)
- {
- u16 ctrl_addr;
- uint interrupt;
- ctrl_addr = (((table << TABLE_SEL_SHIFT) | TABLE_READ) << 8) | addr;
- interrupt = hw_block_intr(hw);
- writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET);
- HW_DELAY(hw, KS884X_IACR_OFFSET);
- *data = readl(hw->io + KS884X_ACC_DATA_0_OFFSET);
- hw_restore_intr(hw, interrupt);
- }
- /**
- * sw_w_table_64 - write 8 bytes of data to the switch table
- * @hw: The hardware instance.
- * @table: The table selector.
- * @addr: The address of the table entry.
- * @data_hi: The high part of data to be written (bit63 ~ bit32).
- * @data_lo: The low part of data to be written (bit31 ~ bit0).
- *
- * This routine writes 8 bytes of data to the table of the switch.
- * Hardware interrupts are disabled to minimize corruption of written data.
- */
- static void sw_w_table_64(struct ksz_hw *hw, int table, u16 addr, u32 data_hi,
- u32 data_lo)
- {
- u16 ctrl_addr;
- uint interrupt;
- ctrl_addr = ((table << TABLE_SEL_SHIFT) << 8) | addr;
- interrupt = hw_block_intr(hw);
- writel(data_hi, hw->io + KS884X_ACC_DATA_4_OFFSET);
- writel(data_lo, hw->io + KS884X_ACC_DATA_0_OFFSET);
- writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET);
- HW_DELAY(hw, KS884X_IACR_OFFSET);
- hw_restore_intr(hw, interrupt);
- }
- /**
- * sw_w_sta_mac_table - write to the static MAC table
- * @hw: The hardware instance.
- * @addr: The address of the table entry.
- * @mac_addr: The MAC address.
- * @ports: The port members.
- * @override: The flag to override the port receive/transmit settings.
- * @valid: The flag to indicate entry is valid.
- * @use_fid: The flag to indicate the FID is valid.
- * @fid: The FID value.
- *
- * This routine writes an entry of the static MAC table of the switch. It
- * calls sw_w_table_64() to write the data.
- */
- static void sw_w_sta_mac_table(struct ksz_hw *hw, u16 addr, u8 *mac_addr,
- u8 ports, int override, int valid, int use_fid, u8 fid)
- {
- u32 data_hi;
- u32 data_lo;
- data_lo = ((u32) mac_addr[2] << 24) |
- ((u32) mac_addr[3] << 16) |
- ((u32) mac_addr[4] << 8) | mac_addr[5];
- data_hi = ((u32) mac_addr[0] << 8) | mac_addr[1];
- data_hi |= (u32) ports << STATIC_MAC_FWD_PORTS_SHIFT;
- if (override)
- data_hi |= STATIC_MAC_TABLE_OVERRIDE;
- if (use_fid) {
- data_hi |= STATIC_MAC_TABLE_USE_FID;
- data_hi |= (u32) fid << STATIC_MAC_FID_SHIFT;
- }
- if (valid)
- data_hi |= STATIC_MAC_TABLE_VALID;
- sw_w_table_64(hw, TABLE_STATIC_MAC, addr, data_hi, data_lo);
- }
- /**
- * sw_r_vlan_table - read from the VLAN table
- * @hw: The hardware instance.
- * @addr: The address of the table entry.
- * @vid: Buffer to store the VID.
- * @fid: Buffer to store the VID.
- * @member: Buffer to store the port membership.
- *
- * This function reads an entry of the VLAN table of the switch. It calls
- * sw_r_table() to get the data.
- *
- * Return 0 if the entry is valid; otherwise -1.
- */
- static int sw_r_vlan_table(struct ksz_hw *hw, u16 addr, u16 *vid, u8 *fid,
- u8 *member)
- {
- u32 data;
- sw_r_table(hw, TABLE_VLAN, addr, &data);
- if (data & VLAN_TABLE_VALID) {
- *vid = (u16)(data & VLAN_TABLE_VID);
- *fid = (u8)((data & VLAN_TABLE_FID) >> VLAN_TABLE_FID_SHIFT);
- *member = (u8)((data & VLAN_TABLE_MEMBERSHIP) >>
- VLAN_TABLE_MEMBERSHIP_SHIFT);
- return 0;
- }
- return -1;
- }
- /**
- * port_r_mib_cnt - read MIB counter
- * @hw: The hardware instance.
- * @port: The port index.
- * @addr: The address of the counter.
- * @cnt: Buffer to store the counter.
- *
- * This routine reads a MIB counter of the port.
- * Hardware interrupts are disabled to minimize corruption of read data.
- */
- static void port_r_mib_cnt(struct ksz_hw *hw, int port, u16 addr, u64 *cnt)
- {
- u32 data;
- u16 ctrl_addr;
- uint interrupt;
- int timeout;
- ctrl_addr = addr + PORT_COUNTER_NUM * port;
- interrupt = hw_block_intr(hw);
- ctrl_addr |= (((TABLE_MIB << TABLE_SEL_SHIFT) | TABLE_READ) << 8);
- writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET);
- HW_DELAY(hw, KS884X_IACR_OFFSET);
- for (timeout = 100; timeout > 0; timeout--) {
- data = readl(hw->io + KS884X_ACC_DATA_0_OFFSET);
- if (data & MIB_COUNTER_VALID) {
- if (data & MIB_COUNTER_OVERFLOW)
- *cnt += MIB_COUNTER_VALUE + 1;
- *cnt += data & MIB_COUNTER_VALUE;
- break;
- }
- }
- hw_restore_intr(hw, interrupt);
- }
- /**
- * port_r_mib_pkt - read dropped packet counts
- * @hw: The hardware instance.
- * @port: The port index.
- * @cnt: Buffer to store the receive and transmit dropped packet counts.
- *
- * This routine reads the dropped packet counts of the port.
- * Hardware interrupts are disabled to minimize corruption of read data.
- */
- static void port_r_mib_pkt(struct ksz_hw *hw, int port, u32 *last, u64 *cnt)
- {
- u32 cur;
- u32 data;
- u16 ctrl_addr;
- uint interrupt;
- int index;
- index = KS_MIB_PACKET_DROPPED_RX_0 + port;
- do {
- interrupt = hw_block_intr(hw);
- ctrl_addr = (u16) index;
- ctrl_addr |= (((TABLE_MIB << TABLE_SEL_SHIFT) | T…