/*------------------------------------------------------------------------------------------*\ * Copyright (C) 2011, ..., 2014 AVM GmbH * * 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 version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include "avmnet_debug.h" #include "avmnet_module.h" #include "avmnet_config.h" #include "avmnet_common.h" #include "gsw_reg.h" #include "gsw_reg_top.h" #include "lantiq_gsw.h" #include "lantiq_gsw_flow.h" #include "gsw_flow_core.h" #include "avmnet_f24s.h" #define MODULE_NAME "AVMNET_F24S" static avmnet_module_t *this_module = NULL; static unsigned int slave_reg_rd(avmnet_module_t *this, unsigned int phy_addr, unsigned int reg_addr); static int slave_reg_wr(avmnet_module_t *this, unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data); /* glue cruft */ typedef enum { EXTSWITCH_PORTSPEED_UNK, EXTSWITCH_PORTSPEED_AUTONEG, EXTSWITCH_PORTSPEED_10_MBPS, EXTSWITCH_PORTSPEED_100_MBPS, EXTSWITCH_PORTSPEED_1000_MBPS, EXTSWITCH_PORTSPEED_2500_MBPS, EXTSWITCH_PORTSPEED_10_GBPS } EXTSWITCH_PortSpeeds_e; typedef enum { EXTSWITCH_MACIFACE_UNK, EXTSWITCH_MACIFACE_MII, EXTSWITCH_MACIFACE_RMII, EXTSWITCH_MACIFACE_GMII, EXTSWITCH_MACIFACE_RGMII, EXTSWITCH_MACIFACE_SGMII, EXTSWITCH_MACIFACE_HSGMII } EXTSWITCH_MacIfaces_e; typedef struct { /* Set to True if port isolation mode is enabled */ unsigned long IsPortIsolation; } INTELSW_InitAdditionalParam_t; typedef struct _EXTSWITCH_MacAddressEntry_t { Uint8 Mac[6]; /* Bitmap of ports that Mac may be forwarded to, i.e for each port appropriate Idx bit is set. * For unicast addresses only one bit should be set */ Uint16 Ports; /* Static or learned (via any methods) */ Bool IsStatic; Uint16 Vlan; /* Aging time left for the entry in seconds. * -1 for static entry or in case the information is not available */ Uint32 SecondsLeft; } EXTSWITCH_MacAddressEntry_t; typedef int (*EXTSWITCH_MacCb)(const EXTSWITCH_MacAddressEntry_t * Mac); #define ESHAL_LogDbg(a...) AVMNET_TRC(a) #define ESHAL_LogErr(a...) AVMNET_ERR(a) #define ESHAL_LogWarn(a...) AVMNET_WARN(a) #define ESHAL_LogInfo(a...) AVMNET_INFO(a) #define ESHAL_GetInternalPortIfaceSpeed(DevIdx) EXTSWITCH_PORTSPEED_2500_MBPS #define STATUS GSW_return_t #define STATUS_NOK GSW_statusErr #define STATUS_OK GSW_statusOk #define EXTSWITCH_DEF_ENABLED_PORTS_MASK 0xFF #define EXTSWITCH_IDX_INTERNAL_PORT 0 #define EXTSWITCH_MAX_PORTS 8 #define EXTSWITCH_MAX_SWITCHES 2 #define EXTSWITCH_MAX_HALS 2 #define EXTSWITCH_IDX_INVALID_SWITCH 0xFF #define EXTSWITCH_IDX_INVALID_HAL 0xFF #define EXTSWITCH_IDX_FIRST_LAN_PORT (EXTSWITCH_IDX_INTERNAL_PORT + 1) #define EXTSWITCH_MAX_PCP 7 #define EXTSWITCH_MAX_VLAN 4094 #define EXTSWITCH_MIN_VLAN 1 #define EXTSWITCH_SIZEOF_HALPRIV 1900 #define EXTSWITCH_SIZEOF_VENDOR_DATA 32 #define EXTSWITCH_DEF_LAN_PORTS_VLAN EXTSWITCH_MIN_VLAN #define EXTSWITCH_DEF_LAN_PORTS_PCP 0 //#define EXTSWITCH_DEF_PBM False #define EXTSWITCH_DEF_PBM True #define EXTSWITCH_DEF_LINK_SPEED EXTSWITCH_PORTSPEED_AUTONEG #define EXTSWITCH_DEF_LINK_FD True #define EXTSWITCH_DEF_ENABLED_PORTS_MASK 0xFF #define EXTSWITCH_DEF_STAG_TPID 0x8100 #define EXTSWITCH_DEF_IGMP_SNOOPING_ENA False #define EXTSWITCH_DEF_EEE_ENA_MASK 0 #define EXTSWITCH_DEF_PORT_MIRRORS {EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT, \ EXTSWITCH_IDX_INVALID_PORT} /* stolen from lantiq_sw.c in DOCSIS SDK */ #define LANTIQ_SMDIO_PHY_ADDR (0x1F) #define LANTIQ_SMDIO_BASE_ADDR (0x1F) #define LANTIQ_SMDIO_TARGET_ADDR (0x0) #define LTQ_PARSER_DL 1 #define MAX_LTQ_PORTS 6 #define LTQ_RGMII_PORT 5 #define LTQ_SGMII_PORT 4 #define LAST_INTEGRATED_PHY_PORTS 3 #define FIRST_EXT_PORT EXTSWITCH_IDX_FIRST_LAN_PORT #define LAST_EXT_PORT (EXTSWITCH_IDX_FIRST_LAN_PORT + 3) #define INTERNAL_PORT EXTSWITCH_IDX_INTERNAL_PORT #define PUMA_CONNECTED_PORT(DevIdx) LTQ_SGMII_PORT //ESHAL_GetInternalPortPidx(DevIdx) #define LTQ_CPU_PORTS 5 #define MAX_VLAN_TABLE 0x1000 #define CONFIG_LTQ_QOS 0 #define MAC_TABLE_SIZE 2048 #define RMON_DEBUG 1 #define LTQ_NUM_OF_SUPPORTED_SWITCHES 2 #define START_FID 1 #define INVALID_FID 0xFF #define INVALID_VID 0xFFFF #define INVALID_PCP 0xFF /*PHY Reg 0x4 */ #define PHY_AN_ADV_10HDX 0x20 #define PHY_AN_ADV_10FDX 0x40 #define PHY_AN_ADV_100HDX 0x80 #define PHY_AN_ADV_100FDX 0x100 /*PHY Reg 0x9 */ #define PHY_AN_ADV_1000HDX 0x100 #define PHY_AN_ADV_1000FDX 0x200 /* AQM and WRED defines - should come from the HW querying proper */ #define AQM_NUMOF_QUEUES 32 #define AQM_MAX_WRED_THRESH 1023 #define MMD_ACCESS_CONTROL_REG 0xD #define MMD_ADDRESS_DATA_REG 0xE #define PHY_FIRMWARE_VERSION_REG 0x1E /* Description: 'Polling State Machine Enable' */ #define MMDC_CFG_0_PEN_ALL_OFFSET 0xF40B #define MMDC_CFG_0_PEN_ALL_SHIFT 0 #define MMDC_CFG_0_PEN_ALL_SIZE 7 /* ----------------------------------------------- */ /* Description: 'MDIO Interface Clock Rate' */ #define MMDC_CFG_1_FREQ_OFFSET 0xF40C #define MMDC_CFG_1_FREQ_SHIFT 0 #define MMDC_CFG_1_FREQ_SIZE 8 #define GSW_API_DRV_VERSION "3.0.0" /* Implementation of auto speed decrease WA */ #define PHY_ADS_FW_VERSION 0x853B ethsw_api_dev_t *ecoredev = NULL; static u16 gsw_pcp2class[8] = {1, 0, 2, 3, 4, 5, 6, 7}; typedef struct _GSW_IMPL_DevPriv { Uint8 DevIdx; Uint32 mapApiToPhysicalPort[MAX_LTQ_PORTS]; Uint32 mapApiToPhysicalPortPuma7[MAX_LTQ_PORTS]; Uint32 mapPhysicalToApiPort[MAX_LTQ_PORTS]; Uint32 mapPhysicalToApiPortPuma7[MAX_LTQ_PORTS]; int max_ports; int tpnum; int num_of_queues; int num_of_meters; int num_of_shapers; int avlantsz; int ip_pkt_lnt_size; int prot_table_size; int mac_dasa_table_size; int app_table_size; int cport; int idsmtblsize; int idsltblsize; int mctblsize; int tftblsize; int mactblsize; int gipver; u16 firstmac; u16 last_mac; int mac_rd_index; int vlan_rd_index; int num_of_pppoe; int support_rgmii_int_port; Uint16 lan_port_vid[MAX_LTQ_PORTS]; Uint16 fid_vid[MAX_LTQ_PORTS]; u16 PhyFwVersion; Uint8 lan_port_pcp[MAX_LTQ_PORTS]; Uint8 provider_mode; } GSW_IMPL_DevPriv; typedef struct _GSW_IMPL_PrivData { Uint8 NumOfDevices; GSW_IMPL_DevPriv DevPriv[LTQ_NUM_OF_SUPPORTED_SWITCHES]; } GSW_IMPL_PrivData; typedef struct _EXTSWITCH_PortCounters_t { /* Mandatory counters, must always be provided */ Uint64 GoodPacketsIn; Uint64 BadPacketsIn; Uint64 PacketsOut; /* Optional counters */ #define EXTSWITCH_PORTCNT_UNICAST_IN 0x1 #define EXTSWITCH_PORTCNT_UNICAST_OUT 0x2 #define EXTSWITCH_PORTCNT_MCAST_IN 0x4 #define EXTSWITCH_PORTCNT_MCAST_OUT 0x8 #define EXTSWITCH_PORTCNT_BCAST_IN 0x10 #define EXTSWITCH_PORTCNT_BCAST_OUT 0x20 #define EXTSWITCH_PORTCNT_COLISIONS 0x40 #define EXTSWITCH_PORTCNT_OCTECTS_IN 0x80 #define EXTSWITCH_PORTCNT_OCTECTS_OUT 0x100 /* Combination of EXTSWITCH_PORTCNT_* for marking available counters */ Uint32 ValidCounters; Uint64 UnicastPacketsIn; Uint64 BcastPacketsIn; Uint64 McastPacketsIn; Uint64 UnicastPacketsOut; Uint64 BcastPacketsOut; Uint64 McastPacketsOut; Uint64 Collisions; Uint64 OctectsIn; /* Good octects in */ Uint64 OctectsOut; /* Good octects out */ } EXTSWITCH_PortCounters_t; typedef struct _EXTSWITCH_SwitchCaps_t { /* Capabilities supported by the switch hardware */ #define EXTSWITCH_CAP_IGMP_SNOOPING 0x1 /* IGMP/MLD snooping (no matter what versions) */ #define EXTSWITCH_CAP_EEE 0x2 /* 802.3az */ #define EXTSWITCH_CAP_PORTMIRRORING 0x4 /* Port mirroring */ #define EXTSWITCH_CAP_RSTP 0x8 /* Rapid Spanning Tree */ /* Bitmap of EXTSWITCH_CAP_* */ Uint32 Caps; /* Maximum number of forwarding entries that can be stored in switch forwarding tables */ Uint16 MaxMacs; /* Number of ports */ Uint8 NumOfPorts; /* Descriptors of switch ports. EXTSWITCH_IDX_INTERNAL_PORT index describes port connected to PUMA */ struct { /* Mac interface mode */ EXTSWITCH_MacIfaces_e MacIface; /* True if the port has PHY. False for EXTSWITCH_IDX_INTERNAL_PORT */ Bool HasPhy; /* Ethernet PHY signaling modes */ #define EXTSWITCH_SIG_10GBASET_FD 0x1 #define EXTSWITCH_SIG_1000BASET_FD 0x2 #define EXTSWITCH_SIG_1000BASET_HD 0x4 #define EXTSWITCH_SIG_100BASET2_FD 0x8 #define EXTSWITCH_SIG_100BASETX_FD 0x10 #define EXTSWITCH_SIG_100BASET2_HD 0x20 #define EXTSWITCH_SIG_100BASET4_HD 0x40 #define EXTSWITCH_SIG_100BASETX_HD 0x80 #define EXTSWITCH_SIG_10BASET_FD 0x100 #define EXTSWITCH_SIG_10BASET_HD 0x200 /* If HasPhy, then the value represents combination of EXTSWITCH_SIG_* */ Uint16 PhyModes; } Ports[EXTSWITCH_MAX_PORTS]; } EXTSWITCH_SwitchCaps_t; /* For internal LTQ driver reference */ static GSW_IMPL_PrivData my_priv_data; static GSW_IMPL_DevPriv * GSW_IMPL_CurrentDevPriv = NULL; static GSW_IMPL_DevPriv *_GetDevPriv(uint8_t DevIdx __maybe_unused) { return &(my_priv_data.DevPriv[DevIdx]); } static Uint32 __maybe_unused mapApiToPhysicalPortPuma7[] = {4, 0, 1, 3, 2, 5}; static Uint32 __maybe_unused mapPhysicalToApiPortPuma7[] = {1, 2, 4, 3, 0, 5}; #define MAP_API_TO_PHYSICAL_PORT(ApiPort) mapApiToPhysicalPortPuma7[ApiPort] #define MAP_PHYSICAL_TO_API_PORT(PhyPort) mapPhysicalToApiPortPuma7[PhyPort] static STATUS GSW_IMPL_SetLanPortVlan(Uint8 DevIdx, Uint8 LanPortIdx, Uint16 Vid); static STATUS GSW_IMPL_SetLanPortPcp(Uint8 DevIdx, Uint8 LanPortIdx, Uint8 Pcp); #define PCE_MC_M(val, msk, ns, out, len, type, flags, ipv4_len) \ { val, msk, (ns<<10 | out<<4 | len>>1),\ (len&1)<<15 | type<<13 | flags<<9 | ipv4_len<<8 } const PCE_MICROCODE pce_mc_gsw_22 = { /*-----------------------------------------------------------------*/ /** value mask ns out_fields L type flags ipv4_len **/ /*-----------------------------------------------------------------*/ PCE_MC_M(0x88c3 , 0xFFFF , 1 , GOUT_ITAG0 , 4 , INSTR , GFLAG_ITAG , 0), PCE_MC_M(0x8100 , 0xFFFF , 4 , GOUT_STAG0 , 2 , INSTR , GFLAG_SVLAN , 0), PCE_MC_M(0x88A8 , 0xFFFF , 4 , GOUT_STAG0 , 2 , INSTR , GFLAG_SVLAN , 0), PCE_MC_M(0x9100 , 0xFFFF , 4 , GOUT_STAG0 , 2 , INSTR , GFLAG_SVLAN , 0), PCE_MC_M(0x8100 , 0xFFFF , 5 , GOUT_VTAG0 , 2 , INSTR , GFLAG_VLAN , 0), PCE_MC_M(0x88A8 , 0xFFFF , 6 , GOUT_VTAG0 , 2 , INSTR , GFLAG_VLAN , 0), PCE_MC_M(0x9100 , 0xFFFF , 4 , GOUT_VTAG0 , 2 , INSTR , GFLAG_VLAN , 0), PCE_MC_M(0x8864 , 0xFFFF , 20 , GOUT_ETHTYP , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0800 , 0xFFFF , 24 , GOUT_ETHTYP , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x86DD , 0xFFFF , 25 , GOUT_ETHTYP , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x8863 , 0xFFFF , 19 , GOUT_ETHTYP , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0xF800 , 13 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 44 , GOUT_ETHTYP , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0600 , 0x0600 , 44 , GOUT_ETHTYP , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 15 , GOUT_NONE , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0xAAAA , 0xFFFF , 17 , GOUT_NONE , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0300 , 0xFF00 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_SNAP , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_DIP7 , 3 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 21 , GOUT_DIP7 , 3 , INSTR , GFLAG_PPPOE , 0), PCE_MC_M(0x0021 , 0xFFFF , 24 , GOUT_NONE , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0057 , 0xFFFF , 25 , GOUT_NONE , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 44 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x4000 , 0xF000 , 27 , GOUT_IP0 , 4 , INSTR , GFLAG_IPV4 , 1), PCE_MC_M(0x6000 , 0xF000 , 30 , GOUT_IP0 , 3 , INSTR , GFLAG_IPV6 , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 28 , GOUT_IP3 , 2 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 29 , GOUT_SIP0 , 4 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 44 , GOUT_NONE , 0 , LENACCU , GFLAG_NO , 0), PCE_MC_M(0x1100 , 0xFF00 , 43 , GOUT_PROT , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0600 , 0xFF00 , 43 , GOUT_PROT , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0xFF00 , 36 , GOUT_IP3 , 17 , INSTR , GFLAG_HOP , 0), PCE_MC_M(0x2B00 , 0xFF00 , 36 , GOUT_IP3 , 17 , INSTR , GFLAG_NN1 , 0), PCE_MC_M(0x3C00 , 0xFF00 , 36 , GOUT_IP3 , 17 , INSTR , GFLAG_NN2 , 0), PCE_MC_M(0x0000 , 0x0000 , 43 , GOUT_PROT , 1 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x00F0 , 38 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 44 , GOUT_NONE , 0 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0xFF00 , 36 , GOUT_NONE , 0 , IPV6 , GFLAG_HOP , 0), PCE_MC_M(0x2B00 , 0xFF00 , 36 , GOUT_NONE , 0 , IPV6 , GFLAG_NN1 , 0), PCE_MC_M(0x3C00 , 0xFF00 , 36 , GOUT_NONE , 0 , IPV6 , GFLAG_NN2 , 0), PCE_MC_M(0x0000 , 0x00FC , 44 , GOUT_PROT , 0 , IPV6 , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 44 , GOUT_NONE , 0 , IPV6 , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 44 , GOUT_SIP0 , 16 , INSTR , GFLAG_NO , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_APP0 , 4 , INSTR , GFLAG_IGMP , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), PCE_MC_M(0x0000 , 0x0000 , 45 , GOUT_NONE , 0 , INSTR , GFLAG_END , 0), }; #define _PhysicalToApiPorts(PhysPorts, pApiPorts) \ do { \ int i; \ *(pApiPorts) = 0; \ for (i = 0; i != MAX_LTQ_PORTS; i++) \ { \ if (PhysPorts & (1 << i)) \ { \ *(pApiPorts) |= 1 << MAP_PHYSICAL_TO_API_PORT(i); \ } \ } \ } while (0) static GSW_IMPL_DevPriv * _RegisterDevIdx(Uint8 DevIdx) { GSW_IMPL_PrivData * PrivData; PrivData = &my_priv_data; //(GSW_IMPL_PrivData *) ESHAL_GetHalPrivData(DevIdx); if (PrivData->NumOfDevices == LTQ_NUM_OF_SUPPORTED_SWITCHES) { return (GSW_IMPL_DevPriv *)(0); } PrivData->DevPriv[PrivData->NumOfDevices].DevIdx = DevIdx; return &PrivData->DevPriv[PrivData->NumOfDevices++]; } GSW_return_t gsw_reg_read(u16 offset, u16 shift, u16 size, u16 *retVal) { uint16_t rvalue, mask; rvalue = slave_reg_rd(this_module, 0x1F, offset); mask = (1 << size) - 1; rvalue = (rvalue >> shift); *retVal = (rvalue & mask); return GSW_statusOk; } GSW_return_t gsw_reg_write(u16 offset, u16 shift, u16 size, u16 value) { u16 rvalue, mask; int result; if(size != 16){ rvalue = slave_reg_rd(this_module, 0x1F, offset); /* Prepare the mask */ mask = (1 << size) - 1 ; mask = (mask << shift); /* Shift the value to the right place and mask the rest of the bit*/ value = ( value << shift ) & mask; /* Mask out the bit field from the read register and place in the new value */ value = ( rvalue & ~mask ) | value ; } result = slave_reg_wr(this_module, 0x1F, offset, value); return result == 0 ? GSW_statusOk : GSW_statusErr; } GSW_return_t pctrl_bas_busy(void *pdev) { u16 r; GSW_return_t s; do { s = gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &r); if (s != GSW_statusOk) return s; } while (r); return GSW_statusOk; } GSW_return_t pctrl_bas_set(void *pdev) { GSW_return_t s; s = gsw_reg_write(PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, 1); if (s != GSW_statusOk) return s; return GSW_statusOk; } GSW_return_t gsw_pce_parser_table_write(void *cdev, pctbl_prog_t *ptdata) { u16 value, udata; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value) != GSW_statusOk) return GSW_statusErr; } while (value); value = ptdata->pcindex; if (gsw_reg_write(PCE_TBL_ADDR_ADDR_OFFSET, \ PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, value) != GSW_statusOk) return GSW_statusErr; udata = ptdata->table; if (gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, \ PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, udata)!= GSW_statusOk) return GSW_statusErr; value = PCE_OP_MODE_ADWR; if(gsw_reg_write(PCE_TBL_CTRL_OPMOD_OFFSET, \ PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_3_VAL3_OFFSET, \ PCE_TBL_VAL_3_VAL3_SHIFT, \ PCE_TBL_VAL_3_VAL3_SIZE, ptdata->val[3])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_2_VAL2_OFFSET, \ PCE_TBL_VAL_2_VAL2_SHIFT, \ PCE_TBL_VAL_2_VAL2_SIZE, ptdata->val[2])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_1_VAL1_OFFSET, \ PCE_TBL_VAL_1_VAL1_SHIFT, \ PCE_TBL_VAL_1_VAL1_SIZE, ptdata->val[1])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, ptdata->val[0])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); return GSW_statusOk; } GSW_return_t gsw_pce_table_write(void *cdev, pctbl_prog_t *ptdata) { u16 value, udata; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value) != GSW_statusOk) return GSW_statusErr; } while (value); value = ptdata->pcindex; if (gsw_reg_write(PCE_TBL_ADDR_ADDR_OFFSET, \ PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, value) != GSW_statusOk) return GSW_statusErr; udata = ptdata->table; if (gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, \ PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, udata)!= GSW_statusOk) return GSW_statusErr; value = PCE_OP_MODE_ADWR; if(gsw_reg_write(PCE_TBL_CTRL_OPMOD_OFFSET, \ PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_8_KEY8_OFFSET, \ PCE_TBL_KEY_8_KEY8_SHIFT,PCE_TBL_KEY_8_KEY8_SIZE, \ ptdata->key[8])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_7_KEY7_OFFSET, \ PCE_TBL_KEY_7_KEY7_SHIFT, PCE_TBL_KEY_7_KEY7_SIZE, \ ptdata->key[7])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_6_KEY6_OFFSET, \ PCE_TBL_KEY_6_KEY6_SHIFT, \ PCE_TBL_KEY_6_KEY6_SIZE, ptdata->key[6])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_5_KEY5_OFFSET, \ PCE_TBL_KEY_5_KEY5_SHIFT, \ PCE_TBL_KEY_5_KEY5_SIZE, ptdata->key[5])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_4_KEY4_OFFSET, \ PCE_TBL_KEY_4_KEY4_SHIFT, \ PCE_TBL_KEY_4_KEY4_SIZE, ptdata->key[4])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_3_KEY3_OFFSET, \ PCE_TBL_KEY_3_KEY3_SHIFT, \ PCE_TBL_KEY_3_KEY3_SIZE, ptdata->key[3])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_2_KEY2_OFFSET, \ PCE_TBL_KEY_2_KEY2_SHIFT, \ PCE_TBL_KEY_2_KEY2_SIZE, ptdata->key[2])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_1_KEY1_OFFSET, \ PCE_TBL_KEY_1_KEY1_SHIFT, \ PCE_TBL_KEY_1_KEY1_SIZE, ptdata->key[1])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_0_KEY0_OFFSET, \ PCE_TBL_KEY_0_KEY0_SHIFT, \ PCE_TBL_KEY_0_KEY0_SIZE, ptdata->key[0])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_MASK_0_MASK0_OFFSET, \ PCE_TBL_MASK_0_MASK0_SHIFT, \ PCE_TBL_MASK_0_MASK0_SIZE, ptdata->mask[0])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_6_VAL6_OFFSET, \ PCE_TBL_VAL_6_VAL6_SHIFT, \ PCE_TBL_VAL_6_VAL6_SIZE, ptdata->val[6])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_5_VAL5_OFFSET, \ PCE_TBL_VAL_5_VAL5_SHIFT, \ PCE_TBL_VAL_5_VAL5_SIZE, ptdata->val[5])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_4_VAL4_OFFSET, \ PCE_TBL_VAL_4_VAL4_SHIFT, \ PCE_TBL_VAL_4_VAL4_SIZE, ptdata->val[4])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_3_VAL3_OFFSET, \ PCE_TBL_VAL_3_VAL3_SHIFT, \ PCE_TBL_VAL_3_VAL3_SIZE, ptdata->val[3])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_2_VAL2_OFFSET, \ PCE_TBL_VAL_2_VAL2_SHIFT, \ PCE_TBL_VAL_2_VAL2_SIZE, ptdata->val[2])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_1_VAL1_OFFSET, \ PCE_TBL_VAL_1_VAL1_SHIFT, \ PCE_TBL_VAL_1_VAL1_SIZE, ptdata->val[1])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, ptdata->val[0])!= GSW_statusOk) return GSW_statusErr; value = ptdata->kformat; if (gsw_reg_write(PCE_TBL_CTRL_KEYFORM_OFFSET, \ PCE_TBL_CTRL_KEYFORM_SHIFT, \ PCE_TBL_CTRL_KEYFORM_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->type; if (gsw_reg_write(PCE_TBL_CTRL_TYPE_OFFSET, \ PCE_TBL_CTRL_TYPE_SHIFT, \ PCE_TBL_CTRL_TYPE_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->valid; if (gsw_reg_write(PCE_TBL_CTRL_VLD_OFFSET, \ PCE_TBL_CTRL_VLD_SHIFT, \ PCE_TBL_CTRL_VLD_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->group; if (gsw_reg_write(PCE_TBL_CTRL_GMAP_OFFSET, \ PCE_TBL_CTRL_GMAP_SHIFT, \ PCE_TBL_CTRL_GMAP_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); return GSW_statusOk; } GSW_return_t gsw_pce_table_read(void *cdev, pctbl_prog_t *ptdata) { u16 value; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); if (gsw_reg_write(PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, \ PCE_TBL_ADDR_ADDR_SIZE, ptdata->pcindex)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, \ PCE_TBL_CTRL_ADDR_SIZE, ptdata->table)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_OPMOD_OFFSET, PCE_TBL_CTRL_OPMOD_SHIFT, \ PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_ADRD)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); if (gsw_reg_read(PCE_TBL_KEY_8_KEY8_OFFSET, \ PCE_TBL_KEY_8_KEY8_SHIFT, \ PCE_TBL_KEY_8_KEY8_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[8] = value; if (gsw_reg_read(PCE_TBL_KEY_7_KEY7_OFFSET, \ PCE_TBL_KEY_7_KEY7_SHIFT, \ PCE_TBL_KEY_7_KEY7_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[7] = value; if (gsw_reg_read(PCE_TBL_KEY_6_KEY6_OFFSET, \ PCE_TBL_KEY_6_KEY6_SHIFT, \ PCE_TBL_KEY_6_KEY6_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[6] = value; if (gsw_reg_read(PCE_TBL_KEY_5_KEY5_OFFSET, \ PCE_TBL_KEY_5_KEY5_SHIFT, \ PCE_TBL_KEY_5_KEY5_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[5] = value; if (gsw_reg_read(PCE_TBL_KEY_4_KEY4_OFFSET, \ PCE_TBL_KEY_4_KEY4_SHIFT, \ PCE_TBL_KEY_4_KEY4_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[4] = value; if (gsw_reg_read(PCE_TBL_KEY_3_KEY3_OFFSET, \ PCE_TBL_KEY_3_KEY3_SHIFT, \ PCE_TBL_KEY_3_KEY3_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[3] = value; if (gsw_reg_read(PCE_TBL_KEY_2_KEY2_OFFSET, \ PCE_TBL_KEY_2_KEY2_SHIFT, \ PCE_TBL_KEY_2_KEY2_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[2] = value; if (gsw_reg_read(PCE_TBL_KEY_1_KEY1_OFFSET, \ PCE_TBL_KEY_1_KEY1_SHIFT, \ PCE_TBL_KEY_1_KEY1_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[1] = value; if (gsw_reg_read(PCE_TBL_KEY_0_KEY0_OFFSET, \ PCE_TBL_KEY_0_KEY0_SHIFT, \ PCE_TBL_KEY_0_KEY0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[0] = value; if (gsw_reg_read(PCE_TBL_VAL_6_VAL6_OFFSET, \ PCE_TBL_VAL_6_VAL6_SHIFT, \ PCE_TBL_VAL_6_VAL6_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[6] = value; if (gsw_reg_read(PCE_TBL_VAL_5_VAL5_OFFSET, \ PCE_TBL_VAL_5_VAL5_SHIFT, \ PCE_TBL_VAL_5_VAL5_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[5] = value; if (gsw_reg_read(PCE_TBL_VAL_4_VAL4_OFFSET, \ PCE_TBL_VAL_4_VAL4_SHIFT, \ PCE_TBL_VAL_4_VAL4_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[4] = value; if (gsw_reg_read(PCE_TBL_VAL_3_VAL3_OFFSET, \ PCE_TBL_VAL_3_VAL3_SHIFT, \ PCE_TBL_VAL_3_VAL3_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[3] = value; if (gsw_reg_read(PCE_TBL_VAL_2_VAL2_OFFSET, \ PCE_TBL_VAL_2_VAL2_SHIFT, \ PCE_TBL_VAL_2_VAL2_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[2] = value; if (gsw_reg_read(PCE_TBL_VAL_1_VAL1_OFFSET, \ PCE_TBL_VAL_1_VAL1_SHIFT, \ PCE_TBL_VAL_1_VAL1_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[1] = value; if (gsw_reg_read(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[0] = value; if (gsw_reg_read(PCE_TBL_MASK_0_MASK0_OFFSET, \ PCE_TBL_MASK_0_MASK0_SHIFT, \ PCE_TBL_MASK_0_MASK0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->mask[0] = value; if (gsw_reg_read(PCE_TBL_CTRL_TYPE_OFFSET, \ PCE_TBL_CTRL_TYPE_SHIFT, \ PCE_TBL_CTRL_TYPE_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->type = value; if (gsw_reg_read(PCE_TBL_CTRL_VLD_OFFSET, \ PCE_TBL_CTRL_VLD_SHIFT, \ PCE_TBL_CTRL_VLD_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->valid = value; if (gsw_reg_read(PCE_TBL_CTRL_GMAP_OFFSET, \ PCE_TBL_CTRL_GMAP_SHIFT, \ PCE_TBL_CTRL_GMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->group = value; return GSW_statusOk; } GSW_return_t gsw_pce_table_key_read(void *cdev, pctbl_prog_t *ptdata) { u16 value; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); value = ptdata->table; if (gsw_reg_write( PCE_TBL_CTRL_ADDR_OFFSET, \ PCE_TBL_CTRL_ADDR_SHIFT, \ PCE_TBL_CTRL_ADDR_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[8]; if (gsw_reg_write( PCE_TBL_KEY_8_KEY8_OFFSET, \ PCE_TBL_KEY_8_KEY8_SHIFT, \ PCE_TBL_KEY_8_KEY8_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[7]; if (gsw_reg_write( PCE_TBL_KEY_7_KEY7_OFFSET, \ PCE_TBL_KEY_7_KEY7_SHIFT, \ PCE_TBL_KEY_7_KEY7_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[6]; if (gsw_reg_write( PCE_TBL_KEY_6_KEY6_OFFSET, \ PCE_TBL_KEY_6_KEY6_SHIFT, \ PCE_TBL_KEY_6_KEY6_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[5]; if (gsw_reg_write( PCE_TBL_KEY_5_KEY5_OFFSET, \ PCE_TBL_KEY_5_KEY5_SHIFT, \ PCE_TBL_KEY_5_KEY5_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[4]; if (gsw_reg_write( PCE_TBL_KEY_4_KEY4_OFFSET, \ PCE_TBL_KEY_4_KEY4_SHIFT, \ PCE_TBL_KEY_4_KEY4_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[3]; if (gsw_reg_write( PCE_TBL_KEY_3_KEY3_OFFSET, \ PCE_TBL_KEY_3_KEY3_SHIFT, \ PCE_TBL_KEY_3_KEY3_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[2]; if (gsw_reg_write( PCE_TBL_KEY_2_KEY2_OFFSET, \ PCE_TBL_KEY_2_KEY2_SHIFT, \ PCE_TBL_KEY_2_KEY2_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[1]; if (gsw_reg_write( PCE_TBL_KEY_1_KEY1_OFFSET, \ PCE_TBL_KEY_1_KEY1_SHIFT, \ PCE_TBL_KEY_1_KEY1_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[0]; if (gsw_reg_write( PCE_TBL_KEY_0_KEY0_OFFSET, \ PCE_TBL_KEY_0_KEY0_SHIFT, \ PCE_TBL_KEY_0_KEY0_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( PCE_TBL_CTRL_OPMOD_OFFSET, \ PCE_TBL_CTRL_OPMOD_SHIFT, \ PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_KSRD)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); if (gsw_reg_read(PCE_TBL_VAL_6_VAL6_OFFSET, \ PCE_TBL_VAL_6_VAL6_SHIFT, \ PCE_TBL_VAL_6_VAL6_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[6] = value; if (gsw_reg_read(PCE_TBL_VAL_5_VAL5_OFFSET, \ PCE_TBL_VAL_5_VAL5_SHIFT, \ PCE_TBL_VAL_5_VAL5_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[5] = value; if (gsw_reg_read(PCE_TBL_VAL_4_VAL4_OFFSET, \ PCE_TBL_VAL_4_VAL4_SHIFT, \ PCE_TBL_VAL_4_VAL4_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[4] = value; if (gsw_reg_read(PCE_TBL_VAL_3_VAL3_OFFSET, \ PCE_TBL_VAL_3_VAL3_SHIFT, \ PCE_TBL_VAL_3_VAL3_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[3] = value; if (gsw_reg_read(PCE_TBL_VAL_2_VAL2_OFFSET, \ PCE_TBL_VAL_2_VAL2_SHIFT, \ PCE_TBL_VAL_2_VAL2_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[2] = value; if (gsw_reg_read(PCE_TBL_VAL_1_VAL1_OFFSET, \ PCE_TBL_VAL_1_VAL1_SHIFT, \ PCE_TBL_VAL_1_VAL1_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[1] = value; if (gsw_reg_read(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[0] = value; if (gsw_reg_read(PCE_TBL_MASK_0_MASK0_OFFSET, \ PCE_TBL_MASK_0_MASK0_SHIFT, \ PCE_TBL_MASK_0_MASK0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->mask[0] = value; if (gsw_reg_read(PCE_TBL_CTRL_TYPE_OFFSET, \ PCE_TBL_CTRL_TYPE_SHIFT, \ PCE_TBL_CTRL_TYPE_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->type = value; if (gsw_reg_read(PCE_TBL_CTRL_VLD_OFFSET, \ PCE_TBL_CTRL_VLD_SHIFT, \ PCE_TBL_CTRL_VLD_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->valid = value; if (gsw_reg_read(PCE_TBL_CTRL_GMAP_OFFSET, \ PCE_TBL_CTRL_GMAP_SHIFT, \ PCE_TBL_CTRL_GMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->group = value; if (gsw_reg_read(PCE_TBL_ADDR_ADDR_OFFSET, \ PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->pcindex = value; return GSW_statusOk; } GSW_return_t gsw_pce_table_key_write(void *cdev, pctbl_prog_t *ptdata) { u16 value; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); if (gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, \ PCE_TBL_CTRL_ADDR_SHIFT, \ PCE_TBL_CTRL_ADDR_SIZE, ptdata->table)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_OPMOD_OFFSET, \ PCE_TBL_CTRL_OPMOD_SHIFT, \ PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_KSWR)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[8]; if (gsw_reg_write(PCE_TBL_KEY_8_KEY8_OFFSET, \ PCE_TBL_KEY_8_KEY8_SHIFT, \ PCE_TBL_KEY_8_KEY8_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[7]; if (gsw_reg_write(PCE_TBL_KEY_7_KEY7_OFFSET, \ PCE_TBL_KEY_7_KEY7_SHIFT, \ PCE_TBL_KEY_7_KEY7_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[6]; if (gsw_reg_write(PCE_TBL_KEY_6_KEY6_OFFSET, \ PCE_TBL_KEY_6_KEY6_SHIFT, \ PCE_TBL_KEY_6_KEY6_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[5]; if (gsw_reg_write(PCE_TBL_KEY_5_KEY5_OFFSET, \ PCE_TBL_KEY_5_KEY5_SHIFT, \ PCE_TBL_KEY_5_KEY5_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[4]; if (gsw_reg_write(PCE_TBL_KEY_4_KEY4_OFFSET, \ PCE_TBL_KEY_4_KEY4_SHIFT, \ PCE_TBL_KEY_4_KEY4_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[3]; if (gsw_reg_write(PCE_TBL_KEY_3_KEY3_OFFSET, \ PCE_TBL_KEY_3_KEY3_SHIFT, \ PCE_TBL_KEY_3_KEY3_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[2]; if (gsw_reg_write(PCE_TBL_KEY_2_KEY2_OFFSET, \ PCE_TBL_KEY_2_KEY2_SHIFT, \ PCE_TBL_KEY_2_KEY2_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[1]; if (gsw_reg_write(PCE_TBL_KEY_1_KEY1_OFFSET, \ PCE_TBL_KEY_1_KEY1_SHIFT, \ PCE_TBL_KEY_1_KEY1_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->key[0]; if (gsw_reg_write(PCE_TBL_KEY_0_KEY0_OFFSET, \ PCE_TBL_KEY_0_KEY0_SHIFT, \ PCE_TBL_KEY_0_KEY0_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->mask[0]; if (gsw_reg_write(PCE_TBL_MASK_0_MASK0_OFFSET, \ PCE_TBL_MASK_0_MASK0_SHIFT, \ PCE_TBL_MASK_0_MASK0_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[6]; if (gsw_reg_write(PCE_TBL_VAL_6_VAL6_OFFSET, \ PCE_TBL_VAL_6_VAL6_SHIFT, \ PCE_TBL_VAL_6_VAL6_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[5]; if (gsw_reg_write(PCE_TBL_VAL_5_VAL5_OFFSET, \ PCE_TBL_VAL_5_VAL5_SHIFT, \ PCE_TBL_VAL_5_VAL5_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[4]; if (gsw_reg_write(PCE_TBL_VAL_4_VAL4_OFFSET, \ PCE_TBL_VAL_4_VAL4_SHIFT, \ PCE_TBL_VAL_4_VAL4_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[3]; if (gsw_reg_write(PCE_TBL_VAL_3_VAL3_OFFSET, \ PCE_TBL_VAL_3_VAL3_SHIFT, \ PCE_TBL_VAL_3_VAL3_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[2]; if (gsw_reg_write(PCE_TBL_VAL_2_VAL2_OFFSET, \ PCE_TBL_VAL_2_VAL2_SHIFT, \ PCE_TBL_VAL_2_VAL2_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[1]; if (gsw_reg_write(PCE_TBL_VAL_1_VAL1_OFFSET, \ PCE_TBL_VAL_1_VAL1_SHIFT, \ PCE_TBL_VAL_1_VAL1_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->val[0]; if (gsw_reg_write(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->type; if (gsw_reg_write(PCE_TBL_CTRL_TYPE_OFFSET, \ PCE_TBL_CTRL_TYPE_SHIFT, \ PCE_TBL_CTRL_TYPE_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->valid; if (gsw_reg_write( PCE_TBL_CTRL_VLD_OFFSET, \ PCE_TBL_CTRL_VLD_SHIFT, \ PCE_TBL_CTRL_VLD_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->group; if (gsw_reg_write(PCE_TBL_CTRL_GMAP_OFFSET, \ PCE_TBL_CTRL_GMAP_SHIFT, \ PCE_TBL_CTRL_GMAP_SIZE, ptdata->group)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); return GSW_statusOk; } GSW_return_t gsw_mem_table_write(void *cdev, pctbl_prog_t *ptdata) { u16 value, udata; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value) != GSW_statusOk) return GSW_statusErr; } while (value); value = ptdata->pcindex; if (gsw_reg_write(PCE_TBL_ADDR_ADDR_OFFSET, \ PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, value) != GSW_statusOk) return GSW_statusErr; udata = ptdata->table; if (gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, \ PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_SIZE, udata)!= GSW_statusOk) return GSW_statusErr; value = PCE_OP_MODE_ADWR; if(gsw_reg_write(PCE_TBL_CTRL_OPMOD_OFFSET, \ PCE_TBL_CTRL_OPMOD_SHIFT, PCE_TBL_CTRL_OPMOD_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_KEY_0_KEY0_OFFSET, \ PCE_TBL_KEY_0_KEY0_SHIFT, \ PCE_TBL_KEY_0_KEY0_SIZE, ptdata->key[0])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_MASK_0_MASK0_OFFSET, \ PCE_TBL_MASK_0_MASK0_SHIFT, \ PCE_TBL_MASK_0_MASK0_SIZE, ptdata->mask[0])!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, ptdata->val[0])!= GSW_statusOk) return GSW_statusErr; value = ptdata->kformat; if (gsw_reg_write(PCE_TBL_CTRL_KEYFORM_OFFSET, \ PCE_TBL_CTRL_KEYFORM_SHIFT, \ PCE_TBL_CTRL_KEYFORM_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->type; if (gsw_reg_write(PCE_TBL_CTRL_TYPE_OFFSET, \ PCE_TBL_CTRL_TYPE_SHIFT, \ PCE_TBL_CTRL_TYPE_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->valid; if (gsw_reg_write(PCE_TBL_CTRL_VLD_OFFSET, \ PCE_TBL_CTRL_VLD_SHIFT, \ PCE_TBL_CTRL_VLD_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = ptdata->group; if (gsw_reg_write(PCE_TBL_CTRL_GMAP_OFFSET, \ PCE_TBL_CTRL_GMAP_SHIFT, \ PCE_TBL_CTRL_GMAP_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); return GSW_statusOk; } GSW_return_t gsw_mem_table_read(void *cdev, pctbl_prog_t *ptdata) { u16 value; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); if (gsw_reg_write(PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, \ PCE_TBL_ADDR_ADDR_SIZE, ptdata->pcindex)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, \ PCE_TBL_CTRL_ADDR_SIZE, ptdata->table)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_OPMOD_OFFSET, PCE_TBL_CTRL_OPMOD_SHIFT, \ PCE_TBL_CTRL_OPMOD_SIZE, PCE_OP_MODE_ADRD)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_TBL_CTRL_BAS_OFFSET, PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(PCE_TBL_CTRL_BAS_OFFSET, \ PCE_TBL_CTRL_BAS_SHIFT, \ PCE_TBL_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value != 0); if (gsw_reg_read(PCE_TBL_KEY_0_KEY0_OFFSET, \ PCE_TBL_KEY_0_KEY0_SHIFT, \ PCE_TBL_KEY_0_KEY0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->key[0] = value; if (gsw_reg_read(PCE_TBL_VAL_0_VAL0_OFFSET, \ PCE_TBL_VAL_0_VAL0_SHIFT, \ PCE_TBL_VAL_0_VAL0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->val[0] = value; if (gsw_reg_read(PCE_TBL_MASK_0_MASK0_OFFSET, \ PCE_TBL_MASK_0_MASK0_SHIFT, \ PCE_TBL_MASK_0_MASK0_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->mask[0] = value; if (gsw_reg_read(PCE_TBL_CTRL_TYPE_OFFSET, \ PCE_TBL_CTRL_TYPE_SHIFT, \ PCE_TBL_CTRL_TYPE_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->type = value; if (gsw_reg_read(PCE_TBL_CTRL_VLD_OFFSET, \ PCE_TBL_CTRL_VLD_SHIFT, \ PCE_TBL_CTRL_VLD_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->valid = value; if (gsw_reg_read(PCE_TBL_CTRL_GMAP_OFFSET, \ PCE_TBL_CTRL_GMAP_SHIFT, \ PCE_TBL_CTRL_GMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; ptdata->group = value; return GSW_statusOk; } GSW_return_t GSW_MDIO_DataRead(void *cdev, GSW_MDIO_data_t *parm) { u16 value; do { if (gsw_reg_read((MDIO_CTRL_MBUSY_OFFSET + GSW_TREG_OFFSET), \ MDIO_CTRL_MBUSY_SHIFT, MDIO_CTRL_MBUSY_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value); value = ((0x2 << 10) | ((parm->nAddressDev & 0x1F) << 5) | (parm->nAddressReg & 0x1F)); if (gsw_reg_write((MDIO_CTRL_MBUSY_OFFSET + GSW_TREG_OFFSET), 0, 16, value)!= GSW_statusOk) return GSW_statusErr; do { gsw_reg_read((MDIO_CTRL_MBUSY_OFFSET + GSW_TREG_OFFSET), \ MDIO_CTRL_MBUSY_SHIFT, MDIO_CTRL_MBUSY_SIZE, &value); } while (value); if (gsw_reg_read((MDIO_READ_RDATA_OFFSET + GSW_TREG_OFFSET), \ MDIO_READ_RDATA_SHIFT, MDIO_READ_RDATA_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nData = (value & 0xFFFF); return GSW_statusOk; } GSW_return_t GSW_MDIO_DataWrite(void *cdev, GSW_MDIO_data_t *parm) { u16 value; do { if (gsw_reg_read((MDIO_CTRL_MBUSY_OFFSET + GSW_TREG_OFFSET), MDIO_CTRL_MBUSY_SHIFT, MDIO_CTRL_MBUSY_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value); value = parm->nData & 0xFFFF; if (gsw_reg_write((MDIO_WRITE_WDATA_OFFSET + GSW_TREG_OFFSET), \ MDIO_WRITE_WDATA_SHIFT, MDIO_WRITE_WDATA_SIZE, value) != GSW_statusOk) return GSW_statusErr; value = ((0x1 << 10) | ((parm->nAddressDev & 0x1F) << 5) | (parm->nAddressReg & 0x1F)); if (gsw_reg_write((MDIO_CTRL_MBUSY_OFFSET + GSW_TREG_OFFSET), 0, 16, value) != GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read((MDIO_CTRL_MBUSY_OFFSET + GSW_TREG_OFFSET), \ MDIO_CTRL_MBUSY_SHIFT, MDIO_CTRL_MBUSY_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value); return GSW_statusOk; } static GSW_return_t get_gsw_hw_cap(void *cdev) { u16 reg_val; if (gsw_reg_read(ETHSW_CAP_1_PPORTS_OFFSET, ETHSW_CAP_1_PPORTS_SHIFT, ETHSW_CAP_1_PPORTS_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->max_ports = reg_val; if (gsw_reg_read(ETHSW_CAP_1_VPORTS_OFFSET, ETHSW_CAP_1_VPORTS_SHIFT, ETHSW_CAP_1_VPORTS_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->tpnum = reg_val + GSW_IMPL_CurrentDevPriv->max_ports; if (gsw_reg_read(ETHSW_CAP_1_QUEUE_OFFSET, ETHSW_CAP_1_QUEUE_SHIFT, ETHSW_CAP_1_QUEUE_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->num_of_queues = reg_val; if (gsw_reg_read(ETHSW_CAP_3_METERS_OFFSET, ETHSW_CAP_3_METERS_SHIFT, ETHSW_CAP_3_METERS_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->num_of_meters = reg_val; if (gsw_reg_read(ETHSW_CAP_3_SHAPERS_OFFSET, ETHSW_CAP_3_SHAPERS_SHIFT, ETHSW_CAP_3_SHAPERS_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->num_of_shapers = reg_val; if (gsw_reg_read(ETHSW_CAP_4_PPPOE_OFFSET, ETHSW_CAP_4_PPPOE_SHIFT, ETHSW_CAP_4_PPPOE_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->num_of_pppoe = reg_val; if (gsw_reg_read(ETHSW_CAP_4_VLAN_OFFSET, ETHSW_CAP_4_VLAN_SHIFT, ETHSW_CAP_4_VLAN_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->avlantsz = reg_val; if (gsw_reg_read(ETHSW_CAP_5_IPPLEN_OFFSET, ETHSW_CAP_5_IPPLEN_SHIFT, ETHSW_CAP_5_IPPLEN_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->ip_pkt_lnt_size = reg_val; if (gsw_reg_read(ETHSW_CAP_5_PROT_OFFSET, ETHSW_CAP_5_PROT_SHIFT, ETHSW_CAP_5_PROT_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->prot_table_size = reg_val; if (gsw_reg_read(ETHSW_CAP_6_MACDASA_OFFSET, ETHSW_CAP_6_MACDASA_SHIFT, ETHSW_CAP_6_MACDASA_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->mac_dasa_table_size = reg_val; if (gsw_reg_read(ETHSW_CAP_6_APPL_OFFSET, ETHSW_CAP_6_APPL_SHIFT, ETHSW_CAP_6_APPL_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->app_table_size = reg_val; if (gsw_reg_read(ETHSW_CAP_7_IPDASAM_OFFSET, ETHSW_CAP_7_IPDASAM_SHIFT, ETHSW_CAP_7_IPDASAM_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->idsmtblsize = reg_val; if (gsw_reg_read(ETHSW_CAP_7_IPDASAL_OFFSET, ETHSW_CAP_7_IPDASAL_SHIFT, ETHSW_CAP_7_IPDASAL_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->idsltblsize = reg_val; if (gsw_reg_read(ETHSW_CAP_8_MCAST_OFFSET, ETHSW_CAP_8_MCAST_SHIFT, ETHSW_CAP_8_MCAST_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->mctblsize = reg_val; if (gsw_reg_read(ETHSW_CAP_9_FLAGG_OFFSET, ETHSW_CAP_9_FLAGG_SHIFT, ETHSW_CAP_9_FLAGG_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->tftblsize = reg_val; if (gsw_reg_read(ETHSW_CAP_10_MACBT_OFFSET, ETHSW_CAP_10_MACBT_SHIFT, ETHSW_CAP_10_MACBT_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->mactblsize = reg_val; if (gsw_reg_read(ETHSW_VERSION_REV_ID_OFFSET, ETHSW_VERSION_REV_ID_SHIFT, 16, ®_val)!= GSW_statusOk) return GSW_statusErr; GSW_IMPL_CurrentDevPriv->gipver = reg_val; GSW_IMPL_CurrentDevPriv->cport = GSW_PUMA_SOC_CPU_PORT; return GSW_statusOk; } /* PCE Table Micro Code Init routine */ int gsw_pmicro_code_init(void *cdev) { #if defined(LTQ_PARSER_DL) && LTQ_PARSER_DL pctbl_prog_t tbl_entry; #endif u8 i; /* Disable all physical port */ for (i = 0; i < MAX_LTQ_PORTS; i++) { if (gsw_reg_write((FDMA_PCTRL_EN_OFFSET + (i * 0x6)), FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((SDMA_PCTRL_PEN_OFFSET + (i * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; } if (gsw_reg_write((GLOB_CTRL_SE_OFFSET + 0xF400), GLOB_CTRL_SE_SHIFT, GLOB_CTRL_SE_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, \ PCE_GCTRL_0_MC_VALID_SIZE, 0x0)!= GSW_statusOk) return GSW_statusErr; /* Download the microcode */ #if defined(LTQ_PARSER_DL) && LTQ_PARSER_DL for (i = 0; i < 64 /* PCE_MICRO_TABLE_SIZE */; i++) { memset(&tbl_entry, 0, sizeof(tbl_entry)); tbl_entry.val[3] = pce_mc_gsw_22[i].val_3; tbl_entry.val[2] = pce_mc_gsw_22[i].val_2; tbl_entry.val[1] = pce_mc_gsw_22[i].val_1; tbl_entry.val[0] = pce_mc_gsw_22[i].val_0; tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_parser_table_write(cdev, &tbl_entry); } #endif /* LTQ_PARSER_DL */ if (gsw_reg_write( PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, 0x3F)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, 0x3F)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Enable RMON Counter for all ports */ for (i = 0; i < MAX_LTQ_PORTS; i++) { if (gsw_reg_write((BM_PCFG_CNTEN_OFFSET + (i * 0x2)), BM_PCFG_CNTEN_SHIFT, BM_PCFG_CNTEN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RMON_CTRL_BCAST_CNT_OFFSET + (i * 2), BM_RMON_CTRL_BCAST_CNT_SHIFT, BM_RMON_CTRL_BCAST_CNT_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; /* Disable Port-based Traffic Class*/ if (gsw_reg_write(PCE_PCTRL_2_PCLASS_OFFSET + (i * 10), PCE_PCTRL_2_PCLASS_SHIFT, PCE_PCTRL_2_PCLASS_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; } if (gsw_reg_write( BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; for (i = 0; i < MAX_LTQ_PORTS; i++) { if (gsw_reg_write((FDMA_PCTRL_EN_OFFSET + (i * 0x6)), FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((SDMA_PCTRL_PEN_OFFSET + (i * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; } /*Enable TVM for all the ports*/ for (i = 0; i < MAX_LTQ_PORTS; i++) { if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * i)), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; } return GSW_statusOk; } GSW_return_t GSW_MAC_TableClear(void *cdev) { /* flush all entries from the MAC table */ if (gsw_reg_write( PCE_GCTRL_0_MTFL_OFFSET, PCE_GCTRL_0_MTFL_SHIFT, \ PCE_GCTRL_0_MTFL_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_MAC_TableEntryAdd(void *cdev, GSW_MAC_tableAdd_t *parm) { pctbl_prog_t tbl_prog; memset(&tbl_prog, 0, sizeof(pctbl_prog_t)); tbl_prog.table = PCE_MAC_BRIDGE_INDEX; tbl_prog.key[0] = parm->nMAC[4] << 8 | parm->nMAC[5]; tbl_prog.key[1] = parm->nMAC[2] << 8 | parm->nMAC[3]; tbl_prog.key[2] = parm->nMAC[0] << 8 | parm->nMAC[1]; tbl_prog.key[3] = parm->nFId; tbl_prog.val[1] = ((parm->nSubIfId & 0xFFF) << 4); tbl_prog.val[1] |= (1 << 1); /* Valid Entry */ tbl_prog.valid = 1; if (parm->bStaticEntry) { if (parm->nPortId & 0x80000000) { /*Port Map */ tbl_prog.val[0] = (parm->nPortId & 0x7FFF); } else { tbl_prog.val[0] = (1 << parm->nPortId); } tbl_prog.val[1] |= 1; } else { tbl_prog.val[0] = (((parm->nPortId & 0xF) << 4) | (parm->nAgeTimer & 0xF)); } if (gsw_pce_table_key_write(cdev, &tbl_prog)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } static GSW_return_t mac_br_rd(void *pdev, pctbl_prog_t *pt) { u16 r; GSW_return_t s; s = pctrl_bas_busy(pdev); if (s != GSW_statusOk) return s; s = gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_REG_SIZE, 0x000B); if (s != GSW_statusOk) return s; s = pctrl_bas_set(pdev); if (s != GSW_statusOk) return s; s = pctrl_bas_busy(pdev); if (s != GSW_statusOk) return s; s = gsw_reg_read(PCE_TBL_CTRL_VLD_OFFSET, PCE_TBL_CTRL_VLD_SHIFT, PCE_TBL_CTRL_VLD_SIZE, &r); if (s != GSW_statusOk) return s; pt->valid = r; if (pt->valid == 1) { s = gsw_reg_read(PCE_TBL_KEY_3_KEY3_OFFSET, PCE_TBL_KEY_3_KEY3_SHIFT, PCE_TBL_KEY_3_KEY3_SIZE, &r); if (s != GSW_statusOk) return s; pt->key[3] = r; s = gsw_reg_read(PCE_TBL_KEY_2_KEY2_OFFSET, PCE_TBL_KEY_2_KEY2_SHIFT, PCE_TBL_KEY_2_KEY2_SIZE, &r); if (s != GSW_statusOk) return s; pt->key[2] = r; s = gsw_reg_read(PCE_TBL_KEY_1_KEY1_OFFSET, PCE_TBL_KEY_1_KEY1_SHIFT, PCE_TBL_KEY_1_KEY1_SIZE, &r); if (s != GSW_statusOk) return s; pt->key[1] = r; s = gsw_reg_read(PCE_TBL_KEY_0_KEY0_OFFSET, PCE_TBL_KEY_0_KEY0_SHIFT, PCE_TBL_KEY_0_KEY0_SIZE, &r); if (s != GSW_statusOk) return s; pt->key[0] = r; s = gsw_reg_read(PCE_TBL_VAL_1_VAL1_OFFSET, PCE_TBL_VAL_1_VAL1_SHIFT, PCE_TBL_VAL_1_VAL1_SIZE, &r); if (s != GSW_statusOk) return s; pt->val[1] = r; s = gsw_reg_read(PCE_TBL_VAL_0_VAL0_OFFSET, PCE_TBL_VAL_0_VAL0_SHIFT, PCE_TBL_VAL_0_VAL0_SIZE, &r); if (s != GSW_statusOk) return s; pt->val[0] = r; s = gsw_reg_read(PCE_TBL_MASK_0_MASK0_OFFSET, PCE_TBL_MASK_0_MASK0_SHIFT, PCE_TBL_MASK_0_MASK0_SIZE, &r); if (s != GSW_statusOk) return s; pt->mask[0] = r; } return GSW_statusOk; } GSW_return_t GSW2X_MAC_TableEntryRead(void *pdev, GSW_MAC_tableRead_t *parm) { GSW_return_t s; pctbl_prog_t pt; u16 r = 1; ESHAL_LogDbg(" \n***(Line#:%d, mac_rd_index:%d) ***\n",__LINE__,GSW_IMPL_CurrentDevPriv->mac_rd_index); memset(&pt, 0, sizeof(pctbl_prog_t)); if (parm->bInitial == 1) { /*Start from the index 0 */ GSW_IMPL_CurrentDevPriv->mac_rd_index = 0; GSW_IMPL_CurrentDevPriv->firstmac = 0; parm->bInitial = 0; s = gsw_reg_write(PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, 0); if (s != GSW_statusOk) return s; s = gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_REG_SIZE, 0xC00B); if (s != GSW_statusOk) return s; s = pctrl_bas_busy(pdev); if (s != GSW_statusOk) return s; s = gsw_reg_read(PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, &r); if (s != GSW_statusOk) return s; GSW_IMPL_CurrentDevPriv->firstmac = r; } if ((GSW_IMPL_CurrentDevPriv->mac_rd_index >= MAC_TABLE_SIZE /*pd->mactblsize*/) || (r == 0)) { memset(parm, 0, sizeof(GSW_MAC_tableRead_t)); parm->bLast = 1; GSW_IMPL_CurrentDevPriv->mac_rd_index = 0; s = gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_REG_SIZE, 0x000B); if (s != GSW_statusOk) return s; return GSW_statusOk; } GSW_IMPL_CurrentDevPriv->mac_rd_index++; if ((parm->bInitial != 1) && GSW_IMPL_CurrentDevPriv->mac_rd_index) { s = gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_REG_SIZE, 0xC00B); if (s != GSW_statusOk) return s; s = pctrl_bas_busy(pdev); if (s != GSW_statusOk) return s; s = gsw_reg_read(PCE_TBL_ADDR_ADDR_OFFSET, PCE_TBL_ADDR_ADDR_SHIFT, PCE_TBL_ADDR_ADDR_SIZE, &r); if (s != GSW_statusOk) return s; if (GSW_IMPL_CurrentDevPriv->firstmac == r) { s = mac_br_rd(pdev, &pt); if (s != GSW_statusOk) return s; if ((pt.valid == 1)) { parm->nFId = pt.key[3] & 0x3F; parm->bStaticEntry = (pt.val[1] & 0x1); if (parm->bStaticEntry == 1) { parm->nAgeTimer = 0; parm->nPortId = pt.val[0]; } else { u32 timer = 300, mant; u16 rg; /* Aging Counter Mantissa Value */ s = gsw_reg_read(PCE_AGE_1_MANT_OFFSET, PCE_AGE_1_MANT_SHIFT, PCE_AGE_1_MANT_SIZE, &rg); if (s != GSW_statusOk) return s; mant = rg; switch (mant) { case AGETIMER_1_DAY: timer = 86400; break; case AGETIMER_1_HOUR: timer = 3600; break; case AGETIMER_300_SEC: timer = 300; break; case AGETIMER_10_SEC: timer = 10; break; case AGETIMER_1_SEC: timer = 1; break; } parm->nAgeTimer = pt.val[0] & 0xF; parm->nAgeTimer = (timer * parm->nAgeTimer)/0xF; parm->nPortId = (pt.val[0] >> 4) & 0xF; } parm->nMAC[0] = pt.key[2] >> 8; parm->nMAC[1] = pt.key[2] & 0xFF; parm->nMAC[2] = pt.key[1] >> 8; parm->nMAC[3] = pt.key[1] & 0xFF; parm->nMAC[4] = pt.key[0] >> 8; parm->nMAC[5] = pt.key[0] & 0xFF; parm->nSubIfId = (pt.val[1] >> 4 & 0xFFF); } parm->bLast = 1; GSW_IMPL_CurrentDevPriv->mac_rd_index = 0; s = gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_REG_SIZE, 0x000B); if (s != GSW_statusOk) return s; return GSW_statusOk; } } s = mac_br_rd(pdev, &pt); if (s != GSW_statusOk) return s; if ((pt.valid == 1)) { parm->nFId = pt.key[3] & 0x3F; parm->bStaticEntry = (pt.val[1] & 0x1); if (parm->bStaticEntry == 1) { parm->nAgeTimer = 0; parm->nPortId = pt.val[0]; } else { u32 timer = 300, mant; u16 rg; /* Aging Counter Mantissa Value */ s = gsw_reg_read(PCE_AGE_1_MANT_OFFSET, PCE_AGE_1_MANT_SHIFT, PCE_AGE_1_MANT_SIZE, &rg); if (s != GSW_statusOk) return s; mant = rg; switch (mant) { case AGETIMER_1_DAY: timer = 86400; break; case AGETIMER_1_HOUR: timer = 3600; break; case AGETIMER_300_SEC: timer = 300; break; case AGETIMER_10_SEC: timer = 10; break; case AGETIMER_1_SEC: timer = 1; break; } parm->nAgeTimer = pt.val[0] & 0xF; parm->nAgeTimer = (timer * parm->nAgeTimer)/0xF; parm->nPortId = (pt.val[0] >> 4) & 0xF; } parm->nMAC[0] = pt.key[2] >> 8; parm->nMAC[1] = pt.key[2] & 0xFF; parm->nMAC[2] = pt.key[1] >> 8; parm->nMAC[3] = pt.key[1] & 0xFF; parm->nMAC[4] = pt.key[0] >> 8; parm->nMAC[5] = pt.key[0] & 0xFF; parm->nSubIfId = (pt.val[1] >> 4 & 0xFFF); parm->bInitial = 0; parm->bLast = 0; } else { memset(parm, 0, sizeof(GSW_MAC_tableRead_t)); parm->bLast = 1; s = gsw_reg_write(PCE_TBL_CTRL_ADDR_OFFSET, PCE_TBL_CTRL_ADDR_SHIFT, PCE_TBL_CTRL_ADDR_REG_SIZE, 0x000B); if (s != GSW_statusOk) return s; } return GSW_statusOk; } GSW_return_t GSW_MAC_TableEntryQuery(void *cdev, GSW_MAC_tableQuery_t *parm) { pctbl_prog_t tbl_prog; parm->bFound = 0; memset(&tbl_prog, 0, sizeof(pctbl_prog_t)); tbl_prog.table = PCE_MAC_BRIDGE_INDEX; tbl_prog.key[0] = parm->nMAC[4] << 8 | parm->nMAC[5]; tbl_prog.key[1] = parm->nMAC[2] << 8 | parm->nMAC[3]; tbl_prog.key[2] = parm->nMAC[0] << 8 | parm->nMAC[1]; tbl_prog.key[3] = parm->nFId; if (gsw_pce_table_key_read(cdev, &tbl_prog)!= GSW_statusOk) return GSW_statusErr; if (tbl_prog.valid == 1) { parm->bFound = 1; parm->bStaticEntry = (tbl_prog.val[1] & 0x1); parm->nSVLAN_Id = ((tbl_prog.val[1] >> 4) & 0xFFF); if ((tbl_prog.val[1] & 0x1) == 1) { parm->nAgeTimer = 0; parm->nPortId = (tbl_prog.val[0]); } else { u16 mant; u32 timer = 300; /* Aging Counter Mantissa Value */ if (gsw_reg_read(PCE_AGE_1_MANT_OFFSET, PCE_AGE_1_MANT_SHIFT, \ PCE_AGE_1_MANT_SIZE, &mant)!= GSW_statusOk) return GSW_statusErr; switch (mant) { case AGETIMER_1_DAY: timer = 86400; break; case AGETIMER_1_HOUR: timer = 3600; break; case AGETIMER_300_SEC: timer = 300; break; case AGETIMER_10_SEC: timer = 10; break; case AGETIMER_1_SEC: timer = 1; break; } parm->nAgeTimer = tbl_prog.val[0] & 0xF; parm->nAgeTimer = (timer * parm->nAgeTimer)/0xF; parm->nPortId = (tbl_prog.val[0] >> 4) & 0xF; } } return GSW_statusOk; } GSW_return_t GSW_MAC_TableEntryRemove(void *cdev, GSW_MAC_tableRemove_t *parm) { pctbl_prog_t tbl_prog; u16 value; /* Learning Limit Port Lock */ if (gsw_reg_read(PCE_GCTRL_0_MTFL_OFFSET, PCE_GCTRL_0_MTFL_SHIFT, \ PCE_GCTRL_0_MTFL_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; /*if value is 1 means, flush all entries from the MAC table */ if (!value) { memset(&tbl_prog, 0, sizeof(pctbl_prog_t)); tbl_prog.table = PCE_MAC_BRIDGE_INDEX; tbl_prog.key[0] = parm->nMAC[4] << 8 | parm->nMAC[5]; tbl_prog.key[1] = parm->nMAC[2] << 8 | parm->nMAC[3]; tbl_prog.key[2] = parm->nMAC[0] << 8 | parm->nMAC[1]; tbl_prog.key[3] = parm->nFId; if (gsw_pce_table_key_read(cdev, &tbl_prog)!= GSW_statusOk) return GSW_statusErr; if (tbl_prog.valid == 1) { pctbl_prog_t tbl_cl_prog; memset(&tbl_cl_prog, 0, sizeof(pctbl_prog_t)); tbl_cl_prog.table = PCE_MAC_BRIDGE_INDEX; tbl_cl_prog.pcindex = tbl_prog.pcindex; if (gsw_pce_table_write(cdev, &tbl_cl_prog)!= GSW_statusOk) return GSW_statusErr; } } return GSW_statusOk; } GSW_return_t GSW_PortCfgGet(void *cdev, GSW_portCfg_t *parm) { u8 pidx = parm->nPortId; u16 value, monrx = 0, montx = 0, PEN, EN; u16 regval; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; /* See if PORT enable or not */ if (gsw_reg_read((SDMA_PCTRL_PEN_OFFSET + (0x6 * pidx)), \ SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, &PEN)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_read((FDMA_PCTRL_EN_OFFSET + (0x6 * pidx)), \ FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, &EN)!= GSW_statusOk) return GSW_statusErr; /* Port Enable feature only support 6 port */ if (pidx >= MAX_LTQ_PORTS) { parm->eEnable = 1; } else { if ((PEN == 1) && (EN == 1)) parm->eEnable = GSW_PORT_ENABLE_RXTX; else if ((PEN == 1) && (EN == 0)) parm->eEnable = GSW_PORT_ENABLE_RX; else if ((PEN == 0) && (EN == 1)) parm->eEnable = GSW_PORT_ENABLE_TX; else parm->eEnable = GSW_PORT_DISABLE; } /* Learning Limit */ if (gsw_reg_read((PCE_PCTRL_1_LRNLIM_OFFSET + (0xA * pidx)), \ PCE_PCTRL_1_LRNLIM_SHIFT, PCE_PCTRL_1_LRNLIM_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nLearningLimit = value; /* Learning Limit Port Lock */ if (gsw_reg_read((PCE_PCTRL_0_PLOCK_OFFSET + (0xA * pidx)), \ PCE_PCTRL_0_PLOCK_SHIFT, PCE_PCTRL_0_PLOCK_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bLearningMAC_PortLock = value; /* Aging */ if (gsw_reg_read(PCE_PCTRL_0_AGEDIS_OFFSET + (0xA * pidx), \ PCE_PCTRL_0_AGEDIS_SHIFT, PCE_PCTRL_0_AGEDIS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bAging = value; /** MAC address table learning on the port specified. */ if (gsw_reg_read((PCE_PCTRL_3_LNDIS_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_LNDIS_SHIFT, \ PCE_PCTRL_3_LNDIS_SIZE, ®val)!= GSW_statusOk) return GSW_statusErr; parm->bLearning = regval; /** MAC spoofing detection. */ if (gsw_reg_read((PCE_PCTRL_0_SPFDIS_OFFSET + (0xA * pidx)), \ PCE_PCTRL_0_SPFDIS_SHIFT, \ PCE_PCTRL_0_SPFDIS_SIZE, ®val)!= GSW_statusOk) return GSW_statusErr; parm->bMAC_SpoofingDetection = regval; /* UnicastUnknownDrop */ if (gsw_reg_read(PCE_PMAP_3_UUCMAP_OFFSET, \ PCE_PMAP_3_UUCMAP_SHIFT, \ PCE_PMAP_3_UUCMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; /* UnicastUnknownDrop feature support */ if ((value & (1 << pidx)) == 0) parm->bUnicastUnknownDrop = 1; else parm->bUnicastUnknownDrop = 0; /* MulticastUnknownDrop */ if (gsw_reg_read(PCE_PMAP_2_DMCPMAP_OFFSET, \ PCE_PMAP_2_DMCPMAP_SHIFT, \ PCE_PMAP_2_DMCPMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; /* MulticastUnknownDrop feature support */ if ((value & (1 << pidx)) == 0) { parm->bMulticastUnknownDrop = 1; parm->bBroadcastDrop = 1; } else { parm->bMulticastUnknownDrop = 0; parm->bBroadcastDrop = 0; } /* Require to check later - 3M */ parm->bReservedPacketDrop = 0; /* Port Monitor */ if (gsw_reg_read((PCE_PCTRL_3_RXVMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_RXVMIR_SHIFT, \ PCE_PCTRL_3_RXVMIR_SIZE, &monrx)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_read((PCE_PCTRL_3_TXMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_TXMIR_SHIFT, \ PCE_PCTRL_3_TXMIR_SIZE, &montx)!= GSW_statusOk) return GSW_statusErr; if ((monrx == 1) && (montx == 1)) parm->ePortMonitor = GSW_PORT_MONITOR_RXTX; else if ((monrx == 1) && (montx == 0)) parm->ePortMonitor = GSW_PORT_MONITOR_RX; else if ((monrx == 0) && (montx == 1)) parm->ePortMonitor = GSW_PORT_MONITOR_TX; else parm->ePortMonitor = GSW_PORT_MONITOR_NONE; if (gsw_reg_read((PCE_PCTRL_3_VIO_2_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_2_SHIFT, \ PCE_PCTRL_3_VIO_2_SIZE, &monrx)!= GSW_statusOk) return GSW_statusErr; if (monrx == 1) parm->ePortMonitor |= GSW_PORT_MONITOR_VLAN_UNKNOWN; if (gsw_reg_read((PCE_PCTRL_3_VIO_4_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_4_SHIFT, \ PCE_PCTRL_3_VIO_4_SIZE, &monrx)!= GSW_statusOk) return GSW_statusErr; if (monrx == 1) parm->ePortMonitor |= GSW_PORT_MONITOR_VLAN_MEMBERSHIP; if (gsw_reg_read((PCE_PCTRL_3_VIO_5_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_5_SHIFT, \ PCE_PCTRL_3_VIO_5_SIZE, &monrx)!= GSW_statusOk) return GSW_statusErr; if (monrx == 1) parm->ePortMonitor |= GSW_PORT_MONITOR_PORT_STATE; if (gsw_reg_read((PCE_PCTRL_3_VIO_6_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_6_SHIFT, \ PCE_PCTRL_3_VIO_6_SIZE, &monrx)!= GSW_statusOk) return GSW_statusErr; if (monrx == 1) parm->ePortMonitor |= GSW_PORT_MONITOR_LEARNING_LIMIT; if (gsw_reg_read((PCE_PCTRL_3_VIO_7_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_7_SHIFT, \ PCE_PCTRL_3_VIO_7_SIZE, &monrx)!= GSW_statusOk) return GSW_statusErr; if (monrx == 1) parm->ePortMonitor |= GSW_PORT_MONITOR_PORT_LOCK; if (gsw_reg_read((MAC_PSTAT_TXPAUEN_OFFSET + (0xC * pidx)), \ MAC_PSTAT_TXPAUEN_SHIFT, 2, &value)!= GSW_statusOk) return GSW_statusErr; parm->eFlowCtrl = value; return GSW_statusOk; } GSW_return_t GSW_PortCfgSet(void *cdev, GSW_portCfg_t *parm) { u8 pidx = parm->nPortId; u16 value, EN, PEN, PACT; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; /* Learning Limit Port Lock */ if (gsw_reg_write((PCE_PCTRL_0_PLOCK_OFFSET + (0xA * pidx)), \ PCE_PCTRL_0_PLOCK_SHIFT, \ PCE_PCTRL_0_PLOCK_SIZE, parm->bLearningMAC_PortLock)!= GSW_statusOk) return GSW_statusErr; /* Learning Limit Action */ if (parm->nLearningLimit == 0) value = 0; else if (parm->nLearningLimit == 0xFFFF) value = 0xFF; else value = parm->nLearningLimit; /* Learning Limit */ if (gsw_reg_write((PCE_PCTRL_1_LRNLIM_OFFSET + (0xA * pidx)), \ PCE_PCTRL_1_LRNLIM_SHIFT, \ PCE_PCTRL_1_LRNLIM_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /** MAC address table learning on the port specified */ if (gsw_reg_write((PCE_PCTRL_3_LNDIS_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_LNDIS_SHIFT, \ PCE_PCTRL_3_LNDIS_SIZE, parm->bLearning)!= GSW_statusOk) return GSW_statusErr; /** MAC spoofing detection. */ if (gsw_reg_write((PCE_PCTRL_0_SPFDIS_OFFSET + (0xA * pidx)), \ PCE_PCTRL_0_SPFDIS_SHIFT, \ PCE_PCTRL_0_SPFDIS_SIZE, parm->bMAC_SpoofingDetection)!= GSW_statusOk) return GSW_statusErr; /* Aging */ if (gsw_reg_write( PCE_PCTRL_0_AGEDIS_OFFSET + (0xA * pidx), \ PCE_PCTRL_0_AGEDIS_SHIFT, \ PCE_PCTRL_0_AGEDIS_SIZE, parm->bAging)!= GSW_statusOk) return GSW_statusErr; /* UnicastUnknownDrop Read first */ if (gsw_reg_read(PCE_PMAP_3_UUCMAP_OFFSET, \ PCE_PMAP_3_UUCMAP_SHIFT, \ PCE_PMAP_3_UUCMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; if (parm->bUnicastUnknownDrop == 1) value &= ~(1 << pidx); else value |= 1 << pidx; /* UnicastUnknownDrop write back */ if (gsw_reg_write( PCE_PMAP_3_UUCMAP_OFFSET, \ PCE_PMAP_3_UUCMAP_SHIFT, \ PCE_PMAP_3_UUCMAP_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /* MulticastUnknownDrop */ if (gsw_reg_read(PCE_PMAP_2_DMCPMAP_OFFSET, \ PCE_PMAP_2_DMCPMAP_SHIFT, \ PCE_PMAP_2_DMCPMAP_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; if (parm->bMulticastUnknownDrop == 1) value &= ~(1 << pidx); else value |= 1 << pidx; /* MulticastUnknownDrop */ if (gsw_reg_write( PCE_PMAP_2_DMCPMAP_OFFSET, \ PCE_PMAP_2_DMCPMAP_SHIFT, \ PCE_PMAP_2_DMCPMAP_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /* Flow Control */ if (pidx < MAX_LTQ_PORTS) { if (gsw_reg_read((MDC_CFG_0_PEN_0_OFFSET + GSW_TREG_OFFSET), \ (MDC_CFG_0_PEN_0_SHIFT + pidx), MDC_CFG_0_PEN_0_SIZE, &PEN)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_read((MDIO_STAT_0_PACT_OFFSET + GSW_TREG_OFFSET + pidx), \ MDIO_STAT_0_PACT_SHIFT, MDIO_STAT_0_PACT_SIZE, &PACT)!= GSW_statusOk) return GSW_statusErr; /* PHY polling statemachine (of the MAC) is activated and */ /* an external PHY reacts on the MDIO accesses. */ /* Therefore update the MDIO register of the attached PHY.*/ if ((PEN == 1) && (PACT == 1)) { GSW_MDIO_data_t mddata; /* Write directly to MDIO register */ if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - pidx) + GSW_TREG_OFFSET), \ PHY_ADDR_0_ADDR_SHIFT, PHY_ADDR_0_ADDR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; mddata.nAddressDev = value; mddata.nAddressReg = 0x4; if (GSW_MDIO_DataRead(cdev, &mddata)!= GSW_statusOk) return GSW_statusErr; mddata.nData &= ~(0xC00); switch (parm->eFlowCtrl) { case GSW_FLOW_OFF: break; case GSW_FLOW_TX: mddata.nData |= 0x800; break; case GSW_FLOW_RXTX: mddata.nData |= 0x400; break; case GSW_FLOW_RX: case GSW_FLOW_AUTO: mddata.nData |= 0xC00; break; } if (GSW_MDIO_DataWrite(cdev, &mddata)!= GSW_statusOk) return GSW_statusErr; /* Restart Auto negotiation */ mddata.nAddressReg = 0x0; if (GSW_MDIO_DataRead(cdev, &mddata)!= GSW_statusOk) return GSW_statusErr; mddata.nData |= 0x1200; if (GSW_MDIO_DataWrite(cdev, &mddata)!= GSW_statusOk) return GSW_statusErr; } else { /* Either PHY polling statemachine (of the MAC) is disable, */ /* or the statemachine did not find any attached PHY. */ u16 RX = 0, TX = 0; switch (parm->eFlowCtrl) { case GSW_FLOW_AUTO: case GSW_FLOW_OFF: RX = 0; TX = 0; break; case GSW_FLOW_RXTX: RX = 1; TX = 1; break; case GSW_FLOW_RX: RX = 1; TX = 0; break; case GSW_FLOW_TX: RX = 0; TX = 1; break; } if (gsw_reg_write((MAC_CTRL_0_FCON_OFFSET + (0xC * pidx)), \ MAC_CTRL_0_FCON_SHIFT, MAC_CTRL_0_FCON_SIZE, parm->eFlowCtrl)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PHY_ADDR_0_FCONTX_OFFSET - (0x1 * pidx)), \ PHY_ADDR_0_FCONTX_SHIFT, PHY_ADDR_0_FCONTX_SIZE , TX)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PHY_ADDR_0_FCONRX_OFFSET - (0x1 * pidx)), \ PHY_ADDR_0_FCONRX_SHIFT, PHY_ADDR_0_FCONRX_SIZE, RX)!= GSW_statusOk) return GSW_statusErr; } } switch (parm->ePortMonitor) { case GSW_PORT_MONITOR_NONE: if (gsw_reg_write((PCE_PCTRL_3_RXVMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_RXVMIR_SHIFT, PCE_PCTRL_3_RXVMIR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_TXMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_TXMIR_SHIFT, PCE_PCTRL_3_TXMIR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_VIO_2_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_2_SHIFT, PCE_PCTRL_3_VIO_2_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_VIO_4_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_4_SHIFT, PCE_PCTRL_3_VIO_4_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_VIO_5_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_5_SHIFT, PCE_PCTRL_3_VIO_5_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_VIO_6_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_6_SHIFT, PCE_PCTRL_3_VIO_6_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_VIO_7_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_7_SHIFT, PCE_PCTRL_3_VIO_7_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_RX: if (gsw_reg_write((PCE_PCTRL_3_RXVMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_RXVMIR_SHIFT, PCE_PCTRL_3_RXVMIR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_TXMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_TXMIR_SHIFT, PCE_PCTRL_3_TXMIR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_TX: if (gsw_reg_write((PCE_PCTRL_3_RXVMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_RXVMIR_SHIFT, PCE_PCTRL_3_RXVMIR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_TXMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_TXMIR_SHIFT, PCE_PCTRL_3_TXMIR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_RXTX: if (gsw_reg_write((PCE_PCTRL_3_RXVMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_RXVMIR_SHIFT, PCE_PCTRL_3_RXVMIR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_PCTRL_3_TXMIR_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_TXMIR_SHIFT, PCE_PCTRL_3_TXMIR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_VLAN_UNKNOWN: if (gsw_reg_write((PCE_PCTRL_3_VIO_2_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_2_SHIFT, PCE_PCTRL_3_VIO_2_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_VLAN_MEMBERSHIP: if (gsw_reg_write((PCE_PCTRL_3_VIO_4_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_4_SHIFT, PCE_PCTRL_3_VIO_4_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_PORT_STATE: if (gsw_reg_write((PCE_PCTRL_3_VIO_5_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_5_SHIFT, PCE_PCTRL_3_VIO_5_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_LEARNING_LIMIT: if (gsw_reg_write((PCE_PCTRL_3_VIO_6_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_6_SHIFT, PCE_PCTRL_3_VIO_6_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_PORT_MONITOR_PORT_LOCK: if (gsw_reg_write((PCE_PCTRL_3_VIO_7_OFFSET + (0xA * pidx)), \ PCE_PCTRL_3_VIO_7_SHIFT, PCE_PCTRL_3_VIO_7_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; } if (parm->eEnable == GSW_PORT_ENABLE_RXTX) { PEN = 1; EN = 1; } else if (parm->eEnable == GSW_PORT_ENABLE_RX) { PEN = 1; EN = 0; } else if (parm->eEnable == GSW_PORT_ENABLE_TX) { PEN = 0; EN = 1; } else { PEN = 0; EN = 0; } /* Set SDMA_PCTRL_PEN PORT enable */ if (gsw_reg_write((SDMA_PCTRL_PEN_OFFSET + (6 * pidx)), \ SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, PEN)!= GSW_statusOk) return GSW_statusErr; /* Set FDMA_PCTRL_EN PORT enable */ if (gsw_reg_write((FDMA_PCTRL_EN_OFFSET + (0x6 * pidx)), \ FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, EN)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_CPU_PortCfgGet(void *cdev, GSW_CPU_PortCfg_t *parm) { u8 pidx = parm->nPortId; u16 value; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; if (pidx == LTQ_CPU_PORTS) parm->bCPU_PortValid = 1; else parm->bCPU_PortValid = 0; /* Special Tag Egress*/ if (gsw_reg_read ((FDMA_PCTRL_STEN_OFFSET + (0x6 * pidx)), FDMA_PCTRL_STEN_SHIFT, FDMA_PCTRL_STEN_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bSpecialTagEgress = value; /* Special Tag Igress*/ if (gsw_reg_read((PCE_PCTRL_0_IGSTEN_OFFSET + (0xa * pidx)), PCE_PCTRL_0_IGSTEN_SHIFT, PCE_PCTRL_0_IGSTEN_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bSpecialTagIngress = value; /* FCS Check */ if (gsw_reg_read((SDMA_PCTRL_FCSIGN_OFFSET + (0x6 * pidx)), SDMA_PCTRL_FCSIGN_SHIFT,SDMA_PCTRL_FCSIGN_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bFcsCheck = value; /* FCS Generate */ if (gsw_reg_read((MAC_CTRL_0_FCS_OFFSET + (0xC * pidx)), MAC_CTRL_0_FCS_SHIFT, MAC_CTRL_0_FCS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bFcsGenerate = value; if (gsw_reg_read((FDMA_PCTRL_ST_TYPE_OFFSET + (0x6 * pidx)), FDMA_PCTRL_ST_TYPE_SHIFT, FDMA_PCTRL_ST_TYPE_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bSpecialTagEthType = value; return GSW_statusOk; } GSW_return_t GSW_CPU_PortCfgSet(void *cdev, GSW_CPU_PortCfg_t *parm) { u8 pidx = parm->nPortId; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; if (pidx == LTQ_CPU_PORTS) parm->bCPU_PortValid = 1; else parm->bCPU_PortValid = 0; /* Special Tag Egress*/ if (gsw_reg_write((FDMA_PCTRL_STEN_OFFSET + (0x6 * pidx)), FDMA_PCTRL_STEN_SHIFT, FDMA_PCTRL_STEN_SIZE, parm->bSpecialTagEgress)!= GSW_statusOk) return GSW_statusErr; /* Special Tag Igress*/ if (gsw_reg_write((PCE_PCTRL_0_IGSTEN_OFFSET + (0xa * pidx)), PCE_PCTRL_0_IGSTEN_SHIFT,PCE_PCTRL_0_IGSTEN_SIZE, parm->bSpecialTagIngress)!= GSW_statusOk) return GSW_statusErr; /* FCS Check */ if (gsw_reg_write((SDMA_PCTRL_FCSIGN_OFFSET + (0x6 * pidx)), SDMA_PCTRL_FCSIGN_SHIFT,SDMA_PCTRL_FCSIGN_SIZE, parm->bFcsCheck)!= GSW_statusOk) return GSW_statusErr; if (parm->bSpecialTagEthType == GSW_CPU_ETHTYPE_FLOWID) { if (gsw_reg_write((FDMA_PCTRL_ST_TYPE_OFFSET + (0x6 * pidx)), FDMA_PCTRL_ST_TYPE_SHIFT, FDMA_PCTRL_ST_TYPE_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; } else { if (gsw_reg_write((FDMA_PCTRL_ST_TYPE_OFFSET + (0x6 * pidx)), FDMA_PCTRL_ST_TYPE_SHIFT, FDMA_PCTRL_ST_TYPE_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; } return GSW_statusOk; } GSW_return_t GSW_RMON_Clear(void *cdev, GSW_RMON_clear_t *parm) { u8 index, pidx = parm->nRmonId; switch (parm->eRmonType) { case GSW_RMON_ALL_TYPE: /* Software Reset for All Interface RMON RAM */ if (gsw_reg_write(BM_RMON_GCTRL_ALLITF_RES_OFFSET, BM_RMON_GCTRL_ALLITF_RES_SHIFT, BM_RMON_GCTRL_ALLITF_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Software Reset for PMAC RMON RAM*/ if (gsw_reg_write(BM_RMON_GCTRL_PMAC_RES_OFFSET, BM_RMON_GCTRL_PMAC_RES_SHIFT, BM_RMON_GCTRL_PMAC_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Software Reset for Meter RMON RAM */ if (gsw_reg_write(BM_RMON_GCTRL_METER_RES_OFFSET, BM_RMON_GCTRL_METER_RES_SHIFT, BM_RMON_GCTRL_METER_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Software Reset for Redirection RMON RAM */ if (gsw_reg_write(BM_RMON_GCTRL_RED_RES_OFFSET, BM_RMON_GCTRL_RED_RES_SHIFT, BM_RMON_GCTRL_RED_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Reset all port based RMON counter */ for (index = 0; index < MAX_LTQ_PORTS; index++) { if (gsw_reg_write(BM_RMON_CTRL_RAM1_RES_OFFSET + (index * 2), BM_RMON_CTRL_RAM1_RES_SHIFT, BM_RMON_CTRL_RAM1_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RMON_CTRL_RAM2_RES_OFFSET + (index * 2), BM_RMON_CTRL_RAM2_RES_SHIFT, BM_RMON_CTRL_RAM2_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Software Reset for Routing RMON RAM */ if (gsw_reg_write(BM_RMON_CTRL_ROUT_RES_OFFSET + (index * 2), BM_RMON_CTRL_ROUT_RES_SHIFT, BM_RMON_CTRL_ROUT_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; } break; case GSW_RMON_PORT_TYPE: if (pidx >= MAX_LTQ_PORTS) return GSW_statusErr; /* Reset all RMON counter */ if (gsw_reg_write(BM_RMON_CTRL_RAM1_RES_OFFSET + (pidx * 2), BM_RMON_CTRL_RAM1_RES_SHIFT, BM_RMON_CTRL_RAM1_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RMON_CTRL_RAM2_RES_OFFSET + (pidx * 2), BM_RMON_CTRL_RAM2_RES_SHIFT, BM_RMON_CTRL_RAM2_RES_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; break; default: break; } return GSW_statusOk; } GSW_return_t GSW_RMON_Port_Get(void *cdev, GSW_RMON_Port_cnt_t *parm) { u16 pidx, i, rvalue, rvalue1, bcast_cnt; u32 data = 0; u32 r_frame = 0, r_unicast = 0, r_multicast = 0, t_frame = 0, t_unicast = 0, t_multicast = 0; u32 rgbcl = 0, rbbcl = 0, tgbcl = 0; unsigned long long int rgbch = 0, rbbch = 0, tgbch = 0; pidx = parm->nPortId; if (gsw_reg_write(BM_PCFG_CNTEN_OFFSET + (pidx * 2), BM_PCFG_CNTEN_SHIFT, BM_PCFG_CNTEN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; memset(parm, 0, sizeof(GSW_RMON_Port_cnt_t)); parm->nPortId = pidx; if (gsw_reg_read(BM_RMON_CTRL_BCAST_CNT_OFFSET + (pidx * 2), BM_RMON_CTRL_BCAST_CNT_SHIFT, BM_RMON_CTRL_BCAST_CNT_SIZE, &bcast_cnt)!= GSW_statusOk) return GSW_statusErr; for (i = 0; i < RMON_COUNTER_OFFSET; i++) { if (gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, i)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, pidx)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; rvalue = 1; if (gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, rvalue)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &rvalue)!= GSW_statusOk) return GSW_statusErr; } while (rvalue); if (gsw_reg_read(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, &rvalue)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_read(BM_RAM_VAL_1_VAL1_OFFSET, BM_RAM_VAL_1_VAL1_SHIFT, BM_RAM_VAL_1_VAL1_SIZE, &rvalue1)!= GSW_statusOk) return GSW_statusErr; data = (rvalue1 << 16 | rvalue); switch (i) { case 0x1F: /* Receive Frme Count */ if (bcast_cnt == 1) parm->nRxBroadcastPkts = data; else parm->nRxGoodPkts = data; r_frame = data; break; case 0x23: /* Receive Unicast Frame Count */ parm->nRxUnicastPkts = data; r_unicast = data; break; case 0x22: /* Receive Multicast Frame Count1 */ parm->nRxMulticastPkts = data; r_multicast = data; break; case 0x21: /* Receive CRC Errors Count */ parm->nRxFCSErrorPkts = data; break; #if defined(RMON_DEBUG) && RMON_DEBUG case 0x1D: /* Receive Undersize Good Count */ parm->nRxUnderSizeGoodPkts = data; break; case 0x1B: /* Receive Oversize Good Count */ parm->nRxOversizeGoodPkts = data; break; case 0x1E: /* Receive Undersize Bad Count */ parm->nRxUnderSizeErrorPkts = data; break; case 0x20: /* Receive Pause Good Count */ parm->nRxGoodPausePkts = data; break; case 0x1C: /* Receive Oversize Bad Count */ parm->nRxOversizeErrorPkts = data; break; #endif case 0x1A: /* Receive Alignment Errors Count */ parm->nRxAlignErrorPkts = data; break; #if defined(RMON_DEBUG) && RMON_DEBUG case 0x12: /* Receive Size 64 Frame Count1 */ parm->nRx64BytePkts = data; break; case 0x13: /* Receive Size 65-127 Frame Count */ parm->nRx127BytePkts = data; break; case 0x14: /* Receive Size 128-255 Frame Count */ parm->nRx255BytePkts = data; break; case 0x15: /* Receive Size 256-511 Frame Count */ parm->nRx511BytePkts = data; break; case 0x16: /* Receive Size 512-1023 Frame Count */ parm->nRx1023BytePkts = data; break; case 0x17: /* Receive Size Greater 1023 Frame Count */ parm->nRxMaxBytePkts = data; break; case 0x18: /* Receive Discard (Tail-Drop) Frame Count */ parm->nRxDroppedPkts = data; break; #endif case 0x19: /* Receive Drop (Filter) Frame Count */ parm->nRxFilteredPkts = data; break; case 0x24: /* Receive Good Byte Count (Low) */ rgbcl = data; break; case 0x25: /* Receive Good Byte Count (High) */ rgbch = data; break; #if defined(RMON_DEBUG) && RMON_DEBUG case 0x26: /* Receive Bad Byte Count (Low) */ rbbcl = data; break; case 0x27: /* Receive Bad Byte Count (High) */ rbbch = data; break; #endif case 0x0C: /* Transmit Frame Count */ if (bcast_cnt == 1) parm->nTxBroadcastPkts = data; else parm->nTxGoodPkts = data; t_frame = data; break; case 0x06: /* Transmit Unicast Frame Count */ parm->nTxUnicastPkts = data; t_unicast = data; break; case 0x07: /* Transmit Multicast Frame Count1 */ parm->nTxMulticastPkts = data; t_multicast = data; break; #if defined(RMON_DEBUG) && RMON_DEBUG case 0x00: /* Transmit Size 64 Frame Count */ parm->nTx64BytePkts = data; break; case 0x01: /* Transmit Size 65-127 Frame Count */ parm->nTx127BytePkts = data; break; case 0x02: /* Transmit Size 128-255 Frame Count */ parm->nTx255BytePkts = data; break; case 0x03: /* Transmit Size 256-511 Frame Count */ parm->nTx511BytePkts = data; break; case 0x04: /* Transmit Size 512-1023 Frame Count */ parm->nTx1023BytePkts = data; break; case 0x05: /* Transmit Size Greater 1024 Frame Count */ parm->nTxMaxBytePkts = data; break; case 0x08: /* Transmit Single Collision Count. */ parm->nTxSingleCollCount = data; break; case 0x09: /* Transmit Multiple Collision Count */ parm->nTxMultCollCount = data; break; case 0x0A: /* Transmit Late Collision Count */ parm->nTxLateCollCount = data; break; case 0x0B: /* Transmit Excessive Collision.*/ parm->nTxExcessCollCount = data; break; case 0x0D: /* Transmit Pause Frame Count */ parm->nTxPauseCount = data; break; case 0x10: /* Transmit Drop Frame Count */ parm->nTxDroppedPkts = data; break; case 0x11: /* Transmit Dropped Packet Cound, based on Congestion Management.*/ parm->nTxAcmDroppedPkts = data; break; #endif case 0x0E: /* Transmit Good Byte Count (Low) */ tgbcl = data; break; case 0x0F: /* Transmit Good Byte Count (High) */ tgbch = data; break; } } if (bcast_cnt == 1) { parm->nRxGoodPkts = r_frame + r_unicast + r_multicast; parm->nTxGoodPkts = t_frame + t_unicast + t_multicast; } else { /* Receive Broadcase Frme Count */ parm->nRxBroadcastPkts = r_frame - r_unicast - r_multicast; /* Transmit Broadcase Frme Count */ parm->nTxBroadcastPkts = t_frame - t_unicast - t_multicast; } /* Receive Good Byte Count */ parm->nRxGoodBytes = (rgbch << 32) | rgbcl; /* Receive Bad Byte Count */ parm->nRxBadBytes = (rbbch << 32) | rbbcl; /* Transmit Good Byte Count */ parm->nTxGoodBytes = (tgbch << 32) | tgbcl; return GSW_statusOk; } GSW_return_t GSW_VLAN_IdCreate(void *cdev, GSW_VLAN_IdCreate_t *parm) { pctbl_prog_t pcetable; memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = parm->nVId; pcetable.table = PCE_VLANMAP_INDEX; pcetable.val[0] = (parm->nFId & 0x3F); if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; /* debug */ ESHAL_LogDbg("\n*** %s:%d, 4K VLAN, pcindex %u, fid %u ***\n", __func__, __LINE__, (u32)pcetable.pcindex, (u32)pcetable.val[0]); return GSW_statusOk; } GSW_return_t GSW_VLAN_IdDelete(void *cdev, GSW_VLAN_IdDelete_t *parm) { pctbl_prog_t pcetable; memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = parm->nVId; pcetable.table = PCE_VLANMAP_INDEX; if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; /* debug */ ESHAL_LogDbg("\n*** %s:%d, 4K VLAN, pcindex %u, fid %u ***\n", __func__, __LINE__, (u32)pcetable.pcindex, (u32)pcetable.val[0]); return GSW_statusOk; } GSW_return_t GSW_VLAN_IdGet(void *cdev, GSW_VLAN_IdGet_t *parm) { pctbl_prog_t pcetable; memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = parm->nVId; pcetable.table = PCE_VLANMAP_INDEX; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; parm->nFId = pcetable.val[0] & 0x3F; return GSW_statusOk; } GSW_return_t GSW_VLAN_PortCfgGet(void *cdev, GSW_VLAN_portCfg_t *parm) { u16 value; ltq_bool_t uvr, vimr, vemr; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; if (gsw_reg_read((PCE_DEFPVID_PVID_OFFSET + (10 * parm->nPortId)), PCE_DEFPVID_PVID_SHIFT, PCE_DEFPVID_PVID_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nPortVId = value; if (gsw_reg_read((PCE_VCTRL_UVR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_UVR_SHIFT, PCE_VCTRL_UVR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; uvr = value; if (uvr == 1) parm->bVLAN_UnknownDrop = 1; else parm->bVLAN_UnknownDrop = 0; if (gsw_reg_read((PCE_VCTRL_VSR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VSR_SHIFT, PCE_VCTRL_VSR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bVLAN_ReAssign = value; if (gsw_reg_read((PCE_VCTRL_VIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; vimr = value; if (gsw_reg_read((PCE_VCTRL_VEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; vemr = value; if (vimr == 0 && vemr == 0) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_NO; else if (vimr == 1 && vemr == 0) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_INGRESS; else if (vimr == 0 && vemr == 1) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_EGRESS; else if (vimr == 1 && vemr == 1) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_BOTH; if (gsw_reg_read((PCE_VCTRL_VINR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VINR_SHIFT, PCE_VCTRL_VINR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; switch (value) { case 0: parm->eAdmitMode = GSW_VLAN_ADMIT_ALL; break; case 1: parm->eAdmitMode = GSW_VLAN_ADMIT_TAGGED; break; case 2: parm->eAdmitMode = GSW_VLAN_ADMIT_UNTAGGED; break; default: break; } if (gsw_reg_read((PCE_PCTRL_0_TVM_OFFSET + (10 * parm->nPortId)), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bTVM = value; return GSW_statusOk; } GSW_return_t GSW_VLAN_PortCfgSet(void *cdev, GSW_VLAN_portCfg_t *parm) { u16 value; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; value = parm->nPortVId; if (gsw_reg_write((PCE_DEFPVID_PVID_OFFSET + (10 * parm->nPortId)), PCE_DEFPVID_PVID_SHIFT, PCE_DEFPVID_PVID_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = 0; if (parm->bVLAN_UnknownDrop == 1) value = 1; if (gsw_reg_write((PCE_VCTRL_UVR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_UVR_SHIFT, PCE_VCTRL_UVR_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = parm->bVLAN_ReAssign; if (gsw_reg_write((PCE_VCTRL_VSR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VSR_SHIFT, PCE_VCTRL_VSR_SIZE, value)!= GSW_statusOk) return GSW_statusErr; switch (parm->eVLAN_MemberViolation) { case GSW_VLAN_MEMBER_VIOLATION_NO: if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_VLAN_MEMBER_VIOLATION_INGRESS: if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_VLAN_MEMBER_VIOLATION_EGRESS: if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_VLAN_MEMBER_VIOLATION_BOTH: if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; default: ESHAL_LogErr("WARNING:(eVLAN_MemberViolation) %s:%s:%d\n", __FILE__, __func__, __LINE__); } switch (parm->eAdmitMode) { case GSW_VLAN_ADMIT_ALL: value = 0; break; case GSW_VLAN_ADMIT_TAGGED: value = 1; break; case GSW_VLAN_ADMIT_UNTAGGED: value = 2; break; default: value = 0; ESHAL_LogErr("%s:%s:%d (eAdmitMode)\n", __FILE__, __func__, __LINE__); } if (gsw_reg_write((PCE_VCTRL_VINR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_VINR_SHIFT, PCE_VCTRL_VINR_SIZE, value)!= GSW_statusOk) return GSW_statusErr; value = 0; if (parm->bTVM == 1) value = 1; if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * parm->nPortId)), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, value)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_VLAN_PortMemberAdd(void *cdev, GSW_VLAN_portMemberAdd_t *parm) { pctbl_prog_t pcetable; u16 portmap, tagmap, val0; if ((parm->nPortId >= MAX_LTQ_PORTS)) return GSW_statusErr; if (parm->nVId > MAX_VLAN_TABLE) { ESHAL_LogErr("ERROR: %s:%s:%d, (VID:%d)\n", __FILE__, __func__, __LINE__, parm->nVId); return GSW_statusErr; } memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; portmap = (pcetable.val[1]); tagmap = (pcetable.val[2]); val0 = (pcetable.val[0]); /* Support portmap information. */ /* To differentiate between port index and portmap, */ /* the MSB (highest data bit) should be 1.*/ if (parm->nPortId & 0x80000000) { /*Port Map */ portmap |= ((parm->nPortId) & 0xFFFF); if (parm->bVLAN_TagEgress) tagmap |= ((parm->nPortId) & 0xFFFF); else tagmap &= ~((parm->nPortId) & 0xFFFF); } else { portmap |= 1 << parm->nPortId; if (parm->bVLAN_TagEgress) tagmap |= 1 << parm->nPortId; else tagmap &= ~(1 << parm->nPortId); } pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; pcetable.val[0] = val0; pcetable.val[1] = portmap; pcetable.val[2] = tagmap; if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; /* debug */ ESHAL_LogDbg("\n*** %s:%d, 4K VLAN, pcindex %u, port %u, map 0x%04X/0x%04X ***\n", __func__, __LINE__, (u32)pcetable.pcindex, (u32)parm->nPortId, (u32)pcetable.val[1], (u32)pcetable.val[2]); return GSW_statusOk; } GSW_return_t GSW_VLAN_PortMemberReadVlan(void *cdev, GSW_VLAN_portMemberRead_t *parm) { pctbl_prog_t pcetable; if ((parm->nPortId >= MAX_LTQ_PORTS)) return GSW_statusErr; if (parm->nVId > MAX_VLAN_TABLE) { ESHAL_LogErr("ERROR: %s:%s:%d, (VID:%d)\n", __FILE__, __func__, __LINE__, parm->nVId); return GSW_statusErr; } memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; parm->nPortId = (pcetable.val[1]); parm->nTagId = (pcetable.val[2]); return GSW_statusOk; } GSW_return_t GSW_VLAN_PortMemberRead(void *cdev, GSW_VLAN_portMemberRead_t *parm) { pctbl_prog_t pcetable; if (parm->bInitial == 1) { /*Start from the index 0 */ GSW_IMPL_CurrentDevPriv->vlan_rd_index = 0; pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = GSW_IMPL_CurrentDevPriv->vlan_rd_index; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; parm->nVId = GSW_IMPL_CurrentDevPriv->vlan_rd_index; /* Port Map */ parm->nPortId = (pcetable.val[1] | 0x80000000); parm->nTagId = (pcetable.val[2] | 0x80000000); parm->bInitial = 0; parm->bLast = 0; } if (parm->bLast != 1) { if (GSW_IMPL_CurrentDevPriv->vlan_rd_index < MAX_VLAN_TABLE) { GSW_IMPL_CurrentDevPriv->vlan_rd_index++; pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = GSW_IMPL_CurrentDevPriv->vlan_rd_index; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; parm->nVId = GSW_IMPL_CurrentDevPriv->vlan_rd_index; /* Port Map */ parm->nPortId = (pcetable.val[1] | 0x80000000); parm->nTagId = (pcetable.val[2] | 0x80000000); } else { parm->bLast = 1; GSW_IMPL_CurrentDevPriv->vlan_rd_index = 0; } } return GSW_statusOk; } GSW_return_t GSW_VLAN_PortMemberRemove(void *cdev, GSW_VLAN_portMemberRemove_t *parm) { pctbl_prog_t pcetable; u16 portmap, tagmap , val0; if ((parm->nPortId >= MAX_LTQ_PORTS)) return GSW_statusErr; if (parm->nVId > MAX_VLAN_TABLE) { ESHAL_LogErr("ERROR: %s:%s:%d, (VID:%d)\n", __FILE__, __func__, __LINE__, parm->nVId); return GSW_statusErr; } memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; portmap = (pcetable.val[1]); tagmap = (pcetable.val[2]); val0 = (pcetable.val[0]); if (parm->nPortId & 0x80000000) { portmap &= ~((parm->nPortId) & 0x7FFF); tagmap &= ~((parm->nPortId) & 0x7FFF); } else { portmap &= ~(1 << parm->nPortId); tagmap &= ~(1 << parm->nPortId); } pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; pcetable.val[0] = val0; pcetable.val[1] = portmap; pcetable.val[2] = tagmap; if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; /* debug */ ESHAL_LogDbg("\n*** %s:%d, 4K VLAN, pcindex %u, port %u, map 0x%04X/0x%04X ***\n", __func__, __LINE__, (u32)pcetable.pcindex, (u32)parm->nPortId, (u32)pcetable.val[1], (u32)pcetable.val[2]); return GSW_statusOk; } GSW_return_t GSW_VLAN_ReservedAdd(void *cdev, GSW_VLAN_reserved_t *parm) { pctbl_prog_t pcetable; if (parm->nVId > MAX_VLAN_TABLE) { ESHAL_LogErr("ERROR: %s:%s:%d,(VID:%d)\n", __FILE__, __func__, __LINE__, parm->nVId); return GSW_statusErr; } memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; pcetable.val[0] |= (1 << 8); if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_VLAN_ReservedRemove(void *cdev, GSW_VLAN_reserved_t *parm) { pctbl_prog_t pcetable; if (parm->nVId > MAX_VLAN_TABLE) { ESHAL_LogErr("ERROR: %s:%s:%d,(VID:%d)\n", __FILE__, __func__, __LINE__, parm->nVId); return GSW_statusErr; } memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_VLANMAP_INDEX; pcetable.pcindex = parm->nVId; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; pcetable.val[0] &= ~(1 << 8); if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_SVLAN_CfgGet(void *cdev, GSW_SVLAN_cfg_t *parm) { u16 reg_val; if (gsw_reg_read((FDMA_SVTETYPE_OFFSET), FDMA_SVTETYPE_ETYPE_SHIFT, FDMA_SVTETYPE_ETYPE_SIZE, ®_val)!= GSW_statusOk) return GSW_statusErr; parm->nEthertype = reg_val; return GSW_statusOk; } GSW_return_t GSW_SVLAN_CfgSet(void *cdev, GSW_SVLAN_cfg_t *parm) { u16 reg_val; reg_val = parm->nEthertype & 0xFFFF; if (gsw_reg_write((FDMA_SVTETYPE_OFFSET), FDMA_SVTETYPE_ETYPE_SHIFT, FDMA_SVTETYPE_ETYPE_SIZE, reg_val)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((MAC_VLAN_ETYPE_1_INNER_OFFSET), MAC_VLAN_ETYPE_1_INNER_SHIFT, MAC_VLAN_ETYPE_1_INNER_SIZE, reg_val)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_SVLAN_PortCfgGet(void *cdev, GSW_SVLAN_portCfg_t *parm) { u16 value; ltq_bool_t svimr, svemr; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; /** nPortVId: retrieve the corresponding VLAN ID */ /* from the Active VLAN Table*/ if (gsw_reg_read((PCE_DEFPSVID_PVID_OFFSET + (2 * parm->nPortId)), PCE_DEFPSVID_PVID_SHIFT, PCE_DEFPSVID_PVID_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nPortVId = value; /* bSVLAN_TagSupport */ if (gsw_reg_read((PCE_VCTRL_STEN_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_STEN_SHIFT, PCE_VCTRL_STEN_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bSVLAN_TagSupport = value; /** bVLAN_ReAssign */ if (gsw_reg_read((PCE_VCTRL_SVSR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVSR_SHIFT, PCE_VCTRL_SVSR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bVLAN_ReAssign = value; /** bVlanMemberViolationIngress */ if (gsw_reg_read((PCE_VCTRL_SVIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; svimr = value; /** bVlanMemberViolationEgress */ if (gsw_reg_read((PCE_VCTRL_SVEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; svemr = value; if (svimr == 0 && svemr == 0) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_NO; if (svimr == 1 && svemr == 0) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_INGRESS; if (svimr == 0 && svemr == 1) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_EGRESS; if (svimr == 1 && svemr == 1) parm->eVLAN_MemberViolation = GSW_VLAN_MEMBER_VIOLATION_BOTH; /* eAdmitMode: */ if (gsw_reg_read((PCE_VCTRL_SVINR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVINR_SHIFT, PCE_VCTRL_SVINR_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; switch (value) { case 0: parm->eAdmitMode = GSW_VLAN_ADMIT_ALL; break; case 1: parm->eAdmitMode = GSW_VLAN_ADMIT_TAGGED; break; case 2: parm->eAdmitMode = GSW_VLAN_ADMIT_UNTAGGED; break; default: break; } /* ----- end switch ----- */ /** bSVLAN_MACbasedTag */ if (gsw_reg_read((PCE_VCTRL_MACEN_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_MACEN_SHIFT, PCE_VCTRL_MACEN_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->bSVLAN_MACbasedTag = value; return GSW_statusOk; } GSW_return_t GSW_SVLAN_PortCfgSet(void *cdev, GSW_SVLAN_portCfg_t *parm) { u16 value; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; value = parm->nPortVId; if (gsw_reg_write((PCE_DEFPSVID_PVID_OFFSET + (2 * parm->nPortId)), PCE_DEFPSVID_PVID_SHIFT, PCE_DEFPSVID_PVID_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /* bSVLAN_TagSupport */ value = parm->bSVLAN_TagSupport; if (gsw_reg_write((PCE_VCTRL_STEN_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_STEN_SHIFT, PCE_VCTRL_STEN_SIZE, value)!= GSW_statusOk) return GSW_statusErr; if (parm->bSVLAN_TagSupport == 1) { if (gsw_reg_write((FDMA_PCTRL_SVLANMOD_OFFSET + (6 * parm->nPortId)), FDMA_PCTRL_SVLANMOD_SHIFT, FDMA_PCTRL_SVLANMOD_SIZE, 3)!= GSW_statusOk) return GSW_statusErr; } else { if (gsw_reg_write((FDMA_PCTRL_SVLANMOD_OFFSET + (6 * parm->nPortId)), FDMA_PCTRL_SVLANMOD_SHIFT, FDMA_PCTRL_SVLANMOD_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; } /** bVLAN_ReAssign */ value = parm->bVLAN_ReAssign; if (gsw_reg_write((PCE_VCTRL_SVSR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVSR_SHIFT, PCE_VCTRL_SVSR_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /** eVLAN_MemberViolation */ switch (parm->eVLAN_MemberViolation) { case GSW_VLAN_MEMBER_VIOLATION_NO: if (gsw_reg_write((PCE_VCTRL_SVIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_SVEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_VLAN_MEMBER_VIOLATION_INGRESS: if (gsw_reg_write((PCE_VCTRL_SVIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_SVEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_VLAN_MEMBER_VIOLATION_EGRESS: if (gsw_reg_write((PCE_VCTRL_SVIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_SVEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; case GSW_VLAN_MEMBER_VIOLATION_BOTH: if (gsw_reg_write((PCE_VCTRL_SVIMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((PCE_VCTRL_SVEMR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; break; } /* ----- end switch ----- */ /** eAdmitMode */ switch (parm->eAdmitMode) { case GSW_VLAN_ADMIT_ALL: value = 0; break; case GSW_VLAN_ADMIT_TAGGED: value = 1; break; case GSW_VLAN_ADMIT_UNTAGGED: value = 2; break; default: value = 0; } /* ----- end switch ----- */ if (gsw_reg_write((PCE_VCTRL_SVINR_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_SVINR_SHIFT, PCE_VCTRL_SVINR_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /** bSVLAN_MACbasedTag */ value = parm->bSVLAN_MACbasedTag; if (gsw_reg_write((PCE_VCTRL_MACEN_OFFSET + (10 * parm->nPortId)), PCE_VCTRL_MACEN_SHIFT, PCE_VCTRL_MACEN_SIZE, value)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_QoS_SVLAN_ClassPCP_PortGet(void *cdev, GSW_QoS_SVLAN_ClassPCP_PortCfg_t *parm) { pctbl_prog_t pcetable; u16 value, dei; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; for (value = 0; value < 16; value++) { memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = (((parm->nPortId & 0xF) << 4) | (value)); pcetable.table = PCE_EGREMARK_INDEX; if (gsw_pce_table_read(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; parm->nDSCP[value] = (pcetable.val[0] & 0x3F); parm->nCPCP[value] = ((pcetable.val[0] >> 8) & 0x7); parm->nSPCP[value] = ((pcetable.val[1] >> 8) & 0x7); dei = ((pcetable.val[1]) & 0x1); parm->nSPCP[value] |= (dei << 7); } return GSW_statusOk; } GSW_return_t GSW_QoS_SVLAN_ClassPCP_PortSet(void *cdev, GSW_QoS_SVLAN_ClassPCP_PortCfg_t *parm) { pctbl_prog_t pcetable; u16 value; u8 cpcp, dscp, spcp, dei; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; for (value = 0; value < 16; value++) { memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = (((parm->nPortId & 0xF) << 4) | (value)); dscp = parm->nDSCP[value] & 0x3F; spcp = parm->nSPCP[value] & 0x7; cpcp = parm->nCPCP[value] & 0x7; dei = ((parm->nSPCP[value] >> 7) & 1); pcetable.val[1] = ((spcp << 8) | dei); pcetable.val[0] = (dscp | (cpcp << 8)); pcetable.table = PCE_EGREMARK_INDEX; if (gsw_pce_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; } return GSW_statusOk; } GSW_return_t GSW_QoS_SVLAN_PCP_ClassGet(void *cdev, GSW_QoS_SVLAN_PCP_ClassCfg_t *parm) { pctbl_prog_t ptbl; u16 value; memset(&ptbl, 0, sizeof(pctbl_prog_t)); for (value = 0; value < 16; value++) { ptbl.table = PCE_SPCP_INDEX; ptbl.pcindex = value; if (gsw_mem_table_read(cdev, &ptbl)!= GSW_statusOk) return GSW_statusErr; parm->nTrafficClass[value] = ptbl.val[0] & 0xF; parm->nTrafficColor[value] = ((ptbl.val[0] >> 6) & 0x3); parm->nPCP_Remark_Enable[value] = ((ptbl.val[0] >> 4) & 0x1); parm->nDEI_Remark_Enable[value] = ((ptbl.val[0] >> 5) & 0x1); } return GSW_statusOk; } GSW_return_t GSW_QoS_SVLAN_PCP_ClassSet(void *cdev, GSW_QoS_SVLAN_PCP_ClassCfg_t *parm) { pctbl_prog_t pcetable; u16 value; for (value = 0; value < 16; value++) { memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_SPCP_INDEX; pcetable.pcindex = value; pcetable.val[0] = parm->nTrafficClass[value] & 0xF; pcetable.val[0] |= (parm->nTrafficColor[value] & 0x3) << 6; pcetable.val[0] |= (parm->nPCP_Remark_Enable[value] & 0x1) << 4; pcetable.val[0] |= (parm->nDEI_Remark_Enable[value] & 0x1) << 5; if (gsw_mem_table_write(cdev, &pcetable)!= GSW_statusOk) return GSW_statusErr; } return GSW_statusOk; } GSW_return_t GSW_QoS_WredQueueCfgGet(void *cdev, GSW_QoS_WRED_QueueCfg_t *parm) { u16 qid = parm->nQueueId, addr, data0, data1; u8 crcode; u16 value; /* gsw_r32(cdev, ETHSW_CAP_1_QUEUE_OFFSET, */ /* ETHSW_CAP_1_QUEUE_SHIFT, */ /* ETHSW_CAP_1_QUEUE_SIZE, &value); */ if (qid >= 32) return GSW_statusErr; /* For different color 0(not drop) 1(Green) 2(Yellow) 3(Red) */ for (crcode = 1; crcode < 4; crcode++) { addr = ((qid << 3) | crcode); gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, addr); gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0x9); /* Table Access Operation Mode Write */ gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0x0); value = 1; gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, value); do { gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value); } while (value); gsw_reg_read(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, &data0); gsw_reg_read(BM_RAM_VAL_1_VAL1_OFFSET, BM_RAM_VAL_1_VAL1_SHIFT, BM_RAM_VAL_1_VAL1_SIZE, &data1); switch (crcode) { case 3: parm->nRed_Max = data1; parm->nRed_Min = data0; break; case 2: parm->nYellow_Max = data1; parm->nYellow_Min = data0; break; case 1: parm->nGreen_Max = data1; parm->nGreen_Min = data0; break; case 0: break; } } return GSW_statusOk; } GSW_return_t GSW_QoS_WredQueueCfgSet(void *cdev, GSW_QoS_WRED_QueueCfg_t *parm) { u16 qid = parm->nQueueId, value, addr, data0 = 0, data1 = 0; u8 crcode; if (gsw_reg_read(ETHSW_CAP_1_QUEUE_OFFSET, ETHSW_CAP_1_QUEUE_SHIFT, ETHSW_CAP_1_QUEUE_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; if (qid >= value) return GSW_statusErr; /* For different color 0(not drop) 1(Green) 2(Yellow) 3(Red) */ for (crcode = 1; crcode < 4; crcode++) { addr = (((qid << 3) & 0xF8) | crcode); if (gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, addr)!= GSW_statusOk) return GSW_statusErr; /* Specify the PQMCTXT = 0x9 */ if (gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0x9)!= GSW_statusOk) return GSW_statusErr; /* Table Access Operation Mode Write */ if (gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; switch (crcode) { case 3: data1 = parm->nRed_Max; data0 = parm->nRed_Min; break; case 2: data1 = parm->nYellow_Max; data0 = parm->nYellow_Min; break; case 1: data1 = parm->nGreen_Max; data0 = parm->nGreen_Min; break; case 0: data0 = 0; data1 = 0; break; } if (gsw_reg_write(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, data0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RAM_VAL_1_VAL1_OFFSET, BM_RAM_VAL_1_VAL1_SHIFT, BM_RAM_VAL_1_VAL1_SIZE, data1)!= GSW_statusOk) return GSW_statusErr; value = 1; if (gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, value)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value); } return GSW_statusOk; } GSW_return_t GSW_QoS_WredCfgSet(void *cdev, GSW_QoS_WRED_Cfg_t *parm) { if (gsw_reg_write(BM_QUEUE_GCTRL_DPROB_OFFSET, BM_QUEUE_GCTRL_DPROB_SHIFT, BM_QUEUE_GCTRL_DPROB_SIZE, parm->eProfile)!= GSW_statusOk) return GSW_statusErr; switch (parm->eThreshMode) { case GSW_QOS_WRED_Local_Thresh: if (gsw_reg_write(BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, 0x0)!= GSW_statusOk) return GSW_statusErr; break; case GSW_QOS_WRED_Global_Thresh: if (gsw_reg_write(BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; break; default: if (gsw_reg_write(BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, 0x0)!= GSW_statusOk) return GSW_statusErr; } if (gsw_reg_write(BM_WRED_RTH_0_MINTH_OFFSET, BM_WRED_RTH_0_MINTH_SHIFT, BM_WRED_RTH_0_MINTH_SIZE, parm->nRed_Min)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_WRED_RTH_1_MAXTH_OFFSET, BM_WRED_RTH_1_MAXTH_SHIFT, BM_WRED_RTH_1_MAXTH_SIZE, parm->nRed_Max)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_WRED_YTH_0_MINTH_OFFSET, BM_WRED_YTH_0_MINTH_SHIFT, BM_WRED_YTH_0_MINTH_SIZE, parm->nYellow_Min)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_WRED_YTH_1_MAXTH_OFFSET, BM_WRED_YTH_1_MAXTH_SHIFT, BM_WRED_YTH_1_MAXTH_SIZE, parm->nYellow_Max)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_WRED_GTH_0_MINTH_OFFSET, BM_WRED_GTH_0_MINTH_SHIFT, BM_WRED_GTH_0_MINTH_SIZE, parm->nGreen_Min)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_WRED_GTH_1_MAXTH_OFFSET, BM_WRED_GTH_1_MAXTH_SHIFT, BM_WRED_GTH_1_MAXTH_SIZE, parm->nGreen_Max)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_QoS_WredCfgGet(void *cdev, GSW_QoS_WRED_Cfg_t *parm) { u16 value; /* Description: 'Drop Probability Profile' */ gsw_reg_read(BM_QUEUE_GCTRL_DPROB_OFFSET, BM_QUEUE_GCTRL_DPROB_SHIFT, BM_QUEUE_GCTRL_DPROB_SIZE, &value); parm->eProfile = value; /*Automatic/Manual - Adaptive Watermark Type */ gsw_reg_read(BM_QUEUE_GCTRL_BUFMOD_OFFSET, BM_QUEUE_GCTRL_BUFMOD_SHIFT, BM_QUEUE_GCTRL_BUFMOD_SIZE, &value); parm->eMode = value; /* Get the Local/Global threshold */ gsw_reg_read(BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, &value); parm->eThreshMode = value; /* WRED Red Threshold - Minimum */ gsw_reg_read(BM_WRED_RTH_0_MINTH_OFFSET, BM_WRED_RTH_0_MINTH_SHIFT, BM_WRED_RTH_0_MINTH_SIZE, &value); parm->nRed_Min = value; /* WRED Red Threshold - Maximum */ gsw_reg_read(BM_WRED_RTH_1_MAXTH_OFFSET, BM_WRED_RTH_1_MAXTH_SHIFT, BM_WRED_RTH_1_MAXTH_SIZE, &value); parm->nRed_Max = value; /* WRED Yellow Threshold - Minimum */ gsw_reg_read(BM_WRED_YTH_0_MINTH_OFFSET, BM_WRED_YTH_0_MINTH_SHIFT, BM_WRED_YTH_0_MINTH_SIZE, &value); parm->nYellow_Min = value; /* WRED Yellow Threshold - Maximum */ gsw_reg_read(BM_WRED_YTH_1_MAXTH_OFFSET, BM_WRED_YTH_1_MAXTH_SHIFT, BM_WRED_YTH_1_MAXTH_SIZE, &value); parm->nYellow_Max = value; /* WRED Green Threshold - Minimum */ gsw_reg_read(BM_WRED_GTH_0_MINTH_OFFSET, BM_WRED_GTH_0_MINTH_SHIFT, BM_WRED_GTH_0_MINTH_SIZE, &value); parm->nGreen_Min = value; /* WRED Green Threshold - Maximum */ gsw_reg_read(BM_WRED_GTH_1_MAXTH_OFFSET, BM_WRED_GTH_1_MAXTH_SHIFT, BM_WRED_GTH_1_MAXTH_SIZE, &value); parm->nGreen_Max = value; return GSW_statusOk; } GSW_return_t GSW_QoS_WredPortCfgGet(void *cdev, GSW_QoS_WRED_PortCfg_t *parm) { u16 value; if (parm->nPortId >= 6) return GSW_statusErr; /* Supported for GSWIP 2.2 and newer and returns with*/ /* an error for older hardware revisions. */ /** WRED Red Threshold Min [number of segments].*/ gsw_reg_read((BM_PWRED_RTH_0_MINTH_OFFSET + (parm->nPortId * 0x6)), BM_PWRED_RTH_0_MINTH_SHIFT, BM_PWRED_RTH_0_MINTH_SIZE, &value); parm->nRed_Min = value; /** WRED Red Threshold Max [number of segments].*/ gsw_reg_read((BM_PWRED_RTH_1_MAXTH_OFFSET + (parm->nPortId * 0x6)), BM_PWRED_RTH_1_MAXTH_SHIFT, BM_PWRED_RTH_1_MAXTH_SIZE, &value); parm->nRed_Max = value; /* WRED Yellow Threshold - Minimum */ gsw_reg_read((BM_PWRED_YTH_0_MINTH_OFFSET + (parm->nPortId * 0x6)), BM_PWRED_YTH_0_MINTH_SHIFT, BM_PWRED_YTH_0_MINTH_SIZE, &value); parm->nYellow_Min = value; /* WRED Yellow Threshold - Maximum */ gsw_reg_read((BM_PWRED_YTH_1_MAXTH_OFFSET + (parm->nPortId * 0x6)), BM_PWRED_YTH_1_MAXTH_SHIFT, BM_PWRED_YTH_1_MAXTH_SIZE, &value); parm->nYellow_Max = value; /* WRED Green Threshold - Minimum */ gsw_reg_read((BM_PWRED_GTH_0_MINTH_OFFSET + (parm->nPortId * 0x6)), BM_PWRED_GTH_0_MINTH_SHIFT, BM_PWRED_GTH_0_MINTH_SIZE, &value); parm->nGreen_Min = value; /* WRED Green Threshold - Maximum */ gsw_reg_read((BM_PWRED_GTH_1_MAXTH_OFFSET + (parm->nPortId * 0x6)), BM_PWRED_GTH_1_MAXTH_SHIFT, BM_PWRED_GTH_1_MAXTH_SIZE, &value); parm->nGreen_Max = value; return GSW_statusOk; } GSW_return_t GSW_QoS_FlowctrlCfgSet(void *cdev, GSW_QoS_FlowCtrlCfg_t *parm) { if (gsw_reg_write(SDMA_FCTHR1_THR1_OFFSET, SDMA_FCTHR1_THR1_SHIFT, SDMA_FCTHR1_THR1_SIZE, parm->nFlowCtrlNonConform_Min)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(SDMA_FCTHR2_THR2_OFFSET, SDMA_FCTHR2_THR2_SHIFT, SDMA_FCTHR2_THR2_SIZE, parm->nFlowCtrlNonConform_Max)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(SDMA_FCTHR3_THR3_OFFSET, SDMA_FCTHR3_THR3_SHIFT, SDMA_FCTHR3_THR3_SIZE, parm->nFlowCtrlConform_Min)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(SDMA_FCTHR4_THR4_OFFSET, SDMA_FCTHR4_THR4_SHIFT, SDMA_FCTHR4_THR4_SIZE, parm->nFlowCtrlConform_Max)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_QoS_FlowctrlCfgGet(void *cdev, GSW_QoS_FlowCtrlCfg_t *parm) { u16 value; if (gsw_reg_read(SDMA_FCTHR1_THR1_OFFSET, SDMA_FCTHR1_THR1_SHIFT, SDMA_FCTHR1_THR1_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nFlowCtrlNonConform_Min = value; if (gsw_reg_read(SDMA_FCTHR2_THR2_OFFSET, SDMA_FCTHR2_THR2_SHIFT, SDMA_FCTHR2_THR2_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nFlowCtrlNonConform_Max = value; if (gsw_reg_read(SDMA_FCTHR3_THR3_OFFSET, SDMA_FCTHR3_THR3_SHIFT, SDMA_FCTHR3_THR3_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nFlowCtrlConform_Min = value; if (gsw_reg_read(SDMA_FCTHR4_THR4_OFFSET, SDMA_FCTHR4_THR4_SHIFT, SDMA_FCTHR4_THR4_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nFlowCtrlConform_Max = value; return GSW_statusOk; } GSW_return_t GSW_QoS_ClassPCP_Get(void *cdev, GSW_QoS_ClassPCP_Cfg_t *parm) { pctbl_prog_t pcetable; u16 value; for (value = 0; value < 16; value++) { pcetable.table = PCE_REMARKING_INDEX; pcetable.pcindex = value; gsw_pce_table_read(cdev, &pcetable); parm->nPCP[value] = (pcetable.val[0] >> 8) & 0x7; } return GSW_statusOk; } GSW_return_t GSW_QoS_FlowctrlPortCfgSet(void *cdev, GSW_QoS_FlowCtrlPortCfg_t *parm) { if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; if (gsw_reg_write((SDMA_PFCTHR8_THR8_OFFSET22 + (parm->nPortId * 0x4)), SDMA_PFCTHR8_THR8_SHIFT, SDMA_PFCTHR8_THR8_SIZE, parm->nFlowCtrl_Min)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((SDMA_PFCTHR9_THR9_OFFSET22 + (parm->nPortId * 0x4)), SDMA_PFCTHR9_THR9_SHIFT, SDMA_PFCTHR9_THR9_SIZE, parm->nFlowCtrl_Max)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } GSW_return_t GSW_QoS_FlowctrlPortCfgGet(void *cdev, GSW_QoS_FlowCtrlPortCfg_t *parm) { u16 value; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; if (gsw_reg_read((SDMA_PFCTHR8_THR8_OFFSET22 + (parm->nPortId * 0x4)), SDMA_PFCTHR8_THR8_SHIFT, SDMA_PFCTHR8_THR8_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nFlowCtrl_Min = value; if (gsw_reg_read((SDMA_PFCTHR9_THR9_OFFSET22 + (parm->nPortId * 0x4)), SDMA_PFCTHR9_THR9_SHIFT, SDMA_PFCTHR9_THR9_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; parm->nFlowCtrl_Max = value; return GSW_statusOk; } /* Function: Internal function to calculate the mrate when */ /* Shaper and Meter API is called.*/ /* Description: Calculate the mrate by input Ibs, Exp and Mant.*/ /* The algorithm designed based on software architecture spec.*/ static u32 mratecalc(u32 ibsid, u32 expont, u32 mants) { static const u16 ibs_table[] = {8*8, 32*8, 64*8, 96*8}; u16 ibs; u32 mrate; if ((ibsid == 0) && (expont == 0) && (mants == 0)) return 0; ibs = ibs_table[ibsid]; mrate = ((ibs * 25000) >> expont) / mants; return mrate; } GSW_return_t GSW_QoS_MeterCfgGet(void *cdev, GSW_QoS_meterCfg_t *parm) { u16 mid = parm->nMeterId, exp, mant, ibs; u16 value; gsw_reg_write(GSW_INST_SEL_INST_OFFSET, GSW_INST_SEL_INST_SHIFT, GSW_INST_SEL_INST_SIZE, mid); /* Enable/Disable the meter shaper */ gsw_reg_read(GSW_PCE_TCM_CTRL_TCMEN_OFFSET, GSW_PCE_TCM_CTRL_TCMEN_SHIFT, GSW_PCE_TCM_CTRL_TCMEN_SIZE, &value); parm->bEnable = value; /* Committed Burst Size */ gsw_reg_read(GSW_PCE_TCM_CBS_CBS_OFFSET, GSW_PCE_TCM_CBS_CBS_SHIFT, GSW_PCE_TCM_CBS_CBS_SIZE, &value); parm->nCbs = (value * 64); /* Excess Burst Size (EBS [bytes]) */ gsw_reg_read(GSW_PCE_TCM_EBS_EBS_OFFSET, GSW_PCE_TCM_EBS_EBS_SHIFT, GSW_PCE_TCM_EBS_EBS_SIZE, &value); parm->nEbs = (value * 64); /* Rate Counter Exponent */ gsw_reg_read(GSW_PCE_TCM_CIR_EXP_EXP_OFFSET, GSW_PCE_TCM_CIR_EXP_EXP_SHIFT, GSW_PCE_TCM_CIR_EXP_EXP_SIZE, &exp); /* Rate Counter Mantissa */ gsw_reg_read(GSW_PCE_TCM_CIR_MANT_MANT_OFFSET, GSW_PCE_TCM_CIR_MANT_MANT_SHIFT, GSW_PCE_TCM_CIR_MANT_MANT_SIZE, &mant); /* Rate Counter iBS */ gsw_reg_read(GSW_PCE_TCM_IBS_IBS_OFFSET, GSW_PCE_TCM_IBS_IBS_SHIFT, GSW_PCE_TCM_IBS_IBS_SIZE, &ibs); /* calc the Rate */ parm->nRate = mratecalc(ibs, exp, mant); /* Rate Counter Exponent */ gsw_reg_read(GSW_PCE_TCM_PIR_EXP_EXP_OFFSET, GSW_PCE_TCM_PIR_EXP_EXP_SHIFT, GSW_PCE_TCM_PIR_EXP_EXP_SIZE, &exp); /* Rate Counter Mantissa */ gsw_reg_read(GSW_PCE_TCM_PIR_MANT_MANT_OFFSET, GSW_PCE_TCM_PIR_MANT_MANT_SHIFT, GSW_PCE_TCM_PIR_MANT_MANT_SIZE, &mant); /* Rate Counter iBS */ gsw_reg_read(GSW_PCE_TCM_IBS_IBS_OFFSET, GSW_PCE_TCM_IBS_IBS_SHIFT, GSW_PCE_TCM_IBS_IBS_SIZE, &ibs); /* calc the Rate */ parm->nPiRate = mratecalc(ibs, exp, mant); /* parm->nPbs=??? how to calculate it*/ gsw_reg_read(GSW_PCE_TCM_CTRL_TMOD_OFFSET, GSW_PCE_TCM_CTRL_TMOD_SHIFT, GSW_PCE_TCM_CTRL_TMOD_SIZE, &value); parm->eMtrType = value; return GSW_statusOk; } #if 0 GSW_return_t GSW_QoS_MeterPortGet(void *cdev, GSW_QoS_meterPortGet_t *parm) { pctbl_prog_t pcetable; u32 value = 0; static u32 meter_cnt; memset(&pcetable, 0, sizeof(pctbl_prog_t)); /* gsw_r32(cdev, ETHSW_CAP_3_METERS_OFFSET,*/ /* ETHSW_CAP_3_METERS_SHIFT,*/ /* ETHSW_CAP_3_METERS_SIZE, &value); */ value = 16; if (parm->bInitial == 1) { meter_cnt = 0; parm->bInitial = 0; } else { if (meter_cnt > (value * 2)) parm->bLast = 1; } if (meter_cnt > value) pcetable.table = PCE_METER_INS_1_INDEX; else pcetable.table = PCE_METER_INS_0_INDEX; pcetable.pcindex = meter_cnt; gsw_pce_table_read(cdev, &pcetable); if (pcetable.valid) { parm->nMeterId = (pcetable.val[0] & 0x3F); parm->nPortEgressId = ((pcetable.key[0] >> 8) & 0xF); parm->nPortIngressId = (pcetable.key[0] & 0xF); if ((pcetable.mask[0] & 0x5) == 0) parm->eDir = GSW_DIRECTION_BOTH; else if ((pcetable.mask[0] & 0x5) == 1) parm->eDir = GSW_DIRECTION_EGRESS; else if ((pcetable.mask[0] & 0x5) == 4) parm->eDir = GSW_DIRECTION_INGRESS; else parm->eDir = GSW_DIRECTION_NONE; } meter_cnt++; return GSW_statusOk; } #endif GSW_return_t GSW_QoS_PortCfgGet(void *cdev, GSW_QoS_portCfg_t *parm) { u16 dscp, cpcp, spcp = 0; u16 value; if (parm->nPortId >= MAX_LTQ_PORTS) return GSW_statusErr; gsw_reg_read((PCE_PCTRL_2_DSCP_OFFSET + (10 * parm->nPortId)), PCE_PCTRL_2_DSCP_SHIFT, PCE_PCTRL_2_DSCP_SIZE, &dscp); gsw_reg_read((PCE_PCTRL_2_PCP_OFFSET + (10 * parm->nPortId)), PCE_PCTRL_2_PCP_SHIFT, PCE_PCTRL_2_PCP_SIZE, &cpcp); gsw_reg_read((PCE_PCTRL_2_SPCP_OFFSET + (10 * parm->nPortId)), PCE_PCTRL_2_SPCP_SHIFT, PCE_PCTRL_2_SPCP_SIZE, &spcp); if ((dscp == 0) && (cpcp == 0) && (spcp == 0)) parm->eClassMode = GSW_QOS_CLASS_SELECT_NO; else if ((dscp == 2) && (cpcp == 0) && (spcp == 0)) parm->eClassMode = GSW_QOS_CLASS_SELECT_DSCP; else if ((dscp == 0) && (cpcp == 1) && (spcp == 0)) parm->eClassMode = GSW_QOS_CLASS_SELECT_PCP; else if ((dscp == 2) && (cpcp == 1) && (spcp == 0)) parm->eClassMode = GSW_QOS_CLASS_SELECT_DSCP_PCP; else if ((dscp == 1) && (cpcp == 1) && (spcp == 0)) parm->eClassMode = GSW_QOS_CLASS_SELECT_PCP_DSCP; else if ((dscp == 0) && (cpcp == 0) && (spcp == 1)) parm->eClassMode = GSW_QOS_CLASS_SELECT_SPCP; else if ((dscp == 1) && (cpcp == 0) && (spcp == 1)) parm->eClassMode = GSW_QOS_CLASS_SELECT_SPCP_DSCP; else if ((dscp == 2) && (cpcp == 0) && (spcp == 1)) parm->eClassMode = GSW_QOS_CLASS_SELECT_DSCP_SPCP; else if ((dscp == 0) && (cpcp == 1) && (spcp == 1)) parm->eClassMode = GSW_QOS_CLASS_SELECT_SPCP_PCP; else if ((dscp == 1) && (cpcp == 1) && (spcp == 1)) parm->eClassMode = GSW_QOS_CLASS_SELECT_SPCP_PCP_DSCP; else if ((dscp == 2) && (cpcp == 1) && (spcp == 1)) parm->eClassMode = GSW_QOS_CLASS_SELECT_DSCP_SPCP_PCP; else parm->eClassMode = GSW_QOS_CLASS_SELECT_NO; gsw_reg_read((PCE_PCTRL_2_PCLASS_OFFSET + (10 * parm->nPortId)), PCE_PCTRL_2_PCLASS_SHIFT, PCE_PCTRL_2_PCLASS_SIZE, &value); parm->nTrafficClass = value; return GSW_statusOk; } GSW_return_t GSW_QoS_QueueBufferReserveCfgSet(void *cdev, GSW_QoS_QueueBufferReserveCfg_t *parm) { u16 value, addr; if (gsw_reg_read(ETHSW_CAP_1_QUEUE_OFFSET, ETHSW_CAP_1_QUEUE_SHIFT, ETHSW_CAP_1_QUEUE_SIZE, &value) != GSW_statusOk) return GSW_statusErr; if (parm->nQueueId >= value) return GSW_statusErr; addr = (((parm->nQueueId << 3) & 0xF8)); if (gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, addr) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, parm->nBufferReserved) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0x9) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0x1) != GSW_statusOk) return GSW_statusErr; value = 1; if (gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, value) != GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value) != GSW_statusOk) return GSW_statusErr; } while (value); return GSW_statusOk; } GSW_return_t GSW_QoS_QueueBufferReserveCfgGet(void *cdev, GSW_QoS_QueueBufferReserveCfg_t *parm) { u16 addr; u16 value; /* gsw_r32(cdev, ETHSW_CAP_1_QUEUE_OFFSET, */ /* ETHSW_CAP_1_QUEUE_SHIFT, */ /* ETHSW_CAP_1_QUEUE_SIZE, &value); */ if (parm->nQueueId >= 32) return GSW_statusErr; /* Supported for GSWIP 2.2 and newer and returns with an error */ /* for older hardware revisions. */ /* Colourcode = 0 and fixed offset = 0 */ /* Set the BM RAM ADDR */ addr = (((parm->nQueueId << 3) & 0xF8)); gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, addr); /* Specify the PQMCTXT = 0x9 */ gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0x9); /* Table Access Operation Mode Read */ gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0x0); value = 1; /* Active */ gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, value); do { gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value); } while (value); gsw_reg_read(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, &value); parm->nBufferReserved = value; return GSW_statusOk; } GSW_return_t GSW_QoS_QueuePortGet(void *cdev, GSW_QoS_queuePort_t *parm) { pctbl_prog_t pcetable; u16 value; memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_QUEUE_MAP_INDEX; pcetable.pcindex = ((((parm->nPortId << 4) & 0xF0) | (parm->nTrafficClassId & 0xF))); if (parm->bRedirectionBypass == 1) pcetable.pcindex |= (1 << 8); gsw_pce_table_read(cdev, &pcetable); parm->nQueueId = (pcetable.val[0] & 0x3F); gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, parm->nQueueId); /* Specify the Table Address */ gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0xE); /* Assign Read operation */ gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0); value = 1; /* Active */ gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, value); do { gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value); } while (value); gsw_reg_read(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, &value); parm->nRedirectPortId = (value & 0x7); parm->nRedirectPortId |= (((value >> 4) & 1) << 3); return GSW_statusOk; } GSW_return_t GSW_QoS_SchedulerCfgGet(void *cdev, GSW_QoS_schedulerCfg_t *parm) { int qid = parm->nQueueId; u16 value; /* gsw_r32(cdev, ETHSW_CAP_1_QUEUE_OFFSET,*/ /* ETHSW_CAP_1_QUEUE_SHIFT, */ /* ETHSW_CAP_1_QUEUE_SIZE, &value); */ if (qid >= 32) return GSW_statusErr; gsw_reg_write(BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, qid); gsw_reg_write(BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0x8); /* Table Access Operation Mode read */ gsw_reg_write(BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0x0); gsw_reg_write(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, 1); do { gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value); } while (value); gsw_reg_read(BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, &value); parm->nWeight = value; if (value == 0xFFFF || value == 0x1800) parm->eType = GSW_QOS_SCHEDULER_STRICT; else parm->eType = GSW_QOS_SCHEDULER_WFQ; return GSW_statusOk; } GSW_return_t GSW_QoS_ShaperCfgGet(void *cdev, GSW_QoS_ShaperCfg_t *parm) { int rshid = parm->nRateShaperId; u16 exp, mant, ibs; u16 value; /* gsw_r32(cdev, ETHSW_CAP_3_SHAPERS_OFFSET, */ /* ETHSW_CAP_3_SHAPERS_SHIFT, */ /* ETHSW_CAP_3_SHAPERS_SIZE, &value); */ if (rshid >= 32) return GSW_statusErr; /* Enable/Disable the rate shaper */ gsw_reg_read(RS_CTRL_RSEN_OFFSET + (rshid * 0x5), RS_CTRL_RSEN_SHIFT, RS_CTRL_RSEN_SIZE, &value); parm->bEnable = value; /* Committed Burst Size (CBS [bytes]) */ gsw_reg_read(RS_CBS_CBS_OFFSET + (rshid * 0x5), RS_CBS_CBS_SHIFT, RS_CBS_CBS_SIZE, &value); parm->nCbs = (value * 64); /** Rate [Mbit/s] */ gsw_reg_read(RS_CIR_EXP_EXP_OFFSET + (rshid * 0x5), RS_CIR_EXP_EXP_SHIFT, RS_CIR_EXP_EXP_SIZE, &exp); gsw_reg_read(RS_CIR_MANT_MANT_OFFSET + (rshid * 0x5), RS_CIR_MANT_MANT_SHIFT, RS_CIR_MANT_MANT_SIZE, &mant); gsw_reg_read(RS_IBS_IBS_OFFSET + (rshid * 0x5), RS_IBS_IBS_SHIFT, RS_IBS_IBS_SIZE, &ibs); /* calc the Rate */ parm->nRate = mratecalc(ibs, exp, mant); gsw_reg_read(RS_CTRL_RSMOD_OFFSET + (rshid * 0x5), RS_CTRL_RSMOD_SHIFT, RS_CTRL_RSMOD_SIZE, &value); parm->bAVB = value; return GSW_statusOk; } GSW_return_t GSW_QoS_ShaperQueueGet(void *cdev, GSW_QoS_ShaperQueueGet_t *parm) { u16 rsh, value; u8 qid = parm->nQueueId; /* gsw_r32(cdev, ETHSW_CAP_1_QUEUE_OFFSET, */ /* ETHSW_CAP_1_QUEUE_SHIFT, */ /* ETHSW_CAP_1_QUEUE_SIZE, &rsh); */ if (qid >= 32) return GSW_statusErr; parm->bAssigned = 0; parm->nRateShaperId = 0; gsw_reg_read(PQM_RS_EN1_OFFSET + (qid * 2), PQM_RS_EN1_SHIFT, PQM_RS_EN1_SIZE, &rsh); if (rsh == 1) { parm->bAssigned = 1; gsw_reg_read(PQM_RS_RS1_OFFSET + (qid * 2), PQM_RS_RS1_SHIFT, PQM_RS_RS1_SIZE, &value); parm->nRateShaperId = value; } gsw_reg_read(PQM_RS_EN2_OFFSET + (qid * 2), PQM_RS_EN2_SHIFT, PQM_RS_EN2_SIZE, &rsh); if (rsh == 1) { gsw_reg_read(PQM_RS_RS2_OFFSET + (qid * 2), PQM_RS_RS2_SHIFT, PQM_RS_RS2_SIZE, &value); parm->nRateShaperId = value; } return GSW_statusOk; } GSW_return_t GSW_QoS_StormCfgGet(void *cdev, GSW_QoS_stormCfg_t *parm) { u16 value; /* Storm Control Mode */ gsw_reg_read(PCE_GCTRL_0_SCONMOD_OFFSET, PCE_GCTRL_0_SCONMOD_SHIFT, PCE_GCTRL_0_SCONMOD_SIZE, &value); if (value == 0) { parm->nMeterId = 0; parm->bBroadcast = 0; parm->bMulticast = 0; parm->bUnknownUnicast = 0; } else { gsw_reg_read(PCE_GCTRL_0_SCONMET_OFFSET, PCE_GCTRL_0_SCONMET_SHIFT, PCE_GCTRL_0_SCONMET_SIZE, &value); parm->nMeterId = value; /* Meter instances used for broadcast traffic */ gsw_reg_read(PCE_GCTRL_0_SCONBC_OFFSET, PCE_GCTRL_0_SCONBC_SHIFT, PCE_GCTRL_0_SCONBC_SIZE, &value); parm->bBroadcast = value; /* Meter instances used for multicast traffic */ gsw_reg_read(PCE_GCTRL_0_SCONMC_OFFSET, PCE_GCTRL_0_SCONMC_SHIFT, PCE_GCTRL_0_SCONMC_SIZE, &value); parm->bMulticast = value; /* Meter instances used for unknown unicast traffic */ gsw_reg_read(PCE_GCTRL_0_SCONUC_OFFSET, PCE_GCTRL_0_SCONUC_SHIFT, PCE_GCTRL_0_SCONUC_SIZE, &value); parm->bUnknownUnicast = value; } return GSW_statusOk; } GSW_return_t GSW_QoS_SchedulerCfgSet(void *cdev, GSW_QoS_schedulerCfg_t *parm) { int qid = parm->nQueueId; u16 value; if (gsw_reg_read(ETHSW_CAP_1_QUEUE_OFFSET, ETHSW_CAP_1_QUEUE_SHIFT, ETHSW_CAP_1_QUEUE_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; if (qid >= value) return GSW_statusErr; if ((parm->eType == GSW_QOS_SCHEDULER_WFQ) && (parm->nWeight == 0)) return GSW_statusErr; if (gsw_reg_write( BM_RAM_ADDR_ADDR_OFFSET, BM_RAM_ADDR_ADDR_SHIFT, BM_RAM_ADDR_ADDR_SIZE, qid)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write( BM_RAM_CTRL_ADDR_OFFSET, BM_RAM_CTRL_ADDR_SHIFT, BM_RAM_CTRL_ADDR_SIZE, 0x8)!= GSW_statusOk) return GSW_statusErr; if (parm->eType == GSW_QOS_SCHEDULER_STRICT) value = 0xFFFF; else value = parm->nWeight; if (gsw_reg_write( BM_RAM_VAL_0_VAL0_OFFSET, BM_RAM_VAL_0_VAL0_SHIFT, BM_RAM_VAL_0_VAL0_SIZE, value)!= GSW_statusOk) return GSW_statusErr; /* Table Access Operation Mode Write */ if (gsw_reg_write( BM_RAM_CTRL_OPMOD_OFFSET, BM_RAM_CTRL_OPMOD_SHIFT, BM_RAM_CTRL_OPMOD_SIZE, 0x1)!= GSW_statusOk) return GSW_statusErr; /* Active */ if (gsw_reg_write( BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; do { if (gsw_reg_read(BM_RAM_CTRL_BAS_OFFSET, BM_RAM_CTRL_BAS_SHIFT, BM_RAM_CTRL_BAS_SIZE, &value)!= GSW_statusOk) return GSW_statusErr; } while (value); return GSW_statusOk; } GSW_return_t GSW_QoS_PCP_ClassSet(void *cdev, GSW_QoS_PCP_ClassCfg_t *parm) { pctbl_prog_t pcetable; u16 vlnpcp; memset(&pcetable, 0, sizeof(pctbl_prog_t)); for (vlnpcp = 0; vlnpcp < 8; vlnpcp++) { pcetable.table = PCE_PCP_INDEX; pcetable.pcindex = vlnpcp; pcetable.val[0] = (parm->nTrafficClass[vlnpcp] & 0xF); if (gsw_mem_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } } return GSW_statusOk; } GSW_return_t GSW_QoS_PCP_ClassGet(void *cdev, GSW_QoS_PCP_ClassCfg_t *parm) { pctbl_prog_t pcetable; u16 vlnpcp; for (vlnpcp = 0; vlnpcp < 8; vlnpcp++) { pcetable.table = PCE_PCP_INDEX; pcetable.pcindex = vlnpcp; gsw_pce_table_read(cdev, &pcetable); if (gsw_mem_table_read(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } parm->nTrafficClass[vlnpcp] = (pcetable.val[0] & 0xF); } return GSW_statusOk; } GSW_return_t GSW_RegisterGet(void *cdev, GSW_register_t *parm) { u16 rvalue, raddr = parm->nRegAddr; if (gsw_reg_read(raddr, 0, 16, &rvalue)!= GSW_statusOk) return GSW_statusErr; parm->nData = rvalue; return GSW_statusOk; } GSW_return_t GSW_RegisterSet(void *cdev, GSW_register_t *parm) { u16 rvalue = parm->nData, raddr = parm->nRegAddr; if (gsw_reg_write(raddr, 0, 16, rvalue)!= GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } extern int gpio_set_value(int gpio, int value); GSW_return_t GSW_Reset(void *cdev, GSW_reset_t *parm) { u16 value; int result; /* Reset the Switch via Switch IP register*/ ESHAL_LogErr(" \nInitialising soft reset\n"); value = 1; if (gsw_reg_write( ETHSW_SWRES_R0_OFFSET, ETHSW_SWRES_R0_SHIFT, ETHSW_SWRES_R0_SIZE, value)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = -1; goto err_out; } do { if (gsw_reg_read(ETHSW_SWRES_R0_OFFSET, ETHSW_SWRES_R0_SHIFT, ETHSW_SWRES_R0_SIZE, &value)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = -1; goto err_out; } } while (value); err_out: return result == 0 ? GSW_statusOk : GSW_statusErr; } GSW_return_t GSW_Enable(void *cdev) { u8 j; for (j = 0; j < MAX_LTQ_PORTS; j++) { if (gsw_reg_write((FDMA_PCTRL_EN_OFFSET + (j * 0x6)), FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((BM_PCFG_CNTEN_OFFSET + (j * 2)), BM_PCFG_CNTEN_SHIFT, BM_PCFG_CNTEN_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; } return GSW_statusOk; } GSW_return_t GSW_Disable(void *cdev) { u8 j; /* Disable all physical port */ for (j = 0; j < MAX_LTQ_PORTS; j++) { if (gsw_reg_write((FDMA_PCTRL_EN_OFFSET + (j * 0x6)), FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write((SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 0)!= GSW_statusOk) return GSW_statusErr; } return GSW_statusOk; } #if 0 static int force_to_configure_phy_settings(void *cdev, u8 pidx, u8 link_status) { u16 mdio_stat_reg, phy_addr_reg = 0; if (pidx >= MAX_LTQ_PORTS) return STATUS_NOK; if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - pidx) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, 16, &phy_addr_reg) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read((MDIO_STAT_0_TXPAUEN_OFFSET + GSW_TREG_OFFSET + pidx), MDIO_STAT_0_TXPAUEN_SHIFT, 16, &mdio_stat_reg)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (link_status) { /* PHY active Status */ if ((mdio_stat_reg >> 6) & 0x1) { u32 temp = 0; /* Link Status */ if ((mdio_stat_reg >> 5) & 0x1) { phy_addr_reg &= ~(0xFFE0); phy_addr_reg |= (1 << 13); /* Link up */ temp = ((mdio_stat_reg >> 3) & 0x3); /*Speed */ phy_addr_reg |= (temp << 11); /*Speed */ if ((mdio_stat_reg >> 2) & 0x1) /*duplex */ { phy_addr_reg |= (0x1 << 9); /*duplex */ } else { phy_addr_reg |= (0x3 << 9); } /*Receive Pause Enable Status */ if ((mdio_stat_reg >> 1) & 0x1) { /*Receive Pause Enable Status */ phy_addr_reg |= (0x1 << 5); } else { phy_addr_reg |= (0x3 << 5); } /*Transmit Pause Enable Status */ if ((mdio_stat_reg >> 0) & 0x1) { /*Transmit Pause Enable Status */ phy_addr_reg |= (0x1 << 7); } else { phy_addr_reg |= (0x3 << 7); } if (gsw_reg_write(((PHY_ADDR_0_ADDR_OFFSET - pidx) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, 16, phy_addr_reg)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } } } else { phy_addr_reg &= ~(0xFFE0); phy_addr_reg |= (0x3 << 11); if (gsw_reg_write(((PHY_ADDR_0_ADDR_OFFSET - pidx) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, 16, phy_addr_reg)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } return 1; } /* static inline void ltq_mdelay(int delay) { int i; for (i = delay; i > 0; i--) udelay(1000); } */ static GSW_return_t GSW_MMD_MDIO_DataWrite(void *cdev, GSW_MDIO_data_t *parm, u8 pidx, u8 dev) { GSW_MDIO_data_t mmd_data; u16 mdc_reg; if (pidx >= MAX_LTQ_PORTS) return STATUS_NOK; if (force_to_configure_phy_settings(cdev, pidx, 1) != STATUS_OK) return STATUS_NOK; if (gsw_reg_read((MDC_CFG_0_PEN_0_OFFSET + GSW_TREG_OFFSET), MDC_CFG_0_PEN_0_SHIFT, 6, &mdc_reg)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } mdc_reg &= ~(1 << pidx); if (gsw_reg_write((MDC_CFG_0_PEN_0_OFFSET + GSW_TREG_OFFSET), MDC_CFG_0_PEN_0_SHIFT, 6, mdc_reg)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } // ltq_mdelay(20); mmd_data.nAddressDev = parm->nAddressDev; mmd_data.nAddressReg = 0xd; mmd_data.nData = dev; GSW_MDIO_DataWrite(NULL, &mmd_data); mmd_data.nAddressDev = parm->nAddressDev; mmd_data.nAddressReg = 0xe; mmd_data.nData = parm->nAddressReg; GSW_MDIO_DataWrite(NULL, &mmd_data); mmd_data.nAddressDev = parm->nAddressDev; mmd_data.nAddressReg = 0xd; mmd_data.nData = ((0x4000) | (dev & 0x1F)); GSW_MDIO_DataWrite(NULL, &mmd_data); mmd_data.nAddressDev = parm->nAddressDev; mmd_data.nAddressReg = 0xe; mmd_data.nData = parm->nData; GSW_MDIO_DataWrite(NULL, &mmd_data); mdc_reg |= (1 << pidx); if (gsw_reg_write((MDC_CFG_0_PEN_0_OFFSET + GSW_TREG_OFFSET), MDC_CFG_0_PEN_0_SHIFT, 6, mdc_reg)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } // ltq_mdelay(100); if (force_to_configure_phy_settings(cdev, pidx, 0) != STATUS_OK) return STATUS_NOK; return GSW_statusOk; } #endif GSW_return_t gsw_enable_buffer_reservation(void) { GSW_QoS_QueueBufferReserveCfg_t bparam; GSW_QoS_WRED_Cfg_t wparam; GSW_QoS_FlowCtrlPortCfg_t pfparam; GSW_QoS_FlowCtrlCfg_t fcparam; GSW_QoS_WRED_QueueCfg_t wqparam; int i; memset(&bparam, 0, sizeof(GSW_QoS_QueueBufferReserveCfg_t)); memset(&wparam, 0, sizeof(GSW_QoS_WRED_Cfg_t)); memset(&pfparam, 0, sizeof(GSW_QoS_FlowCtrlPortCfg_t)); memset(&fcparam, 0, sizeof(GSW_QoS_FlowCtrlCfg_t)); for (i = 0 ; i < 32; i++) { bparam.nBufferReserved = 0x1E; bparam.nQueueId = i; if (GSW_QoS_QueueBufferReserveCfgSet(NULL, &bparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } } wparam.eProfile = 0; wparam.eThreshMode = 0; wparam.nRed_Min = 0x3ff; wparam.nRed_Max =0x3ff; wparam.nYellow_Min = 0x3ff; wparam.nYellow_Max = 0x3ff; wparam.nGreen_Min = 0x100; wparam.nGreen_Max =0x100; if (GSW_QoS_WredCfgSet(NULL, &wparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } for (i = 0; i < MAX_LTQ_PORTS; i++) { pfparam.nPortId = i; pfparam.nFlowCtrl_Min = 0x18; pfparam.nFlowCtrl_Max = 0x1E; if (GSW_QoS_FlowctrlPortCfgSet(NULL, &pfparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } } fcparam.nFlowCtrlNonConform_Min = 0x3FF; fcparam.nFlowCtrlNonConform_Max = 0x3FF; fcparam.nFlowCtrlConform_Min = 0x3FF; fcparam.nFlowCtrlConform_Max = 0x3FF; if (GSW_QoS_FlowctrlCfgSet(NULL, &fcparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } for (i = 0 ; i < 32; i++) { ESHAL_LogDbg(" \n*** %s:%d (intportqueue#:%d) ***\n", __func__,__LINE__,i); memset(&wqparam, 0, sizeof(GSW_QoS_WRED_QueueCfg_t)); wqparam.nRed_Min = 80; wqparam.nRed_Max = 80; wqparam.nYellow_Min = 80; wqparam.nYellow_Max = 80; wqparam.nGreen_Min = 0x3ff; wqparam.nGreen_Max = 0x3ff; wqparam.nQueueId = i; if (GSW_QoS_WredQueueCfgSet(NULL, &wqparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } } return GSW_statusOk; } static GSW_return_t disable_lan_ports(void) { GSW_MDIO_data_t mddata; int i; for (i = 0; i < 4; i++) { mddata.nAddressDev = i; mddata.nAddressReg = 0x0; mddata.nData = 0x800; if (GSW_MDIO_DataWrite(NULL, &mddata)!= GSW_statusOk) return STATUS_NOK; } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } static GSW_return_t Cport_sgmii_config(void) { if (gsw_reg_write(0xfa01, 0, 16, 0x0030) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xfa01, 0, 14, 0x0010) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xD009, 0, 16, 0x0009) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xD004, 0, 16, 0x053A) != GSW_statusOk) return GSW_statusErr; /*Reset of TBI FSM's*/ if (gsw_reg_write(0xD305, 0, 16, 0x0033) != GSW_statusOk) return GSW_statusErr; /*Release TBI FSM's*/ if (gsw_reg_write(0xD305, 0, 16, 0x0032) != GSW_statusOk) return GSW_statusErr; /* TX Buffer and pointers are initialized */ if (gsw_reg_write(0xD404, 0, 16, 0x0003) != GSW_statusOk) return GSW_statusErr; /* TX Buffer and pointers are normally operating */ if (gsw_reg_write(0xD404, 0, 16, 0x0001) != GSW_statusOk) return GSW_statusErr; /* RX Buffer and pointers are initialized */ if (gsw_reg_write(0xD401, 0, 16, 0x0003) != GSW_statusOk) return GSW_statusErr; /* RX Buffer and pointers are normally operating */ if (gsw_reg_write(0xD401, 0, 16, 0x0001) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xD300, 0, 16, 0x0018) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xD301, 0, 16, 0x0001) != GSW_statusOk) return GSW_statusErr; /* Restart Autonegotiation */ if (gsw_reg_write(0xD304, 0, 16, 0x80b8) != GSW_statusOk) return GSW_statusErr; /*SGMII_PHY SGMII PHY mode */ if (gsw_reg_write(0xD304, 0, 16, 0x80b0) != GSW_statusOk) return GSW_statusErr; /*Foced the SGMII @2.5G/FD mode*/ if (gsw_reg_write(0xD30A, 0, 16, 0x0041) != GSW_statusOk) return GSW_statusErr; /* set clock (PLL Config) */ if (gsw_reg_write(0xD100, 0, 16, 0x80) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xD101, 0, 16, 0x30) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xD102, 0, 16, 0x1100) != GSW_statusOk) return GSW_statusErr; return GSW_statusOk; } /* This is the switch core layer init function.*/ /* \param ethcinit This parameter is a pointer */ /* to the switch core context. */ /* \return Return value as follows: */ /* cdev: if successful */ int ethsw_api_core_init(void) { if (ecoredev) kfree(ecoredev); ecoredev = (ethsw_api_dev_t *)kmalloc(sizeof(ethsw_api_dev_t), GFP_KERNEL); if (!ecoredev) { ESHAL_LogErr("%s:%s:%d (memory allocation failed)\n", __FILE__, __func__, __LINE__); return -1; } ESHAL_LogDbg("%s:%d \n", __func__, __LINE__); memset(ecoredev, 0, sizeof(ethsw_api_dev_t)); if (get_gsw_hw_cap(ecoredev)!= GSW_statusOk) return GSW_statusErr; ecoredev->rst = 0; ecoredev->hwinit = 0; ecoredev->matimer = DEFAULT_AGING_TIMEOUT; ESHAL_LogDbg("\n *** Switch API: PCE MicroCode loaded start!! ***\n"); if (gsw_pmicro_code_init(ecoredev)!= GSW_statusOk) return GSW_statusErr; ESHAL_LogDbg("\n*** Switch API: PCE MicroCode loaded done!!***\n"); /* Set the the source MAC register of pause frame */ if (gsw_reg_write(MAC_PFSA_0_PFAD_OFFSET, MAC_PFSA_0_PFAD_SHIFT, MAC_PFSA_0_PFAD_SIZE, 0x0000)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(MAC_PFSA_1_PFAD_OFFSET, MAC_PFSA_1_PFAD_SHIFT, MAC_PFSA_1_PFAD_SIZE, 0x9600)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(MAC_PFSA_2_PFAD_OFFSET, MAC_PFSA_2_PFAD_SHIFT, MAC_PFSA_2_PFAD_SIZE, 0xAC9A)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(PCE_GCTRL_1_VLANMD_OFFSET, PCE_GCTRL_1_VLANMD_SHIFT, PCE_GCTRL_1_VLANMD_SIZE, 1)!= GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0xF3E0, 0, 16, 0x0)!= GSW_statusOk) return GSW_statusErr; /* Disable the LAN ports to block the traffic into switch before system up*/ if (disable_lan_ports() != GSW_statusOk) return GSW_statusErr; if (Cport_sgmii_config()!= GSW_statusOk) return GSW_statusErr; if (gsw_enable_buffer_reservation()!= GSW_statusOk) return GSW_statusErr; /*Disable the flow control*/ /*if (gsw_reg_write(0xF411, 0, 16, 0x33E4)!= GSW_statusOk) return GSW_statusErr;*/ return GSW_statusOk; } /* Following 4 functions are used to manage Port/VID and VID/FID mapping gsw_GetPortVid gsw_GetPortFid gsw_AllocFid - allocate FID for port/VID gsw_FreeFid - free FID from port/VID Port refers to LAN Port (portid < MAX_LTQ_PORTS) in these functions. Table programming: 4K VLAN - index is VID, value is FID, Portmap Active VLAN - index is FID+STAG_RULES_INDEX-START_FID value is VID Flow - index is same as Active VLAN table */ static Uint16 gsw_GetPortVid(Uint8 portid) { if (portid>=MAX_LTQ_PORTS) return INVALID_VID; else return GSW_IMPL_CurrentDevPriv->lan_port_vid[portid]; } static Uint8 gsw_GetPortFid(Uint8 portid) { Uint16 vid; Uint8 fid; if (portid>=MAX_LTQ_PORTS) return INVALID_FID; vid = GSW_IMPL_CurrentDevPriv->lan_port_vid[portid]; if (vid==INVALID_VID) return INVALID_FID; for (fid=0; fidfid_vid[fid]==vid) return fid+START_FID; } return INVALID_FID; } /* debug */ static void dumpVid(void) { int i; ESHAL_LogDbg("lan_port_vid:"); for (i=0; ilan_port_vid[i]); ESHAL_LogDbg("\n"); ESHAL_LogDbg("fid_vid: "); for (i=0; ifid_vid[i]); ESHAL_LogDbg("\n"); ESHAL_LogDbg("lan_port_pcp: "); for (i=0; ilan_port_pcp[i]); ESHAL_LogDbg("\n"); } static Uint8 gsw_AllocFid(Uint8 portid, Uint16 vid, Uint8 *flagNew) { Uint8 firstFid=INVALID_FID, fid; if (portid>=MAX_LTQ_PORTS) return INVALID_FID; for (fid=0; fidfid_vid[fid]==vid) { GSW_IMPL_CurrentDevPriv->lan_port_vid[portid] = vid; if (flagNew!=NULL) *flagNew = 0; /* debug */ ESHAL_LogDbg("\n*** %s:%d, *flagNew 0 ***\n", __func__, __LINE__); dumpVid(); return fid+START_FID; } else if (firstFid==INVALID_FID && GSW_IMPL_CurrentDevPriv->fid_vid[fid]==INVALID_VID) firstFid = fid; } if (firstFid!=INVALID_FID) { GSW_IMPL_CurrentDevPriv->lan_port_vid[portid] = vid; GSW_IMPL_CurrentDevPriv->fid_vid[firstFid]=vid; } if (flagNew!=NULL) *flagNew = 1; /* debug */ ESHAL_LogDbg("\n*** %s:%d, *flagNew 1 ***\n", __func__, __LINE__); dumpVid(); return firstFid==INVALID_FID ? INVALID_FID : firstFid+START_FID; } static void gsw_FreeFid(Uint8 portid, Uint16 vid, Uint8 *flagLast) { Uint8 pid; Uint8 fid; if (gsw_GetPortVid(portid)!=vid) { if (flagLast!=NULL) *flagLast = 0; return; } GSW_IMPL_CurrentDevPriv->lan_port_vid[portid] = INVALID_VID; for (pid=0; pidlan_port_vid[pid]==vid) { /* another port has same vid */ if (flagLast!=NULL) *flagLast = 0; /* debug */ ESHAL_LogDbg("\n*** %s:%d, *flagLast 0 ***\n", __func__, __LINE__); dumpVid(); return; } } for (fid=0; fidfid_vid[fid]==vid) GSW_IMPL_CurrentDevPriv->fid_vid[fid] = INVALID_VID; } if (flagLast!=NULL) *flagLast = 1; /* debug */ ESHAL_LogDbg("\n*** %s:%d, *flagLast 1 ***\n", __func__, __LINE__); dumpVid(); return; } /* PCE Rule for STAG is managed in GSW_IMPL_SetLanPortVlan */ #if 0 GSW_return_t InitSTAG_PCETable(u16 vlanid, Uint8 PortIdx) { pctbl_prog_t pcetable; u16 pceid, i; ESHAL_LogDbg(" \n*** %s (first entry Line#:%d, vlanid:%d, PortIdx:%d) ***\n", __func__,__LINE__, vlanid, PortIdx); for (pceid = 0; pceid < 64; pceid++) { memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = pceid; pcetable.table = PCE_ACTVLAN_INDEX; if (gsw_mem_table_read(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (pcetable.valid != 1) { ESHAL_LogDbg(" \n*** %s (first entry Line#:%d, vlanid:%d, PortIdx:%d) ***\n", __func__,__LINE__, vlanid, PortIdx); memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = pceid; pcetable.key[0] = vlanid; pcetable.valid = 1; pcetable.table = PCE_ACTVLAN_INDEX; if (gsw_mem_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } memset(&pcetable, 0, sizeof(pctbl_prog_t)); for (i = 0; i <= 8; i++) { pcetable.key[i] = 0xFFFF; } pcetable.key[8] = 0xFF; pcetable.key[8] |= (pceid << 8); pcetable.pcindex = pceid; pcetable.valid = 1; // pcetable.val[0] = 0x2003; /*VLAN action enable:b1, Port map action enable:b0 */ pcetable.val[0] = 0x003; /*VLAN action enable:b1, Port map action enable:b0 */ pcetable.val[1] = (1 << MAP_API_TO_PHYSICAL_PORT(PortIdx)); pcetable.val[2] = 0; pcetable.val[3] = 0x7F1F; pcetable.val[4] = 0x0; /* traffic flow portmap:b2:3 */ pcetable.val[5] = 0x4; /*ctag_vlanignore = 1 */ pcetable.val[6] = 0x1; /* Port BitMap Mux control:b0 */ pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } break; } else { if (pcetable.key[0] == vlanid) { pcetable.pcindex = pceid; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_read(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (pcetable.valid == 1) { pcetable.val[1] |= (1 << MAP_API_TO_PHYSICAL_PORT(PortIdx)); pcetable.pcindex = pceid; pcetable.valid = 1; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } break; } } } } return GSW_statusOk; } #endif GSW_return_t GetSTAG_PCETableId(u16 vlanid) { pctbl_prog_t pcetable; u16 pceid; ESHAL_LogDbg(" \n*** %s (Start Line#:%d, vlanid:%d) ***\n", __func__,__LINE__, vlanid); for (pceid = 0; pceid < 64; pceid++) { memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = pceid; pcetable.table = PCE_ACTVLAN_INDEX; if (gsw_mem_table_read(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (pcetable.valid == 1) { if (pcetable.key[0] == vlanid) { ESHAL_LogDbg(" \n*** %s (found entry Line#:%d, vlanid:%d) ***\n", __func__,__LINE__, vlanid); return pceid; } } } ESHAL_LogDbg(" \n*** %s (End Line#:%d, vlanid:%d) ***\n", __func__,__LINE__, vlanid); return GSW_statusErr; } GSW_return_t AddSTAG_PCETable(u16 index, Uint8 PortIdx) { pctbl_prog_t pcetable; ESHAL_LogDbg(" \n*** %s (Line#:%d, index:%d, PortIdx:%d) ***\n", __func__,__LINE__, index, PortIdx); memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = index; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_read(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (pcetable.valid == 1) { pcetable.val[1] |= (1 << MAP_API_TO_PHYSICAL_PORT(PortIdx)); pcetable.pcindex = index; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* debug */ ESHAL_LogDbg("\n*** %s:%d, Flow, pcindex %u, port %u/%u, portmap 0x%04X ***\n", __func__, __LINE__, (u32)index, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)pcetable.val[1]); } else { u16 vid = gsw_GetPortVid(PortIdx); u8 fid = gsw_GetPortFid(PortIdx); int i; if (vid==INVALID_VID || fid==INVALID_FID) { ESHAL_LogErr("\n*** %s (wrong vid/fid: 0x%04X/0x%02X) ***\n", __func__, (u32)vid, (u32)fid); return GSW_statusErr; } /* Add Active VLAN table entry */ memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.key[0] = vid; pcetable.pcindex = index; /* Active VLAN Table use same index as STAG Rule */ pcetable.valid = 1; pcetable.table = PCE_ACTVLAN_INDEX; if (gsw_mem_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* debug */ ESHAL_LogDbg("\n*** %s:%d, Active VLAN, pcindex %u, port %u/%u, vid %u ***\n", __func__, __LINE__, (u32)index, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)pcetable.key[0]); /* Add default PCE rule */ memset(&pcetable, 0, sizeof(pctbl_prog_t)); for (i=0; i<8; i++) pcetable.key[i] = 0xFFFF; pcetable.key[8] = (index<<8) | 0xFF; pcetable.val[0] = 0x0003; /* VLAN and Portmap Action Enable */ pcetable.val[1] = 1 << MAP_API_TO_PHYSICAL_PORT(PortIdx); pcetable.val[2] = (u16)fid<<8; /* alternative FID */ pcetable.val[4] = 0; /* default port map selected */ pcetable.val[5] = 0x000C | (vid<<4); /* CTAG ignore, FID Enable, CVID*/ pcetable.val[6] = 0x0001; /* STAG port member */ /* debug */ pcetable.val[0] |= 0x1000; /* RMON Action Enable */ pcetable.val[4] |= index<<8; /* Flow Counter is same as index */ pcetable.pcindex = index; pcetable.valid = 1; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* debug */ ESHAL_LogDbg("\n*** %s:%d, Flow, pcindex %u, port %u/%u, vid %u, fid %u ***\n", __func__, __LINE__, (u32)index, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)vid, (u32)fid); } return GSW_statusOk; } GSW_return_t rmSTAG_PCETable(u16 index, Uint8 PortIdx) { pctbl_prog_t pcetable; ESHAL_LogDbg(" \n*** %s (Line#:%d, index:%d, PortIdx:%d) ***\n", __func__,__LINE__, index, PortIdx); memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = index; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_read(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (pcetable.valid == 1) { pcetable.val[1] &= ~(1 << MAP_API_TO_PHYSICAL_PORT(PortIdx)); if (pcetable.val[1]==0) /* If no member, delete the STAG from Flow table */ pcetable.valid = 0; pcetable.pcindex = index; pcetable.table = PCE_TFLOW_INDEX; if (gsw_pce_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* debug */ ESHAL_LogDbg("\n*** %s:%d, Flow, pcindex %u, port %u/%u, portmap 0x%04X, valid %u ***\n", __func__, __LINE__, (u32)index, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)pcetable.val[1], (u32)pcetable.valid); if (pcetable.val[1]==0) { /* If no member, delete the STAG from Active VLAN table */ memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.pcindex = index; pcetable.valid = 0; pcetable.table = PCE_ACTVLAN_INDEX; if (gsw_mem_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* debug */ ESHAL_LogDbg("\n*** %s:%d, Active VLAN, pcindex %u, port %u/%u, vid %u, valid %u ***\n", __func__, __LINE__, (u32)index, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)pcetable.key[0], (u32)pcetable.valid); } } return GSW_statusOk; } /**************************************************************************/ /*! \fn static int gsw_CfgPortIngressVlanMode(Uint8 PortIdx, Uint8 portIngressMode); ************************************************************************** * \brief - set the port to work in 802.1Q mode modes * \param[in] - PortIdx (1-5) * \param[in] - Port ingress mode * 0-802.1q disables, * 1 - 802.1q enabled in fallback, * 2 - 802.1q enabled in check, * 3 - 802.1q enabled in scrue, * \return OK/NOK **************************************************************************/ static int gsw_CfgPortIngressVlanMode(Uint8 PortIdx, Uint8 portIngressMode) { int result = STATUS_OK; ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d, portIngressMode:%d Start***\n", __func__, __LINE__, PortIdx, portIngressMode); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } switch(portIngressMode) { case 0: /* bTVM = 1*/ if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /*VIMR = 0*/ if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } break; case 1: case 2: /* bTVM = 0*/ if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /*VIMR = 0*/ if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } break; case 3: /* bTVM = 0*/ if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /*VIMR = 1*/ if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } break; default: ESHAL_LogErr("\n *** %s:%d, PortIdx:%d, portIngressMode:%d End***\n", __func__, __LINE__, PortIdx, portIngressMode); result = STATUS_NOK; break; } ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d, portIngressMode:%d End***\n", __func__, __LINE__, PortIdx, portIngressMode); return result; } /**************************************************************************/ /*! \fn int gsw_SetPortEgressMode(Uint8 PortIdx, Uint8 egressMode) ************************************************************************** * \brief - enable / disable port * \param[in] - PortIdx (1-5) * \param[in] - egressMode * \return OK/NOK **************************************************************************/ int gsw_SetPortEgressMode(Uint8 PortIdx, Uint8 egressMode) { int result = STATUS_OK; ESHAL_LogDbg("\n*** %s:%d, PortIdx:%d,egressMode:%d Start*** \n", __func__, __LINE__, PortIdx, egressMode); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } switch(egressMode) { case 0: /* Untagged and tagged frames exit unmodified */ case 1: /* Untagged frames exit as is, tagged have vlan tag removed */ if (gsw_reg_write((FDMA_PCTRL_VLANMOD_OFFSET + (6 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), FDMA_PCTRL_VLANMOD_SHIFT, FDMA_PCTRL_VLANMOD_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } break; case 2: /* Untagged frames exit tagged (add 0x8100 + Ingress port default valn), tagged exit as is */ if (gsw_reg_write((FDMA_PCTRL_VLANMOD_OFFSET + (6 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), FDMA_PCTRL_VLANMOD_SHIFT, FDMA_PCTRL_VLANMOD_SIZE, 3)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } break; case 3: /* Discard if egress port is not in frame vlan. */ if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } break; } ESHAL_LogDbg("\n*** %s:%d, PortIdx:%d,egressMode:%d End*** \n", __func__, __LINE__, PortIdx, egressMode); return result; } /**************************************************************************/ /*! \fn int gsw_PerPortCfgSchedMode(Uint8 PortIdx, Uint8 schedMode) ************************************************************************** * \brief - configure the scheduling policy mode for each port * \param[in] - PortIdx (1-5) * \param[in] - schedMode * \return OK/NOK **************************************************************************/ static int gsw_PerPortCfgSchedMode(Uint8 PortIdx, Uint8 schedMode) { GSW_QoS_schedulerCfg_t param; u16 index; int result = STATUS_OK; ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d schedMode:%d Start***\n", __func__, __LINE__, PortIdx, schedMode); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } memset(¶m, 0, sizeof(GSW_QoS_schedulerCfg_t)); /* eType : Scheduler Type (Strict Priority/Weighted Fair Queuing). Supported Values: ----------------- 0: Strict Priority. 1: Weighted Fair Queuing. nWeight : Weight in Token. Parameter used for WFQ configuration. Sets the weight in token in relation to all remaining queues on this egress port having WFQ configuration. This parameter is only used when 'eType=GSW_QOS_SCHEDULER_WFQ'. */ switch(schedMode) { case 0: /* WEIGHTED_RR: */ for (index = 0; index < 4; index ++) { param.eType = 1; param.nQueueId = ((MAP_API_TO_PHYSICAL_PORT(PortIdx) * 4) + index); param.nWeight = 0xFFFF; if (GSW_QoS_SchedulerCfgSet(NULL, ¶m) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } break; case 1: /* STRICT_3_WEIGHTED_RR_0_2: */ for (index = 0; index < 4; index ++) { if (index == 3) param.eType = 0; else param.eType = 1; param.nQueueId = ((MAP_API_TO_PHYSICAL_PORT(PortIdx) * 4) + index); param.nWeight = 0xFFFF; if (GSW_QoS_SchedulerCfgSet(NULL, ¶m) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } break; case 2: /* STRICT_3_2_WEIGHTED_RR_0_1: */ for (index = 0; index < 4; index ++) { if ((index == 3) || (index == 2)) param.eType = 0; else param.eType = 1; param.nQueueId = ((MAP_API_TO_PHYSICAL_PORT(PortIdx) * 4) + index); param.nWeight = 0xFFFF; if (GSW_QoS_SchedulerCfgSet(NULL, ¶m) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } break; case 3: /* STRICT: */ for (index = 0; index < 4; index ++) { param.eType = 0; param.nQueueId = ((MAP_API_TO_PHYSICAL_PORT(PortIdx) * 4) + index); param.nWeight = 0xFFFF; if (GSW_QoS_SchedulerCfgSet(NULL, ¶m) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } break; default: ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = STATUS_NOK; break; } ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d schedMode:%d End***\n", __func__, __LINE__, PortIdx, schedMode); return result; } static int gsw_initINT802Dot1qMode(Uint8 portIngressMode) { ESHAL_LogDbg("\n *** %s:%d, portIngressMode:%d start ***\n", __func__, __LINE__, portIngressMode); if (gsw_CfgPortIngressVlanMode(INTERNAL_PORT, portIngressMode) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if(gsw_SetPortEgressMode(INTERNAL_PORT, 0) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_PerPortCfgSchedMode(INTERNAL_PORT, 3) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } ESHAL_LogDbg("\n *** %s:%d, portIngressMode:%d End ***\n", __func__, __LINE__, portIngressMode); return STATUS_OK; } static int gsw_initLAN802Dot1qMode(Uint8 portIngressMode) { Uint8 PortIdx; ESHAL_LogDbg("\n *** %s:%d, portIngressMode:%d start ***\n", __func__, __LINE__, portIngressMode); for (PortIdx = FIRST_EXT_PORT; PortIdx <= LAST_EXT_PORT; PortIdx++) { if (gsw_CfgPortIngressVlanMode(PortIdx, portIngressMode) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if(gsw_SetPortEgressMode(PortIdx, 1) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_PerPortCfgSchedMode(PortIdx, 3) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } ESHAL_LogDbg("\n *** %s:%d, portIngressMode:%d End ***\n", __func__, __LINE__, portIngressMode); return STATUS_OK; } /**************************************************************************/ /*! \fn int gsw_CfgPortQinQProviderSideMode(Uint8 PortIdx, Uint16 portEType) ************************************************************************** * \brief - enable port Q in Q feature * \param[in] - PortIdx (1-5) * \param[in] - portEType * \return OK/NOK **************************************************************************/ int gsw_CfgPortQinQProviderSideMode(Uint8 PortIdx, Uint16 portEType) { GSW_SVLAN_cfg_t param; GSW_QoS_PCP_ClassCfg_t cpcpcfg; GSW_QoS_SVLAN_PCP_ClassCfg_t spcpcfg; GSW_QoS_SVLAN_ClassPCP_PortCfg_t spcpegcfg; u16 index; int result = STATUS_OK; ESHAL_LogDbg(" \n *** %s:%d, PortIdx:%d, portEType:0x%x Start***\n", __func__, __LINE__, PortIdx,portEType); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } memset(¶m, 0, sizeof(GSW_SVLAN_cfg_t)); /* nEthertype is for all the ports */ /* Define FDMA Service VLAN tag Ethernet type to portEtype*/ param.nEthertype = portEType; GSW_SVLAN_CfgSet(NULL, ¶m); /* bSVLAN_TagSupport (Enable PortIdx Service VLAN tag ) */ if (gsw_reg_write((PCE_VCTRL_STEN_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_STEN_SHIFT, PCE_VCTRL_STEN_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* memset(&cpcpcfg, 0, sizeof(GSW_QoS_PCP_ClassCfg_t)); */ for (index=0; index= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_VCTRL_STEN_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_STEN_SHIFT, PCE_VCTRL_STEN_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, &value) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (value) { if (gsw_reg_write(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, 0) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } if (gsw_reg_write((PCE_VCTRL_STVM_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_STVM_SHIFT, PCE_VCTRL_STVM_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_VCTRL_SVIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (gsw_reg_write((PCE_VCTRL_SVEMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } if (gsw_reg_write((FDMA_PCTRL_SVLANMOD_OFFSET + (6 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), FDMA_PCTRL_SVLANMOD_SHIFT, FDMA_PCTRL_SVLANMOD_SIZE, 3)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } ESHAL_LogDbg(" \n *** %s:%d, PortIdx:%d, End***\n", __func__, __LINE__, PortIdx); return result; } /**************************************************************************/ /*! \fn int gsw_CfgPortQinQCustomerSideMode(Uint8 PortIdx) ************************************************************************** * \brief - enable port in customer mode - a Q in Q transparent port * \param[in] - PortIdx (1-5) * \return OK/NOK **************************************************************************/ int gsw_CfgPortQinQCustomerSideMode(Uint8 PortIdx) { int result = STATUS_OK; u16 value; ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d *** Start\n", __func__, __LINE__, PortIdx); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, &value) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (!value) { /* Enable VLAN-aware Switching */ if (gsw_reg_write(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, 1) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } /* Disable bSVLAN_TagSupport */ if (gsw_reg_write((PCE_VCTRL_STEN_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_STEN_SHIFT, PCE_VCTRL_STEN_SIZE, 0)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* bTVM = 1*/ if (gsw_reg_write((PCE_PCTRL_0_TVM_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_PCTRL_0_TVM_SHIFT, PCE_PCTRL_0_TVM_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* SVIMR Enable PortIdx Service VLAN tag discard on ingress SVIMR*/ if (gsw_reg_write((PCE_VCTRL_SVIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_SVIMR_SHIFT, PCE_VCTRL_SVIMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* Enable PortIdx Service VLAN tag discard on ingress SVEMR */ if (gsw_reg_write((PCE_VCTRL_SVEMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_SVEMR_SHIFT, PCE_VCTRL_SVEMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /*Enable PortIdx Customer VLAN tag discard on ingress VIMR*/ if (gsw_reg_write((PCE_VCTRL_VIMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VIMR_SHIFT, PCE_VCTRL_VIMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Enable PortIdx Customer VLAN tag discard on ingress VEMR*/ if (gsw_reg_write((PCE_VCTRL_VEMR_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_VCTRL_VEMR_SHIFT, PCE_VCTRL_VEMR_SIZE, 1)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d *** End\n", __func__, __LINE__, PortIdx); return result; } /**************************************************************************/ /*! \fn int gsw_CfgPortQinQProviderSetVlan(Uint8 PortIdx, Uint16 vlanid) ************************************************************************** * \brief - enable port Q in Q feature * \param[in] - PortIdx (1-5) * \param[in] - The VID that will be assigned as a tag * \return OK/NOK **************************************************************************/ int gsw_CfgPortQinQProviderSetVlan(Uint8 PortIdx, Uint16 vlanid) { int result = STATUS_OK; u16 value; ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d, vlanid:%d Start***\n", __func__, __LINE__, PortIdx, vlanid); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, &value) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (!value) { /* Enable VLAN-aware Switching */ if (gsw_reg_write(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, 1) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } if (gsw_reg_write((PCE_DEFPSVID_PVID_OFFSET + (2 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_DEFPSVID_PVID_SHIFT, PCE_DEFPSVID_PVID_SIZE, vlanid)!= GSW_statusOk){ ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* PCE Rule for STAG is managed in GSW_IMPL_SetLanPortVlan */ #if 0 if(InitSTAG_PCETable(vlanid, PortIdx) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } #endif ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d, vlanid:%d End***\n", __func__, __LINE__, PortIdx, vlanid); return result; } int gsw_dis_CfgPortQinQProviderSetVlan(Uint8 PortIdx, Uint16 vlanid) { int result = STATUS_OK; u16 value; GSW_return_t rpceid; ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d, vlanid:%d Start***\n", __func__, __LINE__, PortIdx, vlanid); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, &value) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (value) { if (gsw_reg_write(PCE_GCTRL_0_VLAN_OFFSET, PCE_GCTRL_0_VLAN_SHIFT, PCE_GCTRL_0_VLAN_SIZE, 0) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } if (gsw_reg_write((PCE_DEFPSVID_PVID_OFFSET + (2 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_DEFPSVID_PVID_SHIFT, PCE_DEFPSVID_PVID_SIZE, 0)!= GSW_statusOk){ ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } rpceid = GetSTAG_PCETableId(vlanid); ESHAL_LogDbg(" \n*** %s ( VLAN in table Line#:%d, rpceid:%d) ***\n", __func__,__LINE__,rpceid); if ((rpceid >= 0) && (rpceid < 64)) { if ( rmSTAG_PCETable(rpceid, PortIdx) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } else { ESHAL_LogWarn(" \n*** %s (Not found VLAN in table Line#:%d) ***\n", __func__,__LINE__); } ESHAL_LogDbg("\n *** %s:%d, PortIdx:%d, vlanid:%d End***\n", __func__, __LINE__, PortIdx, vlanid); return result; } /**************************************************************************/ /*! \fn int gsw_ChangePortDefaultVid(Uint16 vlanid, Uint8 PortIdx); ************************************************************************** * \brief - get or clean violation register * The default vlan is used to tag an untagged traffic when the port is configured to be * a 802.1q port. * The port has 3 egress modes: * PORT IS MEMBER EGRESS UNMODIFIED - packets leave unmodified with VLAN tag * PORT IS MEMBER EGRESS UNTAGGED - packets leave without a VLAN tag * PORT IS MEMBER EGRESS TAGGED - packets leave with a VLAN tag * packets ingress without VLAN receive the default vlan tag of the ports belonging to the sub VLAN network * packets ingress with VLAN there VLAN must match the default VLAN tag of the ports belonging to the sub VLAN network * * \param[in] - vlanid * \param[in] - PortIdx * \return OK/NOK **************************************************************************/ int gsw_ChangePortDefaultVid(Uint16 vlanid, Uint8 PortIdx) { int result = STATUS_OK; ESHAL_LogDbg(" \n *** %s:%d, vlanid:%d, PortIdx:%d Start***\n", __func__, __LINE__, vlanid, PortIdx); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_DEFPVID_PVID_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_DEFPVID_PVID_SHIFT, PCE_DEFPVID_PVID_SIZE, vlanid)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_DEFPSVID_PVID_OFFSET + (2 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_DEFPSVID_PVID_SHIFT, PCE_DEFPSVID_PVID_SIZE, vlanid)!= GSW_statusOk){ ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* debug */ { u16 v1, v2; gsw_reg_read((PCE_DEFPVID_PVID_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_DEFPVID_PVID_SHIFT, PCE_DEFPVID_PVID_SIZE, &v1); gsw_reg_read((PCE_DEFPSVID_PVID_OFFSET + (2 * MAP_API_TO_PHYSICAL_PORT(PortIdx))), PCE_DEFPSVID_PVID_SHIFT, PCE_DEFPSVID_PVID_SIZE, &v2); ESHAL_LogDbg("\n*** %s:%d, port %u/%u DEFPVID %u, DEFPSVID %d ***\n", __func__, __LINE__, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)v1, (u32)v2); } ESHAL_LogDbg(" \n *** %s:%d, vlanid:%d, PortIdx:%d End***\n", __func__, __LINE__, vlanid, PortIdx); return result; } /**************************************************************************/ /*! \fn int gsw_VlanPortAdd(Uint16 vlanid, Uint8 PortIdx, VTU_MEMBER_TAG_e portMemberTag); ************************************************************************** * \brief - add/remove a VLAN tag to a port * \param[in] - vlanid * \param[in] - PortIdx (1-5) * \param[in] - portMemberTag * \return OK/NOK **************************************************************************/ int gsw_VlanPortAdd(Uint16 vlanid, Uint8 PortIdx, Uint8 portMemberTag) { int result = STATUS_OK; u8 fid; u8 flagNew; GSW_VLAN_IdCreate_t idparam; GSW_VLAN_portMemberAdd_t mparam; ESHAL_LogDbg("\n*** %s:%d, vlanid:%d, PortIdx:%d,portMemberTag:%d Start*** \n", __func__, __LINE__, vlanid, PortIdx, portMemberTag); if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* PCE_DEFPVID.PVID and PCE_DEFPSVID.PVID */ if (gsw_ChangePortDefaultVid(vlanid, PortIdx) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } fid = gsw_AllocFid(PortIdx, vlanid, &flagNew); if (fid==INVALID_FID) { ESHAL_LogErr("\n*** %s (gsw_AllocFid(%d, %d) fail) ***\n", __func__, (u32)PortIdx, (u32)vlanid); return STATUS_NOK; } /* debug */ ESHAL_LogDbg("\n*** %s:%d, gsw_AllocFid(%u/%u, %u) return %u ***\n", __func__, __LINE__, (u32)PortIdx, (u32)MAP_API_TO_PHYSICAL_PORT(PortIdx), (u32)vlanid, (u32)fid); /* Add STAG rule for LAN Port */ if (AddSTAG_PCETable(fid+STAG_RULES_INDEX-START_FID, PortIdx) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Add STAG rule for Internal Port */ if (flagNew && AddSTAG_PCETable(fid+STAG_RULES_INDEX-START_FID, INTERNAL_PORT) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Create VLAN ID (CTAG) to link with FID */ if (flagNew) { memset(&idparam, 0, sizeof(idparam)); idparam.nVId = vlanid; idparam.nFId = fid; if (GSW_VLAN_IdCreate(NULL, &idparam)!=GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } /* Add CTAG (4K VLAN) for LAN port */ memset(&mparam, 0, sizeof(mparam)); mparam.nVId = vlanid; mparam.nPortId = MAP_API_TO_PHYSICAL_PORT(PortIdx); mparam.bVLAN_TagEgress = portMemberTag==2 ? 1 : 0; if (GSW_VLAN_PortMemberAdd(NULL, &mparam)!=GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Add CTAG (4K VLAN) for Internal port */ if (flagNew) { memset(&mparam, 0, sizeof(mparam)); mparam.nVId = vlanid; mparam.nPortId = MAP_API_TO_PHYSICAL_PORT(INTERNAL_PORT); mparam.bVLAN_TagEgress = portMemberTag==2 ? 1 : 0; if (GSW_VLAN_PortMemberAdd(NULL, &mparam)!=GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } ESHAL_LogDbg("\n*** %s:%d, vlanid:%d, PortIdx:%d,portMemberTag:%d End*** \n", __func__, __LINE__, vlanid, PortIdx, portMemberTag); return result; } int gsw_VlanPortRemove(Uint16 vlanid, Uint8 PortIdx) { int result = STATUS_OK; GSW_VLAN_portMemberRemove_t rparam; Uint8 fid; u8 flagLast; GSW_VLAN_IdDelete_t idparam; ESHAL_LogDbg("\n*** %s:%d, vlanid:%d, PortIdx:%d Start*** \n", __func__, __LINE__, vlanid, PortIdx); if (gsw_ChangePortDefaultVid(0, PortIdx) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Remove port from VLAN (CTAG) */ memset(&rparam, 0, sizeof(GSW_VLAN_portMemberRemove_t)); rparam.nVId = vlanid; rparam.nPortId = MAP_API_TO_PHYSICAL_PORT(PortIdx); if (GSW_VLAN_PortMemberRemove(NULL, &rparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Remove port from VLAN (STAG) */ fid = gsw_GetPortFid(PortIdx); if (fid!=INVALID_FID && rmSTAG_PCETable(fid+STAG_RULES_INDEX-START_FID, PortIdx) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Free FID from PortIdx/vlanid */ flagLast = 0; gsw_FreeFid(PortIdx, vlanid, &flagLast); /* Remove Internal port if no more LAN port in the VLAN */ if (flagLast) { /* Remove Internal port from VLAN (CTAG) */ memset(&rparam, 0, sizeof(GSW_VLAN_portMemberRemove_t)); rparam.nVId = vlanid; rparam.nPortId = MAP_API_TO_PHYSICAL_PORT(INTERNAL_PORT); if (GSW_VLAN_PortMemberRemove(NULL, &rparam) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Delete VLAN ID (CTAG) */ memset(&idparam, 0, sizeof(idparam)); idparam.nVId = vlanid; if (GSW_VLAN_IdDelete(NULL, &idparam)!=GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Remove Internal port from VLAN (STAG) */ if (fid!=INVALID_FID && rmSTAG_PCETable(fid+STAG_RULES_INDEX-START_FID, INTERNAL_PORT) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } ESHAL_LogDbg("\n*** %s:%d, vlanid:%d, PortIdx:%d End*** \n", __func__, __LINE__, vlanid, PortIdx); return result; } static int gsw_setCpuPortVlan(Uint16 Vid) { ESHAL_LogDbg("%s:%d GSW implementation Start (Vid:%d)...!\n", __func__, __LINE__,Vid); if (Vid >= 4096) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_CfgPortQinQProviderSetVlan(INTERNAL_PORT, Vid) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* CPU Port VLAN is coupled in LAN Port VLAN, no need to add here */ #if 0 if (gsw_VlanPortAdd(Vid, INTERNAL_PORT, 2) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } #endif ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } static int gsw_disCpuPortVlan(Uint16 Vid) { pctbl_prog_t pcetable; u16 idx; ESHAL_LogDbg("%s:%d GSW implementation Start (Vid:%d)...!\n", __func__, __LINE__,Vid); if (Vid >= 4096) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_dis_CfgPortQinQProviderSetVlan(INTERNAL_PORT, Vid) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } #if 0 /* not add Internal Port to default again */ if (gsw_VlanPortAdd(Vid, INTERNAL_PORT, 1) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } #else /* de-activate Active VLAN and Flow Table entries */ memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_ACTVLAN_INDEX; pcetable.valid = 0; for (idx=0; idx<64; idx++) { pcetable.pcindex = idx; if (gsw_mem_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } memset(&pcetable, 0, sizeof(pctbl_prog_t)); pcetable.table = PCE_TFLOW_INDEX; pcetable.valid = 0; for (idx=STAG_RULES_INDEX; idx<=STAG_RULES_INDEX_MAX; idx++) { pcetable.pcindex = idx; if (gsw_pce_table_write(NULL, &pcetable)!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } #endif ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #if 0 /* In ProviderBridgedMode, LAN Port is added to VLAN. In Non-ProviderBridgedMode, VLAN is not aware. */ static int gsw_setLanPortVlan(Uint8 LanPortIdx, Uint16 Vid) { ESHAL_LogDbg("%s:%d GSW implementation Start (LanPortIdx:%d, Vid:%d)...!\n", __func__, __LINE__,LanPortIdx,Vid); if ((LanPortIdx >= MAX_LTQ_PORTS) || ((Vid > EXTSWITCH_MAX_VLAN) && (Vid < EXTSWITCH_MIN_VLAN))) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_ChangePortDefaultVid(Vid, LanPortIdx) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_VlanPortAdd(Vid, LanPortIdx, 1) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #endif /* MAC DA Table index write */ static int pce_da_mac_tbl_write(void *cdev, u16 index, pce_da_prog_t *parm) { pctbl_prog_t ptbl; memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACDA_INDEX; ptbl.pcindex = index; ptbl.key[0] = (parm->mac[4] << 8 | parm->mac[5]); ptbl.key[1] = (parm->mac[2] << 8 | parm->mac[3]); ptbl.key[2] = (parm->mac[0] << 8 | parm->mac[1]); ptbl.mask[0] = parm->mac_mask; ptbl.valid = 1; return gsw_pce_table_write(cdev, &ptbl); } /* MAC DA Table delete */ static int pce_tm_da_mac_tbl_delete(void *cdev, u16 index) { pctbl_prog_t ptbl; memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACDA_INDEX; ptbl.pcindex = index; return gsw_pce_table_write(cdev, &ptbl); } static GSW_return_t gsw_lacpConfig(u8 enable) { pce_da_prog_t macda; pctbl_prog_t pcetable; int i; if (enable) { /* Allocate MAC DA table entr 0 for LACP */ memset(&macda, 0, sizeof(macda)); macda.mac[0] = 0x01; macda.mac[1] = 0x80; macda.mac[2] = 0xC2; macda.mac[3] = 0x00; macda.mac[4] = 0x00; macda.mac[5] = 0x02; macda.mac_mask = 0; if (pce_da_mac_tbl_write(NULL, 0, &macda)!=GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } /* LACP rule for LAN Ports ingress packet */ memset(&pcetable, 0, sizeof(pcetable)); for (i=0; i<9; i++) pcetable.key[i] = 0xFFFF; pcetable.key[5] &= 0x00FF; /* MAC DA Table Entry 0 */ pcetable.val[0] = 0x0001; /* Portmap Action Enable */ pcetable.val[1] = 1<DevPriv[i], 0, sizeof(PrivData->DevPriv[i])); PrivData->DevPriv[i].DevIdx = EXTSWITCH_IDX_INVALID_SWITCH; memcpy(PrivData->DevPriv[i].mapApiToPhysicalPort, mapApiToPhysicalPort_def, sizeof(PrivData->DevPriv[i].mapApiToPhysicalPort)); memcpy(PrivData->DevPriv[i].mapApiToPhysicalPortPuma7, mapApiToPhysicalPortPuma7_def, sizeof(PrivData->DevPriv[i].mapApiToPhysicalPortPuma7)); memcpy(PrivData->DevPriv[i].mapPhysicalToApiPort, mapPhysicalToApiPort_def, sizeof(PrivData->DevPriv[i].mapPhysicalToApiPort)); memcpy(PrivData->DevPriv[i].mapPhysicalToApiPortPuma7, mapPhysicalToApiPortPuma7_def, sizeof(PrivData->DevPriv[i].mapPhysicalToApiPortPuma7)); for (j=0; jDevPriv[i].lan_port_vid[j] = INVALID_VID; PrivData->DevPriv[i].fid_vid[j] = INVALID_VID; PrivData->DevPriv[i].lan_port_pcp[j] = INVALID_PCP; } } return STATUS_OK; } /**************************************************************************/ /*! \fn STATUS GSW_IMPL_EnableProviderBridgedMode(Uint16 STagTpid) ************************************************************************** * \brief * Puts switch in Provider Bridged Mode. In this mode the switch processes the frames according to the following rules: * Ingressing from: * Internal port (port that connects to Puma): * Accept condition: * 1. Frame is tagged (possibly double) * 2. Outer VTAG TPID equals to STagTpid * Possible egress ports: * LAN Ports (Any ports except Internal) assigned to outer VTAG VID (via SetLanPortVlan) * Modifications: * Outer VTAG is removed * * LAN Port: * Accept condition: * Anything goes * Possible egress ports: * LAN ports assigned to the same VLAN (via SetLanPortVlan) and the Internal port * Modifications: * When egressing on Internal port: * VTAG added with TPID == STagTpid, VID == LAN port VLAN * Egressing on a LAN port: * None * * Enables strict priority scheduling of the egressing frames for all ports as recommended by the 802.1p. * Untagged frames are considered having PCP == 0 (best effort). * For tagged frames (either outer VTAG TPID == 0x8100 for LAN-ingressing frames, or outer VTAG TPID == STagTpid for Internal port-ingressing frames), * outer VTAG PCP is used for priority mapping. The following mapping should be used: * PCP Priority Acronym Traffic types * 1 0 (lowest) BK Background * 0 1 BE Best Effort * 2 2 EE Excellent Effort * 3 3 CA Critical Applications * 4 4 VI Video, < 100 ms latency and jitter * 5 5 VO Voice, < 10 ms latency and jitter * 6 6 IC Internetwork Control * 7 7 (highest) NC Network Control * * It is expected that switch will enforce strict priority scheduling upon selecting a frame for transmission. * i.e. If N frames are ready to be transmitted on a port, frame having the highest priority will be selected for transmission. * * Calling this function when the switch is already in Provider Bridge Mode is allowed and will change STagTpid. * * \param[in] * STagTpid - Frames ingressing from the Internal port must have this TPID, otherwise they will be dropped. * Frames egressing from the Internal port is added with VTAG having TPID set to this value. * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_EnableProviderBridgedMode(Uint8 DevIdx, Uint16 STagTpid) { Uint8 idx; ESHAL_LogDbg("%s:%d GSW implementation Start (DevIdx:%d, STagTpid:0x%x)...!\n", __func__, __LINE__, DevIdx, STagTpid); /* Setup DevIdx for internal RTK driver functions */ GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_initINT802Dot1qMode(1) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_CfgPortQinQProviderSideMode(INTERNAL_PORT, STagTpid) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } for ( idx = FIRST_EXT_PORT; idx <= LAST_EXT_PORT; idx++) { if (gsw_CfgPortQinQCustomerSideMode(idx) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } if (gsw_setCpuPortVlan(EXTSWITCH_DEF_LAN_PORTS_VLAN) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Set provider mode flag before recover VLAN and PCP */ GSW_IMPL_CurrentDevPriv->provider_mode = 1; for ( idx = FIRST_EXT_PORT; idx <= LAST_EXT_PORT; idx++) { Uint16 vid; Uint8 pcp; /* either recover VLAN or use default VLAN */ vid = GSW_IMPL_CurrentDevPriv->lan_port_vid[idx]; if (vid==INVALID_VID) vid = EXTSWITCH_DEF_LAN_PORTS_VLAN; else GSW_IMPL_CurrentDevPriv->lan_port_vid[idx] = INVALID_VID; if (GSW_IMPL_SetLanPortVlan(DevIdx, idx, vid) != STATUS_OK) { GSW_IMPL_CurrentDevPriv->provider_mode = 0; ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* either recover PCP or use default PCP */ pcp = GSW_IMPL_CurrentDevPriv->lan_port_pcp[idx]; if (pcp==INVALID_PCP) pcp = EXTSWITCH_DEF_LAN_PORTS_PCP; else GSW_IMPL_CurrentDevPriv->lan_port_pcp[idx] = INVALID_PCP; if (GSW_IMPL_SetLanPortPcp(DevIdx, idx, pcp) != STATUS_OK) { GSW_IMPL_CurrentDevPriv->provider_mode = 0; ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } /* enable LACP packet forwarding from LAN to Internal port (no flooding) */ if (gsw_lacpConfig(1)!=GSW_statusOk) { GSW_IMPL_CurrentDevPriv->provider_mode = 0; ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } /**************************************************************************/ /*! \fn STATUS GSW_IMPL_DisableProviderBridgedMode(void) ************************************************************************** * \brief * Puts switch in VLAN unaware mode. No 802.1q support - every port communicates with every port, * frames are not dropped due to VLAN rules nor modified. * \param[in] * None * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_DisableProviderBridgedMode(Uint8 DevIdx) { Uint8 idx; ESHAL_LogDbg("%s:%d GSW implementation Start (DevIdx:%d)...!\n", __func__, __LINE__, DevIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* disable LACP packet forwarding from LAN to Internal port (no flooding) */ if (gsw_lacpConfig(0)!=GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } gsw_dis_CfgPortQinQProviderSideMode(INTERNAL_PORT); gsw_disCpuPortVlan(EXTSWITCH_DEF_LAN_PORTS_VLAN); /* free all fid_vid because 4K VLAN/Active VLAN/Flow (STAG) tables are reset. but keep lan_port_vid and lan_port_pcp for re-enable Provider Bridged Mode. */ for (idx=0; idxfid_vid[idx] = INVALID_VID; /* clear default port PCP and disable SPCP remarking */ for ( idx = FIRST_EXT_PORT; idx <= LAST_EXT_PORT; idx++) { if (gsw_reg_write((PCE_PCTRL_2_SPCPEN_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(idx))), PCE_PCTRL_2_SPCPEN_SHIFT, PCE_PCTRL_2_SPCPEN_SIZE, 0) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_PCTRL_2_PCLASS_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(idx))), PCE_PCTRL_2_PCLASS_SHIFT, PCE_PCTRL_2_PCLASS_SIZE, 0) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } /* clear provider mode flag to indicate bypass table/register programming in GSW_IMPL_SetLanPortVlan and GSW_IMPL_SetLanPortPcp */ GSW_IMPL_CurrentDevPriv->provider_mode = 0; ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } /**************************************************************************/ /*! \fn STATUS GSW_IMPL_SetLanPortVlan(Uint8 LanPortIdx, Uint16 Vid) ************************************************************************** * \brief * Set LAN Port VLAN. LAN Port is any port except the port connected to PUMA. * Only one VLAN can be assigned to a LAN port. * Refer to EnableProviderBridgedMode for more information. * * \param[in] * LanPortIdx - Index of the LAN port. Valid values are indexes of LAN ports (excluding EXTSWITCH_IDX_INTERNAL_PORT) * Vid - VLAN Id for assignment. Valid values are EXTSWITCH_MIN_VLAN to EXTSWITCH_MAX_VLAN. * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_SetLanPortVlan(Uint8 DevIdx, Uint8 LanPortIdx, Uint16 Vid) { u16 pvid; ESHAL_LogDbg("%s:%d GSW implementation Start (DevIdx:%d, LanPortIdx:%d, Vid:%d)...!\n", __func__, __LINE__,DevIdx, LanPortIdx,Vid); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if ((LanPortIdx >= MAX_LTQ_PORTS) || ((Vid > EXTSWITCH_MAX_VLAN) && (Vid < EXTSWITCH_MIN_VLAN))) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* Port is in VLAN with Vid */ pvid = gsw_GetPortVid(LanPortIdx); if (pvid==Vid) return STATUS_OK; /* if not in provider mode, record Vid only and bypass table/register programming */ if (!GSW_IMPL_CurrentDevPriv->provider_mode) { GSW_IMPL_CurrentDevPriv->lan_port_vid[LanPortIdx] = Vid; return STATUS_OK; } /* Remove Port from existing VLAN */ if (pvid!=INVALID_VID && gsw_VlanPortRemove(pvid, LanPortIdx) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_VlanPortAdd(Vid, LanPortIdx, 1) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } /**************************************************************************/ /*! \fn STATUS GSW_IMPL_SetLanPortPcp(Uint8 LanPortIdx, Uint16 Pcp) ************************************************************************** * \brief * Set LAN Port PCP. LAN Port is any port except the port connected to PUMA. * Only one VLAN can be assigned to a LAN port. * Refer to EnableProviderBridgedMode for more information. * * \param[in] * LanPortIdx - Index of the LAN port. Valid values are indexes of LAN ports (excluding EXTSWITCH_IDX_INTERNAL_PORT) * Pcp - Pcp for assignment. Valid values are EXTSWITCH_MIN_VLAN to EXTSWITCH_MAX_VLAN. * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_SetLanPortPcp(Uint8 DevIdx, Uint8 LanPortIdx, Uint8 Pcp) { ESHAL_LogDbg("%s:%d GSW implementation Start (DevIdx:%d, LanPortIdx:%d, Pcp:%d)...!\n", __func__, __LINE__, (u32)DevIdx, (u32)LanPortIdx, (u32)Pcp); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if ((LanPortIdx >= MAX_LTQ_PORTS) || (Pcp > EXTSWITCH_MAX_PCP)) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } GSW_IMPL_CurrentDevPriv->lan_port_pcp[LanPortIdx] = Pcp; if (GSW_IMPL_CurrentDevPriv->provider_mode) { if (gsw_reg_write((PCE_PCTRL_2_SPCPEN_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(LanPortIdx))), PCE_PCTRL_2_SPCPEN_SHIFT, PCE_PCTRL_2_SPCPEN_SIZE, 1) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_write((PCE_PCTRL_2_PCLASS_OFFSET + (10 * MAP_API_TO_PHYSICAL_PORT(LanPortIdx))), PCE_PCTRL_2_PCLASS_SHIFT, PCE_PCTRL_2_PCLASS_SIZE, gsw_pcp2class[Pcp]) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #if 0 /**************************************************************************/ /*! \fn STATUS GSW_IMPL_GetPortCounters(Uint8 PortIdx, EXTSWITCH_PortCounters_t * PortCounters) ************************************************************************** * \brief * Get port counters. * \param[in] * PortIdx - Port index. * \param[out] * PortCounters * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_GetPortCounters(Uint8 DevIdx, Uint8 PortIdx, EXTSWITCH_PortCounters_t * PortCounters) { GSW_RMON_Port_cnt_t param; ESHAL_LogDbg("%s:%d GSW implementation Start (DevIdx:%d, PortIdx:%d)...!\n", __func__, __LINE__, DevIdx, PortIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if ((GSW_IMPL_CurrentDevPriv->support_rgmii_int_port) && (PortIdx == EXTSWITCH_IDX_FIRST_LAN_PORT)) { ESHAL_LogWarn("Port %d: Counters are in-operative in isolation mode", EXTSWITCH_IDX_FIRST_LAN_PORT); } memset(¶m, 0, sizeof(GSW_RMON_Port_cnt_t)); param.nPortId = MAP_API_TO_PHYSICAL_PORT(PortIdx); if (GSW_RMON_Port_Get(NULL, ¶m) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } #if defined(RMON_DEBUG) && RMON_DEBUG ESHAL_LogDbg(" \n***Port Counters :---------------\n"); ESHAL_LogDbg("nPortId: %d\n", param.nPortId); ESHAL_LogDbg("nRxGoodPkts:%d\n", param.nRxGoodPkts); ESHAL_LogDbg("nRxUnicastPkts:%d\n", param.nRxUnicastPkts); ESHAL_LogDbg("nRxBroadcastPkts:%d\n", param.nRxBroadcastPkts); ESHAL_LogDbg("nRxMulticastPkts:%d\n", param.nRxMulticastPkts); ESHAL_LogDbg("nRxFCSErrorPkts:%d\n", param.nRxFCSErrorPkts); ESHAL_LogDbg("nRxUnderSizeGoodPkts:%d\n", param.nRxUnderSizeGoodPkts); ESHAL_LogDbg("nRxOversizeGoodPkts:%d\n", param.nRxOversizeGoodPkts); ESHAL_LogDbg("nRxUnderSizeErrorPkts:%d\n", param.nRxUnderSizeErrorPkts); ESHAL_LogDbg("nRxGoodPausePkts:%d\n", param.nRxGoodPausePkts); ESHAL_LogDbg("nRxOversizeErrorPkts:%d\n", param.nRxOversizeErrorPkts); ESHAL_LogDbg("nRxAlignErrorPkts:%d\n", param.nRxAlignErrorPkts); ESHAL_LogDbg("nRxFilteredPkts:%d\n", param.nRxFilteredPkts); ESHAL_LogDbg("nRx64BytePkts:%d\n", param.nRx64BytePkts); ESHAL_LogDbg("nRx127BytePkts:%d\n", param.nRx127BytePkts); ESHAL_LogDbg("nRx255BytePkts:%d\n", param.nRx255BytePkts); ESHAL_LogDbg("nRx511BytePkts:%d\n", param.nRx511BytePkts); ESHAL_LogDbg("nRx1023BytePkts:%d\n", param.nRx1023BytePkts); ESHAL_LogDbg("nRxMaxBytePkts:%d\n", param.nRxMaxBytePkts); ESHAL_LogDbg("nTxGoodPkts:%d\n", param.nTxGoodPkts); ESHAL_LogDbg("nTxUnicastPkts:%d\n", param.nTxUnicastPkts); ESHAL_LogDbg("nTxBroadcastPkts:%d\n", param.nTxBroadcastPkts); ESHAL_LogDbg("nTxMulticastPkts:%d\n", param.nTxMulticastPkts); ESHAL_LogDbg("nTxSingleCollCount:%d\n", param.nTxSingleCollCount); ESHAL_LogDbg("nTxMultCollCount:%d\n", param.nTxMultCollCount); ESHAL_LogDbg("nTxLateCollCount:%d\n", param.nTxLateCollCount); ESHAL_LogDbg("nTxExcessCollCount:%d\n", param.nTxExcessCollCount); ESHAL_LogDbg("nTxCollCount:%d\n", param.nTxCollCount); ESHAL_LogDbg("nTxPauseCount:%d\n", param.nTxPauseCount); ESHAL_LogDbg("nTx64BytePkts:%d\n", param.nTx64BytePkts); ESHAL_LogDbg("nTx127BytePkts:%d\n", param.nTx127BytePkts); ESHAL_LogDbg("nTx255BytePkts:%d\n", param.nTx255BytePkts); ESHAL_LogDbg("nTx511BytePkts:%d\n", param.nTx511BytePkts); ESHAL_LogDbg("nTx1023BytePkts:%d\n", param.nTx1023BytePkts); ESHAL_LogDbg("nTxMaxBytePkts:%d\n", param.nTxMaxBytePkts); ESHAL_LogDbg("nTxDroppedPkts:%d\n", param.nTxDroppedPkts); ESHAL_LogDbg("nTxAcmDroppedPkts:%d\n", param.nTxAcmDroppedPkts); ESHAL_LogDbg("nRxDroppedPkts:%d\n", param.nRxDroppedPkts); ESHAL_LogDbg("\t%40s:\t%lu (0x%0lx)\n", "nRxGoodBytes", (unsigned long)param.nRxGoodBytes, (unsigned long)param.nRxGoodBytes); ESHAL_LogDbg("\t%40s:\t%lu (0x%0lx)\n", "nRxBadBytes", (unsigned long)param.nRxBadBytes, (unsigned long)param.nRxBadBytes); ESHAL_LogDbg("\t%40s:\t%lu (0x%0lx)\n", "nTxGoodBytes", (unsigned long)param.nTxGoodBytes, (unsigned long)param.nTxGoodBytes); #endif PortCounters->GoodPacketsIn = param.nRxGoodPkts; PortCounters->BadPacketsIn = (param.nRxFCSErrorPkts \ + param.nRxAlignErrorPkts); PortCounters->PacketsOut = param.nTxGoodPkts; PortCounters->UnicastPacketsIn = param.nRxUnicastPkts; PortCounters->BcastPacketsIn = param.nRxBroadcastPkts; PortCounters->McastPacketsIn = param.nRxMulticastPkts; PortCounters->UnicastPacketsOut = param.nTxUnicastPkts; PortCounters->BcastPacketsOut = param.nTxBroadcastPkts; PortCounters->McastPacketsOut = param.nTxMulticastPkts; PortCounters->Collisions = (param.nTxSingleCollCount \ + param.nTxCollCount + param.nTxMultCollCount + param.nTxLateCollCount);\ PortCounters->OctectsIn = param.nRxGoodBytes; PortCounters->OctectsOut = param.nTxGoodBytes; PortCounters->ValidCounters = (EXTSWITCH_PORTCNT_UNICAST_IN | EXTSWITCH_PORTCNT_UNICAST_OUT | EXTSWITCH_PORTCNT_MCAST_IN | EXTSWITCH_PORTCNT_MCAST_OUT | EXTSWITCH_PORTCNT_BCAST_IN | EXTSWITCH_PORTCNT_BCAST_OUT | EXTSWITCH_PORTCNT_COLISIONS | EXTSWITCH_PORTCNT_OCTECTS_IN | EXTSWITCH_PORTCNT_OCTECTS_OUT); ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #endif /**************************************************************************/ /*! \fn STATUS GSW_IMPL_SetPhyPortSpeedDuplex(Uint8 PhyPortIdx, EXTSWITCH_PortSpeeds_e PhySpeed, Bool FullDp); ************************************************************************** * \brief * Set speed and duplex on a MAC-PHY port. * MAC-PHY ports can be determined via EXTSWITCH_GetConfig * \param[in] * PhyPortIdx - Port index. Valid values are indexes of ports with PHY attached. * Phy ports can be determined via EXTSWITCH_GetSwitchCaps * * LinkSpeed - Desired link speed for MAC/PHY or EXTSWITCH_SPEED_AUTONEG. * * FullDp - Desired duplex mode. * Only relevant if LinkSpeed is not EXTSWITCH_SPEED_AUTONEG. * * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_SetPhyPortSpeedDuplex(Uint8 DevIdx, Uint8 PhyPortIdx, EXTSWITCH_PortSpeeds_e PhySpeed, Bool FullDp) { u16 data, phy_addr, phy_ctrl = 0; GSW_MDIO_data_t mddata, rddata; ESHAL_LogDbg("%s:%d GSW implementation Start(DevIdx:%d, PhyPortIdx:%d)...!\n", __func__, __LINE__, DevIdx, PhyPortIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (PhyPortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (PhyPortIdx != INTERNAL_PORT) { data = 3; /*default value*/ switch(PhySpeed) { case EXTSWITCH_PORTSPEED_UNK: break; case EXTSWITCH_PORTSPEED_AUTONEG: break; case EXTSWITCH_PORTSPEED_10_MBPS: data = 0; if(FullDp == 0) phy_ctrl = PHY_AN_ADV_10HDX; else phy_ctrl = PHY_AN_ADV_10FDX; break; case EXTSWITCH_PORTSPEED_100_MBPS: data = 1; if(FullDp == 0) phy_ctrl = PHY_AN_ADV_100HDX; else phy_ctrl = PHY_AN_ADV_100FDX; break; case EXTSWITCH_PORTSPEED_1000_MBPS: if(FullDp == 0) { ESHAL_LogErr(" \n*** %s (HD @1G not supported#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; /* phy_ctrl = PHY_AN_ADV_1000HDX; */ } else phy_ctrl = PHY_AN_ADV_1000FDX; data = 2; break; case EXTSWITCH_PORTSPEED_10_GBPS: break; case EXTSWITCH_PORTSPEED_2500_MBPS: break; } if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - MAP_API_TO_PHYSICAL_PORT(PhyPortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, 16, &phy_addr) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } mddata.nAddressDev = phy_addr; GSW_MDIO_DataRead(NULL, &mddata); if ((data == 0) || (data == 1)) { mddata.nAddressReg = 4; GSW_MDIO_DataRead(NULL, &mddata); mddata.nData &= ~(PHY_AN_ADV_10HDX | PHY_AN_ADV_10FDX | PHY_AN_ADV_100HDX | PHY_AN_ADV_100FDX); mddata.nData |= phy_ctrl; GSW_MDIO_DataWrite(NULL, &mddata); mddata.nAddressReg = 9; GSW_MDIO_DataRead(NULL, &mddata); mddata.nData &= ~(PHY_AN_ADV_1000HDX | PHY_AN_ADV_1000FDX); GSW_MDIO_DataWrite(NULL, &mddata); } if (data == 2) { mddata.nAddressReg = 9; GSW_MDIO_DataRead(NULL, &mddata); mddata.nData &= ~(PHY_AN_ADV_1000HDX | PHY_AN_ADV_1000FDX); mddata.nData |= phy_ctrl; GSW_MDIO_DataWrite(NULL, &mddata); mddata.nAddressReg = 4; GSW_MDIO_DataRead(NULL, &mddata); mddata.nData &= ~(PHY_AN_ADV_10HDX | PHY_AN_ADV_10FDX | PHY_AN_ADV_100HDX | PHY_AN_ADV_100FDX); GSW_MDIO_DataWrite(NULL, &mddata); } if (data == 3) { mddata.nAddressReg = 4; GSW_MDIO_DataRead(NULL, &mddata); if (FullDp == 0) { mddata.nData &= ~(PHY_AN_ADV_10HDX | PHY_AN_ADV_10FDX | PHY_AN_ADV_100HDX | PHY_AN_ADV_100FDX); mddata.nData |= (PHY_AN_ADV_10HDX | PHY_AN_ADV_100HDX); } else { mddata.nData |= (PHY_AN_ADV_10HDX | PHY_AN_ADV_10FDX | PHY_AN_ADV_100HDX | PHY_AN_ADV_100FDX); } GSW_MDIO_DataWrite(NULL, &mddata); mddata.nAddressReg = 9; GSW_MDIO_DataRead(NULL, &mddata); if (FullDp == 0) { mddata.nData &= ~(PHY_AN_ADV_1000HDX | PHY_AN_ADV_1000FDX); mddata.nData |= (PHY_AN_ADV_1000HDX); } else { mddata.nData |= (PHY_AN_ADV_1000HDX | PHY_AN_ADV_1000FDX); } GSW_MDIO_DataWrite(NULL, &mddata); } rddata.nAddressDev = phy_addr; rddata.nAddressReg = 0; GSW_MDIO_DataRead(NULL, &rddata); mddata.nAddressDev = phy_addr; mddata.nAddressReg = 0; mddata.nData = (rddata.nData | (1 << 12)); GSW_MDIO_DataWrite(NULL, &mddata); } else { if (PUMA_CONNECTED_PORT(DevIdx) == LTQ_SGMII_PORT) { switch(PhySpeed) { case EXTSWITCH_PORTSPEED_1000_MBPS: /*NCO_CTRL*/ /*if (gsw_reg_write(0xf968, 0, 16, 0x0000)!= GSW_statusOk) return GSW_statusErr;*/ if (gsw_reg_write(0xf968, 0, 16, 0x0000)!= GSW_statusOk) return STATUS_NOK; if (Cport_sgmii_config()!= GSW_statusOk) return STATUS_NOK; break; case EXTSWITCH_PORTSPEED_2500_MBPS: /*NCO_CTRL*/ if (gsw_reg_write(0xf968, 0, 16, 0x000e)!= GSW_statusOk) return STATUS_NOK; if (Cport_sgmii_config()!= GSW_statusOk) return STATUS_NOK; break; default: return STATUS_NOK; } } else { /*ToDo*/ } } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } static STATUS GSW_IMPL_DisablePort(Uint8 DevIdx, Uint8 PortIdx); /**************************************************************************/ /*! \fn STATUS GSW_IMPL_EnablePort(Uint8 PortIdx) ************************************************************************** * \brief * Enable port. * * \param[in] * PortIdx - Port index. * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_EnablePort(Uint8 DevIdx, Uint8 PortIdx) { GSW_MDIO_data_t mddata; u16 value; ESHAL_LogDbg("%s:%d GSW implementation Start(PortIdx:%d)...!\n", __func__, __LINE__,PortIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if ((PortIdx == LTQ_RGMII_PORT) && (!GSW_IMPL_CurrentDevPriv->support_rgmii_int_port)) { /* Force RGMII port down if support_rgmii_int_port is disabled */ return GSW_IMPL_DisablePort(DevIdx, PortIdx); } if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d,PortIdx:%d ) ***\n", __func__,__LINE__, PortIdx); return STATUS_NOK; } if (PortIdx != INTERNAL_PORT) { if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - MAP_API_TO_PHYSICAL_PORT(PortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, PHY_ADDR_0_ADDR_SIZE, &value) != GSW_statusOk) return STATUS_NOK; mddata.nAddressDev = value; mddata.nAddressReg = 0x0; mddata.nData = 0x1240; if (GSW_MDIO_DataWrite(NULL, &mddata)!= GSW_statusOk) return STATUS_NOK; ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); } else if(PortIdx == INTERNAL_PORT) { if (gsw_reg_write(((PHY_ADDR_0_LNKST_OFFSET - MAP_API_TO_PHYSICAL_PORT(PortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_LNKST_SHIFT, PHY_ADDR_0_LNKST_SIZE, 1) != GSW_statusOk) return STATUS_NOK; } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } /**************************************************************************/ /*! \fn STATUS GSW_IMPL_DisablePort(Uint8 PortIdx) ************************************************************************** * \brief * Disable port. No traffic should flow in or out. * * \param[in] * PortIdx - Port index. * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_DisablePort(Uint8 DevIdx, Uint8 PortIdx) { GSW_MDIO_data_t mddata; u16 value; ESHAL_LogDbg("%s:%d GSW implementation Start(DevIdx:%d, PortIdx:%d)...!\n", __func__, __LINE__, DevIdx, PortIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (PortIdx >= MAX_LTQ_PORTS) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d,PortIdx:%d ) ***\n", __func__,__LINE__, PortIdx); return STATUS_NOK; } if (PortIdx != INTERNAL_PORT) { if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - MAP_API_TO_PHYSICAL_PORT(PortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, PHY_ADDR_0_ADDR_SIZE, &value) != GSW_statusOk) return STATUS_NOK; mddata.nAddressDev = value; mddata.nAddressReg = 0x0; mddata.nData = 0x800; if (GSW_MDIO_DataWrite(NULL, &mddata)!= GSW_statusOk) return STATUS_NOK; } else if(PortIdx == INTERNAL_PORT) { if (gsw_reg_write(((PHY_ADDR_0_LNKST_OFFSET - MAP_API_TO_PHYSICAL_PORT(PortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_LNKST_SHIFT, PHY_ADDR_0_LNKST_SIZE, 2) != GSW_statusOk) return STATUS_NOK; } ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #if 0 /**************************************************************************/ /*! \fn STATUS GSW_IMPL_EnablePhyPortEee(Uint8 PhyPortIdx) ************************************************************************** * \brief * Enable 802.3az or other energy efficient ethernet features on a MAC-PHY port. * * \param[in] * PhyPortIdx - Port index. Valid values are indexes of ports with PHY attached * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_EnablePhyPortEee(Uint8 DevIdx, Uint8 PhyPortIdx) { GSW_MDIO_data_t mddata; u16 value; ESHAL_LogDbg("%s:%d GSW implementation Start(DevIdx:%d, PhyPortIdx:%d)...!\n", __func__, __LINE__, DevIdx, PhyPortIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if ((PhyPortIdx >= MAX_LTQ_PORTS) && (PhyPortIdx == INTERNAL_PORT)) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } memset(&mddata, 0, sizeof(GSW_MDIO_data_t)); /*parm->bLPI*/ if (gsw_reg_write((MAC_CTRL_4_LPIEN_OFFSET + (0xC * MAP_API_TO_PHYSICAL_PORT(PhyPortIdx))), MAC_CTRL_4_LPIEN_SHIFT, MAC_CTRL_4_LPIEN_SIZE, 1) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* LPI Wait Time for 1G -- 50us */ if (gsw_reg_write((MAC_CTRL_4_GWAIT_OFFSET + (0xC * MAP_API_TO_PHYSICAL_PORT(PhyPortIdx))), MAC_CTRL_4_GWAIT_SHIFT, MAC_CTRL_4_GWAIT_SIZE, 0x32) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* LPI Wait Time for 100M -- 21us */ if (gsw_reg_write((MAC_CTRL_4_WAIT_OFFSET + (0xC * MAP_API_TO_PHYSICAL_PORT(PhyPortIdx))), MAC_CTRL_4_WAIT_SHIFT, MAC_CTRL_4_WAIT_SIZE, 0x15) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* LPI request controlled by data available for port */ if (gsw_reg_write((FDMA_CTRL_LPI_MODE_OFFSET), FDMA_CTRL_LPI_MODE_SHIFT, FDMA_CTRL_LPI_MODE_SIZE, 0x4) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - MAP_API_TO_PHYSICAL_PORT(PhyPortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, PHY_ADDR_0_ADDR_SIZE, &value) != GSW_statusOk) return GSW_statusErr; mddata.nAddressDev = value; mddata.nAddressReg = 0x3C; mddata.nData = 0x6; GSW_MMD_MDIO_DataWrite(NULL, &mddata, value, 0x07); mddata.nAddressDev = value; mddata.nAddressReg = 0; mddata.nData = 0x1200; GSW_MDIO_DataWrite(NULL, &mddata); ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } /**************************************************************************/ /*! \fn STATUS GSW_IMPL_DisablePhyPortEee(Uint8 PhyPortIdx) ************************************************************************** * \brief * Disable 802.3az or other energy efficient ethernet features on a MAC-PHY port. * \param[in] * PhyPortIdx - Port index. Valid values are indexes of ports with PHY attached. * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_DisablePhyPortEee(Uint8 DevIdx, Uint8 PhyPortIdx) { GSW_MDIO_data_t mddata; u16 value; ESHAL_LogDbg("%s:%d GSW implementation Start(DevIdx:%d, PhyPortIdx:%d)...!\n", __func__, __LINE__, DevIdx, PhyPortIdx); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if ((PhyPortIdx >= MAX_LTQ_PORTS) && (PhyPortIdx == INTERNAL_PORT)) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } memset(&mddata, 0, sizeof(GSW_MDIO_data_t)); /*parm->bLPI*/ if (gsw_reg_write((MAC_CTRL_4_LPIEN_OFFSET + (0xC * MAP_API_TO_PHYSICAL_PORT(PhyPortIdx))), MAC_CTRL_4_LPIEN_SHIFT, MAC_CTRL_4_LPIEN_SIZE, 0) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* LPI Wait Time for 1G -- 50us */ if (gsw_reg_write((MAC_CTRL_4_GWAIT_OFFSET + (0xC * MAP_API_TO_PHYSICAL_PORT(PhyPortIdx))), MAC_CTRL_4_GWAIT_SHIFT, MAC_CTRL_4_GWAIT_SIZE, 0x32) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* LPI Wait Time for 100M -- 21us */ if (gsw_reg_write((MAC_CTRL_4_WAIT_OFFSET + (0xC * MAP_API_TO_PHYSICAL_PORT(PhyPortIdx))), MAC_CTRL_4_WAIT_SHIFT, MAC_CTRL_4_WAIT_SIZE, 0x15) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* LPI request controlled by data available for port */ if (gsw_reg_write((FDMA_CTRL_LPI_MODE_OFFSET), FDMA_CTRL_LPI_MODE_SHIFT, FDMA_CTRL_LPI_MODE_SIZE, 0x4) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } if (gsw_reg_read(((PHY_ADDR_0_ADDR_OFFSET - MAP_API_TO_PHYSICAL_PORT(PhyPortIdx)) + GSW_TREG_OFFSET), PHY_ADDR_0_ADDR_SHIFT, PHY_ADDR_0_ADDR_SIZE, &value) != GSW_statusOk) return GSW_statusErr; mddata.nAddressDev = value; mddata.nAddressReg = 0x3C; mddata.nData = 0x0; GSW_MMD_MDIO_DataWrite(NULL, &mddata, value, 0x07); mddata.nAddressDev = value; mddata.nAddressReg = 0; mddata.nData = 0x1200; GSW_MDIO_DataWrite(NULL, &mddata); ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #endif /* Initialize the ADS WA */ static GSW_return_t GSW_AdsWaInit(Uint8 DevIdx) { int i; GSW_return_t result; GSW_MDIO_data_t parm; /* Stop MDIO bus automatic polling */ if ((gsw_reg_write(MMDC_CFG_0_PEN_ALL_OFFSET, 0, 16, 0x60)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } mdelay(100); /* sleep 0.1 sec */ /* Read phy firmware version */ parm.nAddressDev = 0; parm.nAddressReg = PHY_FIRMWARE_VERSION_REG; result = GSW_MDIO_DataRead(NULL, &parm); if (result != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = GSW_statusErr; goto finish; } GSW_IMPL_CurrentDevPriv->PhyFwVersion = parm.nData; if (PHY_ADS_FW_VERSION == GSW_IMPL_CurrentDevPriv->PhyFwVersion) { /* Increase MDC clock polling rate */ if ((gsw_reg_write(MMDC_CFG_1_FREQ_OFFSET, 0, 16, 0x0107)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = GSW_statusErr; goto finish; } /* Change ADS threshold */ for (i=0; i <= LAST_INTEGRATED_PHY_PORTS; i++) { parm.nAddressDev = i; parm.nAddressReg = 0x14; parm.nData = 0xC006; if (GSW_MDIO_DataWrite(NULL, &parm) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = GSW_statusErr; goto finish; } } } finish: /* Restart MDIO bus automatic polling */ if ((gsw_reg_write(MMDC_CFG_0_PEN_ALL_OFFSET, 0, 16, 0x6F)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = GSW_statusErr; } return result; } #if 0 /* Periodically activate the Ads fix */ static GSW_return_t GSW_AdsWaFix(Uint8 DevIdx) { GSW_return_t result = GSW_statusOk; GSW_MDIO_data_t parm; int i; /* Stop MDIO bus automatic polling */ if ((gsw_reg_write(MMDC_CFG_0_PEN_ALL_OFFSET, 0, 16, 0x60)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return GSW_statusErr; } mdelay(100); /* sleep 0.1 sec */ result = GSW_statusOk; /* loop over all LAN ports */ for (i=0; i <= LAST_INTEGRATED_PHY_PORTS; i++) { /* Set MMD command to set MMD register address */ parm.nAddressDev = i; parm.nAddressReg = MMD_ACCESS_CONTROL_REG; parm.nData = 0x1F; if (GSW_MDIO_DataWrite(NULL, &parm) != GSW_statusOk) { result = GSW_statusErr; } /* Select MMD register address value */ parm.nAddressDev = i; parm.nAddressReg = MMD_ADDRESS_DATA_REG; parm.nData = 0xA1; if (GSW_MDIO_DataWrite(NULL, &parm) != GSW_statusOk) { result = GSW_statusErr; } /* Set MMD command to write /read register */ parm.nAddressDev = i; parm.nAddressReg = MMD_ACCESS_CONTROL_REG; parm.nData = 0x401F; if (GSW_MDIO_DataWrite(NULL, &parm) != GSW_statusOk) { result = GSW_statusErr; } /* write MMD register value */ parm.nAddressDev = i; parm.nAddressReg = MMD_ADDRESS_DATA_REG; parm.nData = 0x00; if (GSW_MDIO_DataWrite(NULL, &parm) != GSW_statusOk) { result = GSW_statusErr; } } /* Restart MDIO bus automatic polling */ if ((gsw_reg_write(MMDC_CFG_0_PEN_ALL_OFFSET, 0, 16, 0x6F)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return result = GSW_statusErr; } return result; } #endif /**************************************************************************/ /*! \fn STATUS GSW_IMPL_ResetSwitch(Uint8 DevIdx, const Uint8 *pVendorInitParam, Uint32 VendorInitParamSize) ************************************************************************** * \brief * Reset switch to default configuration and clear run-time data. * Upon completion the switch should have the configuration: * * - Provider Bridge Mode state is defined by EXTSWITCH_DEF_PBM. See DisableProviderBridgedMode/EnableProviderBridgedMode. * - STagTpid is defined by EXTSWITCH_DEF_STAG_TPID. See EnableProviderBridgedMode. * - All LAN ports are assigned to EXTSWITCH_DEF_LAN_PORTS_VLAN Vlan. see SetLanPortVlan. * - All MAC-PHY ports are set to EXTSWITCH_DEF_LINK_SPEED seed and duplex EXTSWITCH_DEF_LINK_FD. See SetPhyPortSpeedDuplex. * - All MAC-only ports are in default hardware-defined MII mode. (It is fixed per board board design and not intended to be changed at run-time). * - Enabled (tx/rx on) ports are defined by EXTSWITCH_DEF_ENABLED_PORTS_MASK. See EnablePort/EXTSWITCH_DisablePort. * - RGMII tx/rx setup delay enabled ports are defined by EXTSWITCH_DEF_RGMIIDELAY_MASK. See EnableRgmiiDelay/DisableRgmiiDelay * - IGMP/MLD Snooping state is defined by EXTSWITCH_DEF_IGMP_SNOOPING_ENA. See EnableIgmpSnooping/DisableIgmpSnooping. * - EEE enabled MAC-PHY ports are defined by EXTSWITCH_DEF_EEE_ENA. See EnablePhyPortEee/DisablePhyPortEee. * - Port mirroring is defined by EXTSWITCH_DEF_PORT_MIRRORS. See SetPortMirror. * * In addition, port counters, forwarding tables and all other run-time built data must be flushed. * * Other configuration settings are switch vendor defined. * In case the configuration cannot be set as required by the table (e.g. EXTSWITCH_DEF_EEE_ENA is True but * the switch does not support EEE), the function must fail - It is SDK responsibility to request a relevant default configuration state. * * \param[in] * DevIdx - index of external switch device. * pVendorInitParam - Additional vendor specific default reset parameters pointer. * It is the low level driver responsibility to record the * parameters block and to use it if subsequent calls to reset don't * provide * VendorInitParamSize - Size (in bytes) of the additional parameters block * \param[out] * None * \return * STATUS **************************************************************************/ static STATUS GSW_IMPL_ResetSwitch(Uint8 DevIdx, const Uint8 *pVendorInitParam, Uint32 VendorInitParamSize) { GSW_reset_t param; Uint8 i, j; u16 mac2_ctrl; pctbl_prog_t pcetable; INTELSW_InitAdditionalParam_t *pInitParams; GSW_QoS_QueueBufferReserveCfg_t QRsrv; GSW_QoS_WRED_Cfg_t WredCfg; GSW_QoS_WRED_QueueCfg_t WredQCfg; GSW_QoS_FlowCtrlPortCfg_t PortFc; ESHAL_LogDbg("%s:%d GSW implementation Start...!\n", __func__, __LINE__); GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { /* First call for DevIdx? */ GSW_IMPL_CurrentDevPriv = _RegisterDevIdx(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr("%s:%d Could not register DevIdx:%d\n", __func__, __LINE__, DevIdx); return STATUS_NOK; } } if ((pVendorInitParam != NULL) && (VendorInitParamSize >= sizeof(INTELSW_InitAdditionalParam_t))) { pInitParams = (INTELSW_InitAdditionalParam_t*)pVendorInitParam; GSW_IMPL_CurrentDevPriv->support_rgmii_int_port = pInitParams->IsPortIsolation != 0; } memset(¶m, 0, sizeof(GSW_reset_t)); GSW_Reset(NULL, ¶m); if (ethsw_api_core_init()!= GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d), DevIdx:%d ***\n", __func__,__LINE__, DevIdx); return STATUS_NOK; } if (GSW_AdsWaInit(DevIdx) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d), DevIdx:%d ***\n", __func__,__LINE__, DevIdx); return STATUS_NOK; } //ESHAL_LogErr(" \n*** %s (Line#:%d, EXTSWITCH_DEF_ENABLED_PORTS_MASK:%d) ***\n", __func__,__LINE__,EXTSWITCH_DEF_ENABLED_PORTS_MASK); if (PUMA_CONNECTED_PORT(DevIdx) == LTQ_SGMII_PORT) { if (gsw_reg_write(0xf410, 0, 16, 0x1805) != GSW_statusOk) return GSW_statusErr; } for (i = 0; i < MAX_LTQ_PORTS; i++) { /* enable max MTU on all ports */ if (gsw_reg_read(0x905 + 0xC * i, 0, 16, &mac2_ctrl) != GSW_statusOk) return GSW_statusErr; if (gsw_reg_write(0x905 + 0xC * i, 0, 16, mac2_ctrl | 8) != GSW_statusOk) return GSW_statusErr; if ( ((EXTSWITCH_DEF_ENABLED_PORTS_MASK >> i) & 0x1) == 0x1) { if (GSW_IMPL_EnablePort(DevIdx, i) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d), DevIdx:%d ***\n", __func__,__LINE__, DevIdx); return STATUS_NOK; } } else { if (GSW_IMPL_DisablePort(DevIdx, i) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d), DevIdx:%d ***\n", __func__,__LINE__, DevIdx); return STATUS_NOK; } } } if (gsw_initLAN802Dot1qMode(1) != STATUS_OK) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d), DevIdx:%d ***\n", __func__,__LINE__,DevIdx); return STATUS_NOK; } /* Should initialize PCE Class/Q map, BM Q/Port map, BM WFQ tables. Default value of BM Q/Port map should work (4 queue per port). BM WFQ is programmed in gsw_initLAN802Dot1qMode and gsw_initINT802Dot1qMode separately. Program PCE Class/Q map below. */ memset(&pcetable, 0, sizeof(pcetable)); pcetable.table = PCE_QUEUE_MAP_INDEX; for (i=0; isupport_rgmii_int_port) { ESHAL_LogInfo("Activate port isolation"); /* configure RGMII port */ /* extswitch>writePortReg 0 0 0xebc0 0x5102 */ if ((gsw_reg_write(0xebc0, 0, 16, 0x5102)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* extswitch>writePortReg 0 0 0xebde 0x5102 */ if ((gsw_reg_write(0xebde, 0, 16, 0x5102)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* extswitch>writePortReg 0 0 0xf410 0x1800 */ if ((gsw_reg_write(0xf410, 0, 16, 0x1800)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* extswitch>writePortReg 0 0 0xf130 0x0101 */ if ((gsw_reg_write(0xf130, 0, 16, 0x0101)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } /* writePortReg 0 0 0xf100 0x4144 */ if ((gsw_reg_write(0xf100, 0, 16, 0x4144)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } } else { for( i = 0; i < 10; i++ ) { u16 val; ESHAL_LogInfo(" \n*** %s (Line#:%d) Switching off RGMII, try nr. %d***\n", __func__,__LINE__, i); /* writePortReg 0 0 0xf100 0x4144 -> normal op: EN(14)=1, ISOL(13)=0 writePortReg 0 0 0xf100 0x2044 -> workaround to disable and isolate RGMII: EN(14)=0, ISOL(13)=1, reset value */ if ((gsw_reg_write(0xf100, 0, 16, 0x2044)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } msleep(10); if ((gsw_reg_read(0xf100, 0, 16, &val)) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); msleep(5); continue; } else { if( val == 0x2044 ) { break; } else { msleep(5); continue; } } } if( i == 10 ) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) RGMII init failed! ***\n", __func__,__LINE__); } } /* Reconfigure AQM and buffer reservations for Puma7 designs - START */ /* Disable the flow control on SGMII port, PHY_ADDR = 4, FULL DUPLEX, SPEED = 1Gb/s (2.5Gb/s) */ if (gsw_reg_write(0xF411, 0, 16, 0x33E4)!= GSW_statusOk) return GSW_statusErr; /* Set buffer reservation to maximum in order to disable WRED */ QRsrv.nBufferReserved = AQM_MAX_WRED_THRESH; for (i = 0 ; i < AQM_NUMOF_QUEUES; i++) { QRsrv.nQueueId = i; if (GSW_QoS_QueueBufferReserveCfgSet(NULL, &QRsrv) != GSW_statusOk) { return STATUS_NOK; } } /* Set Global Wred Thresholds */ WredCfg.eMode = GSW_QOS_WRED_Adaptive; WredCfg.eProfile = GSW_QOS_WRED_PROFILE_P0; WredCfg.eThreshMode = GSW_QOS_WRED_Local_Thresh; WredCfg.nGreen_Max = AQM_MAX_WRED_THRESH; WredCfg.nGreen_Min = AQM_MAX_WRED_THRESH; WredCfg.nRed_Max = AQM_MAX_WRED_THRESH; WredCfg.nRed_Min = AQM_MAX_WRED_THRESH; WredCfg.nYellow_Max = AQM_MAX_WRED_THRESH; WredCfg.nYellow_Min = AQM_MAX_WRED_THRESH; if (GSW_QoS_WredCfgSet(NULL, &WredCfg) != GSW_statusOk) { return STATUS_NOK; } /* Set Q Wred */ WredQCfg.nGreen_Max = AQM_MAX_WRED_THRESH; WredQCfg.nGreen_Min= AQM_MAX_WRED_THRESH; WredQCfg.nRed_Max = AQM_MAX_WRED_THRESH; WredQCfg.nRed_Min = AQM_MAX_WRED_THRESH; WredQCfg.nYellow_Max = AQM_MAX_WRED_THRESH; WredQCfg.nYellow_Min = AQM_MAX_WRED_THRESH; for (i = 0 ; i < AQM_NUMOF_QUEUES; i++) { WredQCfg.nQueueId = i; if (GSW_QoS_WredQueueCfgSet(NULL, &WredQCfg) != GSW_statusOk) { return STATUS_NOK; } } PortFc.nFlowCtrl_Min = AQM_MAX_WRED_THRESH; PortFc.nFlowCtrl_Max = AQM_MAX_WRED_THRESH; for (i = 0; i < MAX_LTQ_PORTS; i++) { PortFc.nPortId = i; if (GSW_QoS_FlowctrlPortCfgSet(NULL, &PortFc) != GSW_statusOk) { return STATUS_NOK; } } /* Reconfigure AQM and buffer reservations for Puma7 designs - END */ ESHAL_LogDbg("%s:%d GSW implementation End...!\n", __func__, __LINE__); return STATUS_OK; } #if 0 static STATUS GSW_IMPL_PrintMachineState(Uint8 DevIdx) { int i; u16 Val, data1, data2; GSW_QoS_ClassPCP_Cfg_t classpcp; GSW_QoS_FlowCtrlCfg_t flowctrl; GSW_QoS_FlowCtrlPortCfg_t portfc; GSW_QoS_meterCfg_t metercfg; GSW_QoS_portCfg_t portcfg; GSW_QoS_QueueBufferReserveCfg_t qres; GSW_QoS_schedulerCfg_t schedcfg; GSW_QoS_ShaperCfg_t shapercfg; GSW_QoS_ShaperQueueGet_t shaperq; GSW_QoS_stormCfg_t storm; GSW_QoS_WRED_Cfg_t wredcfg; GSW_QoS_WRED_PortCfg_t wredport; GSW_QoS_WRED_QueueCfg_t wqparam; GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } pr_err("\n--------------| RESOURCES |-------------\n"); /* ports */ gsw_reg_read(ETHSW_CAP_1_PPORTS_OFFSET, ETHSW_CAP_1_PPORTS_SHIFT, ETHSW_CAP_1_PPORTS_SIZE, &Val); pr_err("Ports Cnt: %d\n", Val); gsw_reg_read(ETHSW_CAP_1_QUEUE_OFFSET, ETHSW_CAP_1_QUEUE_SHIFT, ETHSW_CAP_1_QUEUE_SIZE, &Val); pr_err("Q Cnt: %d\n", Val); gsw_reg_read(ETHSW_CAP_3_METERS_OFFSET, ETHSW_CAP_3_METERS_SHIFT, ETHSW_CAP_3_METERS_SIZE, &Val); pr_err("Meters Cnt: %d\n", Val); gsw_reg_read(ETHSW_CAP_3_SHAPERS_OFFSET, ETHSW_CAP_3_SHAPERS_SHIFT, ETHSW_CAP_3_SHAPERS_SIZE, &Val); pr_err("Shapers Cnt: %d\n", Val); gsw_reg_read(ETHSW_VERSION_REV_ID_OFFSET, ETHSW_VERSION_REV_ID_SHIFT, 16, &Val); pr_err("HW Rev: %d\n", Val); gsw_reg_read(ETHSW_CAP_11_BSIZEL_OFFSET, \ ETHSW_CAP_11_BSIZEL_SHIFT, ETHSW_CAP_11_BSIZEL_SIZE, &data1); gsw_reg_read(ETHSW_CAP_12_BSIZEH_OFFSET, \ ETHSW_CAP_12_BSIZEH_SHIFT, ETHSW_CAP_12_BSIZEH_SIZE, &data2); pr_err("Pkt Buff Size: %d\n", (data2 << 16 | data1)); gsw_reg_read(BM_FSQM_GCTRL_SEGNUM_OFFSET, \ BM_FSQM_GCTRL_SEGNUM_SHIFT, BM_FSQM_GCTRL_SEGNUM_SIZE, &Val); pr_err("Segment Cnt: %d\n", Val); /* Description: 'Number of Consumed Segments' */ gsw_reg_read(BM_CONS_SEG_FSEG_OFFSET, \ BM_CONS_SEG_FSEG_SHIFT, BM_CONS_SEG_FSEG_SIZE, &Val); pr_err("Consumed Segments Cnt: %d\n", Val); gsw_reg_read(BM_CONS_PKT_FQP_OFFSET, \ BM_CONS_PKT_FQP_SHIFT, BM_CONS_PKT_FQP_SIZE, &Val); pr_err("Consumed Pkts Ptrs Cnt: %d\n", Val); pr_err("\n--------------| TC CLASS PCP |-------------\n"); memset(&classpcp, 0, sizeof(GSW_QoS_ClassPCP_Cfg_t)); if (GSW_QoS_ClassPCP_Get(NULL, &classpcp) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_ClassPCP_Get() failed\n"); return STATUS_NOK; } for (i = 0; i < 16; i++) { pr_err("TC %d: PCP: %d\n", i, classpcp.nPCP[i]); } pr_err("\n--------------| FLOW CTRL |-------------\n"); memset(&flowctrl, 0, sizeof(GSW_QoS_FlowCtrlCfg_t)); if (GSW_QoS_FlowctrlCfgGet(NULL, &flowctrl) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_FlowctrlCfgGet() failed\n"); return STATUS_NOK; } pr_err("Non conform min: %d\n", flowctrl.nFlowCtrlNonConform_Min); pr_err("Non conform max: %d\n", flowctrl.nFlowCtrlNonConform_Max); pr_err("Conform min: %d\n", flowctrl.nFlowCtrlConform_Min); pr_err("Conform max: %d\n", flowctrl.nFlowCtrlConform_Max); pr_err("\n--------------| PORT FLOW CTRL |-------------\n"); for (i = 0 ; i < MAX_LTQ_PORTS; i++) { memset(&portfc, 0, sizeof(GSW_QoS_FlowCtrlPortCfg_t)); portfc.nPortId = i; if (GSW_QoS_FlowctrlPortCfgGet(NULL, &portfc) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_FlowctrlPortCfgGet() failed, Port: %d\n", i); return STATUS_NOK; } pr_err("Port %d: Fc Min: %d, Fc Max: %d\n", i, portfc.nFlowCtrl_Min, portfc.nFlowCtrl_Max); } pr_err("\n--------------| METERS |-------------\n"); for (i = 0 ; i < 16; i++) { memset(&metercfg, 0, sizeof(GSW_QoS_meterCfg_t)); metercfg.nMeterId = i; if (GSW_QoS_MeterCfgGet(NULL, &metercfg) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_MeterCfgGet() failed, Meter: %d\n", i); return STATUS_NOK; } pr_err("Mid %d: Ena: %d, Type: %d, nCbs: %d, nEbs: %d, nRate: %d, nPiRate: %d\n", i, metercfg.bEnable, metercfg.eMtrType, metercfg.nCbs, metercfg.nEbs, metercfg.nRate, metercfg.nPiRate); } pr_err("\n--------------| PORT QOS |-------------\n"); for (i = 0 ; i < MAX_LTQ_PORTS; i++) { memset(&portcfg, 0, sizeof(GSW_QoS_portCfg_t)); portcfg.nPortId = i; if (GSW_QoS_PortCfgGet(NULL, &portcfg) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_PortCfgGet() failed, Port: %d\n", i); return STATUS_NOK; } pr_err("Port %d: Mode: %d, Class: %d\n", i, portcfg.eClassMode, portcfg.nTrafficClass); } pr_err("\n--------------| Q RSRV |-------------\n"); for (i = 0 ; i < 32; i++) { memset(&qres, 0, sizeof(GSW_QoS_QueueBufferReserveCfg_t)); qres.nQueueId = i; if (GSW_QoS_QueueBufferReserveCfgGet(NULL, &qres) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_QueueBufferReserveCfgGet() failed, Qidx %d\n", i); return STATUS_NOK; } pr_err("Q: %d, Rsvd: %d\n", i, qres.nBufferReserved); } /* pr_err("--------------| Q PORT |-------------\n"); GSW_return_t GSW_QoS_QueuePortGet(void *cdev, GSW_QoS_queuePort_t *parm) */ pr_err("\n--------------| Q SCHED |-------------\n"); for (i = 0 ; i < 32; i++) { memset(&schedcfg, 0, sizeof(GSW_QoS_schedulerCfg_t)); schedcfg.nQueueId = i; if (GSW_QoS_SchedulerCfgGet(NULL, &schedcfg) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_SchedulerCfgGet() failed, Qidx %d\n", i); return STATUS_NOK; } pr_err("Q: %d, Type: %d, Weight: %d\n", i, schedcfg.eType, schedcfg.nWeight); } pr_err("\n--------------| SHAPER |-------------\n"); for (i = 0 ; i < 32; i++) { memset(&shapercfg, 0, sizeof(GSW_QoS_ShaperCfg_t)); shapercfg.nRateShaperId = i; if (GSW_QoS_ShaperCfgGet(NULL, &shapercfg) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_ShaperCfgGet() failed, Qidx %d\n", i); return STATUS_NOK; } pr_err("Shaper: %d, Ena: %d, AVB: %d, Cbs: %d, Rate: %d\n", i, shapercfg.bEnable, shapercfg.bAVB, shapercfg.nCbs, shapercfg.nRate); } pr_err("\n--------------| SHAPER Q |-------------\n"); for (i = 0 ; i < 32; i++) { memset(&shaperq, 0, sizeof(GSW_QoS_ShaperQueueGet_t)); shaperq.nQueueId = i; if (GSW_QoS_ShaperQueueGet(NULL, &shaperq) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_ShaperQueueGet() failed, Qidx %d\n", i); return STATUS_NOK; } pr_err("Q: %d, Asigned: %d, Shaper Id: %d\n", i, shaperq.bAssigned, shaperq.nRateShaperId); } pr_err("\n--------------| STROM |-------------\n"); memset(&storm, 0, sizeof(GSW_QoS_stormCfg_t)); if (GSW_QoS_StormCfgGet(NULL, &storm) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_StormCfgGet()\n"); return STATUS_NOK; } pr_err("MeterId: %d, Bcast: %d, Mcast: %d, UnkUni: %d\n", storm.nMeterId, storm.bBroadcast, storm.bMulticast, storm.bUnknownUnicast); pr_err("\n--------------| GLOB WRED |-------------\n"); memset(&wredcfg, 0, sizeof(GSW_QoS_WRED_QueueCfg_t)); if (GSW_QoS_WredCfgGet(NULL, &wredcfg) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_WredCfgGet() failed\n"); return STATUS_NOK; } pr_err("Profile: %d\n", wredcfg.eProfile); pr_err("Mode: %d\n", wredcfg.eMode); pr_err("Thresh Mode: %d\n", wredcfg.eThreshMode); pr_err("Red Min: %d\n", wredcfg.nRed_Min); pr_err("Red Max: %d\n", wredcfg.nRed_Max); pr_err("Yellow Min: %d\n", wredcfg.nYellow_Min); pr_err("Yellow Max: %d\n", wredcfg.nYellow_Max); pr_err("Green Min: %d\n", wredcfg.nGreen_Min); pr_err("Green Max: %d\n", wredcfg.nGreen_Max); pr_err("\n--------------| PORT WRED |-------------\n"); for (i = 0 ; i < MAX_LTQ_PORTS; i++) { memset(&wredport, 0, sizeof(GSW_QoS_WRED_PortCfg_t)); wredport.nPortId = i; if (GSW_QoS_WredPortCfgGet(NULL, &wredport) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_WredPortCfgGet() failed, Port: %d\n", i); return STATUS_NOK; } pr_err("Port %d: Red Min: %d, Red Max: %d, Yel Min: %d, Yel Max: %d, Gre Min: %d, Gre Max: %d\n", i, wredport.nRed_Min, wredport.nRed_Max, wredport.nYellow_Min, wredport.nYellow_Max, wredport.nGreen_Min, wredport.nGreen_Max); } pr_err("\n--------------| Q WRED |-------------\n"); for (i = 0 ; i < 32; i++) { memset(&wqparam, 0, sizeof(GSW_QoS_WRED_QueueCfg_t)); wqparam.nQueueId = i; if (GSW_QoS_WredQueueCfgGet(NULL, &wqparam) != GSW_statusOk) { ESHAL_LogErr("*** GSW_QoS_WredQueueCfgGet() failed, Qidx %d\n", i); return STATUS_NOK; } pr_err("Q %d: Red Min: %d, Red Max: %d, Yel Min: %d, Yel Max: %d, Gre Min: %d, Gre Max: %d\n", i, wqparam.nRed_Min, wqparam.nRed_Max, wqparam.nYellow_Min, wqparam.nYellow_Max, wqparam.nGreen_Min, wqparam.nGreen_Max); } return STATUS_OK; } static STATUS GSW_IMPL_SetPortFc(Uint8 DevIdx, Uint8 PortId, Uint16 Min, Uint16 Max) { GSW_QoS_FlowCtrlPortCfg_t param; GSW_IMPL_CurrentDevPriv = _GetDevPriv(DevIdx); if (!GSW_IMPL_CurrentDevPriv) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); return STATUS_NOK; } param.nPortId = PortId; param.nFlowCtrl_Min = Min; param.nFlowCtrl_Max = Max; if (GSW_QoS_FlowctrlPortCfgSet(NULL, ¶m) != GSW_statusOk) { return STATUS_NOK; } return STATUS_OK; } #endif /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_lock(avmnet_module_t *this) { return this->parent->lock(this->parent); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avmnet_f24s_unlock(avmnet_module_t *this) { this->parent->unlock(this->parent); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_trylock(avmnet_module_t *this) { return this->parent->trylock(this->parent); } static unsigned int slave_reg_rd(avmnet_module_t *this, unsigned int phy_addr, unsigned int reg_addr) { int result; uint16_t value; if ((reg_addr & 0xD000) != 0xD000){ reg_addr |= 0xE000; } value = 0xFFFF; result = this->parent->reg_write(this->parent, phy_addr, F24S_SMDIO_ADDR, reg_addr); if (result != 0){ AVMNET_ERR("[%s] reg_write failed: %d phy_addr: 0x%04x, reg_addr: 0x%04x\n", __func__, result, phy_addr, reg_addr); goto err_out; } value = this->parent->reg_read(this->parent, phy_addr, F24S_SMDIO_TARGET); err_out: return value; } static int slave_reg_wr(avmnet_module_t *this, unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data) { int result; if ((reg_addr & 0xD000) != 0xD000){ reg_addr |= 0xE000; } result = this->parent->reg_write(this->parent, phy_addr, F24S_SMDIO_ADDR, reg_addr); if (result != 0){ AVMNET_ERR("[%s] reg_write failed: %d phy_addr: 0x%04x, reg_addr: 0x%04x\n", __func__, result, phy_addr, reg_addr); goto err_out; } result = this->parent->reg_write(this->parent, phy_addr, F24S_SMDIO_TARGET, write_data & 0xffff); err_out: return result; } static int sw_reg_read(avmnet_module_t *this, uint16_t addr, uint16_t reg, uint16_t *data) { unsigned int val; int result; do{ val = slave_reg_rd(this, F24S_SMDIO_ADDR, F24S_MMDIO_CTRL); }while(val & MMDIO_CTRL_BSY); val = MMDIO_CTRL_OP_RD | ((addr << MMDIO_CTRL_PHYAD_SFT) & MMDIO_CTRL_PHYAD_MSK) | ((reg << MMDIO_CTRL_REGAD_SFT) & MMDIO_CTRL_REGAD_MSK); result = slave_reg_wr(this, F24S_SMDIO_ADDR, F24S_MMDIO_CTRL, val); if(result != 0){ goto err_out; } do{ val = slave_reg_rd(this, F24S_SMDIO_ADDR, F24S_MMDIO_CTRL); }while(val & MMDIO_CTRL_BSY); val = slave_reg_rd(this, F24S_SMDIO_ADDR, F24S_MMDIO_READ); *data = val & 0xFFFF; err_out: return result; } static int sw_reg_write(avmnet_module_t *this, uint16_t addr, uint16_t reg, uint16_t data) { unsigned int val; int result; do{ val = slave_reg_rd(this, F24S_SMDIO_ADDR, F24S_MMDIO_CTRL); }while(val & MMDIO_CTRL_BSY); result = slave_reg_wr(this, F24S_SMDIO_ADDR, F24S_MMDIO_WRITE, (data & 0xFFFF)); if(result != 0){ goto err_out; } val = MMDIO_CTRL_OP_WR | ((addr << MMDIO_CTRL_PHYAD_SFT) & MMDIO_CTRL_PHYAD_MSK) | ((reg << MMDIO_CTRL_REGAD_SFT) & MMDIO_CTRL_REGAD_MSK); result = slave_reg_wr(this, F24S_SMDIO_ADDR, F24S_MMDIO_CTRL, val); do{ val = slave_reg_rd(this, F24S_SMDIO_ADDR, F24S_MMDIO_CTRL); }while(val & MMDIO_CTRL_BSY); err_out: return result; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int avmnet_f24s_reg_read(avmnet_module_t *this, unsigned int phy_addr, unsigned int reg_addr) { uint16_t val; int result; /*--- AVMNET_DEBUG(KERN_ERR "[%s] Phy 0x%x reg_addr 0x%x\n", __func__, phy_addr, reg_addr); ---*/ result = sw_reg_read(this, (phy_addr & 0xFFFF), (reg_addr & 0xFFFF), &val); if(result != 0){ val = 0xFFFF; } return val; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_reg_write(avmnet_module_t *this, unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data) { /*--- AVMNET_DEBUG(KERN_ERR "[%s] Phy 0x%x reg_addr 0x%x write_data 0x%x\n", __func__, phy_addr, reg_addr, write_data); ---*/ return sw_reg_write(this, (phy_addr & 0xFFFF), (reg_addr & 0xFFFF), (write_data & 0xFFFF)); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_status_poll(avmnet_module_t *this) { int i; AVMNET_DEBUG("[%s] on %s\n", __func__, this->name); for(i = 0; i < this->num_children; i++){ /*--- AVMNET_DEBUG("[%s] call %s\n", __func__, this->children[i]->name); ---*/ this->children[i]->poll(this->children[i]); } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_set_status(avmnet_module_t *this, avmnet_device_t *device_id, avmnet_linkstatus_t status) { AVMNET_DEBUG("[%s] %s Status %s changed actual %s speed %d\n", __func__, device_id->device_name, this->name, status.Details.link ? "on":"off", status.Details.speed); this->parent->set_status(this->parent, device_id, status); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_setup_interrupt(avmnet_module_t *this, unsigned int on_off) { return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avmnet_f24s_status_changed(avmnet_module_t *this, avmnet_module_t *caller __attribute__ ((unused))) { avmnet_module_t *parent = this->parent; AVMNET_DEBUG("[%s] context_name %s\n", __func__, this->name); parent->status_changed(parent, this); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int rmon_show(struct seq_file *seq, void *data __attribute__ ((unused)) ) { avmnet_module_t *this; GSW_RMON_Port_cnt_t param; unsigned int i; int result; this = (avmnet_module_t *) seq->private; result = 0; for(i = 0; i < MAX_LTQ_PORTS; ++i){ memset(¶m, 0, sizeof(GSW_RMON_Port_cnt_t)); param.nPortId = MAP_API_TO_PHYSICAL_PORT(i); if (GSW_RMON_Port_Get(NULL, ¶m) != GSW_statusOk) { ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = -EINVAL; goto err_out; } seq_printf(seq, "***Logical Port %d Counters :---------------\n", i); seq_printf(seq, "nPortId: %d\n", param.nPortId); seq_printf(seq, "nRxGoodPkts:%d\n", param.nRxGoodPkts); seq_printf(seq, "nRxUnicastPkts:%d\n", param.nRxUnicastPkts); seq_printf(seq, "nRxBroadcastPkts:%d\n", param.nRxBroadcastPkts); seq_printf(seq, "nRxMulticastPkts:%d\n", param.nRxMulticastPkts); seq_printf(seq, "nRxFCSErrorPkts:%d\n", param.nRxFCSErrorPkts); seq_printf(seq, "nRxUnderSizeGoodPkts:%d\n", param.nRxUnderSizeGoodPkts); seq_printf(seq, "nRxOversizeGoodPkts:%d\n", param.nRxOversizeGoodPkts); seq_printf(seq, "nRxUnderSizeErrorPkts:%d\n", param.nRxUnderSizeErrorPkts); seq_printf(seq, "nRxGoodPausePkts:%d\n", param.nRxGoodPausePkts); seq_printf(seq, "nRxOversizeErrorPkts:%d\n", param.nRxOversizeErrorPkts); seq_printf(seq, "nRxAlignErrorPkts:%d\n", param.nRxAlignErrorPkts); seq_printf(seq, "nRxFilteredPkts:%d\n", param.nRxFilteredPkts); seq_printf(seq, "nRx64BytePkts:%d\n", param.nRx64BytePkts); seq_printf(seq, "nRx127BytePkts:%d\n", param.nRx127BytePkts); seq_printf(seq, "nRx255BytePkts:%d\n", param.nRx255BytePkts); seq_printf(seq, "nRx511BytePkts:%d\n", param.nRx511BytePkts); seq_printf(seq, "nRx1023BytePkts:%d\n", param.nRx1023BytePkts); seq_printf(seq, "nRxMaxBytePkts:%d\n", param.nRxMaxBytePkts); seq_printf(seq, "nTxGoodPkts:%d\n", param.nTxGoodPkts); seq_printf(seq, "nTxUnicastPkts:%d\n", param.nTxUnicastPkts); seq_printf(seq, "nTxBroadcastPkts:%d\n", param.nTxBroadcastPkts); seq_printf(seq, "nTxMulticastPkts:%d\n", param.nTxMulticastPkts); seq_printf(seq, "nTxSingleCollCount:%d\n", param.nTxSingleCollCount); seq_printf(seq, "nTxMultCollCount:%d\n", param.nTxMultCollCount); seq_printf(seq, "nTxLateCollCount:%d\n", param.nTxLateCollCount); seq_printf(seq, "nTxExcessCollCount:%d\n", param.nTxExcessCollCount); seq_printf(seq, "nTxCollCount:%d\n", param.nTxCollCount); seq_printf(seq, "nTxPauseCount:%d\n", param.nTxPauseCount); seq_printf(seq, "nTx64BytePkts:%d\n", param.nTx64BytePkts); seq_printf(seq, "nTx127BytePkts:%d\n", param.nTx127BytePkts); seq_printf(seq, "nTx255BytePkts:%d\n", param.nTx255BytePkts); seq_printf(seq, "nTx511BytePkts:%d\n", param.nTx511BytePkts); seq_printf(seq, "nTx1023BytePkts:%d\n", param.nTx1023BytePkts); seq_printf(seq, "nTxMaxBytePkts:%d\n", param.nTxMaxBytePkts); seq_printf(seq, "nTxDroppedPkts:%d\n", param.nTxDroppedPkts); seq_printf(seq, "nTxAcmDroppedPkts:%d\n", param.nTxAcmDroppedPkts); seq_printf(seq, "nRxDroppedPkts:%d\n", param.nRxDroppedPkts); seq_printf(seq, "nRxGoodBytes:%llu (0x%llx)\n", param.nRxGoodBytes, param.nRxGoodBytes); seq_printf(seq, "nRxBadBytes:%llu (0x%llx)\n", param.nRxBadBytes, param.nRxBadBytes); seq_printf(seq, "nTxGoodBytes:%llu (0x%llx)\n", param.nTxGoodBytes, param.nTxGoodBytes); } err_out: return result; } static int rmon_open(struct inode *inode, struct file *file) { avmnet_module_t *this; this = (avmnet_module_t *) PDE_DATA(inode); return single_open(file, rmon_show, this); } static const struct file_operations rmon_fops = { .open = rmon_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int serdes_reset(int n){ while(n-->0){ ESHAL_LogErr(" \nResetting ModPHY\n"); modphy_reset_client(MODPHY_SGMII1_2_5G_CLIENT_ID); mdelay(100); ESHAL_LogErr(" \nResetting SerDes RX\n"); if (gsw_reg_write(0xd003, 0, 16, 0x002f) != GSW_statusOk){ return -STATUS_NOK; } mdelay(10); } return 0; } static int serdes_write(struct file *file __attribute__ ((unused)), const char __user *buf, size_t count, loff_t *offset __attribute__((unused))) { serdes_reset(1); return count; } static int serdes_show(struct seq_file *seq, void *data __attribute__ ((unused)) ) { avmnet_module_t *this; u16 val; this = (avmnet_module_t *) seq->private; seq_printf(seq, "\n************* SerDes PHY Registers *************************\n\n"); gsw_reg_read(0xD000, 0, 16, &val); seq_printf(seq, "SGMII PHY Reset (%#x) = %#x\n", 0xD000,val); gsw_reg_read(0xD001, 0, 16, &val); seq_printf(seq, "SGMII PHY MPLL CFG1 (%#x) = %#x\n", 0xD001,val); gsw_reg_read(0xD002, 0, 16, &val); seq_printf(seq, "SGMII PHY MPLL CFG2 (%#x) = %#x\n", 0xD002,val); gsw_reg_read(0xD003, 0, 16, &val); seq_printf(seq, "SGMII PHY RX0 CFG1 (%#x) = %#x\n", 0xD003,val); gsw_reg_read(0xD004, 0, 16, &val); seq_printf(seq, "SGMII PHY RX0 CFG2 (%#x) = %#x\n", 0xD004,val); gsw_reg_read(0xD005, 0, 16, &val); seq_printf(seq, "SGMII PHY TX0 CFG1 (%#x) = %#x\n", 0xD005,val); gsw_reg_read(0xD006, 0, 16, &val); seq_printf(seq, "SGMII PHY TX0 CFG2 (%#x) = %#x\n", 0xD006,val); gsw_reg_read(0xD007, 0, 16, &val); seq_printf(seq, "SGMII PHY TX0 CFG3 (%#x) = %#x\n", 0xD007,val); gsw_reg_read(0xD008, 0, 16, &val); seq_printf(seq, "SGMII PHY MISC (%#x) = %#x\n", 0xD008,val); gsw_reg_read(0xD009, 0, 16, &val); seq_printf(seq, "SGMII HWBU CTRL (%#x) = %#x\n", 0xD009,val); gsw_reg_read(0xD00a, 0, 16, &val); seq_printf(seq, "SGMII PHY Status (%#x) = %#x\n", 0xD00a,val); gsw_reg_read(0xD100, 0, 16, &val); seq_printf(seq, "SGMII PHY D (%#x) = %#x\n", 0xD100,val); gsw_reg_read(0xD101, 0, 16, &val); seq_printf(seq, "SGMII PHY A (%#x) = %#x\n", 0xD101,val); gsw_reg_read(0xD102, 0, 16, &val); seq_printf(seq, "SGMII PHY C (%#x) = %#x\n", 0xD102,val); seq_printf(seq, "\n************* SerDes TBI Submodule Registers ***************\n\n"); gsw_reg_read(0xD300, 0, 16, &val); seq_printf(seq, "SGMII Transmit Autonegotiation High Byte (%#x) = %#x\n", 0xD300,val); gsw_reg_read(0xD301, 0, 16, &val); seq_printf(seq, "SGMII Transmit Autonegotiation Low Byte (%#x) = %#x\n", 0xD301,val); gsw_reg_read(0xD302, 0, 16, &val); seq_printf(seq, "Receive Autonegotiation High Byte (%#x) = %#x\n", 0xD302,val); gsw_reg_read(0xD303, 0, 16, &val); seq_printf(seq, "Receive Autonegotiation Low Byte(%#x) = %#x\n", 0xD303,val); gsw_reg_read(0xD304, 0, 16, &val); seq_printf(seq, "Autonegotiation Control Bits (%#x) = %#x\n", 0xD304,val); gsw_reg_read(0xD305, 0, 16, &val); seq_printf(seq, "SGMII TBI Control Bits (%#x) = %#x\n", 0xD305,val); gsw_reg_read(0xD306, 0, 16, &val); seq_printf(seq, "SGMII TBI Control Bits TX (%#x) = %#x\n", 0xD306,val); gsw_reg_read(0xD307, 0, 16, &val); seq_printf(seq, "SGMII TBI Test Control Bits (%#x) = %#x\n", 0xD307,val); gsw_reg_read(0xD308, 0, 16, &val); seq_printf(seq, "SGMII RX Error Counter (%#x) = %#x\n", 0xD308,val); gsw_reg_read(0xD309, 0, 16, &val); seq_printf(seq, "SGMII TBI Status (%#x) = %#x\n", 0xD309,val); gsw_reg_read(0xD30a, 0, 16, &val); seq_printf(seq, "SGMII Link Partner Status (%#x) = %#x\n", 0xD30a,val); gsw_reg_read(0xD30b, 0, 16, &val); seq_printf(seq, "SGMII Interrupt Status (%#x) = %#x\n", 0xD30b,val); gsw_reg_read(0xD30c, 0, 16, &val); seq_printf(seq, "SGMII Interrupt Mask(%#x) = %#x\n", 0xD30c,val); gsw_reg_read(0xD30d, 0, 16, &val); seq_printf(seq, "SGMII Transmitter State (%#x) = %#x\n", 0xD30d,val); gsw_reg_read(0xD30e, 0, 16, &val); seq_printf(seq, "SGMII Receiver State (%#x) = %#x\n", 0xD30e,val); seq_printf(seq, "\n************* SerDes PCS Register File *********************\n\n"); gsw_reg_read(0xD400, 0, 16, &val); seq_printf(seq, "SGMII PCS Configuration (%#x) = %#x\n", 0xD400,val); gsw_reg_read(0xD401, 0, 16, &val); seq_printf(seq, "SGMII Receive Buffer Control (%#x) = %#x\n", 0xD401,val); gsw_reg_read(0xD402, 0, 16, &val); seq_printf(seq, "SGMII Receive Buffer Configuration (%#x) = %#x\n", 0xD402,val); gsw_reg_read(0xD403, 0, 16, &val); seq_printf(seq, "SGMII PCS Receive Buffer Status(%#x) = %#x\n", 0xD403,val); gsw_reg_read(0xD404, 0, 16, &val); seq_printf(seq, "SGMII PCS Transmit Buffer Control (%#x) = %#x\n", 0xD404,val); gsw_reg_read(0xD405, 0, 16, &val); seq_printf(seq, "SGMII PCS Transmit Buffer Configuration (%#x) = %#x\n", 0xD405,val); gsw_reg_read(0xD406, 0, 16, &val); seq_printf(seq, "SGMII PCS Transmit Buffer Status (%#x) = %#x\n", 0xD406,val); seq_printf(seq, "\n************************************************************\n"); return 0; } static int serdes_open(struct inode *inode, struct file *file) { avmnet_module_t *this; this = (avmnet_module_t *) PDE_DATA(inode); return single_open(file, serdes_show, this); } static const struct file_operations serdes_fops = { .open = serdes_open, .read = seq_read, .write = serdes_write, .llseek = seq_lseek, .release = single_release, }; #if 0 /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int avmnet_f24s_disable_learning(avmnet_module_t *this) { unsigned int i; uint16_t value; int result; result = 0; if(this->initdata.swi.flags & SWI_DISABLE_LEARNING){ result = gsw_reg_write(PCE_GCTRL_0_PLIMMOD_OFFSET, PCE_GCTRL_0_PLIMMOD_SHIFT, PCE_GCTRL_0_PLIMMOD_SIZE, 1); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } for(i = FIRST_EXT_PORT; i <= LAST_EXT_PORT; ++i){ result = gsw_reg_write((PCE_PCTRL_1_LRNLIM_OFFSET + (0xA * MAP_API_TO_PHYSICAL_PORT(i))), PCE_PCTRL_1_LRNLIM_SHIFT, PCE_PCTRL_1_LRNLIM_SIZE, 0); if(result != 0){ AVMNET_ERR("[%s] Setting learning limit failed for port %d\n", __func__, i); goto err_out; } /*--- unicast ---*/ result = gsw_reg_read(PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, &value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } value &= ~(1 << MAP_API_TO_PHYSICAL_PORT(i)); result = gsw_reg_write(PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } /*--- multicast ---*/ result = gsw_reg_read(PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, &value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } value &= ~(1 << MAP_API_TO_PHYSICAL_PORT(i)); result = gsw_reg_write(PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } } result = gsw_reg_write((PCE_PCTRL_1_LRNLIM_OFFSET + (0xA * LTQ_SGMII_PORT)), PCE_PCTRL_1_LRNLIM_SHIFT, PCE_PCTRL_1_LRNLIM_SIZE, 0); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } /*--- unicast ---*/ result = gsw_reg_read(PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, &value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } value |= 1 << LTQ_SGMII_PORT; result = gsw_reg_write(PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } /*--- multicast ---*/ result = gsw_reg_read(PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, &value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } value |= 1 << LTQ_SGMII_PORT; result = gsw_reg_write(PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, value); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } // clear mirror port map result = gsw_reg_write(PCE_PMAP_1_MPMAP_OFFSET, PCE_PMAP_1_MPMAP_SHIFT, PCE_PMAP_1_MPMAP_SIZE, 0); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } result = gsw_reg_write(PCE_GCTRL_0_MTFL_OFFSET, PCE_GCTRL_0_MTFL_SHIFT, PCE_GCTRL_0_MTFL_SIZE, 1); if(result != 0){ AVMNET_ERR("[%s] Setting bLearningLimitAction failed\n", __func__); goto err_out; } } err_out: return result; } #endif /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_init(avmnet_module_t *this) { struct f24s_context *ctx; avmnet_device_t *dev; int i, result; AVMNET_DEBUG("[%s] Init on module %s called.\n", __func__, this->name); ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if(ctx == NULL){ AVMNET_ERR("[%s] init of avmnet-module %s failed.\n", __func__, this->name); return -ENOMEM; } this->priv = ctx; ctx->this_module = this; this_module = this; sema_init(&(ctx->mdio_lock), 1); GSW_IMPL_InitOnce((char *)&my_priv_data); BUG_ON(avmnet_hw_config_entry == NULL); for(i = 0; i < avmnet_hw_config_entry->nr_avm_devices; ++i){ dev = avmnet_hw_config_entry->avm_devices[i]; AVMNET_ERR("[%s] i: %d dev: %s ext_port: %d vlan: %d\n", __func__, i, dev->device_name, dev->external_port_no, dev->vlanID); my_priv_data.DevPriv[0].lan_port_vid[FIRST_EXT_PORT + dev->external_port_no] = dev->vlanID; } if(this->initdata.swi.flags & AVMNET_CONFIG_FLAG_RESET){ AVMNET_INFO("{%s} reset %d irq %d\n", __func__, this->initdata.swi.reset, this->initdata.swi.irq); } for(i = 0; i < this->num_children; ++i){ result = this->children[i]->init(this->children[i]); if(result < 0){ // handle error } } avmnet_cfg_register_module(this); return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_setup(avmnet_module_t *this) { int i, result; AVMNET_DEBUG("[%s] Init on module %s called.\n", __func__, this->name); ESHAL_LogErr(" \nAsserting reset GPIO\n"); result = gpio_set_value(PUMA7_GPIO_EXTSWITCH_RESET, 0); if(result != 0){ ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); goto err_out; } mdelay(10); ESHAL_LogErr(" \nReleasing reset GPIO\n"); result = gpio_set_value(PUMA7_GPIO_EXTSWITCH_RESET, 1); if(result != 0){ ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); goto err_out; } mdelay(100); result = GSW_IMPL_ResetSwitch(0, NULL, 0); if(result != GSW_statusOk){ AVMNET_ERR("[%s] ethsw_api_core_init() failed\n", __func__); goto err_out; } if(serdes_reset(2)){ ESHAL_LogErr(" \n*** %s (Failed Line#:%d) ***\n", __func__,__LINE__); result = -1; goto err_out; } for(i = 0; i < this->num_children; ++i){ result = this->children[i]->setup(this->children[i]); if(result < 0){ // handle error } } this->powerup(this); avmnet_cfg_add_seq_procentry(this, "rmon", &rmon_fops); // cannot be done before avmnet_cfg_register_module avmnet_cfg_add_seq_procentry(this, "serdes", &serdes_fops); err_out: return result; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avmnet_f24s_exit(avmnet_module_t *this) { int i, result; AVMNET_DEBUG("[%s] Exit on module %s called.\n", __func__, this->name); for(i = 0; i < this->num_children; ++i){ result = this->children[i]->exit(this->children[i]); if(result != 0){ // handle error } } kfree(this->priv); return 0; } int avmnet_f24s_powerup(avmnet_module_t *this) { unsigned int i; int result; AVMNET_ERR("[%s] Called.\n", __func__); #if 1 for(i = 0; i < this->num_children; ++i){ result = this->children[i]->powerup(this->children[i]); if(result != 0){ AVMNET_ERR("[%s] Powerup failed for module %s\n", __func__, this->children[i]->name); goto err_out; } } #endif result = gsw_reg_write(((PHY_ADDR_0_LNKST_OFFSET - this->initdata.swi.cpu_mac_port) + GSW_TREG_OFFSET), PHY_ADDR_0_LNKST_SHIFT, PHY_ADDR_0_LNKST_SIZE, 1); if(result != 0){ AVMNET_ERR("[%s] Link force up failed for module %s\n", __func__, this->name); goto err_out; } err_out: return result; } int avmnet_f24s_powerdown(avmnet_module_t *this) { unsigned int i; int result; AVMNET_ERR("[%s] Called.\n", __func__); result = gsw_reg_write(((PHY_ADDR_0_LNKST_OFFSET - this->initdata.swi.cpu_mac_port) + GSW_TREG_OFFSET), PHY_ADDR_0_LNKST_SHIFT, PHY_ADDR_0_LNKST_SIZE, 2); if(result != 0){ AVMNET_ERR("[%s] Link force down failed for module %s\n", __func__, this->name); goto err_out; } #if 1 for(i = 0; i < this->num_children; ++i){ result = this->children[i]->powerdown(this->children[i]); if(result != 0){ AVMNET_ERR("[%s] Powerdown failed for module %s\n", __func__, this->children[i]->name); goto err_out; } } #endif err_out: return result; } int avmnet_f24s_suspend(avmnet_module_t *this __maybe_unused, avmnet_module_t *caller __maybe_unused) { return 0; } int avmnet_f24s_resume(avmnet_module_t *this __maybe_unused, avmnet_module_t *caller __maybe_unused) { return 0; }