diff options
author | raghavendra.koushik@neterion.com <raghavendra.koushik@neterion.com> | 2005-08-03 15:27:09 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-11 00:10:44 -0400 |
commit | 5e25b9ddb6683fe225a2266b53d73c57381a0c18 (patch) | |
tree | b67e4253ec02e5a38c82cef823f76a815318db4f | |
parent | 20346722ec474245446bcbf460594a935a5c0512 (diff) |
[PATCH] S2io: Hardware fixes
Hi,
Below patch addresses few h/w specific issues.
1. Check for additional ownership bit on Rx path before
starting Rx processing.
2. Enable only 4 PCCs(Per Context Controller) for Xframe I
revisions less than 4.
3. Program Rx and Tx round robin registers depending on
no. of rings/FIFOs.
4. Tx continous interrupts is now a loadable parameter.
5. Reset the card if we get double-bit ECC errors.
6. A soft reset of XGXS being done to force a link state change has been
eliminated.
7. After a reset, clear "parity error detected" bit,
PCI-X ECC status register, and PCI_STATUS bit in
tx_pic_int register.
8. The error in the disabling allmulticast implementation has been
rectified.
9. Leave the PCI-X parameters MMRBC, OST etc. at their
BIOS/system defaults.
Signed-off-by: Ravinandan Arakali <ravinandan.arakali@neterion.com>
Signed-off-by: Raghavendra Koushik <raghavendra.koushik@neterion.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/net/s2io-regs.h | 7 | ||||
-rw-r--r-- | drivers/net/s2io.c | 410 | ||||
-rw-r--r-- | drivers/net/s2io.h | 4 |
3 files changed, 341 insertions, 80 deletions
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index 8746740e6efd..826deb0eb03a 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h | |||
@@ -62,6 +62,7 @@ typedef struct _XENA_dev_config { | |||
62 | #define ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6) | 62 | #define ADAPTER_STATUS_RMAC_REMOTE_FAULT BIT(6) |
63 | #define ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7) | 63 | #define ADAPTER_STATUS_RMAC_LOCAL_FAULT BIT(7) |
64 | #define ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8) | 64 | #define ADAPTER_STATUS_RMAC_PCC_IDLE vBIT(0xFF,8,8) |
65 | #define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE vBIT(0x0F,8,8) | ||
65 | #define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8) | 66 | #define ADAPTER_STATUS_RC_PRC_QUIESCENT vBIT(0xFF,16,8) |
66 | #define ADAPTER_STATUS_MC_DRAM_READY BIT(24) | 67 | #define ADAPTER_STATUS_MC_DRAM_READY BIT(24) |
67 | #define ADAPTER_STATUS_MC_QUEUES_READY BIT(25) | 68 | #define ADAPTER_STATUS_MC_QUEUES_READY BIT(25) |
@@ -245,6 +246,7 @@ typedef struct _XENA_dev_config { | |||
245 | #define STAT_TRSF_PER(n) TBD | 246 | #define STAT_TRSF_PER(n) TBD |
246 | #define PER_SEC 0x208d5 | 247 | #define PER_SEC 0x208d5 |
247 | #define SET_UPDT_PERIOD(n) vBIT((PER_SEC*n),32,32) | 248 | #define SET_UPDT_PERIOD(n) vBIT((PER_SEC*n),32,32) |
249 | #define SET_UPDT_CLICKS(val) vBIT(val, 32, 32) | ||
248 | 250 | ||
249 | u64 stat_addr; | 251 | u64 stat_addr; |
250 | 252 | ||
@@ -289,6 +291,7 @@ typedef struct _XENA_dev_config { | |||
289 | 291 | ||
290 | u64 pcc_err_reg; | 292 | u64 pcc_err_reg; |
291 | #define PCC_FB_ECC_DB_ERR vBIT(0xFF, 16, 8) | 293 | #define PCC_FB_ECC_DB_ERR vBIT(0xFF, 16, 8) |
294 | #define PCC_ENABLE_FOUR vBIT(0x0F,0,8) | ||
292 | 295 | ||
293 | u64 pcc_err_mask; | 296 | u64 pcc_err_mask; |
294 | u64 pcc_err_alarm; | 297 | u64 pcc_err_alarm; |
@@ -690,6 +693,10 @@ typedef struct _XENA_dev_config { | |||
690 | #define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22) | 693 | #define MC_ERR_REG_MIRI_CRI_ERR_0 BIT(22) |
691 | #define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23) | 694 | #define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23) |
692 | #define MC_ERR_REG_SM_ERR BIT(31) | 695 | #define MC_ERR_REG_SM_ERR BIT(31) |
696 | #define MC_ERR_REG_ECC_ALL_SNG (BIT(6) | \ | ||
697 | BIT(7) | BIT(17) | BIT(19)) | ||
698 | #define MC_ERR_REG_ECC_ALL_DBL (BIT(14) | \ | ||
699 | BIT(15) | BIT(18) | BIT(20)) | ||
693 | u64 mc_err_mask; | 700 | u64 mc_err_mask; |
694 | u64 mc_err_alarm; | 701 | u64 mc_err_alarm; |
695 | 702 | ||
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 0721e78dd8b0..e2144fc7df9a 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -68,6 +68,16 @@ | |||
68 | static char s2io_driver_name[] = "Neterion"; | 68 | static char s2io_driver_name[] = "Neterion"; |
69 | static char s2io_driver_version[] = "Version 1.7.7"; | 69 | static char s2io_driver_version[] = "Version 1.7.7"; |
70 | 70 | ||
71 | static inline int RXD_IS_UP2DT(RxD_t *rxdp) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) && | ||
76 | (GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK)); | ||
77 | |||
78 | return ret; | ||
79 | } | ||
80 | |||
71 | /* | 81 | /* |
72 | * Cards with following subsystem_id have a link state indication | 82 | * Cards with following subsystem_id have a link state indication |
73 | * problem, 600B, 600C, 600D, 640B, 640C and 640D. | 83 | * problem, 600B, 600C, 600D, 640B, 640C and 640D. |
@@ -230,6 +240,7 @@ static unsigned int rx_ring_sz[MAX_RX_RINGS] = | |||
230 | static unsigned int Stats_refresh_time = 4; | 240 | static unsigned int Stats_refresh_time = 4; |
231 | static unsigned int rts_frm_len[MAX_RX_RINGS] = | 241 | static unsigned int rts_frm_len[MAX_RX_RINGS] = |
232 | {[0 ...(MAX_RX_RINGS - 1)] = 0 }; | 242 | {[0 ...(MAX_RX_RINGS - 1)] = 0 }; |
243 | static unsigned int use_continuous_tx_intrs = 1; | ||
233 | static unsigned int rmac_pause_time = 65535; | 244 | static unsigned int rmac_pause_time = 65535; |
234 | static unsigned int mc_pause_threshold_q0q3 = 187; | 245 | static unsigned int mc_pause_threshold_q0q3 = 187; |
235 | static unsigned int mc_pause_threshold_q4q7 = 187; | 246 | static unsigned int mc_pause_threshold_q4q7 = 187; |
@@ -638,7 +649,7 @@ static int init_nic(struct s2io_nic *nic) | |||
638 | mac_control = &nic->mac_control; | 649 | mac_control = &nic->mac_control; |
639 | config = &nic->config; | 650 | config = &nic->config; |
640 | 651 | ||
641 | /* to set the swapper control on the card */ | 652 | /* to set the swapper controle on the card */ |
642 | if(s2io_set_swapper(nic)) { | 653 | if(s2io_set_swapper(nic)) { |
643 | DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n"); | 654 | DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n"); |
644 | return -1; | 655 | return -1; |
@@ -756,6 +767,13 @@ static int init_nic(struct s2io_nic *nic) | |||
756 | val64 |= BIT(0); /* To enable the FIFO partition. */ | 767 | val64 |= BIT(0); /* To enable the FIFO partition. */ |
757 | writeq(val64, &bar0->tx_fifo_partition_0); | 768 | writeq(val64, &bar0->tx_fifo_partition_0); |
758 | 769 | ||
770 | /* | ||
771 | * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug | ||
772 | * SXE-008 TRANSMIT DMA ARBITRATION ISSUE. | ||
773 | */ | ||
774 | if (get_xena_rev_id(nic->pdev) < 4) | ||
775 | writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable); | ||
776 | |||
759 | val64 = readq(&bar0->tx_fifo_partition_0); | 777 | val64 = readq(&bar0->tx_fifo_partition_0); |
760 | DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n", | 778 | DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n", |
761 | &bar0->tx_fifo_partition_0, (unsigned long long) val64); | 779 | &bar0->tx_fifo_partition_0, (unsigned long long) val64); |
@@ -823,37 +841,250 @@ static int init_nic(struct s2io_nic *nic) | |||
823 | } | 841 | } |
824 | writeq(val64, &bar0->rx_queue_cfg); | 842 | writeq(val64, &bar0->rx_queue_cfg); |
825 | 843 | ||
826 | /* Initializing the Tx round robin registers to 0 | ||
827 | * filling tx and rx round robin registers as per | ||
828 | * the number of FIFOs and Rings is still TODO | ||
829 | */ | ||
830 | writeq(0, &bar0->tx_w_round_robin_0); | ||
831 | writeq(0, &bar0->tx_w_round_robin_1); | ||
832 | writeq(0, &bar0->tx_w_round_robin_2); | ||
833 | writeq(0, &bar0->tx_w_round_robin_3); | ||
834 | writeq(0, &bar0->tx_w_round_robin_4); | ||
835 | |||
836 | /* | 844 | /* |
837 | * TODO | 845 | * Filling Tx round robin registers |
838 | * Disable Rx steering. Hard coding all packets to be steered to | 846 | * as per the number of FIFOs |
839 | * Queue 0 for now. | ||
840 | */ | 847 | */ |
841 | val64 = 0x8080808080808080ULL; | 848 | switch (config->tx_fifo_num) { |
842 | writeq(val64, &bar0->rts_qos_steering); | 849 | case 1: |
850 | val64 = 0x0000000000000000ULL; | ||
851 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
852 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
853 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
854 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
855 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
856 | break; | ||
857 | case 2: | ||
858 | val64 = 0x0000010000010000ULL; | ||
859 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
860 | val64 = 0x0100000100000100ULL; | ||
861 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
862 | val64 = 0x0001000001000001ULL; | ||
863 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
864 | val64 = 0x0000010000010000ULL; | ||
865 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
866 | val64 = 0x0100000000000000ULL; | ||
867 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
868 | break; | ||
869 | case 3: | ||
870 | val64 = 0x0001000102000001ULL; | ||
871 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
872 | val64 = 0x0001020000010001ULL; | ||
873 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
874 | val64 = 0x0200000100010200ULL; | ||
875 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
876 | val64 = 0x0001000102000001ULL; | ||
877 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
878 | val64 = 0x0001020000000000ULL; | ||
879 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
880 | break; | ||
881 | case 4: | ||
882 | val64 = 0x0001020300010200ULL; | ||
883 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
884 | val64 = 0x0100000102030001ULL; | ||
885 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
886 | val64 = 0x0200010000010203ULL; | ||
887 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
888 | val64 = 0x0001020001000001ULL; | ||
889 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
890 | val64 = 0x0203000100000000ULL; | ||
891 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
892 | break; | ||
893 | case 5: | ||
894 | val64 = 0x0001000203000102ULL; | ||
895 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
896 | val64 = 0x0001020001030004ULL; | ||
897 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
898 | val64 = 0x0001000203000102ULL; | ||
899 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
900 | val64 = 0x0001020001030004ULL; | ||
901 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
902 | val64 = 0x0001000000000000ULL; | ||
903 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
904 | break; | ||
905 | case 6: | ||
906 | val64 = 0x0001020304000102ULL; | ||
907 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
908 | val64 = 0x0304050001020001ULL; | ||
909 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
910 | val64 = 0x0203000100000102ULL; | ||
911 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
912 | val64 = 0x0304000102030405ULL; | ||
913 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
914 | val64 = 0x0001000200000000ULL; | ||
915 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
916 | break; | ||
917 | case 7: | ||
918 | val64 = 0x0001020001020300ULL; | ||
919 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
920 | val64 = 0x0102030400010203ULL; | ||
921 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
922 | val64 = 0x0405060001020001ULL; | ||
923 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
924 | val64 = 0x0304050000010200ULL; | ||
925 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
926 | val64 = 0x0102030000000000ULL; | ||
927 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
928 | break; | ||
929 | case 8: | ||
930 | val64 = 0x0001020300040105ULL; | ||
931 | writeq(val64, &bar0->tx_w_round_robin_0); | ||
932 | val64 = 0x0200030106000204ULL; | ||
933 | writeq(val64, &bar0->tx_w_round_robin_1); | ||
934 | val64 = 0x0103000502010007ULL; | ||
935 | writeq(val64, &bar0->tx_w_round_robin_2); | ||
936 | val64 = 0x0304010002060500ULL; | ||
937 | writeq(val64, &bar0->tx_w_round_robin_3); | ||
938 | val64 = 0x0103020400000000ULL; | ||
939 | writeq(val64, &bar0->tx_w_round_robin_4); | ||
940 | break; | ||
941 | } | ||
942 | |||
943 | /* Filling the Rx round robin registers as per the | ||
944 | * number of Rings and steering based on QoS. | ||
945 | */ | ||
946 | switch (config->rx_ring_num) { | ||
947 | case 1: | ||
948 | val64 = 0x8080808080808080ULL; | ||
949 | writeq(val64, &bar0->rts_qos_steering); | ||
950 | break; | ||
951 | case 2: | ||
952 | val64 = 0x0000010000010000ULL; | ||
953 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
954 | val64 = 0x0100000100000100ULL; | ||
955 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
956 | val64 = 0x0001000001000001ULL; | ||
957 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
958 | val64 = 0x0000010000010000ULL; | ||
959 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
960 | val64 = 0x0100000000000000ULL; | ||
961 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
962 | |||
963 | val64 = 0x8080808040404040ULL; | ||
964 | writeq(val64, &bar0->rts_qos_steering); | ||
965 | break; | ||
966 | case 3: | ||
967 | val64 = 0x0001000102000001ULL; | ||
968 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
969 | val64 = 0x0001020000010001ULL; | ||
970 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
971 | val64 = 0x0200000100010200ULL; | ||
972 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
973 | val64 = 0x0001000102000001ULL; | ||
974 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
975 | val64 = 0x0001020000000000ULL; | ||
976 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
977 | |||
978 | val64 = 0x8080804040402020ULL; | ||
979 | writeq(val64, &bar0->rts_qos_steering); | ||
980 | break; | ||
981 | case 4: | ||
982 | val64 = 0x0001020300010200ULL; | ||
983 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
984 | val64 = 0x0100000102030001ULL; | ||
985 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
986 | val64 = 0x0200010000010203ULL; | ||
987 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
988 | val64 = 0x0001020001000001ULL; | ||
989 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
990 | val64 = 0x0203000100000000ULL; | ||
991 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
992 | |||
993 | val64 = 0x8080404020201010ULL; | ||
994 | writeq(val64, &bar0->rts_qos_steering); | ||
995 | break; | ||
996 | case 5: | ||
997 | val64 = 0x0001000203000102ULL; | ||
998 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
999 | val64 = 0x0001020001030004ULL; | ||
1000 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
1001 | val64 = 0x0001000203000102ULL; | ||
1002 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
1003 | val64 = 0x0001020001030004ULL; | ||
1004 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
1005 | val64 = 0x0001000000000000ULL; | ||
1006 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
1007 | |||
1008 | val64 = 0x8080404020201008ULL; | ||
1009 | writeq(val64, &bar0->rts_qos_steering); | ||
1010 | break; | ||
1011 | case 6: | ||
1012 | val64 = 0x0001020304000102ULL; | ||
1013 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
1014 | val64 = 0x0304050001020001ULL; | ||
1015 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
1016 | val64 = 0x0203000100000102ULL; | ||
1017 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
1018 | val64 = 0x0304000102030405ULL; | ||
1019 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
1020 | val64 = 0x0001000200000000ULL; | ||
1021 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
1022 | |||
1023 | val64 = 0x8080404020100804ULL; | ||
1024 | writeq(val64, &bar0->rts_qos_steering); | ||
1025 | break; | ||
1026 | case 7: | ||
1027 | val64 = 0x0001020001020300ULL; | ||
1028 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
1029 | val64 = 0x0102030400010203ULL; | ||
1030 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
1031 | val64 = 0x0405060001020001ULL; | ||
1032 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
1033 | val64 = 0x0304050000010200ULL; | ||
1034 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
1035 | val64 = 0x0102030000000000ULL; | ||
1036 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
1037 | |||
1038 | val64 = 0x8080402010080402ULL; | ||
1039 | writeq(val64, &bar0->rts_qos_steering); | ||
1040 | break; | ||
1041 | case 8: | ||
1042 | val64 = 0x0001020300040105ULL; | ||
1043 | writeq(val64, &bar0->rx_w_round_robin_0); | ||
1044 | val64 = 0x0200030106000204ULL; | ||
1045 | writeq(val64, &bar0->rx_w_round_robin_1); | ||
1046 | val64 = 0x0103000502010007ULL; | ||
1047 | writeq(val64, &bar0->rx_w_round_robin_2); | ||
1048 | val64 = 0x0304010002060500ULL; | ||
1049 | writeq(val64, &bar0->rx_w_round_robin_3); | ||
1050 | val64 = 0x0103020400000000ULL; | ||
1051 | writeq(val64, &bar0->rx_w_round_robin_4); | ||
1052 | |||
1053 | val64 = 0x8040201008040201ULL; | ||
1054 | writeq(val64, &bar0->rts_qos_steering); | ||
1055 | break; | ||
1056 | } | ||
843 | 1057 | ||
844 | /* UDP Fix */ | 1058 | /* UDP Fix */ |
845 | val64 = 0; | 1059 | val64 = 0; |
846 | for (i = 0; i < 8; i++) | 1060 | for (i = 0; i < 8; i++) |
847 | writeq(val64, &bar0->rts_frm_len_n[i]); | 1061 | writeq(val64, &bar0->rts_frm_len_n[i]); |
848 | 1062 | ||
849 | /* Set the default rts frame length for ring0 */ | 1063 | /* Set the default rts frame length for the rings configured */ |
850 | writeq(MAC_RTS_FRM_LEN_SET(dev->mtu+22), | 1064 | val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22); |
851 | &bar0->rts_frm_len_n[0]); | 1065 | for (i = 0 ; i < config->rx_ring_num ; i++) |
1066 | writeq(val64, &bar0->rts_frm_len_n[i]); | ||
1067 | |||
1068 | /* Set the frame length for the configured rings | ||
1069 | * desired by the user | ||
1070 | */ | ||
1071 | for (i = 0; i < config->rx_ring_num; i++) { | ||
1072 | /* If rts_frm_len[i] == 0 then it is assumed that user not | ||
1073 | * specified frame length steering. | ||
1074 | * If the user provides the frame length then program | ||
1075 | * the rts_frm_len register for those values or else | ||
1076 | * leave it as it is. | ||
1077 | */ | ||
1078 | if (rts_frm_len[i] != 0) { | ||
1079 | writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]), | ||
1080 | &bar0->rts_frm_len_n[i]); | ||
1081 | } | ||
1082 | } | ||
852 | 1083 | ||
853 | /* Program statistics memory */ | 1084 | /* Program statistics memory */ |
854 | writeq(mac_control->stats_mem_phy, &bar0->stat_addr); | 1085 | writeq(mac_control->stats_mem_phy, &bar0->stat_addr); |
855 | val64 = SET_UPDT_PERIOD(Stats_refresh_time) | | 1086 | val64 = SET_UPDT_PERIOD(Stats_refresh_time) | |
856 | STAT_CFG_STAT_RO | STAT_CFG_STAT_EN; | 1087 | STAT_CFG_STAT_RO | STAT_CFG_STAT_EN; |
857 | writeq(val64, &bar0->stat_cfg); | 1088 | writeq(val64, &bar0->stat_cfg); |
858 | 1089 | ||
859 | /* | 1090 | /* |
@@ -877,13 +1108,14 @@ static int init_nic(struct s2io_nic *nic) | |||
877 | val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) | | 1108 | val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) | |
878 | TTI_DATA1_MEM_TX_URNG_A(0xA) | | 1109 | TTI_DATA1_MEM_TX_URNG_A(0xA) | |
879 | TTI_DATA1_MEM_TX_URNG_B(0x10) | | 1110 | TTI_DATA1_MEM_TX_URNG_B(0x10) | |
880 | TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN | | 1111 | TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN; |
881 | TTI_DATA1_MEM_TX_TIMER_CI_EN; | 1112 | if (use_continuous_tx_intrs) |
1113 | val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN; | ||
882 | writeq(val64, &bar0->tti_data1_mem); | 1114 | writeq(val64, &bar0->tti_data1_mem); |
883 | 1115 | ||
884 | val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | | 1116 | val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | |
885 | TTI_DATA2_MEM_TX_UFC_B(0x20) | | 1117 | TTI_DATA2_MEM_TX_UFC_B(0x20) | |
886 | TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80); | 1118 | TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80); |
887 | writeq(val64, &bar0->tti_data2_mem); | 1119 | writeq(val64, &bar0->tti_data2_mem); |
888 | 1120 | ||
889 | val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; | 1121 | val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; |
@@ -927,10 +1159,11 @@ static int init_nic(struct s2io_nic *nic) | |||
927 | writeq(val64, &bar0->rti_command_mem); | 1159 | writeq(val64, &bar0->rti_command_mem); |
928 | 1160 | ||
929 | /* | 1161 | /* |
930 | * Once the operation completes, the Strobe bit of the command | 1162 | * Once the operation completes, the Strobe bit of the |
931 | * register will be reset. We poll for this particular condition | 1163 | * command register will be reset. We poll for this |
932 | * We wait for a maximum of 500ms for the operation to complete, | 1164 | * particular condition. We wait for a maximum of 500ms |
933 | * if it's not complete by then we return error. | 1165 | * for the operation to complete, if it's not complete |
1166 | * by then we return error. | ||
934 | */ | 1167 | */ |
935 | time = 0; | 1168 | time = 0; |
936 | while (TRUE) { | 1169 | while (TRUE) { |
@@ -1185,10 +1418,10 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) | |||
1185 | temp64 &= ~((u64) val64); | 1418 | temp64 &= ~((u64) val64); |
1186 | writeq(temp64, &bar0->general_int_mask); | 1419 | writeq(temp64, &bar0->general_int_mask); |
1187 | /* | 1420 | /* |
1188 | * All MC block error interrupts are disabled for now. | 1421 | * Enable all MC Intrs. |
1189 | * TODO | ||
1190 | */ | 1422 | */ |
1191 | writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask); | 1423 | writeq(0x0, &bar0->mc_int_mask); |
1424 | writeq(0x0, &bar0->mc_err_mask); | ||
1192 | } else if (flag == DISABLE_INTRS) { | 1425 | } else if (flag == DISABLE_INTRS) { |
1193 | /* | 1426 | /* |
1194 | * Disable MC Intrs in the general intr mask register | 1427 | * Disable MC Intrs in the general intr mask register |
@@ -1247,23 +1480,41 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) | |||
1247 | } | 1480 | } |
1248 | } | 1481 | } |
1249 | 1482 | ||
1250 | static int check_prc_pcc_state(u64 val64, int flag) | 1483 | static int check_prc_pcc_state(u64 val64, int flag, int rev_id) |
1251 | { | 1484 | { |
1252 | int ret = 0; | 1485 | int ret = 0; |
1253 | 1486 | ||
1254 | if (flag == FALSE) { | 1487 | if (flag == FALSE) { |
1255 | if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) && | 1488 | if (rev_id >= 4) { |
1256 | ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == | 1489 | if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) && |
1257 | ADAPTER_STATUS_RC_PRC_QUIESCENT)) { | 1490 | ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == |
1258 | ret = 1; | 1491 | ADAPTER_STATUS_RC_PRC_QUIESCENT)) { |
1492 | ret = 1; | ||
1493 | } | ||
1494 | } else { | ||
1495 | if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) && | ||
1496 | ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == | ||
1497 | ADAPTER_STATUS_RC_PRC_QUIESCENT)) { | ||
1498 | ret = 1; | ||
1499 | } | ||
1259 | } | 1500 | } |
1260 | } else { | 1501 | } else { |
1261 | if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == | 1502 | if (rev_id >= 4) { |
1262 | ADAPTER_STATUS_RMAC_PCC_IDLE) && | 1503 | if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == |
1263 | (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || | 1504 | ADAPTER_STATUS_RMAC_PCC_IDLE) && |
1264 | ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == | 1505 | (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || |
1265 | ADAPTER_STATUS_RC_PRC_QUIESCENT))) { | 1506 | ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == |
1266 | ret = 1; | 1507 | ADAPTER_STATUS_RC_PRC_QUIESCENT))) { |
1508 | ret = 1; | ||
1509 | } | ||
1510 | } else { | ||
1511 | if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) == | ||
1512 | ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) && | ||
1513 | (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || | ||
1514 | ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == | ||
1515 | ADAPTER_STATUS_RC_PRC_QUIESCENT))) { | ||
1516 | ret = 1; | ||
1517 | } | ||
1267 | } | 1518 | } |
1268 | } | 1519 | } |
1269 | 1520 | ||
@@ -1286,6 +1537,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag) | |||
1286 | { | 1537 | { |
1287 | int ret = 0; | 1538 | int ret = 0; |
1288 | u64 tmp64 = ~((u64) val64); | 1539 | u64 tmp64 = ~((u64) val64); |
1540 | int rev_id = get_xena_rev_id(sp->pdev); | ||
1289 | 1541 | ||
1290 | if (! | 1542 | if (! |
1291 | (tmp64 & | 1543 | (tmp64 & |
@@ -1294,7 +1546,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag) | |||
1294 | ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY | | 1546 | ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY | |
1295 | ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK | | 1547 | ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK | |
1296 | ADAPTER_STATUS_P_PLL_LOCK))) { | 1548 | ADAPTER_STATUS_P_PLL_LOCK))) { |
1297 | ret = check_prc_pcc_state(val64, flag); | 1549 | ret = check_prc_pcc_state(val64, flag, rev_id); |
1298 | } | 1550 | } |
1299 | 1551 | ||
1300 | return ret; | 1552 | return ret; |
@@ -1407,7 +1659,7 @@ static int start_nic(struct s2io_nic *nic) | |||
1407 | 1659 | ||
1408 | /* Enable select interrupts */ | 1660 | /* Enable select interrupts */ |
1409 | interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | | 1661 | interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | |
1410 | RX_MAC_INTR; | 1662 | RX_MAC_INTR | MC_INTR; |
1411 | en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS); | 1663 | en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS); |
1412 | 1664 | ||
1413 | /* | 1665 | /* |
@@ -1439,21 +1691,6 @@ static int start_nic(struct s2io_nic *nic) | |||
1439 | */ | 1691 | */ |
1440 | schedule_work(&nic->set_link_task); | 1692 | schedule_work(&nic->set_link_task); |
1441 | 1693 | ||
1442 | /* | ||
1443 | * Here we are performing soft reset on XGXS to | ||
1444 | * force link down. Since link is already up, we will get | ||
1445 | * link state change interrupt after this reset | ||
1446 | */ | ||
1447 | SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF); | ||
1448 | val64 = readq(&bar0->dtx_control); | ||
1449 | udelay(50); | ||
1450 | SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF); | ||
1451 | val64 = readq(&bar0->dtx_control); | ||
1452 | udelay(50); | ||
1453 | SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF); | ||
1454 | val64 = readq(&bar0->dtx_control); | ||
1455 | udelay(50); | ||
1456 | |||
1457 | return SUCCESS; | 1694 | return SUCCESS; |
1458 | } | 1695 | } |
1459 | 1696 | ||
@@ -1524,7 +1761,7 @@ static void stop_nic(struct s2io_nic *nic) | |||
1524 | 1761 | ||
1525 | /* Disable all interrupts */ | 1762 | /* Disable all interrupts */ |
1526 | interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | | 1763 | interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | |
1527 | RX_MAC_INTR; | 1764 | RX_MAC_INTR | MC_INTR; |
1528 | en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS); | 1765 | en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS); |
1529 | 1766 | ||
1530 | /* Disable PRCs */ | 1767 | /* Disable PRCs */ |
@@ -1737,6 +1974,7 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
1737 | off++; | 1974 | off++; |
1738 | mac_control->rings[ring_no].rx_curr_put_info.offset = off; | 1975 | mac_control->rings[ring_no].rx_curr_put_info.offset = off; |
1739 | #endif | 1976 | #endif |
1977 | rxdp->Control_2 |= SET_RXD_MARKER; | ||
1740 | 1978 | ||
1741 | atomic_inc(&nic->rx_bufs_left[ring_no]); | 1979 | atomic_inc(&nic->rx_bufs_left[ring_no]); |
1742 | alloc_tab++; | 1980 | alloc_tab++; |
@@ -1965,11 +2203,8 @@ static void rx_intr_handler(ring_info_t *ring_data) | |||
1965 | put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + | 2203 | put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + |
1966 | put_info.offset; | 2204 | put_info.offset; |
1967 | #endif | 2205 | #endif |
1968 | while ((!(rxdp->Control_1 & RXD_OWN_XENA)) && | 2206 | while (RXD_IS_UP2DT(rxdp) && |
1969 | #ifdef CONFIG_2BUFF_MODE | 2207 | (((get_offset + 1) % ring_bufs) != put_offset)) { |
1970 | (!rxdp->Control_2 & BIT(0)) && | ||
1971 | #endif | ||
1972 | (((get_offset + 1) % ring_bufs) != put_offset)) { | ||
1973 | skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); | 2208 | skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); |
1974 | if (skb == NULL) { | 2209 | if (skb == NULL) { |
1975 | DBG_PRINT(ERR_DBG, "%s: The skb is ", | 2210 | DBG_PRINT(ERR_DBG, "%s: The skb is ", |
@@ -2153,6 +2388,21 @@ static void alarm_intr_handler(struct s2io_nic *nic) | |||
2153 | schedule_work(&nic->set_link_task); | 2388 | schedule_work(&nic->set_link_task); |
2154 | } | 2389 | } |
2155 | 2390 | ||
2391 | /* Handling Ecc errors */ | ||
2392 | val64 = readq(&bar0->mc_err_reg); | ||
2393 | writeq(val64, &bar0->mc_err_reg); | ||
2394 | if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) { | ||
2395 | if (val64 & MC_ERR_REG_ECC_ALL_DBL) { | ||
2396 | DBG_PRINT(ERR_DBG, "%s: Device indicates ", | ||
2397 | dev->name); | ||
2398 | DBG_PRINT(ERR_DBG, "double ECC error!!\n"); | ||
2399 | netif_stop_queue(dev); | ||
2400 | schedule_work(&nic->rst_timer_task); | ||
2401 | } else { | ||
2402 | /* Device can recover from Single ECC errors */ | ||
2403 | } | ||
2404 | } | ||
2405 | |||
2156 | /* In case of a serious error, the device will be Reset. */ | 2406 | /* In case of a serious error, the device will be Reset. */ |
2157 | val64 = readq(&bar0->serr_source); | 2407 | val64 = readq(&bar0->serr_source); |
2158 | if (val64 & SERR_SOURCE_ANY) { | 2408 | if (val64 & SERR_SOURCE_ANY) { |
@@ -2226,7 +2476,7 @@ void s2io_reset(nic_t * sp) | |||
2226 | { | 2476 | { |
2227 | XENA_dev_config_t __iomem *bar0 = sp->bar0; | 2477 | XENA_dev_config_t __iomem *bar0 = sp->bar0; |
2228 | u64 val64; | 2478 | u64 val64; |
2229 | u16 subid; | 2479 | u16 subid, pci_cmd; |
2230 | 2480 | ||
2231 | val64 = SW_RESET_ALL; | 2481 | val64 = SW_RESET_ALL; |
2232 | writeq(val64, &bar0->sw_reset); | 2482 | writeq(val64, &bar0->sw_reset); |
@@ -2255,6 +2505,18 @@ void s2io_reset(nic_t * sp) | |||
2255 | /* Set swapper to enable I/O register access */ | 2505 | /* Set swapper to enable I/O register access */ |
2256 | s2io_set_swapper(sp); | 2506 | s2io_set_swapper(sp); |
2257 | 2507 | ||
2508 | /* Clear certain PCI/PCI-X fields after reset */ | ||
2509 | pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); | ||
2510 | pci_cmd &= 0x7FFF; /* Clear parity err detect bit */ | ||
2511 | pci_write_config_word(sp->pdev, PCI_COMMAND, pci_cmd); | ||
2512 | |||
2513 | val64 = readq(&bar0->txpic_int_reg); | ||
2514 | val64 &= ~BIT(62); /* Clearing PCI_STATUS error reflected here */ | ||
2515 | writeq(val64, &bar0->txpic_int_reg); | ||
2516 | |||
2517 | /* Clearing PCIX Ecc status register */ | ||
2518 | pci_write_config_dword(sp->pdev, 0x68, 0); | ||
2519 | |||
2258 | /* Reset device statistics maintained by OS */ | 2520 | /* Reset device statistics maintained by OS */ |
2259 | memset(&sp->stats, 0, sizeof (struct net_device_stats)); | 2521 | memset(&sp->stats, 0, sizeof (struct net_device_stats)); |
2260 | 2522 | ||
@@ -2797,6 +3059,8 @@ static void s2io_set_multicast(struct net_device *dev) | |||
2797 | /* Disable all Multicast addresses */ | 3059 | /* Disable all Multicast addresses */ |
2798 | writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr), | 3060 | writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr), |
2799 | &bar0->rmac_addr_data0_mem); | 3061 | &bar0->rmac_addr_data0_mem); |
3062 | writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0), | ||
3063 | &bar0->rmac_addr_data1_mem); | ||
2800 | val64 = RMAC_ADDR_CMD_MEM_WE | | 3064 | val64 = RMAC_ADDR_CMD_MEM_WE | |
2801 | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | | 3065 | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | |
2802 | RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos); | 3066 | RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos); |
@@ -4369,21 +4633,6 @@ static void s2io_init_pci(nic_t * sp) | |||
4369 | (pci_cmd | PCI_COMMAND_PARITY)); | 4633 | (pci_cmd | PCI_COMMAND_PARITY)); |
4370 | pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); | 4634 | pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); |
4371 | 4635 | ||
4372 | /* Set MMRB count to 1024 in PCI-X Command register. */ | ||
4373 | pcix_cmd &= 0xFFF3; | ||
4374 | pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, | ||
4375 | (pcix_cmd | (0x1 << 2))); /* MMRBC 1K */ | ||
4376 | pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, | ||
4377 | &(pcix_cmd)); | ||
4378 | |||
4379 | /* Setting Maximum outstanding splits based on system type. */ | ||
4380 | pcix_cmd &= 0xFF8F; | ||
4381 | pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1); /* 2 splits. */ | ||
4382 | pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, | ||
4383 | pcix_cmd); | ||
4384 | pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, | ||
4385 | &(pcix_cmd)); | ||
4386 | |||
4387 | /* Forcibly disabling relaxed ordering capability of the card. */ | 4636 | /* Forcibly disabling relaxed ordering capability of the card. */ |
4388 | pcix_cmd &= 0xfffd; | 4637 | pcix_cmd &= 0xfffd; |
4389 | pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, | 4638 | pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, |
@@ -4400,6 +4649,7 @@ module_param_array(tx_fifo_len, uint, NULL, 0); | |||
4400 | module_param_array(rx_ring_sz, uint, NULL, 0); | 4649 | module_param_array(rx_ring_sz, uint, NULL, 0); |
4401 | module_param(Stats_refresh_time, int, 0); | 4650 | module_param(Stats_refresh_time, int, 0); |
4402 | module_param_array(rts_frm_len, uint, NULL, 0); | 4651 | module_param_array(rts_frm_len, uint, NULL, 0); |
4652 | module_param(use_continuous_tx_intrs, int, 1); | ||
4403 | module_param(rmac_pause_time, int, 0); | 4653 | module_param(rmac_pause_time, int, 0); |
4404 | module_param(mc_pause_threshold_q0q3, int, 0); | 4654 | module_param(mc_pause_threshold_q0q3, int, 0); |
4405 | module_param(mc_pause_threshold_q4q7, int, 0); | 4655 | module_param(mc_pause_threshold_q4q7, int, 0); |
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 4d2fc7a40434..92db59a0fb11 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h | |||
@@ -372,6 +372,10 @@ typedef struct _RxD_t { | |||
372 | #define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF) | 372 | #define RXD_GET_L4_CKSUM(val) ((u16)(val) & 0xFFFF) |
373 | 373 | ||
374 | u64 Control_2; | 374 | u64 Control_2; |
375 | #define THE_RXD_MARK 0x3 | ||
376 | #define SET_RXD_MARKER vBIT(THE_RXD_MARK, 0, 2) | ||
377 | #define GET_RXD_MARKER(ctrl) ((ctrl & SET_RXD_MARKER) >> 62) | ||
378 | |||
375 | #ifndef CONFIG_2BUFF_MODE | 379 | #ifndef CONFIG_2BUFF_MODE |
376 | #define MASK_BUFFER0_SIZE vBIT(0x3FFF,2,14) | 380 | #define MASK_BUFFER0_SIZE vBIT(0x3FFF,2,14) |
377 | #define SET_BUFFER0_SIZE(val) vBIT(val,2,14) | 381 | #define SET_BUFFER0_SIZE(val) vBIT(val,2,14) |