/* * Copyright c Realtek Semiconductor Corporation, 2009 * All rights reserved. * * Program : Switch table basic operation driver * Abstract : * Author : hyking (hyking_liu@realsil.com.cn) */ #include <net/rtl/rtl_types.h> //#include "types.h" #include "asicRegs.h" #include "asicTabs.h" //#include "rtl_glue.h" #include "rtl865x_hwPatch.h" #include "rtl865x_asicBasic.h" /* * According to ghhuang's suggest, * we DO NOT need to access 8 ASIC entries at once. * We just need to access several entries as we need. */ #define RTL865X_FAST_ASIC_ACCESS /* * For RTL865xC Access protection mechanism * * We define 2 different MACROs for ASIC table * read/write protection correspondingly * */ #define RTL865XC_ASIC_READ_PROTECTION /* Enable/Disable ASIC read protection */ #define RTL865XC_ASIC_WRITE_PROTECTION /* Enable/Disable ASIC write protection */ //#undef RTL865X_READ_MULTIPLECHECK #define RTL865X_READ_MULTIPLECHECK #define RTL865X_READ_MULTIPLECHECK_CNT 2 #define RTL865X_READ_MULTIPLECHECK_MAX_RETRY 10 int8 RtkHomeGatewayChipName[16]; int32 RtkHomeGatewayChipRevisionID; int32 RtkHomeGatewayChipNameID; #ifdef RTL865X_FAST_ASIC_ACCESS uint32 _rtl8651_asicTableSize[] = { 2 /*TYPE_L2_SWITCH_TABLE*/, 1 /*TYPE_ARP_TABLE*/, #if defined(CONFIG_RTL_8685S_HWNAT) 3 /*TYPE_L3_ROUTING_TABLE*/, #else /* CONFIG_RTL_8685S_HWNAT */ 2 /*TYPE_L3_ROUTING_TABLE*/, #endif /* CONFIG_RTL_8685S_HWNAT */ 3 /*TYPE_MULTICAST_TABLE*/, 5 /*TYPE_NETIF_TABLE*/, 3 /*TYPE_EXT_INT_IP_TABLE*/, 3 /*TYPE_VLAN_TABLE*/, 3 /*TYPE_VLAN1_TABLE*/, 4 /*TYPE_SERVER_PORT_TABLE*/, #if defined(CONFIG_RTL_HW_NAPT_4KENTRY) 4 /*TYPE_L4_TCP_UDP_TABLE*/, #else 3 /*TYPE_L4_TCP_UDP_TABLE*/, #endif 3 /*TYPE_L4_ICMP_TABLE*/, 1 /*TYPE_PPPOE_TABLE*/, #if defined(CONFIG_RTL_8685S_HWNAT) 11 /*TYPE_ACL_RULE_TABLE*/, #else /* CONFIG_RTL_8685S_HWNAT */ 8 /*TYPE_ACL_RULE_TABLE*/, #endif /* CONFIG_RTL_8685S_HWNAT */ 1 /*TYPE_NEXT_HOP_TABLE*/, 3 /*TYPE_RATE_LIMIT_TABLE*/, 1 /*TYPE_ALG_TABLE*/, #if defined(CONFIG_RTL_8685S_HWNAT) 9 /*TYPE_DS_LITE_TABLE*/, 6 /*TYPE_6RD_TABLE*/, 6 /*TYPE_L3_V6_ROUTING_TABLE*/, 1 /*TYPE_NEXT_HOP_V6_TABLE*/, 3 /*TYPE_ARP_V6_TABLE*/, 9 /*TYPE_MULTICAST_V6_TABLE*/, #endif /* CONFIG_RTL_8685S_HWNAT */ #if defined(CONFIG_RTL_HW_NAPT_4KENTRY) 0, 0, 0, 4 /*TYPE_L4_TCP_UDP_TABLE*/, #endif }; #endif static void _rtl8651_asicTableAccessForward(uint32 tableType, uint32 eidx, void *entryContent_P) { ASSERT_CSP(entryContent_P); if(!IS_RLE0822C_HWNAT() && tableType==TYPE_L4_TCP_UDP_TABLE && eidx>=1024) return; while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command done #ifdef RTL865X_FAST_ASIC_ACCESS { register uint32 index; for( index = 0; index < _rtl8651_asicTableSize[tableType]; index++ ) { WRITE_MEM32(TCR0+(index<<2), *((uint32 *)entryContent_P + index)); } } #else WRITE_MEM32(TCR0, *((uint32 *)entryContent_P + 0)); WRITE_MEM32(TCR1, *((uint32 *)entryContent_P + 1)); WRITE_MEM32(TCR2, *((uint32 *)entryContent_P + 2)); WRITE_MEM32(TCR3, *((uint32 *)entryContent_P + 3)); WRITE_MEM32(TCR4, *((uint32 *)entryContent_P + 4)); WRITE_MEM32(TCR5, *((uint32 *)entryContent_P + 5)); WRITE_MEM32(TCR6, *((uint32 *)entryContent_P + 6)); WRITE_MEM32(TCR7, *((uint32 *)entryContent_P + 7)); #if defined(CONFIG_RTL_8685S_HWNAT) WRITE_MEM32(TCR8, *((uint32 *)entryContent_P + 8)); WRITE_MEM32(TCR9, *((uint32 *)entryContent_P + 9)); WRITE_MEM32(TCR10, *((uint32 *)entryContent_P + 10)); #endif /* CONFIG_RTL_8685S_HWNAT */ #endif #if defined(CONFIG_RTL_HW_NAPT_4KENTRY) if(IS_RLE0822C_HWNAT() && tableType==TYPE_L4_TCP_UDP_TABLE && eidx>2047) { tableType = TYPE_L4_EXT_TCP_UDP_TABLE; eidx -= 2048; } #endif WRITE_MEM32(SWTAA, ((uint32) rtl8651_asicTableAccessAddrBase(tableType) + eidx * RTL8651_ASICTABLE_ENTRY_LENGTH));//Fill address } int32 _rtl8651_addAsicEntry(uint32 tableType, uint32 eidx, void *entryContent_P) { _rtl8651_asicTableAccessForward(tableType, eidx, entryContent_P); #ifdef RTL865XC_ASIC_WRITE_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,EN_STOP_TLU|READ_MEM32(SWTCR0)); while ( (READ_MEM32(SWTCR0) & STOP_TLU_READY)==0); } #endif WRITE_MEM32(SWTACR, ACTION_START | CMD_ADD );//Activate add command while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command done if ( (READ_MEM32(SWTASR) & TABSTS_MASK) != TABSTS_SUCCESS )//Check status { #ifdef RTL865XC_ASIC_WRITE_PROTECTION if(RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,~EN_STOP_TLU&READ_MEM32(SWTCR0)); } #endif return FAILED; } #ifdef RTL865XC_ASIC_WRITE_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,~EN_STOP_TLU&READ_MEM32(SWTCR0)); } #endif return SUCCESS; } #ifdef CONFIG_PROC_FS static unsigned int mcastForceAddOpCnt=0; unsigned int _rtl865x_getForceAddMcastOpCnt(void) { return mcastForceAddOpCnt; } #endif int32 _rtl8651_forceAddAsicEntry(uint32 tableType, uint32 eidx, void *entryContent_P) { #ifdef CONFIG_PROC_FS if(tableType==TYPE_MULTICAST_TABLE) { mcastForceAddOpCnt++; } #endif #ifdef RTL865XC_ASIC_WRITE_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { /* No need to stop HW table lookup process */ WRITE_MEM32(SWTCR0,EN_STOP_TLU|READ_MEM32(SWTCR0)); while ( (READ_MEM32(SWTCR0) & STOP_TLU_READY)==0); } #endif _rtl8651_asicTableAccessForward(tableType, eidx, entryContent_P); WRITE_MEM32(SWTACR, ACTION_START | CMD_FORCE);//Activate add command while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command done #ifdef RTL865XC_ASIC_WRITE_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,~EN_STOP_TLU&READ_MEM32(SWTCR0)); } #endif return SUCCESS; } #if defined(CONFIG_RTL_8685S_HWNAT) #define MAX_ENTRY_CONTENT_SIZE 11 #else /* CONFIG_RTL_8685S_HWNAT */ #define MAX_ENTRY_CONTENT_SIZE 8 #endif /* CONFIG_RTL_8685S_HWNAT */ int32 _rtl8651_readAsicEntry(uint32 tableType, uint32 eidx, void *entryContent_P) { #if 0 uint32 *entryAddr; uint32 tmp;/* dummy variable, don't remove it */ #ifdef RTL865X_READ_MULTIPLECHECK uint32 entryContent[RTL865X_READ_MULTIPLECHECK_CNT][8]; uint32 entryContentIdx; uint32 entryContent_new = RTL865X_READ_MULTIPLECHECK_CNT;/* to indicate which content is newer */ uint32 entryCompare_max_count = RTL865X_READ_MULTIPLECHECK_MAX_RETRY; uint32 needRetry; #endif #ifdef RTL865XC_ASIC_READ_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { /* No need to stop HW table lookup process */ WRITE_MEM32(SWTCR0,EN_STOP_TLU|READ_MEM32(SWTCR0)); while ( (READ_MEM32(SWTCR0) & STOP_TLU_READY)==0); } #endif ASSERT_CSP(entryContent_P); entryAddr = (uint32 *) ( (uint32) rtl8651_asicTableAccessAddrBase(tableType) + (eidx<<5 /*RTL8651_ASICTABLE_ENTRY_LENGTH*/) ) ; /*(uint32) rtl8651_asicTableAccessAddrBase(tableType) + eidx * RTL8651_ASICTABLE_ENTRY_LENGTH);*/ while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command ready #ifdef RTL865X_READ_MULTIPLECHECK do { for ( entryContentIdx = 0 ; entryContentIdx < RTL865X_READ_MULTIPLECHECK_CNT ; entryContentIdx ++ ) { if ( entryContent_new != entryContentIdx ) { entryContent[entryContentIdx][0] = *(entryAddr + 0); entryContent[entryContentIdx][1] = *(entryAddr + 1); entryContent[entryContentIdx][2] = *(entryAddr + 2); entryContent[entryContentIdx][3] = *(entryAddr + 3); entryContent[entryContentIdx][4] = *(entryAddr + 4); entryContent[entryContentIdx][5] = *(entryAddr + 5); entryContent[entryContentIdx][6] = *(entryAddr + 6); entryContent[entryContentIdx][7] = *(entryAddr + 7); entryContent_new = entryContentIdx; } } needRetry = FALSE; for ( entryContentIdx = 0 ; entryContentIdx < RTL865X_READ_MULTIPLECHECK_CNT ; entryContentIdx ++ ) { uint32 entryCompareContentIdx; for ( entryCompareContentIdx = (entryContentIdx) ; entryCompareContentIdx < RTL865X_READ_MULTIPLECHECK_CNT ; entryCompareContentIdx ++ ) { int32 idx; for ( idx = 0 ; idx < 8 ; idx ++ ) { if ( entryContent[entryContentIdx][idx] != entryContent[entryCompareContentIdx][idx] ) { needRetry = TRUE; goto retry; } } } } retry: entryCompare_max_count --; } while ( ( needRetry == FALSE ) && ( entryCompare_max_count > 0 ) ); /* Update entryAddr for newer one */ entryAddr = &( entryContent[ entryContent_new ][0] ); #endif #ifdef RTL865X_FAST_ASIC_ACCESS { register uint32 index; for( index = 0; index < _rtl8651_asicTableSize[tableType]; index++ ) { *((uint32 *)entryContent_P + index) = READ_MEM32((uint32)(entryAddr + index)); } } #else *((uint32 *)entryContent_P + 0) = *(entryAddr + 0); *((uint32 *)entryContent_P + 1) = *(entryAddr + 1); *((uint32 *)entryContent_P + 2) = *(entryAddr + 2); *((uint32 *)entryContent_P + 3) = *(entryAddr + 3); *((uint32 *)entryContent_P + 4) = *(entryAddr + 4); *((uint32 *)entryContent_P + 5) = *(entryAddr + 5); *((uint32 *)entryContent_P + 6) = *(entryAddr + 6); *((uint32 *)entryContent_P + 7) = *(entryAddr + 7); #endif /* Dummy read. Must read an un-used table entry to refresh asic latch */ tmp = *(uint32 *)((uint32) rtl8651_asicTableAccessAddrBase(TYPE_ACL_RULE_TABLE) + 1024 * RTL8651_ASICTABLE_ENTRY_LENGTH); #ifdef RTL865XC_ASIC_READ_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,~EN_STOP_TLU&READ_MEM32(SWTCR0)); } #endif #else uint32 *entryAddr; uint32 tmp;/* dummy variable, don't remove it */ // uint32 access; #ifdef RTL865X_READ_MULTIPLECHECK uint32 entryContent[RTL865X_READ_MULTIPLECHECK_CNT][MAX_ENTRY_CONTENT_SIZE]; // CONFIG_RTL_8685S_HWNAT uint32 entryContentIdx; uint32 entryContent_new = RTL865X_READ_MULTIPLECHECK_CNT;/* to indicate which content is newer */ uint32 entryCompare_max_count = RTL865X_READ_MULTIPLECHECK_MAX_RETRY; uint32 needRetry; #endif #if defined(CONFIG_RTL_8685S_HWNAT) int i; #endif /* CONFIG_RTL_8685S_HWNAT */ // rtl865x_accessAsicTable(tableType, &access); // if(!access) // return FAILED; // #ifdef RTL865XC_ASIC_READ_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { /* No need to stop HW table lookup process */ WRITE_MEM32(SWTCR0,EN_STOP_TLU|READ_MEM32(SWTCR0)); while ( (READ_MEM32(SWTCR0) & STOP_TLU_READY)==0); } #endif ASSERT_CSP(entryContent_P); entryAddr = (uint32 *) ( (uint32) rtl8651_asicTableAccessAddrBase(tableType) + (eidx<<5 /*RTL8651_ASICTABLE_ENTRY_LENGTH*/) ) ; /*(uint32) rtl8651_asicTableAccessAddrBase(tableType) + eidx * RTL8651_ASICTABLE_ENTRY_LENGTH);*/ while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command ready #ifdef RTL865X_READ_MULTIPLECHECK do { for ( entryContentIdx = 0 ; entryContentIdx < RTL865X_READ_MULTIPLECHECK_CNT ; entryContentIdx ++ ) { entryContent[entryContentIdx][0] = *(entryAddr + 0); entryContent[entryContentIdx][1] = *(entryAddr + 1); entryContent[entryContentIdx][2] = *(entryAddr + 2); entryContent[entryContentIdx][3] = *(entryAddr + 3); entryContent[entryContentIdx][4] = *(entryAddr + 4); entryContent[entryContentIdx][5] = *(entryAddr + 5); entryContent[entryContentIdx][6] = *(entryAddr + 6); entryContent[entryContentIdx][7] = *(entryAddr + 7); #if defined(CONFIG_RTL_8685S_HWNAT) if(_rtl8651_asicTableSize[tableType]>8) { /* The LSB 256bits is defined as before, but bit 335 to bit256 is moved to add addr[15]. for example: ACL rule 0 Virtual Address : bit [255:0] : 0xbb0c_0000 ~ 0xbb0c_001c bit [335:256] : 0xbb0c_8000 ~ 0xbb0c_8008 entryContent[entryContentIdx][8] = *(entryAddr + 0 + (BIT(15) / 4)); entryContent[entryContentIdx][9] = *(entryAddr + 1 + (BIT(15) / 4)); entryContent[entryContentIdx][10] = *(entryAddr + 2 + (BIT(15) / 4)); */ entryContent[entryContentIdx][8] = *(entryAddr + 8192); entryContent[entryContentIdx][9] = *(entryAddr + 8193); entryContent[entryContentIdx][10] = *(entryAddr + 8194); } #endif /* CONFIG_RTL_8685S_HWNAT */ } entryContent_new = RTL865X_READ_MULTIPLECHECK_CNT-1; needRetry = FALSE; for ( entryContentIdx = 1 ; entryContentIdx < RTL865X_READ_MULTIPLECHECK_CNT ; entryContentIdx ++ ) { int32 idx; for ( idx = 0 ; idx < MAX_ENTRY_CONTENT_SIZE ; idx ++ ) // CONFIG_RTL_8685S_HWNAT { if ( entryContent[entryContentIdx][idx] != entryContent[0][idx] ) { needRetry = TRUE; goto retry; } } } retry: entryCompare_max_count --; } while ( ( needRetry == TRUE ) && ( entryCompare_max_count > 0 ) ); /* Update entryAddr for newer one */ entryAddr = &( entryContent[ entryContent_new ][0] ); #endif #if defined(RTL865X_READ_MULTIPLECHECK) && defined(CONFIG_RTL_8685S_HWNAT) #ifdef RTL865X_FAST_ASIC_ACCESS for( i = 0; i < _rtl8651_asicTableSize[tableType]; i++ ) { *((uint32 *)entryContent_P + i) = entryContent[ entryContent_new ][i]; } #else for( i = 0; i < MAX_ENTRY_CONTENT_SIZE; i++ ) { *((uint32 *)entryContent_P + i) = entryContent[ entryContent_new ][i]; } #endif #else /* defined(RTL865X_READ_MULTIPLECHECK) && defined(CONFIG_RTL_8685S_HWNAT) */ #ifdef RTL865X_FAST_ASIC_ACCESS { register uint32 index; for( index = 0; index < _rtl8651_asicTableSize[tableType]; index++ ) { #if defined(CONFIG_RTL_8685S_HWNAT) if(index<8) *((uint32 *)entryContent_P + index) = READ_MEM32((uint32)(entryAddr + index)); else *((uint32 *)entryContent_P + index) = READ_MEM32((uint32)(entryAddr + index-8+8192)); #else *((uint32 *)entryContent_P + index) = READ_MEM32((uint32)(entryAddr + index)); #endif } } #else *((uint32 *)entryContent_P + 0) = *(entryAddr + 0); *((uint32 *)entryContent_P + 1) = *(entryAddr + 1); *((uint32 *)entryContent_P + 2) = *(entryAddr + 2); *((uint32 *)entryContent_P + 3) = *(entryAddr + 3); *((uint32 *)entryContent_P + 4) = *(entryAddr + 4); *((uint32 *)entryContent_P + 5) = *(entryAddr + 5); *((uint32 *)entryContent_P + 6) = *(entryAddr + 6); *((uint32 *)entryContent_P + 7) = *(entryAddr + 7); #if defined(CONFIG_RTL_8685S_HWNAT) *((uint32 *)entryContent_P + 8) = *(entryAddr + 8192); *((uint32 *)entryContent_P + 9) = *(entryAddr + 8193); *((uint32 *)entryContent_P + 10) = *(entryAddr+ 8194); #endif /* CONFIG_RTL_8685S_HWNAT */ #endif #endif /* defined(RTL865X_READ_MULTIPLECHECK) && defined(CONFIG_RTL_8685S_HWNAT) */ /* Dummy read. Must read an un-used table entry to refresh asic latch */ tmp = *(uint32 *)((uint32) rtl8651_asicTableAccessAddrBase(TYPE_ACL_RULE_TABLE) + 1024 * RTL8651_ASICTABLE_ENTRY_LENGTH); #ifdef RTL865XC_ASIC_READ_PROTECTION if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,~EN_STOP_TLU&READ_MEM32(SWTCR0)); } #endif return 0; #endif return 0; } #if 0 //No need to Stop_Table_Lookup process int32 _rtl8651_readAsicEntryStopTLU(uint32 tableType, uint32 eidx, void *entryContent_P) { uint32 *entryAddr; uint32 tmp;/* dummy variable, don't remove it */ ASSERT_CSP(entryContent_P); entryAddr = (uint32 *) ( (uint32) rtl8651_asicTableAccessAddrBase(tableType) + (eidx<<5 /*RTL8651_ASICTABLE_ENTRY_LENGTH*/) ) ; /*(uint32) rtl8651_asicTableAccessAddrBase(tableType) + eidx * RTL8651_ASICTABLE_ENTRY_LENGTH);*/ #if 0 while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command ready #endif if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { /* No need to stop HW table lookup process */ WRITE_MEM32(SWTCR0,EN_STOP_TLU|READ_MEM32(SWTCR0)); #if 0 //while ( (READ_MEM32(SWTCR0) & STOP_TLU_READY)==0); #endif } #ifdef RTL865X_FAST_ASIC_ACCESS { register uint32 index; for( index = 0; index < _rtl8651_asicTableSize[tableType]; index++ ) { *((uint32 *)entryContent_P + index) = READ_MEM32((uint32)(entryAddr + index)); } } #else *((uint32 *)entryContent_P + 0) = *(entryAddr + 0); *((uint32 *)entryContent_P + 1) = *(entryAddr + 1); *((uint32 *)entryContent_P + 2) = *(entryAddr + 2); *((uint32 *)entryContent_P + 3) = *(entryAddr + 3); *((uint32 *)entryContent_P + 4) = *(entryAddr + 4); *((uint32 *)entryContent_P + 5) = *(entryAddr + 5); *((uint32 *)entryContent_P + 6) = *(entryAddr + 6); *((uint32 *)entryContent_P + 7) = *(entryAddr + 7); #endif if (RTL865X_TLU_BUG_FIXED) /* No need to stop HW table lookup process */ { WRITE_MEM32(SWTCR0,~EN_STOP_TLU&READ_MEM32(SWTCR0)); } /* Dummy read. Must read an un-used table entry to refresh asic latch */ tmp = *(uint32 *)((uint32) rtl8651_asicTableAccessAddrBase(TYPE_ACL_RULE_TABLE) + 1024 * RTL8651_ASICTABLE_ENTRY_LENGTH); return 0; } #endif int32 _rtl8651_delAsicEntry(uint32 tableType, uint32 startEidx, uint32 endEidx) { uint32 eidx = startEidx; while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command done #ifdef RTL865X_FAST_ASIC_ACCESS { register uint32 index; for( index = 0; index < _rtl8651_asicTableSize[tableType]; index++ ) { WRITE_MEM32(TCR0+(index<<2), 0); } } #else WRITE_MEM32(TCR0, 0); WRITE_MEM32(TCR1, 0); WRITE_MEM32(TCR2, 0); WRITE_MEM32(TCR3, 0); WRITE_MEM32(TCR4, 0); WRITE_MEM32(TCR5, 0); WRITE_MEM32(TCR6, 0); WRITE_MEM32(TCR7, 0); #if defined(CONFIG_RTL_8685S_HWNAT) WRITE_MEM32(TCR8, 0); WRITE_MEM32(TCR9, 0); WRITE_MEM32(TCR10, 0); #endif /* CONFIG_RTL_8685S_HWNAT */ #endif while (eidx <= endEidx) { if(!IS_RLE0822C_HWNAT() && tableType==TYPE_L4_TCP_UDP_TABLE && eidx>=1024) return SUCCESS; #if defined(CONFIG_RTL_HW_NAPT_4KENTRY) if(IS_RLE0822C_HWNAT() && eidx>=2048 && tableType==TYPE_L4_TCP_UDP_TABLE) WRITE_MEM32(SWTAA, (uint32) rtl8651_asicTableAccessAddrBase(TYPE_L4_EXT_TCP_UDP_TABLE) + (eidx-2048) * RTL8651_ASICTABLE_ENTRY_LENGTH);//Fill address else #endif WRITE_MEM32(SWTAA, (uint32) rtl8651_asicTableAccessAddrBase(tableType) + eidx * RTL8651_ASICTABLE_ENTRY_LENGTH);//Fill address WRITE_MEM32(SWTACR, ACTION_START | CMD_FORCE);//Activate add command while ( (READ_MEM32(SWTACR) & ACTION_MASK) != ACTION_DONE );//Wait for command done if ( (READ_MEM32(SWTASR) & TABSTS_MASK) != TABSTS_SUCCESS )//Check status return FAILED; ++eidx; } return SUCCESS; }