diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini
new file mode 100644
index 000000000000..3fc6db4c8198
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini
@@ -0,0 +1,65 @@
+# name lanes alias
+Ethernet0 9,10,11,12 Ethernet0
+Ethernet4 1,2,3,4 Ethernet4
+Ethernet8 25,26,27,28 Ethernet8
+Ethernet12 17,18,19,20 Ethernet12
+Ethernet16 41,42,43,44 Ethernet16
+Ethernet20 33,34,35,36 Ethernet20
+Ethernet24 57,58,59,60 Ethernet24
+Ethernet28 49,50,51,52 Ethernet28
+Ethernet32 73,74,75,76 Ethernet32
+Ethernet36 65,66,67,68 Ethernet36
+Ethernet40 89,90,91,92 Ethernet40
+Ethernet44 81,82,83,84 Ethernet44
+Ethernet48 105,106,107,108 Ethernet48
+Ethernet52 97,98,99,100 Ethernet52
+Ethernet56 121,122,123,124 Ethernet56
+Ethernet60 113,114,115,116 Ethernet60
+Ethernet64 137,138,139,140 Ethernet64
+Ethernet68 129,130,131,132 Ethernet68
+Ethernet72 153,154,155,156 Ethernet72
+Ethernet76 145,146,147,148 Ethernet76
+Ethernet80 169,170,171,172 Ethernet80
+Ethernet84 161,162,163,164 Ethernet84
+Ethernet88 185,186,187,188 Ethernet88
+Ethernet92 177,178,179,180 Ethernet92
+Ethernet96 201,202,203,204 Ethernet96
+Ethernet100 193,194,195,196 Ethernet100
+Ethernet104 217,218,219,220 Ethernet104
+Ethernet108 209,210,211,212 Ethernet108
+Ethernet112 233,234,235,236 Ethernet112
+Ethernet116 225,226,227,228 Ethernet116
+Ethernet120 249,250,251,252 Ethernet120
+Ethernet124 241,242,243,244 Ethernet124
+Ethernet128 13,14,15,16 Ethernet128
+Ethernet132 5,6,7,8 Ethernet132
+Ethernet136 29,30,31,32 Ethernet136
+Ethernet140 21,22,23,24 Ethernet140
+Ethernet144 45,46,47,48 Ethernet144
+Ethernet148 37,38,39,40 Ethernet148
+Ethernet152 61,62,63,64 Ethernet152
+Ethernet156 53,54,55,56 Ethernet156
+Ethernet160 77,78,79,80 Ethernet160
+Ethernet164 69,70,71,72 Ethernet164
+Ethernet168 93,94,95,96 Ethernet168
+Ethernet172 85,86,87,88 Ethernet172
+Ethernet176 109,110,111,112 Ethernet176
+Ethernet180 101,102,103,104 Ethernet180
+Ethernet184 125,126,127,128 Ethernet184
+Ethernet188 117,118,119,120 Ethernet188
+Ethernet192 141,142,143,144 Ethernet192
+Ethernet196 133,134,135,136 Ethernet196
+Ethernet200 157,158,159,160 Ethernet200
+Ethernet204 149,150,151,152 Ethernet204
+Ethernet208 173,174,175,176 Ethernet208
+Ethernet212 165,166,167,168 Ethernet212
+Ethernet216 189,190,191,192 Ethernet216
+Ethernet220 181,182,183,184 Ethernet220
+Ethernet224 205,206,207,208 Ethernet224
+Ethernet228 197,198,199,200 Ethernet228
+Ethernet232 221,222,223,224 Ethernet232
+Ethernet236 213,214,215,216 Ethernet236
+Ethernet240 237,238,239,240 Ethernet240
+Ethernet244 229,230,231,232 Ethernet244
+Ethernet248 253,254,255,256 Ethernet248
+Ethernet252 245,246,247,248 Ethernet252
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile
new file mode 100644
index 000000000000..74c0e88255c0
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile
@@ -0,0 +1,2 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-d7264q28b-64x100g.config.bcm
+SAI_NUM_ECMP_MEMBERS=32
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm
new file mode 100644
index 000000000000..8ca378382c93
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm
@@ -0,0 +1,841 @@
+# Sequoia BCM Shell config / 100G * 64 ports
+
+core_clock_frequency=1700
+dpp_clock_ratio=2:3
+load_firmware=1
+# EagleCore ports: xe0 & xe1
+portmap_66=257:10
+portmap_100=259:10
+
+# Loopback ports
+portmap_33=260:10
+portmap_67=261:10
+portmap_101=262:10
+portmap_135=263:10
+
+# 64 ports config for 100G
+# For Tomahawk FalconCore:
+# Physical ports in FalconCore[0 - 15] must map to logical port[1 - 32] at any order
+# Physical ports in FalconCore[16 - 31] must map to logical port[34 - 65] at any order
+# Physical ports in FalconCore[32 - 47] must map to logical port[68 - 99] at any order
+# Physical ports in FalconCore[48 - 63] must map to logical port[102 - 133] at any order
+
+## FalconCore[0 - 15]
+portmap_1=9:100
+portmap_2=1:100
+portmap_3=13:100
+portmap_4=5:100
+portmap_5=25:100
+portmap_6=17:100
+portmap_7=29:100
+portmap_8=21:100
+portmap_9=41:100
+portmap_10=33:100
+portmap_11=45:100
+portmap_12=37:100
+portmap_13=57:100
+portmap_14=49:100
+portmap_15=61:100
+portmap_16=53:100
+
+## FalconCore[16 - 31]
+portmap_34=73:100
+portmap_35=65:100
+portmap_36=77:100
+portmap_37=69:100
+portmap_38=89:100
+portmap_39=81:100
+portmap_40=93:100
+portmap_41=85:100
+portmap_42=105:100
+portmap_43=97:100
+portmap_44=109:100
+portmap_45=101:100
+portmap_46=121:100
+portmap_47=113:100
+portmap_48=125:100
+portmap_49=117:100
+
+## FalconCore[32-47]
+portmap_68=137:100
+portmap_69=129:100
+portmap_70=141:100
+portmap_71=133:100
+portmap_72=153:100
+portmap_73=145:100
+portmap_74=157:100
+portmap_75=149:100
+portmap_76=169:100
+portmap_77=161:100
+portmap_78=173:100
+portmap_79=165:100
+portmap_80=185:100
+portmap_81=177:100
+portmap_82=189:100
+portmap_83=181:100
+
+## FalconCore[48-63]
+portmap_102=201:100
+portmap_103=193:100
+portmap_104=205:100
+portmap_105=197:100
+portmap_106=217:100
+portmap_107=209:100
+portmap_108=221:100
+portmap_109=213:100
+portmap_110=233:100
+portmap_111=225:100
+portmap_112=237:100
+portmap_113=229:100
+portmap_114=249:100
+portmap_115=241:100
+portmap_116=253:100
+portmap_117=245:100
+
+pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE
+oversubscribe_mode=1
+l2_mem_entries=73728
+l3_mem_entries=73728
+fpem_mem_entries=65536
+l2xmsg_mode=1
+
+## FalconCore [0-15] port TX Lane Swapping
+phy_chain_tx_lane_map_physical{1.0}=0x3201
+phy_chain_tx_lane_map_physical{5.0}=0x3210
+phy_chain_tx_lane_map_physical{9.0}=0x2301
+phy_chain_tx_lane_map_physical{13.0}=0x3210
+phy_chain_tx_lane_map_physical{17.0}=0x3201
+phy_chain_tx_lane_map_physical{21.0}=0x3201
+phy_chain_tx_lane_map_physical{25.0}=0x3201
+phy_chain_tx_lane_map_physical{29.0}=0x3210
+phy_chain_tx_lane_map_physical{33.0}=0x3201
+phy_chain_tx_lane_map_physical{37.0}=0x3210
+phy_chain_tx_lane_map_physical{41.0}=0x3210
+phy_chain_tx_lane_map_physical{45.0}=0x3210
+phy_chain_tx_lane_map_physical{49.0}=0x3201
+phy_chain_tx_lane_map_physical{53.0}=0x3210
+phy_chain_tx_lane_map_physical{57.0}=0x3210
+phy_chain_tx_lane_map_physical{61.0}=0x3210
+
+
+## FalconCore [16-31] port TX Lane Swapping
+phy_chain_tx_lane_map_physical{65.0}=0x3210
+phy_chain_tx_lane_map_physical{69.0}=0x3201
+phy_chain_tx_lane_map_physical{73.0}=0x3210
+phy_chain_tx_lane_map_physical{77.0}=0x3210
+phy_chain_tx_lane_map_physical{81.0}=0x3210
+phy_chain_tx_lane_map_physical{85.0}=0x3210
+phy_chain_tx_lane_map_physical{89.0}=0x3210
+phy_chain_tx_lane_map_physical{93.0}=0x3210
+phy_chain_tx_lane_map_physical{97.0}=0x3210
+phy_chain_tx_lane_map_physical{101.0}=0x2310
+phy_chain_tx_lane_map_physical{105.0}=0x2310
+phy_chain_tx_lane_map_physical{109.0}=0x3210
+phy_chain_tx_lane_map_physical{113.0}=0x3210
+phy_chain_tx_lane_map_physical{117.0}=0x2310
+phy_chain_tx_lane_map_physical{121.0}=0x2310
+phy_chain_tx_lane_map_physical{125.0}=0x3210
+
+
+## FalconCore [32-47] port TX Lane Swapping
+phy_chain_tx_lane_map_physical{129.0}=0x2301
+phy_chain_tx_lane_map_physical{133.0}=0x3210
+phy_chain_tx_lane_map_physical{137.0}=0x2301
+phy_chain_tx_lane_map_physical{141.0}=0x3210
+phy_chain_tx_lane_map_physical{145.0}=0x2301
+phy_chain_tx_lane_map_physical{149.0}=0x3210
+phy_chain_tx_lane_map_physical{153.0}=0x3210
+phy_chain_tx_lane_map_physical{157.0}=0x3210
+phy_chain_tx_lane_map_physical{161.0}=0x2310
+phy_chain_tx_lane_map_physical{165.0}=0x2310
+phy_chain_tx_lane_map_physical{169.0}=0x2310
+phy_chain_tx_lane_map_physical{173.0}=0x3210
+phy_chain_tx_lane_map_physical{177.0}=0x3210
+phy_chain_tx_lane_map_physical{181.0}=0x2310
+phy_chain_tx_lane_map_physical{185.0}=0x3210
+phy_chain_tx_lane_map_physical{189.0}=0x2310
+
+
+## FalconCore [48-63] port TX Lane Swapping
+phy_chain_tx_lane_map_physical{193.0}=0x2310
+phy_chain_tx_lane_map_physical{197.0}=0x2310
+phy_chain_tx_lane_map_physical{201.0}=0x2310
+phy_chain_tx_lane_map_physical{205.0}=0x2310
+phy_chain_tx_lane_map_physical{209.0}=0x3210
+phy_chain_tx_lane_map_physical{213.0}=0x2310
+phy_chain_tx_lane_map_physical{217.0}=0x3210
+phy_chain_tx_lane_map_physical{221.0}=0x2301
+phy_chain_tx_lane_map_physical{225.0}=0x3210
+phy_chain_tx_lane_map_physical{229.0}=0x2310
+phy_chain_tx_lane_map_physical{233.0}=0x2310
+phy_chain_tx_lane_map_physical{237.0}=0x1023
+phy_chain_tx_lane_map_physical{241.0}=0x3210
+phy_chain_tx_lane_map_physical{245.0}=0x2310
+phy_chain_tx_lane_map_physical{249.0}=0x3210
+phy_chain_tx_lane_map_physical{253.0}=0x2310
+
+## FalconCore [0-15] port RX Lane Swapping
+phy_chain_rx_lane_map_physical{1.0}=0x3210
+phy_chain_rx_lane_map_physical{5.0}=0x3210
+phy_chain_rx_lane_map_physical{9.0}=0x3210
+phy_chain_rx_lane_map_physical{13.0}=0x3210
+phy_chain_rx_lane_map_physical{17.0}=0x2310
+phy_chain_rx_lane_map_physical{21.0}=0x0213
+phy_chain_rx_lane_map_physical{25.0}=0x2310
+phy_chain_rx_lane_map_physical{29.0}=0x3210
+phy_chain_rx_lane_map_physical{33.0}=0x3210
+phy_chain_rx_lane_map_physical{37.0}=0x3210
+phy_chain_rx_lane_map_physical{41.0}=0x3210
+phy_chain_rx_lane_map_physical{45.0}=0x3210
+phy_chain_rx_lane_map_physical{49.0}=0x3210
+phy_chain_rx_lane_map_physical{53.0}=0x3210
+phy_chain_rx_lane_map_physical{57.0}=0x3210
+phy_chain_rx_lane_map_physical{61.0}=0x3210
+
+
+## FalconCore [16-31] port RX Lane Swapping
+phy_chain_rx_lane_map_physical{65.0}=0x3210
+phy_chain_rx_lane_map_physical{69.0}=0x3210
+phy_chain_rx_lane_map_physical{73.0}=0x3210
+phy_chain_rx_lane_map_physical{77.0}=0x3210
+phy_chain_rx_lane_map_physical{81.0}=0x3210
+phy_chain_rx_lane_map_physical{85.0}=0x3210
+phy_chain_rx_lane_map_physical{89.0}=0x3210
+phy_chain_rx_lane_map_physical{93.0}=0x3210
+phy_chain_rx_lane_map_physical{97.0}=0x3210
+phy_chain_rx_lane_map_physical{101.0}=0x3201
+phy_chain_rx_lane_map_physical{105.0}=0x3210
+phy_chain_rx_lane_map_physical{109.0}=0x3210
+phy_chain_rx_lane_map_physical{113.0}=0x3210
+phy_chain_rx_lane_map_physical{117.0}=0x3210
+phy_chain_rx_lane_map_physical{121.0}=0x3210
+phy_chain_rx_lane_map_physical{125.0}=0x3210
+
+
+## FalconCore [32-47] port RX Lane Swapping
+phy_chain_rx_lane_map_physical{129.0}=0x3210
+phy_chain_rx_lane_map_physical{133.0}=0x2301
+phy_chain_rx_lane_map_physical{137.0}=0x3210
+phy_chain_rx_lane_map_physical{141.0}=0x2310
+phy_chain_rx_lane_map_physical{145.0}=0x3210
+phy_chain_rx_lane_map_physical{149.0}=0x3210
+phy_chain_rx_lane_map_physical{153.0}=0x3210
+phy_chain_rx_lane_map_physical{157.0}=0x3210
+phy_chain_rx_lane_map_physical{161.0}=0x3210
+phy_chain_rx_lane_map_physical{165.0}=0x3210
+phy_chain_rx_lane_map_physical{169.0}=0x3210
+phy_chain_rx_lane_map_physical{173.0}=0x3210
+phy_chain_rx_lane_map_physical{177.0}=0x3210
+phy_chain_rx_lane_map_physical{181.0}=0x3210
+phy_chain_rx_lane_map_physical{185.0}=0x3210
+phy_chain_rx_lane_map_physical{189.0}=0x3210
+
+
+## FalconCore [48-63] port RX Lan Swapping
+phy_chain_rx_lane_map_physical{193.0}=0x3210
+phy_chain_rx_lane_map_physical{197.0}=0x3210
+phy_chain_rx_lane_map_physical{201.0}=0x3210
+phy_chain_rx_lane_map_physical{205.0}=0x3210
+phy_chain_rx_lane_map_physical{209.0}=0x3210
+phy_chain_rx_lane_map_physical{213.0}=0x3210
+phy_chain_rx_lane_map_physical{217.0}=0x3210
+phy_chain_rx_lane_map_physical{221.0}=0x3210
+phy_chain_rx_lane_map_physical{225.0}=0x3210
+phy_chain_rx_lane_map_physical{229.0}=0x2301
+phy_chain_rx_lane_map_physical{233.0}=0x3210
+phy_chain_rx_lane_map_physical{237.0}=0x1023
+phy_chain_rx_lane_map_physical{241.0}=0x3210
+phy_chain_rx_lane_map_physical{245.0}=0x3210
+phy_chain_rx_lane_map_physical{249.0}=0x3210
+phy_chain_rx_lane_map_physical{253.0}=0x3210
+
+
+## FalconCore[0-15] ports TX polarity flip
+phy_chain_tx_polarity_flip_physical{1.0}=0x1
+phy_chain_tx_polarity_flip_physical{2.0}=0x1
+phy_chain_tx_polarity_flip_physical{3.0}=0x0
+phy_chain_tx_polarity_flip_physical{4.0}=0x1
+phy_chain_tx_polarity_flip_physical{5.0}=0x0
+phy_chain_tx_polarity_flip_physical{6.0}=0x0
+phy_chain_tx_polarity_flip_physical{7.0}=0x0
+phy_chain_tx_polarity_flip_physical{8.0}=0x0
+phy_chain_tx_polarity_flip_physical{9.0}=0x0
+phy_chain_tx_polarity_flip_physical{10.0}=0x1
+phy_chain_tx_polarity_flip_physical{11.0}=0x0
+phy_chain_tx_polarity_flip_physical{12.0}=0x0
+phy_chain_tx_polarity_flip_physical{13.0}=0x0
+phy_chain_tx_polarity_flip_physical{14.0}=0x0
+phy_chain_tx_polarity_flip_physical{15.0}=0x0
+phy_chain_tx_polarity_flip_physical{16.0}=0x0
+phy_chain_tx_polarity_flip_physical{17.0}=0x0
+phy_chain_tx_polarity_flip_physical{18.0}=0x1
+phy_chain_tx_polarity_flip_physical{19.0}=0x1
+phy_chain_tx_polarity_flip_physical{20.0}=0x0
+phy_chain_tx_polarity_flip_physical{21.0}=0x0
+phy_chain_tx_polarity_flip_physical{22.0}=0x0
+phy_chain_tx_polarity_flip_physical{23.0}=0x0
+phy_chain_tx_polarity_flip_physical{24.0}=0x0
+phy_chain_tx_polarity_flip_physical{25.0}=0x0
+phy_chain_tx_polarity_flip_physical{26.0}=0x1
+phy_chain_tx_polarity_flip_physical{27.0}=0x0
+phy_chain_tx_polarity_flip_physical{28.0}=0x0
+phy_chain_tx_polarity_flip_physical{29.0}=0x0
+phy_chain_tx_polarity_flip_physical{30.0}=0x0
+phy_chain_tx_polarity_flip_physical{31.0}=0x0
+phy_chain_tx_polarity_flip_physical{32.0}=0x0
+phy_chain_tx_polarity_flip_physical{33.0}=0x1
+phy_chain_tx_polarity_flip_physical{34.0}=0x0
+phy_chain_tx_polarity_flip_physical{35.0}=0x1
+phy_chain_tx_polarity_flip_physical{36.0}=0x0
+phy_chain_tx_polarity_flip_physical{37.0}=0x0
+phy_chain_tx_polarity_flip_physical{38.0}=0x0
+phy_chain_tx_polarity_flip_physical{39.0}=0x0
+phy_chain_tx_polarity_flip_physical{40.0}=0x0
+phy_chain_tx_polarity_flip_physical{41.0}=0x1
+phy_chain_tx_polarity_flip_physical{42.0}=0x0
+phy_chain_tx_polarity_flip_physical{43.0}=0x1
+phy_chain_tx_polarity_flip_physical{44.0}=0x0
+phy_chain_tx_polarity_flip_physical{45.0}=0x0
+phy_chain_tx_polarity_flip_physical{46.0}=0x0
+phy_chain_tx_polarity_flip_physical{47.0}=0x0
+phy_chain_tx_polarity_flip_physical{48.0}=0x0
+phy_chain_tx_polarity_flip_physical{49.0}=0x0
+phy_chain_tx_polarity_flip_physical{50.0}=0x0
+phy_chain_tx_polarity_flip_physical{51.0}=0x0
+phy_chain_tx_polarity_flip_physical{52.0}=0x0
+phy_chain_tx_polarity_flip_physical{53.0}=0x0
+phy_chain_tx_polarity_flip_physical{54.0}=0x0
+phy_chain_tx_polarity_flip_physical{55.0}=0x0
+phy_chain_tx_polarity_flip_physical{56.0}=0x0
+phy_chain_tx_polarity_flip_physical{57.0}=0x1
+phy_chain_tx_polarity_flip_physical{58.0}=0x0
+phy_chain_tx_polarity_flip_physical{59.0}=0x0
+phy_chain_tx_polarity_flip_physical{60.0}=0x0
+phy_chain_tx_polarity_flip_physical{61.0}=0x0
+phy_chain_tx_polarity_flip_physical{62.0}=0x0
+phy_chain_tx_polarity_flip_physical{63.0}=0x0
+phy_chain_tx_polarity_flip_physical{64.0}=0x0
+
+## FalconCore[16-31] ports TX polarity flip
+phy_chain_tx_polarity_flip_physical{65.0}=0x1
+phy_chain_tx_polarity_flip_physical{66.0}=0x0
+phy_chain_tx_polarity_flip_physical{67.0}=0x0
+phy_chain_tx_polarity_flip_physical{68.0}=0x0
+phy_chain_tx_polarity_flip_physical{69.0}=0x0
+phy_chain_tx_polarity_flip_physical{70.0}=0x1
+phy_chain_tx_polarity_flip_physical{71.0}=0x0
+phy_chain_tx_polarity_flip_physical{72.0}=0x0
+phy_chain_tx_polarity_flip_physical{73.0}=0x0
+phy_chain_tx_polarity_flip_physical{74.0}=0x0
+phy_chain_tx_polarity_flip_physical{75.0}=0x0
+phy_chain_tx_polarity_flip_physical{76.0}=0x0
+phy_chain_tx_polarity_flip_physical{77.0}=0x1
+phy_chain_tx_polarity_flip_physical{78.0}=0x0
+phy_chain_tx_polarity_flip_physical{79.0}=0x0
+phy_chain_tx_polarity_flip_physical{80.0}=0x0
+phy_chain_tx_polarity_flip_physical{81.0}=0x0
+phy_chain_tx_polarity_flip_physical{82.0}=0x0
+phy_chain_tx_polarity_flip_physical{83.0}=0x0
+phy_chain_tx_polarity_flip_physical{84.0}=0x0
+phy_chain_tx_polarity_flip_physical{85.0}=0x0
+phy_chain_tx_polarity_flip_physical{86.0}=0x1
+phy_chain_tx_polarity_flip_physical{87.0}=0x0
+phy_chain_tx_polarity_flip_physical{88.0}=0x0
+phy_chain_tx_polarity_flip_physical{89.0}=0x1
+phy_chain_tx_polarity_flip_physical{90.0}=0x0
+phy_chain_tx_polarity_flip_physical{91.0}=0x0
+phy_chain_tx_polarity_flip_physical{92.0}=0x0
+phy_chain_tx_polarity_flip_physical{93.0}=0x1
+phy_chain_tx_polarity_flip_physical{94.0}=0x0
+phy_chain_tx_polarity_flip_physical{95.0}=0x0
+phy_chain_tx_polarity_flip_physical{96.0}=0x0
+phy_chain_tx_polarity_flip_physical{97.0}=0x1
+phy_chain_tx_polarity_flip_physical{98.0}=0x0
+phy_chain_tx_polarity_flip_physical{99.0}=0x0
+phy_chain_tx_polarity_flip_physical{100.0}=0x0
+phy_chain_tx_polarity_flip_physical{101.0}=0x0
+phy_chain_tx_polarity_flip_physical{102.0}=0x0
+phy_chain_tx_polarity_flip_physical{103.0}=0x0
+phy_chain_tx_polarity_flip_physical{104.0}=0x0
+phy_chain_tx_polarity_flip_physical{105.0}=0x1
+phy_chain_tx_polarity_flip_physical{106.0}=0x0
+phy_chain_tx_polarity_flip_physical{107.0}=0x0
+phy_chain_tx_polarity_flip_physical{108.0}=0x0
+phy_chain_tx_polarity_flip_physical{109.0}=0x0
+phy_chain_tx_polarity_flip_physical{110.0}=0x0
+phy_chain_tx_polarity_flip_physical{111.0}=0x0
+phy_chain_tx_polarity_flip_physical{112.0}=0x0
+phy_chain_tx_polarity_flip_physical{113.0}=0x0
+phy_chain_tx_polarity_flip_physical{114.0}=0x1
+phy_chain_tx_polarity_flip_physical{115.0}=0x0
+phy_chain_tx_polarity_flip_physical{116.0}=0x0
+phy_chain_tx_polarity_flip_physical{117.0}=0x0
+phy_chain_tx_polarity_flip_physical{118.0}=0x0
+phy_chain_tx_polarity_flip_physical{119.0}=0x0
+phy_chain_tx_polarity_flip_physical{120.0}=0x0
+phy_chain_tx_polarity_flip_physical{121.0}=0x1
+phy_chain_tx_polarity_flip_physical{122.0}=0x0
+phy_chain_tx_polarity_flip_physical{123.0}=0x0
+phy_chain_tx_polarity_flip_physical{124.0}=0x0
+phy_chain_tx_polarity_flip_physical{125.0}=0x0
+phy_chain_tx_polarity_flip_physical{126.0}=0x0
+phy_chain_tx_polarity_flip_physical{127.0}=0x0
+phy_chain_tx_polarity_flip_physical{128.0}=0x0
+
+## FalconCore[32-47] ports TX polarity flip
+phy_chain_tx_polarity_flip_physical{129.0}=0x0
+phy_chain_tx_polarity_flip_physical{130.0}=0x0
+phy_chain_tx_polarity_flip_physical{131.0}=0x0
+phy_chain_tx_polarity_flip_physical{132.0}=0x0
+phy_chain_tx_polarity_flip_physical{133.0}=0x0
+phy_chain_tx_polarity_flip_physical{134.0}=0x0
+phy_chain_tx_polarity_flip_physical{135.0}=0x0
+phy_chain_tx_polarity_flip_physical{136.0}=0x0
+phy_chain_tx_polarity_flip_physical{137.0}=0x0
+phy_chain_tx_polarity_flip_physical{138.0}=0x1
+phy_chain_tx_polarity_flip_physical{139.0}=0x0
+phy_chain_tx_polarity_flip_physical{140.0}=0x0
+phy_chain_tx_polarity_flip_physical{141.0}=0x0
+phy_chain_tx_polarity_flip_physical{142.0}=0x0
+phy_chain_tx_polarity_flip_physical{143.0}=0x0
+phy_chain_tx_polarity_flip_physical{144.0}=0x0
+phy_chain_tx_polarity_flip_physical{145.0}=0x1
+phy_chain_tx_polarity_flip_physical{146.0}=0x0
+phy_chain_tx_polarity_flip_physical{147.0}=0x0
+phy_chain_tx_polarity_flip_physical{148.0}=0x0
+phy_chain_tx_polarity_flip_physical{149.0}=0x0
+phy_chain_tx_polarity_flip_physical{150.0}=0x0
+phy_chain_tx_polarity_flip_physical{151.0}=0x0
+phy_chain_tx_polarity_flip_physical{152.0}=0x0
+phy_chain_tx_polarity_flip_physical{153.0}=0x0
+phy_chain_tx_polarity_flip_physical{154.0}=0x1
+phy_chain_tx_polarity_flip_physical{155.0}=0x0
+phy_chain_tx_polarity_flip_physical{156.0}=0x0
+phy_chain_tx_polarity_flip_physical{157.0}=0x0
+phy_chain_tx_polarity_flip_physical{158.0}=0x0
+phy_chain_tx_polarity_flip_physical{159.0}=0x0
+phy_chain_tx_polarity_flip_physical{160.0}=0x0
+phy_chain_tx_polarity_flip_physical{161.0}=0x1
+phy_chain_tx_polarity_flip_physical{162.0}=0x0
+phy_chain_tx_polarity_flip_physical{163.0}=0x0
+phy_chain_tx_polarity_flip_physical{164.0}=0x0
+phy_chain_tx_polarity_flip_physical{165.0}=0x0
+phy_chain_tx_polarity_flip_physical{166.0}=0x0
+phy_chain_tx_polarity_flip_physical{167.0}=0x0
+phy_chain_tx_polarity_flip_physical{168.0}=0x0
+phy_chain_tx_polarity_flip_physical{169.0}=0x0
+phy_chain_tx_polarity_flip_physical{170.0}=0x1
+phy_chain_tx_polarity_flip_physical{171.0}=0x0
+phy_chain_tx_polarity_flip_physical{172.0}=0x0
+phy_chain_tx_polarity_flip_physical{173.0}=0x0
+phy_chain_tx_polarity_flip_physical{174.0}=0x0
+phy_chain_tx_polarity_flip_physical{175.0}=0x0
+phy_chain_tx_polarity_flip_physical{176.0}=0x0
+phy_chain_tx_polarity_flip_physical{177.0}=0x0
+phy_chain_tx_polarity_flip_physical{178.0}=0x1
+phy_chain_tx_polarity_flip_physical{179.0}=0x0
+phy_chain_tx_polarity_flip_physical{180.0}=0x0
+phy_chain_tx_polarity_flip_physical{181.0}=0x0
+phy_chain_tx_polarity_flip_physical{182.0}=0x0
+phy_chain_tx_polarity_flip_physical{183.0}=0x0
+phy_chain_tx_polarity_flip_physical{184.0}=0x0
+phy_chain_tx_polarity_flip_physical{185.0}=0x0
+phy_chain_tx_polarity_flip_physical{186.0}=0x0
+phy_chain_tx_polarity_flip_physical{187.0}=0x0
+phy_chain_tx_polarity_flip_physical{188.0}=0x0
+phy_chain_tx_polarity_flip_physical{189.0}=0x0
+phy_chain_tx_polarity_flip_physical{190.0}=0x0
+phy_chain_tx_polarity_flip_physical{191.0}=0x0
+phy_chain_tx_polarity_flip_physical{192.0}=0x0
+
+## FalconCore[48-63] ports TX polarity flip
+phy_chain_tx_polarity_flip_physical{193.0}=0x1
+phy_chain_tx_polarity_flip_physical{194.0}=0x0
+phy_chain_tx_polarity_flip_physical{195.0}=0x0
+phy_chain_tx_polarity_flip_physical{196.0}=0x0
+phy_chain_tx_polarity_flip_physical{197.0}=0x0
+phy_chain_tx_polarity_flip_physical{198.0}=0x0
+phy_chain_tx_polarity_flip_physical{199.0}=0x0
+phy_chain_tx_polarity_flip_physical{200.0}=0x0
+phy_chain_tx_polarity_flip_physical{201.0}=0x0
+phy_chain_tx_polarity_flip_physical{202.0}=0x1
+phy_chain_tx_polarity_flip_physical{203.0}=0x0
+phy_chain_tx_polarity_flip_physical{204.0}=0x0
+phy_chain_tx_polarity_flip_physical{205.0}=0x0
+phy_chain_tx_polarity_flip_physical{206.0}=0x0
+phy_chain_tx_polarity_flip_physical{207.0}=0x0
+phy_chain_tx_polarity_flip_physical{208.0}=0x0
+phy_chain_tx_polarity_flip_physical{209.0}=0x0
+phy_chain_tx_polarity_flip_physical{210.0}=0x0
+phy_chain_tx_polarity_flip_physical{211.0}=0x0
+phy_chain_tx_polarity_flip_physical{212.0}=0x0
+phy_chain_tx_polarity_flip_physical{213.0}=0x0
+phy_chain_tx_polarity_flip_physical{214.0}=0x0
+phy_chain_tx_polarity_flip_physical{215.0}=0x0
+phy_chain_tx_polarity_flip_physical{216.0}=0x0
+phy_chain_tx_polarity_flip_physical{217.0}=0x1
+phy_chain_tx_polarity_flip_physical{218.0}=0x0
+phy_chain_tx_polarity_flip_physical{219.0}=0x0
+phy_chain_tx_polarity_flip_physical{220.0}=0x0
+phy_chain_tx_polarity_flip_physical{221.0}=0x0
+phy_chain_tx_polarity_flip_physical{222.0}=0x0
+phy_chain_tx_polarity_flip_physical{223.0}=0x0
+phy_chain_tx_polarity_flip_physical{224.0}=0x0
+phy_chain_tx_polarity_flip_physical{225.0}=0x1
+phy_chain_tx_polarity_flip_physical{226.0}=0x0
+phy_chain_tx_polarity_flip_physical{227.0}=0x0
+phy_chain_tx_polarity_flip_physical{228.0}=0x0
+phy_chain_tx_polarity_flip_physical{229.0}=0x0
+phy_chain_tx_polarity_flip_physical{230.0}=0x0
+phy_chain_tx_polarity_flip_physical{231.0}=0x0
+phy_chain_tx_polarity_flip_physical{232.0}=0x0
+phy_chain_tx_polarity_flip_physical{233.0}=0x1
+phy_chain_tx_polarity_flip_physical{234.0}=0x0
+phy_chain_tx_polarity_flip_physical{235.0}=0x0
+phy_chain_tx_polarity_flip_physical{236.0}=0x0
+phy_chain_tx_polarity_flip_physical{237.0}=0x0
+phy_chain_tx_polarity_flip_physical{238.0}=0x0
+phy_chain_tx_polarity_flip_physical{239.0}=0x0
+phy_chain_tx_polarity_flip_physical{240.0}=0x0
+phy_chain_tx_polarity_flip_physical{241.0}=0x1
+phy_chain_tx_polarity_flip_physical{242.0}=0x0
+phy_chain_tx_polarity_flip_physical{243.0}=0x0
+phy_chain_tx_polarity_flip_physical{244.0}=0x0
+phy_chain_tx_polarity_flip_physical{245.0}=0x0
+phy_chain_tx_polarity_flip_physical{246.0}=0x0
+phy_chain_tx_polarity_flip_physical{247.0}=0x0
+phy_chain_tx_polarity_flip_physical{248.0}=0x1
+phy_chain_tx_polarity_flip_physical{249.0}=0x1
+phy_chain_tx_polarity_flip_physical{250.0}=0x0
+phy_chain_tx_polarity_flip_physical{251.0}=0x0
+phy_chain_tx_polarity_flip_physical{252.0}=0x0
+phy_chain_tx_polarity_flip_physical{253.0}=0x0
+phy_chain_tx_polarity_flip_physical{254.0}=0x0
+phy_chain_tx_polarity_flip_physical{255.0}=0x0
+phy_chain_tx_polarity_flip_physical{256.0}=0x1
+
+## FalconCore[0-15] ports RX polarity flip
+phy_chain_rx_polarity_flip_physical{1.0}=0x0
+phy_chain_rx_polarity_flip_physical{2.0}=0x0
+phy_chain_rx_polarity_flip_physical{3.0}=0x0
+phy_chain_rx_polarity_flip_physical{4.0}=0x0
+phy_chain_rx_polarity_flip_physical{5.0}=0x0
+phy_chain_rx_polarity_flip_physical{6.0}=0x0
+phy_chain_rx_polarity_flip_physical{7.0}=0x0
+phy_chain_rx_polarity_flip_physical{8.0}=0x0
+phy_chain_rx_polarity_flip_physical{9.0}=0x0
+phy_chain_rx_polarity_flip_physical{10.0}=0x0
+phy_chain_rx_polarity_flip_physical{11.0}=0x0
+phy_chain_rx_polarity_flip_physical{12.0}=0x0
+phy_chain_rx_polarity_flip_physical{13.0}=0x0
+phy_chain_rx_polarity_flip_physical{14.0}=0x0
+phy_chain_rx_polarity_flip_physical{15.0}=0x0
+phy_chain_rx_polarity_flip_physical{16.0}=0x0
+phy_chain_rx_polarity_flip_physical{17.0}=0x0
+phy_chain_rx_polarity_flip_physical{18.0}=0x0
+phy_chain_rx_polarity_flip_physical{19.0}=0x0
+phy_chain_rx_polarity_flip_physical{20.0}=0x1
+phy_chain_rx_polarity_flip_physical{21.0}=0x0
+phy_chain_rx_polarity_flip_physical{22.0}=0x0
+phy_chain_rx_polarity_flip_physical{23.0}=0x0
+phy_chain_rx_polarity_flip_physical{24.0}=0x0
+phy_chain_rx_polarity_flip_physical{25.0}=0x0
+phy_chain_rx_polarity_flip_physical{26.0}=0x0
+phy_chain_rx_polarity_flip_physical{27.0}=0x0
+phy_chain_rx_polarity_flip_physical{28.0}=0x1
+phy_chain_rx_polarity_flip_physical{29.0}=0x0
+phy_chain_rx_polarity_flip_physical{30.0}=0x0
+phy_chain_rx_polarity_flip_physical{31.0}=0x0
+phy_chain_rx_polarity_flip_physical{32.0}=0x0
+phy_chain_rx_polarity_flip_physical{33.0}=0x0
+phy_chain_rx_polarity_flip_physical{34.0}=0x0
+phy_chain_rx_polarity_flip_physical{35.0}=0x0
+phy_chain_rx_polarity_flip_physical{36.0}=0x0
+phy_chain_rx_polarity_flip_physical{37.0}=0x0
+phy_chain_rx_polarity_flip_physical{38.0}=0x0
+phy_chain_rx_polarity_flip_physical{39.0}=0x0
+phy_chain_rx_polarity_flip_physical{40.0}=0x0
+phy_chain_rx_polarity_flip_physical{41.0}=0x0
+phy_chain_rx_polarity_flip_physical{42.0}=0x0
+phy_chain_rx_polarity_flip_physical{43.0}=0x0
+phy_chain_rx_polarity_flip_physical{44.0}=0x0
+phy_chain_rx_polarity_flip_physical{45.0}=0x0
+phy_chain_rx_polarity_flip_physical{46.0}=0x0
+phy_chain_rx_polarity_flip_physical{47.0}=0x0
+phy_chain_rx_polarity_flip_physical{48.0}=0x0
+phy_chain_rx_polarity_flip_physical{49.0}=0x0
+phy_chain_rx_polarity_flip_physical{50.0}=0x0
+phy_chain_rx_polarity_flip_physical{51.0}=0x0
+phy_chain_rx_polarity_flip_physical{52.0}=0x0
+phy_chain_rx_polarity_flip_physical{53.0}=0x0
+phy_chain_rx_polarity_flip_physical{54.0}=0x0
+phy_chain_rx_polarity_flip_physical{55.0}=0x0
+phy_chain_rx_polarity_flip_physical{56.0}=0x0
+phy_chain_rx_polarity_flip_physical{57.0}=0x0
+phy_chain_rx_polarity_flip_physical{58.0}=0x0
+phy_chain_rx_polarity_flip_physical{59.0}=0x0
+phy_chain_rx_polarity_flip_physical{60.0}=0x0
+phy_chain_rx_polarity_flip_physical{61.0}=0x0
+phy_chain_rx_polarity_flip_physical{62.0}=0x0
+phy_chain_rx_polarity_flip_physical{63.0}=0x0
+phy_chain_rx_polarity_flip_physical{64.0}=0x0
+
+## FalconCore [16-31] ports RX polarity flip
+phy_chain_rx_polarity_flip_physical{65.0}=0x0
+phy_chain_rx_polarity_flip_physical{66.0}=0x0
+phy_chain_rx_polarity_flip_physical{67.0}=0x0
+phy_chain_rx_polarity_flip_physical{68.0}=0x0
+phy_chain_rx_polarity_flip_physical{69.0}=0x0
+phy_chain_rx_polarity_flip_physical{70.0}=0x0
+phy_chain_rx_polarity_flip_physical{71.0}=0x0
+phy_chain_rx_polarity_flip_physical{72.0}=0x1
+phy_chain_rx_polarity_flip_physical{73.0}=0x0
+phy_chain_rx_polarity_flip_physical{74.0}=0x0
+phy_chain_rx_polarity_flip_physical{75.0}=0x0
+phy_chain_rx_polarity_flip_physical{76.0}=0x0
+phy_chain_rx_polarity_flip_physical{77.0}=0x0
+phy_chain_rx_polarity_flip_physical{78.0}=0x0
+phy_chain_rx_polarity_flip_physical{79.0}=0x1
+phy_chain_rx_polarity_flip_physical{80.0}=0x0
+phy_chain_rx_polarity_flip_physical{81.0}=0x0
+phy_chain_rx_polarity_flip_physical{82.0}=0x0
+phy_chain_rx_polarity_flip_physical{83.0}=0x0
+phy_chain_rx_polarity_flip_physical{84.0}=0x0
+phy_chain_rx_polarity_flip_physical{85.0}=0x0
+phy_chain_rx_polarity_flip_physical{86.0}=0x0
+phy_chain_rx_polarity_flip_physical{87.0}=0x0
+phy_chain_rx_polarity_flip_physical{88.0}=0x0
+phy_chain_rx_polarity_flip_physical{89.0}=0x0
+phy_chain_rx_polarity_flip_physical{90.0}=0x0
+phy_chain_rx_polarity_flip_physical{91.0}=0x0
+phy_chain_rx_polarity_flip_physical{92.0}=0x0
+phy_chain_rx_polarity_flip_physical{93.0}=0x0
+phy_chain_rx_polarity_flip_physical{94.0}=0x0
+phy_chain_rx_polarity_flip_physical{95.0}=0x0
+phy_chain_rx_polarity_flip_physical{96.0}=0x0
+phy_chain_rx_polarity_flip_physical{97.0}=0x0
+phy_chain_rx_polarity_flip_physical{98.0}=0x0
+phy_chain_rx_polarity_flip_physical{99.0}=0x0
+phy_chain_rx_polarity_flip_physical{100.0}=0x0
+phy_chain_rx_polarity_flip_physical{101.0}=0x0
+phy_chain_rx_polarity_flip_physical{102.0}=0x0
+phy_chain_rx_polarity_flip_physical{103.0}=0x0
+phy_chain_rx_polarity_flip_physical{104.0}=0x0
+phy_chain_rx_polarity_flip_physical{105.0}=0x0
+phy_chain_rx_polarity_flip_physical{106.0}=0x0
+phy_chain_rx_polarity_flip_physical{107.0}=0x0
+phy_chain_rx_polarity_flip_physical{108.0}=0x0
+phy_chain_rx_polarity_flip_physical{109.0}=0x0
+phy_chain_rx_polarity_flip_physical{110.0}=0x0
+phy_chain_rx_polarity_flip_physical{111.0}=0x0
+phy_chain_rx_polarity_flip_physical{112.0}=0x0
+phy_chain_rx_polarity_flip_physical{113.0}=0x0
+phy_chain_rx_polarity_flip_physical{114.0}=0x0
+phy_chain_rx_polarity_flip_physical{115.0}=0x0
+phy_chain_rx_polarity_flip_physical{116.0}=0x0
+phy_chain_rx_polarity_flip_physical{117.0}=0x0
+phy_chain_rx_polarity_flip_physical{118.0}=0x0
+phy_chain_rx_polarity_flip_physical{119.0}=0x0
+phy_chain_rx_polarity_flip_physical{120.0}=0x0
+phy_chain_rx_polarity_flip_physical{121.0}=0x0
+phy_chain_rx_polarity_flip_physical{122.0}=0x0
+phy_chain_rx_polarity_flip_physical{123.0}=0x0
+phy_chain_rx_polarity_flip_physical{124.0}=0x0
+phy_chain_rx_polarity_flip_physical{125.0}=0x0
+phy_chain_rx_polarity_flip_physical{126.0}=0x0
+phy_chain_rx_polarity_flip_physical{127.0}=0x0
+phy_chain_rx_polarity_flip_physical{128.0}=0x0
+
+## FalconCore [32-47] ports RX polarity flip
+phy_chain_rx_polarity_flip_physical{129.0}=0x0
+phy_chain_rx_polarity_flip_physical{130.0}=0x0
+phy_chain_rx_polarity_flip_physical{131.0}=0x0
+phy_chain_rx_polarity_flip_physical{132.0}=0x0
+phy_chain_rx_polarity_flip_physical{133.0}=0x0
+phy_chain_rx_polarity_flip_physical{134.0}=0x0
+phy_chain_rx_polarity_flip_physical{135.0}=0x0
+phy_chain_rx_polarity_flip_physical{136.0}=0x0
+phy_chain_rx_polarity_flip_physical{137.0}=0x0
+phy_chain_rx_polarity_flip_physical{138.0}=0x0
+phy_chain_rx_polarity_flip_physical{139.0}=0x0
+phy_chain_rx_polarity_flip_physical{140.0}=0x0
+phy_chain_rx_polarity_flip_physical{141.0}=0x0
+phy_chain_rx_polarity_flip_physical{142.0}=0x0
+phy_chain_rx_polarity_flip_physical{143.0}=0x0
+phy_chain_rx_polarity_flip_physical{144.0}=0x0
+phy_chain_rx_polarity_flip_physical{145.0}=0x0
+phy_chain_rx_polarity_flip_physical{146.0}=0x0
+phy_chain_rx_polarity_flip_physical{147.0}=0x0
+phy_chain_rx_polarity_flip_physical{148.0}=0x1
+phy_chain_rx_polarity_flip_physical{149.0}=0x0
+phy_chain_rx_polarity_flip_physical{150.0}=0x0
+phy_chain_rx_polarity_flip_physical{151.0}=0x0
+phy_chain_rx_polarity_flip_physical{152.0}=0x0
+phy_chain_rx_polarity_flip_physical{153.0}=0x0
+phy_chain_rx_polarity_flip_physical{154.0}=0x0
+phy_chain_rx_polarity_flip_physical{155.0}=0x0
+phy_chain_rx_polarity_flip_physical{156.0}=0x1
+phy_chain_rx_polarity_flip_physical{157.0}=0x0
+phy_chain_rx_polarity_flip_physical{158.0}=0x0
+phy_chain_rx_polarity_flip_physical{159.0}=0x0
+phy_chain_rx_polarity_flip_physical{160.0}=0x0
+phy_chain_rx_polarity_flip_physical{161.0}=0x0
+phy_chain_rx_polarity_flip_physical{162.0}=0x0
+phy_chain_rx_polarity_flip_physical{163.0}=0x0
+phy_chain_rx_polarity_flip_physical{164.0}=0x0
+phy_chain_rx_polarity_flip_physical{165.0}=0x0
+phy_chain_rx_polarity_flip_physical{166.0}=0x0
+phy_chain_rx_polarity_flip_physical{167.0}=0x0
+phy_chain_rx_polarity_flip_physical{168.0}=0x0
+phy_chain_rx_polarity_flip_physical{169.0}=0x0
+phy_chain_rx_polarity_flip_physical{170.0}=0x0
+phy_chain_rx_polarity_flip_physical{171.0}=0x0
+phy_chain_rx_polarity_flip_physical{172.0}=0x0
+phy_chain_rx_polarity_flip_physical{173.0}=0x0
+phy_chain_rx_polarity_flip_physical{174.0}=0x0
+phy_chain_rx_polarity_flip_physical{175.0}=0x0
+phy_chain_rx_polarity_flip_physical{176.0}=0x0
+phy_chain_rx_polarity_flip_physical{177.0}=0x0
+phy_chain_rx_polarity_flip_physical{178.0}=0x0
+phy_chain_rx_polarity_flip_physical{179.0}=0x0
+phy_chain_rx_polarity_flip_physical{180.0}=0x0
+phy_chain_rx_polarity_flip_physical{181.0}=0x0
+phy_chain_rx_polarity_flip_physical{182.0}=0x0
+phy_chain_rx_polarity_flip_physical{183.0}=0x0
+phy_chain_rx_polarity_flip_physical{184.0}=0x0
+phy_chain_rx_polarity_flip_physical{185.0}=0x0
+phy_chain_rx_polarity_flip_physical{186.0}=0x0
+phy_chain_rx_polarity_flip_physical{187.0}=0x1
+phy_chain_rx_polarity_flip_physical{188.0}=0x0
+phy_chain_rx_polarity_flip_physical{189.0}=0x0
+phy_chain_rx_polarity_flip_physical{190.0}=0x0
+phy_chain_rx_polarity_flip_physical{191.0}=0x0
+phy_chain_rx_polarity_flip_physical{192.0}=0x0
+
+## FalconCore [48-63] ports RX polarity flip
+phy_chain_rx_polarity_flip_physical{193.0}=0x0
+phy_chain_rx_polarity_flip_physical{194.0}=0x0
+phy_chain_rx_polarity_flip_physical{195.0}=0x0
+phy_chain_rx_polarity_flip_physical{196.0}=0x0
+phy_chain_rx_polarity_flip_physical{197.0}=0x0
+phy_chain_rx_polarity_flip_physical{198.0}=0x0
+phy_chain_rx_polarity_flip_physical{199.0}=0x0
+phy_chain_rx_polarity_flip_physical{200.0}=0x0
+phy_chain_rx_polarity_flip_physical{201.0}=0x0
+phy_chain_rx_polarity_flip_physical{202.0}=0x0
+phy_chain_rx_polarity_flip_physical{203.0}=0x0
+phy_chain_rx_polarity_flip_physical{204.0}=0x0
+phy_chain_rx_polarity_flip_physical{205.0}=0x0
+phy_chain_rx_polarity_flip_physical{206.0}=0x0
+phy_chain_rx_polarity_flip_physical{207.0}=0x0
+phy_chain_rx_polarity_flip_physical{208.0}=0x0
+phy_chain_rx_polarity_flip_physical{209.0}=0x0
+phy_chain_rx_polarity_flip_physical{210.0}=0x0
+phy_chain_rx_polarity_flip_physical{211.0}=0x1
+phy_chain_rx_polarity_flip_physical{212.0}=0x1
+phy_chain_rx_polarity_flip_physical{213.0}=0x0
+phy_chain_rx_polarity_flip_physical{214.0}=0x0
+phy_chain_rx_polarity_flip_physical{215.0}=0x0
+phy_chain_rx_polarity_flip_physical{216.0}=0x0
+phy_chain_rx_polarity_flip_physical{217.0}=0x0
+phy_chain_rx_polarity_flip_physical{218.0}=0x0
+phy_chain_rx_polarity_flip_physical{219.0}=0x1
+phy_chain_rx_polarity_flip_physical{220.0}=0x0
+phy_chain_rx_polarity_flip_physical{221.0}=0x0
+phy_chain_rx_polarity_flip_physical{222.0}=0x0
+phy_chain_rx_polarity_flip_physical{223.0}=0x0
+phy_chain_rx_polarity_flip_physical{224.0}=0x0
+phy_chain_rx_polarity_flip_physical{225.0}=0x0
+phy_chain_rx_polarity_flip_physical{226.0}=0x0
+phy_chain_rx_polarity_flip_physical{227.0}=0x0
+phy_chain_rx_polarity_flip_physical{228.0}=0x0
+phy_chain_rx_polarity_flip_physical{229.0}=0x0
+phy_chain_rx_polarity_flip_physical{230.0}=0x0
+phy_chain_rx_polarity_flip_physical{231.0}=0x0
+phy_chain_rx_polarity_flip_physical{232.0}=0x0
+phy_chain_rx_polarity_flip_physical{233.0}=0x0
+phy_chain_rx_polarity_flip_physical{234.0}=0x0
+phy_chain_rx_polarity_flip_physical{235.0}=0x0
+phy_chain_rx_polarity_flip_physical{236.0}=0x0
+phy_chain_rx_polarity_flip_physical{237.0}=0x0
+phy_chain_rx_polarity_flip_physical{238.0}=0x0
+phy_chain_rx_polarity_flip_physical{239.0}=0x0
+phy_chain_rx_polarity_flip_physical{240.0}=0x0
+phy_chain_rx_polarity_flip_physical{241.0}=0x0
+phy_chain_rx_polarity_flip_physical{242.0}=0x0
+phy_chain_rx_polarity_flip_physical{243.0}=0x1
+phy_chain_rx_polarity_flip_physical{244.0}=0x0
+phy_chain_rx_polarity_flip_physical{245.0}=0x0
+phy_chain_rx_polarity_flip_physical{246.0}=0x0
+phy_chain_rx_polarity_flip_physical{247.0}=0x0
+phy_chain_rx_polarity_flip_physical{248.0}=0x0
+phy_chain_rx_polarity_flip_physical{249.0}=0x0
+phy_chain_rx_polarity_flip_physical{250.0}=0x0
+phy_chain_rx_polarity_flip_physical{251.0}=0x1
+phy_chain_rx_polarity_flip_physical{252.0}=0x0
+phy_chain_rx_polarity_flip_physical{253.0}=0x0
+phy_chain_rx_polarity_flip_physical{254.0}=0x0
+phy_chain_rx_polarity_flip_physical{255.0}=0x0
+phy_chain_rx_polarity_flip_physical{256.0}=0x0
+
+dport_map_enable=1
+dport_map_port_3=68
+dport_map_port_4=69
+dport_map_port_5=3
+dport_map_port_6=4
+dport_map_port_7=70
+dport_map_port_8=71
+dport_map_port_9=5
+dport_map_port_10=6
+dport_map_port_11=72
+dport_map_port_12=73
+dport_map_port_13=7
+dport_map_port_14=8
+dport_map_port_15=74
+dport_map_port_16=75
+dport_map_port_34=9
+dport_map_port_35=10
+dport_map_port_36=76
+dport_map_port_37=77
+dport_map_port_38=11
+dport_map_port_39=12
+dport_map_port_40=78
+dport_map_port_41=79
+dport_map_port_42=13
+dport_map_port_43=14
+dport_map_port_44=80
+dport_map_port_45=81
+dport_map_port_46=15
+dport_map_port_47=16
+dport_map_port_48=82
+dport_map_port_49=83
+dport_map_port_68=34
+dport_map_port_69=35
+dport_map_port_70=102
+dport_map_port_71=103
+dport_map_port_72=36
+dport_map_port_73=37
+dport_map_port_74=104
+dport_map_port_75=105
+dport_map_port_76=38
+dport_map_port_77=39
+dport_map_port_78=106
+dport_map_port_79=107
+dport_map_port_80=40
+dport_map_port_81=41
+dport_map_port_82=108
+dport_map_port_83=109
+dport_map_port_102=42
+dport_map_port_103=43
+dport_map_port_104=110
+dport_map_port_105=111
+dport_map_port_106=44
+dport_map_port_107=45
+dport_map_port_108=112
+dport_map_port_109=113
+dport_map_port_110=46
+dport_map_port_111=47
+dport_map_port_112=114
+dport_map_port_113=115
+dport_map_port_114=48
+dport_map_port_115=49
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf
new file mode 100644
index 000000000000..1db64ba02c38
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf
@@ -0,0 +1,4 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
+VAR_LOG_SIZE=1024
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc
new file mode 100644
index 000000000000..296f8746f101
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc
@@ -0,0 +1,273 @@
+#LED processor initialization for Inventec Sequoia platform
+
+led 0 stop
+led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=59
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=57
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=58
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=51
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=49
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=50
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=48
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=61
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=62
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=60
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=55
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=53
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=54
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=52
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=41
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=42
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=33
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=34
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=32
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=47
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=45
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=46
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=39
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=37
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=38
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=25
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=26
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=19
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=17
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=18
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=16
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=29
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=30
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=23
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=21
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=22
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=20
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=9
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=10
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=3
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=1
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=2
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=15
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=13
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=14
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=7
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=5
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=6
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4
+led 0 start
+
+led 1 stop
+led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=7
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=5
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=6
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=4
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=15
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=13
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=14
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=12
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=1
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=2
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=11
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=9
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=10
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=23
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=21
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=22
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=20
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=29
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=30
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=28
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=19
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=17
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=18
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=25
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=26
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=39
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=37
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=38
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=36
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=45
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=46
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=44
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=33
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=34
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=43
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=41
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=42
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=55
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=52
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=61
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=62
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=60
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=51
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=49
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=50
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=59
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=57
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=58
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56
+led 1 start
+
+led 2 stop
+led 2 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57
+m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=59
+m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=57
+m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=58
+m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56
+m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=51
+m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=49
+m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=50
+m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=48
+m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63
+m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=61
+m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=62
+m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=60
+m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=55
+m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=53
+m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=54
+m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=52
+m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43
+m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=41
+m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=42
+m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40
+m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35
+m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=33
+m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=34
+m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=32
+m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=47
+m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=45
+m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=46
+m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44
+m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=39
+m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=37
+m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=38
+m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36
+m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27
+m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=25
+m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=26
+m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24
+m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=19
+m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=17
+m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=18
+m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=16
+m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31
+m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=29
+m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=30
+m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28
+m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=23
+m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=21
+m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=22
+m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=20
+m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11
+m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=9
+m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=10
+m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8
+m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=3
+m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=1
+m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=2
+m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0
+m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=15
+m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=13
+m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=14
+m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12
+m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=7
+m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=5
+m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=6
+m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4
+led 2 start
+
+led 3 stop
+led 3 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57
+m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=7
+m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=5
+m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=6
+m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=4
+m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=15
+m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=13
+m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=14
+m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=12
+m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3
+m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=1
+m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=2
+m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0
+m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=11
+m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=9
+m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=10
+m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8
+m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=23
+m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=21
+m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=22
+m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=20
+m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31
+m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=29
+m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=30
+m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=28
+m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=19
+m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=17
+m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=18
+m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16
+m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27
+m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=25
+m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=26
+m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24
+m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=39
+m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=37
+m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=38
+m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=36
+m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47
+m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=45
+m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=46
+m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=44
+m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35
+m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=33
+m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=34
+m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32
+m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=43
+m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=41
+m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=42
+m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40
+m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=55
+m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53
+m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54
+m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=52
+m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63
+m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=61
+m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=62
+m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=60
+m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=51
+m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=49
+m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=50
+m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48
+m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=59
+m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=57
+m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=58
+m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56
+led 3 start
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/minigraph.xml b/device/inventec/x86_64-inventec_d7264q28b-r0/minigraph.xml
new file mode 100644
index 000000000000..b68f712b2624
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/minigraph.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+ OCPSCH0104001MS
+ 10.10.1.26
+ SONiC-Inventec-d7264
+ 10.10.1.25
+ 1
+ 10
+ 3
+
+
+ OCPSCH0104002MS
+ 10.10.2.26
+ SONiC-Inventec-d7264
+ 10.10.2.25
+ 1
+ 10
+ 3
+
+
+
+
+ 64536
+ SONiC-Inventec-d7264
+
+
+ 10.10.1.26
+
+
+
+
+ 10.10.2.26
+
+
+
+
+
+
+
+ 64542
+ OCPSCH0104001MS
+
+
+
+ 64543
+ OCPSCH0104002MS
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 100.0.0.9/32
+
+ 100.0.0.9/32
+
+
+
+
+
+
+
+ SONiC-Inventec-d7264
+
+
+
+
+
+ Ethernet0
+ 10.10.1.25/30
+
+
+
+ Ethernet4
+ 10.10.2.25/30
+
+
+
+
+
+
+
+
+
+
+
+ DeviceInterfaceLink
+ OCPSCH0104001MS
+ Ethernet24
+ SONiC-Inventec-d7264
+ Ethernet0
+
+
+ DeviceInterfaceLink
+ OCPSCH0104002MS
+ Ethernet24
+ SONiC-Inventec-d7264
+ Ethernet4
+
+
+
+
+ SONiC-Inventec-d7264
+ INVENTEC-D7264Q28B
+
+
+
+
+
+
+ SONiC-Inventec-d7264
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+
+
+
+
+ SONiC-Inventec-d7264
+ INVENTEC-D7264Q28B
+
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..de5c24ba0e6d
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Inventec d7032q28b
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+ from sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py
new file mode 100755
index 000000000000..c2337a97f4ea
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py
@@ -0,0 +1,93 @@
+#
+# psuutil.py
+# Platform-specific PSU status interface for SONiC
+#
+
+
+import os.path
+
+try:
+ from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+class PsuUtil(PsuBase):
+ """Platform-specific PSUutil class"""
+
+ PSU_DIR1 = "/sys/class/hwmon/hwmon1/device"
+ PSU_DIR2 = "/sys/class/hwmon/hwmon3/device"
+
+ def __init__(self):
+ PsuBase.__init__(self)
+
+# Get sysfs attribute
+ def get_attr_value(self, attr_path):
+
+ retval = 'ERR'
+ if (not os.path.isfile(attr_path)):
+ return retval
+
+ try:
+ with open(attr_path, 'r') as fd:
+ retval = fd.read()
+ except Exception as error:
+ logging.error("Unable to open ", attr_path, " file !")
+
+ retval = retval.rstrip(' \t\n\r')
+ return retval
+
+ def get_num_psus(self):
+ """
+ Retrieves the number of PSUs available on the device
+ :return: An integer, the number of PSUs available on the device
+ """
+ MAX_PSUS = 2
+ return MAX_PSUS
+
+ def get_psu_status(self, index):
+ """
+ Retrieves the oprational status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is operating properly, False if PSU is\
+ faulty
+ """
+ status = 0
+ attr_file = 'psoc_psu'+ str(index) + '_iout'
+ attr_path = self.PSU_DIR1 +'/' + attr_file
+
+ attr_value = self.get_attr_value(attr_path)
+ if (attr_value == 'ERR'):
+ attr_path = self.PSU_DIR2 +'/' + attr_file
+ attr_value = self.get_attr_value(attr_path)
+ # Check for PSU status
+ if (attr_value != 0):
+ status = 1
+ if (attr_value != 0):
+ status = 1
+ return status
+
+ def get_psu_presence(self, index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by index
+ :param index: An integer, index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ status = 0
+ psu_absent = 0
+ ind = index-1
+ attr_file ='psu'+ str(ind)
+ normal_attr_value = '0 : normal'
+ attr_path = self.PSU_DIR1 +'/' + attr_file
+ attr_value = self.get_attr_value(attr_path)
+ if (attr_value == 'ERR'):
+ attr_path = self.PSU_DIR2 +'/' + attr_file
+ attr_value = self.get_attr_value(attr_path)
+ # Check for PSU presence
+ if (attr_value == normal_attr_value):
+ status = 1
+ if (attr_value == normal_attr_value):
+ status = 1
+ return status
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..aa551932dc78
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py
@@ -0,0 +1,219 @@
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 0
+ PORT_END = 63
+ PORTS_IN_BLOCK = 64
+ QSFP_PORT_START = 0
+ QSFP_PORT_END = 63
+
+ _port_to_eeprom_mapping = {}
+ port_to_i2c_mapping = {
+ 0: 10,
+ 1: 11,
+ 2: 12,
+ 3: 13,
+ 4: 14,
+ 5: 15,
+ 6: 16,
+ 7: 17,
+ 8: 18,
+ 9: 19,
+ 10: 20,
+ 11: 21,
+ 12: 22,
+ 13: 23,
+ 14: 24,
+ 15: 25,
+ 16: 26,
+ 17: 27,
+ 18: 28,
+ 19: 29,
+ 20: 30,
+ 21: 31,
+ 22: 32,
+ 23: 33,
+ 24: 34,
+ 25: 35,
+ 26: 36,
+ 27: 37,
+ 28: 38,
+ 29: 39,
+ 30: 40,
+ 31: 41,
+ 32: 45,
+ 33: 44,
+ 34: 43,
+ 35: 42,
+ 36: 49,
+ 37: 48,
+ 38: 47,
+ 39: 46,
+ 40: 53,
+ 41: 52,
+ 42: 51,
+ 43: 50,
+ 44: 57,
+ 45: 56,
+ 46: 55,
+ 47: 54,
+ 48: 61,
+ 49: 60,
+ 50: 59,
+ 51: 58,
+ 52: 65,
+ 53: 64,
+ 54: 63,
+ 55: 62,
+ 56: 69,
+ 57: 68,
+ 58: 67,
+ 59: 66,
+ 60: 73,
+ 61: 72,
+ 62: 71,
+ 63: 70
+ }
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_port_start(self):
+ return self.QSFP_PORT_START
+
+ @property
+ def qsfp_port_end(self):
+ return self.QSFP_PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom"
+
+ for x in range(0, self.port_end + 1):
+ port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
+ self.port_to_eeprom_mapping[x] = port_eeprom_path
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/present")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ if reg_value == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ if reg_value == 0:
+ return False
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ print "\nError:SFP's don't support this property"
+ return False
+
+ try:
+ reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(reg_file.readline().rstrip())
+
+ # LPMode is active high; set or clear the bit accordingly
+ if lpmode is True:
+ reg_value = 1
+ else:
+ reg_value = 0
+
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+ QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset"
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ print "\nError:SFP's don't support this property"
+ return False
+
+ try:
+ reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = 0
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ # Sleep 2 second to allow it to settle
+ time.sleep(2)
+
+ # Flip the value back write back to the register to take port out of reset
+ try:
+ reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = 1
+ reg_file.write(hex(reg_value))
+ reg_file.close()
+
+ return True
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index 8b24216d0a9d..29b0f20ef01b 100755
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -22,6 +22,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ACCTON_AS7716_32XB_PLATFORM_MODULE) \
$(INVENTEC_D7032Q28B_PLATFORM_MODULE) \
$(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
+ $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
$(CEL_DX010_PLATFORM_MODULE) \
$(CEL_HALIBURTON_PLATFORM_MODULE) \
$(DELTA_AG9032V1_PLATFORM_MODULE) \
diff --git a/platform/broadcom/platform-modules-inventec.mk b/platform/broadcom/platform-modules-inventec.mk
index 0960c2aefbcc..2a6f32f923c4 100644
--- a/platform/broadcom/platform-modules-inventec.mk
+++ b/platform/broadcom/platform-modules-inventec.mk
@@ -1,10 +1,12 @@
-# Inventec d7032q28b and d7054q28b Platform modules
+# Inventec d7032q28b , d7054q28b and d7264q28b Platform modules
INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION = 1.1.0
INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION = 1.1.0
+INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION = 1.1.0
export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION
export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION
+export INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION
INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-inventec
@@ -16,4 +18,8 @@ INVENTEC_D7054Q28B_PLATFORM_MODULE = platform-modules-d7054q28b_$(INVENTEC_D7054
$(INVENTEC_D7054Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7054q28b-r0
$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7054Q28B_PLATFORM_MODULE)))
-SONIC_STRETCH_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE)
+INVENTEC_D7264Q28B_PLATFORM_MODULE = platform-modules-d7264q28b_$(INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
+$(INVENTEC_D7264Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7264q28b-r0
+$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7264Q28B_PLATFORM_MODULE)))
+
+SONIC_STRETCH_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE)
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile
new file mode 100755
index 000000000000..aeffa4376588
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile
@@ -0,0 +1,6 @@
+obj-m += inv_cpld.o inv_psoc.o
+obj-m += inv_platform.o
+obj-m += inv_eeprom.o
+obj-m += swps.o
+swps-objs := inv_swps.o io_expander.o transceiver.o
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c
new file mode 100644
index 000000000000..42401d626672
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c
@@ -0,0 +1,470 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#include "I2CHostCommunication.h"
+
+#define USE_SMBUS 1
+
+/* definition */
+#define CPLD_INFO_OFFSET 0x00
+#define CPLD_PSU_OFFSET 0x08
+#define CPLD_LED_OFFSET 0x0E
+#define CPLD_LED_STATU_OFFSET 0x0D
+#define CPLD_CTL_OFFSET 0x0C
+#define CPLD_BIOSCS_OFFSET 0x04
+
+
+/* Each client has this additional data */
+struct cpld_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+};
+
+/*-----------------------------------------------------------------------*/
+
+static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg[0].buf = msgbuf;
+ msg[0].len = 1;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = count;
+
+ status = i2c_transfer(client->adapter, msg, 2);
+
+ if(status == 2)
+ status = count;
+
+ return status;
+#endif
+}
+
+static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg.flags = 0;
+
+ /* msg.buf is u8 and casts will mask the values */
+ msg.buf = writebuf;
+
+ msg.buf[i++] = offset;
+ memcpy(&msg.buf[i], buf, count);
+ msg.len = i + count;
+
+ status = i2c_transfer(client->adapter, &msg, 1);
+ if (status == 1)
+ status = count;
+
+ return status;
+#endif
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+
+static ssize_t show_info(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 b[4];
+
+ memset(b, 0, 4);
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4);
+ mutex_unlock(&data->update_lock);
+
+ if(status != 4) return sprintf(buf, "read cpld info fail\n");
+
+ status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/
+ status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf);
+ status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf);
+
+ return strlen(buf);
+}
+
+
+static ssize_t show_ctl(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 b[1];
+
+ mutex_lock(&data->update_lock);
+
+ status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1);
+
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld ctl fail\n");
+
+
+ status = sprintf (buf, "0x%X\n", b[0]);
+
+ return strlen(buf);
+}
+
+static ssize_t set_ctl(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+
+ u8 temp = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1);
+ if(temp) byte |= (1<<0);
+ else byte &= ~(1<<0);
+ cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 b[1];
+
+ mutex_lock(&data->update_lock);
+
+ status = cpld_i2c_read(client, b, CPLD_BIOSCS_OFFSET, 1);
+
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n");
+
+
+ status = sprintf (buf, "0x%X\n", b[0] & 0x01);
+
+ return strlen(buf);
+}
+
+static ssize_t set_bios_cs(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+
+ u8 temp = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1);
+ if(temp) byte |= 0x01;
+ else byte &= ~(0x01);
+ cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+
+static char* led_str[] = {
+ "OFF", //000
+ "0.5 Hz", //001
+ "1 Hz", //010
+ "2 Hz", //011
+ "4 Hz", //100
+ "NA", //101
+ "NA", //110
+ "ON", //111
+};
+
+static ssize_t show_led(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d: %s\n", byte, led_str[byte]);
+
+ return strlen(buf);
+}
+
+static ssize_t set_led(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ u8 temp = simple_strtol(buf, NULL, 16);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ temp &= 0x7;
+ //validate temp value: 0,1,2,3,7, TBD
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+ byte &= ~(0x7<update_lock);
+
+ return count;
+}
+
+/*
+CPLD report the PSU0 status
+000 = PSU normal operation
+100 = PSU fault
+010 = PSU unpowered
+111 = PSU not installed
+
+7 6 | 5 4 3 | 2 1 0
+----------------------
+ | psu0 | psu1
+*/
+static char* psu_str[] = {
+ "normal", //000
+ "NA", //001
+ "unpowered", //010
+ "NA", //011
+ "fault", //100
+ "NA", //101
+ "NA", //110
+ "not installed", //111
+};
+
+static ssize_t show_psu(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+ int shift = (attr->index == 1)?0:3;
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
+
+ return strlen(buf);
+}
+
+
+static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0);
+static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0);
+
+static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0);
+static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1);
+
+static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0);
+static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1);
+
+static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0);
+
+static struct attribute *cpld_attributes[] = {
+ //info
+ &sensor_dev_attr_info.dev_attr.attr,
+ &sensor_dev_attr_ctl.dev_attr.attr,
+
+ &sensor_dev_attr_grn_led.dev_attr.attr,
+ &sensor_dev_attr_red_led.dev_attr.attr,
+
+ &sensor_dev_attr_psu0.dev_attr.attr,
+ &sensor_dev_attr_psu1.dev_attr.attr,
+
+ &sensor_dev_attr_bios_cs.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group cpld_group = {
+ .attrs = cpld_attributes,
+};
+
+static struct attribute *cpld2_attributes[] = {
+ //info
+ &sensor_dev_attr_info.dev_attr.attr,
+
+ NULL
+};
+
+static const struct attribute_group cpld2_group = {
+ .attrs = cpld2_attributes,
+};
+
+
+/*-----------------------------------------------------------------------*/
+
+/* device probe and removal */
+
+static int
+cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct cpld_data *data;
+ int status;
+
+// printk("+%s \n", __func__);
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ /* Register sysfs hooks */
+ if(id->driver_data==1) // CPLD2
+ status = sysfs_create_group(&client->dev.kobj, &cpld2_group);
+ else // default CPLD1
+ status = sysfs_create_group(&client->dev.kobj, &cpld_group);
+
+ if (status)
+ goto exit_free;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ status = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ dev_info(&client->dev, "%s: sensor '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &cpld_group);
+exit_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return status;
+}
+
+static int cpld_remove(struct i2c_client *client)
+{
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &cpld_group);
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return 0;
+}
+
+static const struct i2c_device_id cpld_ids[] = {
+ { "inv_cpld" , 0, },
+ { "inv_cpld2", 1, },
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, cpld_ids);
+
+static struct i2c_driver cpld_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "inv_cpld",
+ },
+ .probe = cpld_probe,
+ .remove = cpld_remove,
+ .id_table = cpld_ids,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* module glue */
+
+static int __init inv_cpld_init(void)
+{
+ return i2c_add_driver(&cpld_driver);
+}
+
+static void __exit inv_cpld_exit(void)
+{
+ i2c_del_driver(&cpld_driver);
+}
+
+MODULE_AUTHOR("eddie.lan ");
+MODULE_DESCRIPTION("inv cpld driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_cpld_init);
+module_exit(inv_cpld_exit);
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c
new file mode 100644
index 000000000000..3d13f3b04719
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c
@@ -0,0 +1,181 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+/* Size of EEPROM in bytes */
+#define EEPROM_SIZE 256
+
+#define SLICE_BITS (6)
+#define SLICE_SIZE (1 << SLICE_BITS)
+#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE)
+
+/* Each client has this additional data */
+struct eeprom_data {
+ struct mutex update_lock;
+ u8 valid; /* bitfield, bit!=0 if slice is valid */
+ unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */
+ u8 data[EEPROM_SIZE]; /* Register values */
+};
+
+
+static void inv_eeprom_update_client(struct i2c_client *client, u8 slice)
+{
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ int i, j;
+ int ret;
+ int addr;
+
+
+ mutex_lock(&data->update_lock);
+
+ if (!(data->valid & (1 << slice)) ||
+ time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
+ dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
+
+ addr = slice << SLICE_BITS;
+
+ ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF);
+ /* select the eeprom address */
+ if (ret < 0) {
+ dev_err(&client->dev, "address set failed\n");
+ goto exit;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
+ goto exit;
+ }
+
+ for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) {
+ for (j = i; j < (i+SLICE_SIZE); j++) {
+ int res;
+
+ res = i2c_smbus_read_byte(client);
+ if (res < 0) {
+ goto exit;
+ }
+
+ data->data[j] = res & 0xFF;
+ }
+ }
+
+ data->last_updated[slice] = jiffies;
+ data->valid |= (1 << slice);
+ }
+
+exit:
+ mutex_unlock(&data->update_lock);
+}
+
+static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct eeprom_data *data = i2c_get_clientdata(client);
+ u8 slice;
+
+
+ if (off > EEPROM_SIZE) {
+ return 0;
+ }
+ if (off + count > EEPROM_SIZE) {
+ count = EEPROM_SIZE - off;
+ }
+ if (count == 0) {
+ return 0;
+ }
+
+ /* Only refresh slices which contain requested bytes */
+ for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) {
+ inv_eeprom_update_client(client, slice);
+ }
+
+ memcpy(buf, &data->data[off], count);
+
+ return count;
+}
+
+static struct bin_attribute inv_eeprom_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = inv_eeprom_read,
+};
+
+static int inv_eeprom_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct eeprom_data *data;
+ int err;
+
+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ memset(data->data, 0xff, EEPROM_SIZE);
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ /* create the sysfs eeprom file */
+ err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+ if (err) {
+ goto exit_kfree;
+ }
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int inv_eeprom_remove(struct i2c_client *client)
+{
+ sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static const struct i2c_device_id inv_eeprom_id[] = {
+ { "inv_eeprom", 0 },
+ { }
+};
+
+static struct i2c_driver inv_eeprom_driver = {
+ .driver = {
+ .name = "inv_eeprom",
+ },
+ .probe = inv_eeprom_probe,
+ .remove = inv_eeprom_remove,
+ .id_table = inv_eeprom_id,
+};
+
+module_i2c_driver(inv_eeprom_driver);
+
+MODULE_AUTHOR("Inventec");
+MODULE_DESCRIPTION("Inventec D7054 Mother Board EEPROM driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c
new file mode 100644
index 000000000000..720a4cd2257b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c
@@ -0,0 +1,239 @@
+#include
+//#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//#include
+//#include
+
+//#include
+//#define IO_EXPAND_BASE 64
+//#define IO_EXPAND_NGPIO 16
+
+struct inv_i2c_board_info {
+ int ch;
+ int size;
+ struct i2c_board_info *board_info;
+};
+
+#define bus_id(id) (id)
+static struct pca954x_platform_mode mux_modes_0[] = {
+ {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
+ {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
+ {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
+ {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
+};
+static struct pca954x_platform_mode mux_modes_0_0[] = {
+ {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
+ {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
+ {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
+ {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_1[] = {
+ {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
+ {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
+ {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
+ {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_2[] = {
+ {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
+ {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
+ {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
+ {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_3[] = {
+ {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
+ {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
+ {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),},
+ {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_4[] = {
+ {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),},
+ {.adap_id = bus_id(44),}, {.adap_id = bus_id(45),},
+ {.adap_id = bus_id(46),}, {.adap_id = bus_id(47),},
+ {.adap_id = bus_id(48),}, {.adap_id = bus_id(49),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_5[] = {
+ {.adap_id = bus_id(50),}, {.adap_id = bus_id(51),},
+ {.adap_id = bus_id(52),}, {.adap_id = bus_id(53),},
+ {.adap_id = bus_id(54),}, {.adap_id = bus_id(55),},
+ {.adap_id = bus_id(56),}, {.adap_id = bus_id(57),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_6[] = {
+ {.adap_id = bus_id(58),}, {.adap_id = bus_id(59),},
+ {.adap_id = bus_id(60),}, {.adap_id = bus_id(61),},
+ {.adap_id = bus_id(62),}, {.adap_id = bus_id(63),},
+ {.adap_id = bus_id(64),}, {.adap_id = bus_id(65),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_7[] = {
+ {.adap_id = bus_id(66),}, {.adap_id = bus_id(67),},
+ {.adap_id = bus_id(68),}, {.adap_id = bus_id(69),},
+ {.adap_id = bus_id(70),}, {.adap_id = bus_id(71),},
+ {.adap_id = bus_id(72),}, {.adap_id = bus_id(73),},
+};
+
+//no i2c device driver attach to mux 7
+
+
+static struct pca954x_platform_data mux_data_0 = {
+ .modes = mux_modes_0,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_0 = {
+ .modes = mux_modes_0_0,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_1 = {
+ .modes = mux_modes_0_1,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_2 = {
+ .modes = mux_modes_0_2,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_3 = {
+ .modes = mux_modes_0_3,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_4 = {
+ .modes = mux_modes_0_4,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_5 = {
+ .modes = mux_modes_0_5,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_6 = {
+ .modes = mux_modes_0_6,
+ .num_modes = 8,
+};
+static struct pca954x_platform_data mux_data_0_7 = {
+ .modes = mux_modes_0_7,
+ .num_modes = 8,
+};
+
+static struct i2c_board_info i2c_device_info0[] __initdata = {
+// {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
+ {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
+ {"inv_cpld2", 0, 0x77, 0, 0, 0},//cpld2
+ {"pca9548", 0, 0x70, &mux_data_0, 0, 0},
+};
+
+static struct i2c_board_info i2c_device_info2[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
+};
+static struct i2c_board_info i2c_device_info3[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
+};
+static struct i2c_board_info i2c_device_info4[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
+};
+static struct i2c_board_info i2c_device_info5[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
+};
+static struct i2c_board_info i2c_device_info6[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0},
+};
+static struct i2c_board_info i2c_device_info7[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0},
+};
+static struct i2c_board_info i2c_device_info8[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0},
+};
+static struct i2c_board_info i2c_device_info9[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_7, 0, 0},
+};
+
+
+static struct inv_i2c_board_info i2cdev_list[] = {
+ {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0
+
+ {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0
+ {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1
+ {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2
+ {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3
+ {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4
+ {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5
+ {bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6
+ {bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux 7
+
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+#if 0
+static struct i2c_gpio_platform_data i2c_gpio_platdata0 = {
+ .scl_pin = 58,
+ .sda_pin = 75,
+
+ .udelay = 5, //5:100kHz
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0
+};
+
+static struct platform_device device_i2c_gpio0 = {
+ .name = "i2c-gpio",
+ .id = 1, // adapter number
+ .dev.platform_data = &i2c_gpio_platdata0,
+};
+#endif
+static int __init inv_platform_init(void)
+{
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *e = NULL;
+ int ret = 0;
+ int i,j,k;
+
+ printk("%s \n", __func__);
+
+#if 0
+ //use i2c-gpio
+ //register i2c gpio
+ //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5
+ outl( inl(0x533) | (1<<2), 0x533);
+ outl( inl(0x541) | (1<<3), 0x541);
+ outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69)
+ outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7)
+ outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15)
+ outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27)
+
+ ret = platform_device_register(&device_i2c_gpio0);
+ if (ret) {
+ printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret);
+ }
+#endif
+ for(i=0; i
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//=================================
+#include
+#include
+#include
+#include
+
+#define IPMI_MAX_INTF (4)
+#define NETFN_OEM 0x30
+#define CMD_GETDATA 0x31
+#define CMD_SETDATA 0x32
+#define FAN_NUM 4
+#define PSU_NUM 2
+
+#define PSU1 0x5800
+#define PSU2 0x5900
+#define BMC_PMBusNumber 3
+#define PMBus_Vender 0x99
+#define PMBus_Serial 0x9E
+#define PMBus_Temp2 0x8E
+#define PMBus_Version 0x9B
+#define MaxLeng_Result 0x20
+
+#define MAX_IPMI_RECV_LENGTH 0xff
+
+static long pmbus_reg2data_linear(int data, int linear16);
+struct ipmi_result{
+ char result[MAX_IPMI_RECV_LENGTH];
+ int result_length;
+};
+
+DEFINE_MUTEX(ipmi_mutex);
+DEFINE_MUTEX(ipmi2_mutex);
+static struct ipmi_result ipmiresult;
+static struct device *hwmon_dev;
+static struct kobject *device_kobj;
+static ipmi_user_t ipmi_mh_user = NULL;
+static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data);
+static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
+
+static atomic_t dummy_count = ATOMIC_INIT(0);
+static void dummy_smi_free(struct ipmi_smi_msg *msg)
+{
+ atomic_dec(&dummy_count);
+}
+static void dummy_recv_free(struct ipmi_recv_msg *msg)
+{
+ atomic_dec(&dummy_count);
+}
+static struct ipmi_smi_msg halt_smi_msg = {
+ .done = dummy_smi_free
+};
+static struct ipmi_recv_msg halt_recv_msg = {
+ .done = dummy_recv_free
+};
+
+struct __attribute__ ((__packed__)) psoc_psu_layout {
+ u16 psu1_iin;
+ u16 psu2_iin;
+ u16 psu1_iout;
+ u16 psu2_iout;
+
+ u16 psu1_pin;
+ u16 psu2_pin;
+ u16 psu1_pout;
+ u16 psu2_pout;
+
+ u16 psu1_vin;
+ u16 psu2_vin;
+ u16 psu1_vout;
+ u16 psu2_vout;
+};
+
+struct __attribute__ ((__packed__)) psoc_layout {
+ u8 ctl; //offset: 0
+ u16 switch_temp; //offset: 1
+ u8 reserve0; //offset: 3
+
+ u8 fw_upgrade; //offset: 4
+
+ //i2c bridge
+ u8 i2c_st; //offset: 5
+ u8 i2c_ctl; //offset: 6
+ u8 i2c_addr; //offset: 7
+ u8 i2c_data[0x20]; //offset: 8
+
+ //gpo
+ u8 led_ctl; //offset: 28
+
+ u8 gpio; //offset: 29
+
+ //pwm duty
+ u8 pwm[FAN_NUM]; //offset: 2a
+ u8 pwm_psu[PSU_NUM]; //offset: 2e
+
+ //fan rpm
+ u16 fan[FAN_NUM*2]; //offset: 30
+
+ u8 reserve1[4]; //offset: 40
+
+ //gpi
+ u8 gpi_fan; //offset: 44
+
+ //psu state
+ u8 psu_state; //offset: 45
+
+ //temperature
+ u16 temp[5]; //offset: 46
+ u16 temp_psu[PSU_NUM]; //offset: 50
+
+ //version
+ u8 version[2]; //offset: 54
+
+ u8 reserve2[4]; //offset: 56
+ struct psoc_psu_layout psu_info; //offset: 5a
+};
+
+/* definition */
+/* definition */
+#define PSOC_OFF(m) offsetof(struct psoc_layout, m)
+#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m)
+
+#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp)
+#define PWM_OFFSET PSOC_OFF(pwm)
+#define THERMAL_OFFSET PSOC_OFF(temp)
+#define RPM_OFFSET PSOC_OFF(fan)
+#define DIAG_FLAG_OFFSET PSOC_OFF(ctl)
+#define FAN_LED_OFFSET PSOC_OFF(led_ctl)
+#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan)
+#define PSOC_PSU_OFFSET PSOC_OFF(psu_state)
+#define VERSION_OFFSET PSOC_OFF(version)
+#define PSU_INFO_OFFSET PSOC_OFF(psu_info)
+
+
+static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data)
+{
+ struct ipmi_result *msg_result = recv_msg->user_msg_data;
+
+ if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) {
+ msg_result->result_length=recv_msg->msg.data_len-1;
+ memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1);
+ }
+ ipmi_free_recv_msg(recv_msg);
+ mutex_unlock(&ipmi_mutex);
+
+ return;
+}
+
+int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length)
+{
+ int rv=0,i;
+ int timeout;
+
+ //wait previous command finish at least 50msec
+ timeout=50;
+ while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); }
+ if(timeout==0) { return -1; }
+ mutex_lock(&ipmi_mutex);
+ mutex_lock(&ipmi2_mutex);
+
+ if(ipmi_mh_user == NULL) {
+ for (i=0,rv=1; i0) { usleep_range(1000,1100);}
+ if(timeout==0) {
+ mutex_unlock(&ipmi2_mutex);
+ return -1;
+ }
+ else {
+ *result_length=ipmiresult.result_length;
+ memcpy(result,ipmiresult.result,*result_length);
+ mutex_unlock(&ipmi2_mutex);
+ return 0;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(start_ipmi_command);
+
+static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count)
+{
+ uint8_t data[2];
+ int result_len=0;
+ int rv;
+
+ data[0] = offset;
+ data[1] = count;
+
+ rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len);
+
+ return result_len;
+}
+
+static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count)
+{
+ uint8_t data[count+1],result[1];
+ int result_len;
+
+ data[0] = offset;
+ memcpy(&data[1],buf,count);
+
+ start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len);
+ return count;
+}
+
+
+static u16 psoc_read16(u8 offset)
+{
+ u16 value = 0;
+ u8 buf[]={0,0};
+
+ if(psoc_ipmi_read(buf, offset, 2) == 2)
+ value = (buf[0]<<8 | buf[1]<<0);
+
+ return value;
+}
+
+static u8 psoc_read8(u8 offset)
+{
+ u8 value = 0;
+ u8 buf = 0;
+
+ if(psoc_ipmi_read(&buf, offset, 1) == 1)
+ value = buf;
+
+ return value;
+}
+
+/*
+CPLD report the PSU0 status
+000 = PSU normal operation
+100 = PSU fault
+010 = PSU unpowered
+111 = PSU not installed
+
+7 6 | 5 4 3 | 2 1 0
+----------------------
+ | psu1 | psu0
+*/
+static char* psu_str[] = {
+ "normal", //000
+ "NA", //001
+ "unpowered", //010
+ "NA", //011
+ "fault", //100
+ "NA", //101
+ "NA", //110
+ "not installed", //111
+};
+
+static ssize_t show_psu_st(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status=0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 byte=0;
+ int shift = (attr->index == 0)?3:0;
+
+ status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
+
+ return strlen(buf);
+}
+
+static ssize_t show_ipmi_pmbus(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ uint8_t data[4],result[MaxLeng_Result];
+ int result_len=0;
+
+ data[0] = BMC_PMBusNumber;
+ data[1] = (attr->index & 0xFF00 ) >>7;
+ data[3] = attr->index & 0xff;
+ if(data[3]==PMBus_Temp2)
+ {data[2]=2;}
+ else
+ {data[2]=MaxLeng_Result;}
+
+ if(start_ipmi_command(0x06, 0x52,data,4, result, &result_len)==0)
+ {
+ if(data[3]==PMBus_Temp2)
+ {
+ return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 ));
+ }
+ result[result[0]+1]='\0';
+ return sprintf(buf, "%s\n",&result[1] );
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static ssize_t show_thermal(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status=0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 offset = attr->index * 2 + THERMAL_OFFSET;
+
+ status = psoc_read16(offset);
+
+ return sprintf(buf, "%d\n",
+ (s8)(status>>8) * 1000 );
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status=0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 offset = attr->index + PWM_OFFSET;
+
+ status = psoc_read8(offset);
+
+ return sprintf(buf, "%d\n",
+ status);
+}
+
+static ssize_t set_pwm(struct device *dev,
+ struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 offset = attr->index + PWM_OFFSET;
+
+ u8 pwm = simple_strtol(buf, NULL, 10);
+ if(pwm > 255) pwm = 255;
+
+ psoc_ipmi_write(&pwm, offset, 1);
+
+ return count;
+}
+
+
+static ssize_t show_rpm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status=0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 offset = attr->index*2 + RPM_OFFSET;
+
+ status = psoc_read16(offset);
+
+ return sprintf(buf, "%d\n",
+ status);
+}
+
+static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status=0;
+ u16 temp = 0;
+
+ status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2);
+
+ status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 );
+
+ return strlen(buf);
+}
+
+static ssize_t set_switch_tmp(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ long temp = simple_strtol(buf, NULL, 10);
+ u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ;
+
+ //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF));
+ psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2);
+
+
+ return count;
+}
+
+static ssize_t show_diag(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status=0;
+ u8 diag_flag = 0;
+
+ status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1);
+
+ status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0));
+
+ return strlen(buf);
+}
+
+static ssize_t set_diag(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ u8 value = 0;
+ u8 diag = simple_strtol(buf, NULL, 10);
+
+ diag = diag?1:0;
+
+ psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1);
+ if(diag) value |= (1<<7);
+ else value &= ~(1<<7);
+ psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1);
+
+ return count;
+}
+
+static ssize_t show_version(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status=0;
+
+ status = psoc_read16(VERSION_OFFSET);
+
+ return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) );
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ return sprintf (buf, "inv_psoc\n");
+}
+
+
+static ssize_t show_fan_led(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status=0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 bit = attr->index;
+
+ status = psoc_read8(FAN_LED_OFFSET);
+
+ return sprintf(buf, "%d\n",
+ (status & (1<index;
+ u8 led_state = 0;
+
+ u8 v = simple_strtol(buf, NULL, 10);
+
+ led_state = psoc_read8(FAN_LED_OFFSET);
+ if(v) led_state |= (1<index;
+
+ status = psoc_read8(offset);
+
+ return sprintf(buf, "0x%02X\n", status );
+}
+
+static long pmbus_reg2data_linear(int data, int linear16)
+{
+ s16 exponent;
+ s32 mantissa;
+ long val;
+
+ if (linear16) { /* LINEAR16 */
+ exponent = -9;
+ mantissa = (u16) data;
+ } else { /* LINEAR11 */
+ exponent = ((s16)data) >> 11;
+ exponent = ((s16)( data & 0xF800) ) >> 11;
+ mantissa = ((s32)((data & 0x7ff) << 5)) >> 5;
+ }
+
+ //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa);
+ val = mantissa;
+
+ /* scale result to micro-units for power sensors */
+ val = val * 1000L;
+
+ if (exponent >= 0)
+ val <<= exponent;
+ else
+ val >>= -exponent;
+
+ return val;
+}
+
+static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status=0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ u8 offset = attr->index + PSU_INFO_OFFSET;
+
+ status = psoc_read16(offset);
+
+ return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 ));
+}
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4);
+static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5);
+static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3);
+static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4);
+static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5);
+
+static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0);
+static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7);
+static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8);
+static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9);
+
+static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
+
+static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0);
+static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0);
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+
+static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0);
+static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1);
+static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2);
+static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3);
+static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4);
+static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5);
+static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6);
+static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7);
+
+static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET);
+static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout));
+static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout));
+static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout));
+
+
+static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout));
+static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout));
+static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout));
+
+//IPMI
+static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2);
+static SENSOR_DEVICE_ATTR(psoc_psu1_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vender);
+static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial);
+static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version);
+
+static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2);
+static SENSOR_DEVICE_ATTR(psoc_psu2_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vender);
+static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial);
+static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version);
+
+
+static struct attribute *psoc_attributes[] = {
+ //thermal
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp4_input.dev_attr.attr,
+ &sensor_dev_attr_temp5_input.dev_attr.attr,
+
+ &sensor_dev_attr_thermal_psu1.dev_attr.attr,
+ &sensor_dev_attr_thermal_psu2.dev_attr.attr,
+
+
+ //pwm
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm4.dev_attr.attr,
+ &sensor_dev_attr_pwm_psu1.dev_attr.attr,
+ &sensor_dev_attr_pwm_psu2.dev_attr.attr,
+
+ //rpm
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan5_input.dev_attr.attr,
+ &sensor_dev_attr_fan6_input.dev_attr.attr,
+ &sensor_dev_attr_fan7_input.dev_attr.attr,
+ &sensor_dev_attr_fan8_input.dev_attr.attr,
+
+ &sensor_dev_attr_rpm_psu1.dev_attr.attr,
+ &sensor_dev_attr_rpm_psu2.dev_attr.attr,
+
+ //switch temperature
+ &sensor_dev_attr_switch_tmp.dev_attr.attr,
+
+ //diag flag
+ &sensor_dev_attr_diag.dev_attr.attr,
+
+ //version
+ &sensor_dev_attr_version.dev_attr.attr,
+
+ //fan led
+ &sensor_dev_attr_fan_led_grn1.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn2.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn3.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn4.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red1.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red2.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red3.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red4.dev_attr.attr,
+
+ //fan GPI
+ &sensor_dev_attr_fan_gpi.dev_attr.attr,
+ &sensor_dev_attr_psu0.dev_attr.attr,
+ &sensor_dev_attr_psu1.dev_attr.attr,
+
+
+ //psu_psoc
+ &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr,
+
+ //ipmi_i2c_command
+ &sensor_dev_attr_thermal2_psu1.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_vender.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_serial.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_version.dev_attr.attr,
+
+ &sensor_dev_attr_thermal2_psu2.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vender.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_version.dev_attr.attr,
+
+ &sensor_dev_attr_name.dev_attr.attr,
+
+ NULL
+};
+
+static const struct attribute_group psoc_group = {
+ .attrs = psoc_attributes,
+};
+
+static int __init inv_psoc_init(void)
+{
+ int ret;
+
+ printk("+%s\n", __func__);
+
+ hwmon_dev = hwmon_device_register(NULL);
+ if (IS_ERR(hwmon_dev)) {
+ goto fail_hwmon_device_register;
+ }
+
+ device_kobj = kobject_create_and_add("device", &hwmon_dev->kobj);
+ if(!device_kobj) {
+ goto fail_hwmon_device_register;
+ }
+
+ ret = sysfs_create_group(device_kobj, &psoc_group);
+ if (ret) {
+ goto fail_create_group_hwmon;
+ }
+
+ printk(" Enable IPMI PSoC protocol.\n");
+ return ret;
+
+fail_create_group_hwmon:
+ hwmon_device_unregister(hwmon_dev);
+fail_hwmon_device_register:
+ return -ENOMEM;
+}
+
+static void __exit inv_psoc_exit(void)
+{
+ if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);}
+ if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev);
+ sysfs_remove_group(device_kobj, &psoc_group);
+}
+
+MODULE_AUTHOR("Ting.Jack ");
+MODULE_DESCRIPTION("inv psoc driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_psoc_init);
+module_exit(inv_psoc_exit);
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c
new file mode 100644
index 000000000000..58c1a0aeb048
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c
@@ -0,0 +1,719 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "inv_swps.h"
+
+static int port_major;
+static int ioexp_total;
+static int port_total;
+static struct class *swp_class_p = NULL;
+static struct inv_platform_s *platform_p = NULL;
+static struct inv_ioexp_layout_s *ioexp_layout = NULL;
+static struct inv_port_layout_s *port_layout = NULL;
+
+static int
+__swp_match(struct device *dev,const void *data){
+
+ char *name = (char *)data;
+ if (strcmp(dev_name(dev), name) == 0)
+ return 1;
+ return 0;
+}
+
+
+struct device *
+get_swpdev_by_name(char *name){
+ struct device *dev = class_find_device(swp_class_p,
+ NULL,
+ name,
+ (const void *)__swp_match);
+ return dev;
+}
+
+
+static int
+sscanf_2_int(const char *buf) {
+
+ int result = -EBFONT;
+ char *hex_tag = "0x";
+
+ if (strcspn(buf, hex_tag) == 0) {
+ if (sscanf(buf,"%x",&result)) {
+ return result;
+ }
+ } else {
+ if (sscanf(buf,"%d",&result)) {
+ return result;
+ }
+ if(sscanf(buf,"-%d",&result)) {
+ return -result;
+ }
+ if (sscanf(buf,"%x",&result)) {
+ return result;
+ }
+ }
+ return -EBFONT;
+}
+
+
+static int
+sscanf_2_binary(const char *buf) {
+
+ int result = sscanf_2_int(buf);
+
+ if (result < 0){
+ return -EBFONT;
+ }
+ switch (result) {
+ case 0:
+ case 1:
+ return result;
+ default:
+ break;
+ }
+ return -EBFONT;
+}
+
+/* ========== Show functions: For I/O Expander attribute ==========
+ */
+static ssize_t
+_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+ int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset),
+ char *buf_p) {
+ size_t len;
+ struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name);
+ return -ENODATA;
+ }
+ mutex_lock(&ioexp_p->lock);
+ len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset));
+ mutex_unlock(&ioexp_p->lock);
+ return len;
+}
+
+
+static ssize_t
+show_attr_present(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_present,
+ buf_p);
+}
+
+static ssize_t
+show_attr_tx_fault(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_tx_fault,
+ buf_p);
+}
+
+static ssize_t
+show_attr_rxlos(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_rxlos,
+ buf_p);
+}
+
+static ssize_t
+show_attr_tx_disable(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_tx_disable,
+ buf_p);
+}
+
+static ssize_t
+show_attr_reset(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_reset,
+ buf_p);
+}
+
+static ssize_t
+show_attr_lpmod(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_lpmod,
+ buf_p);
+}
+
+
+static ssize_t
+show_attr_modsel(struct device *dev_p,
+ struct device_attribute *attr_p,
+ char *buf_p){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p){
+ return -ENODEV;
+ }
+ return _show_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->get_modsel,
+ buf_p);
+}
+
+/* ========== Store functions: For I/O Expander (R/W) attribute ==========
+ */
+static ssize_t
+_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+ int (*set_func)(struct ioexp_obj_s *ioexp_p,
+ int virt_offset, int input_val),
+ const char *buf_p,
+ size_t count) {
+
+ int input, err;
+ struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ SWPS_ERR("%s: data corruption! :%s\n",
+ __func__, tobj_p->swp_name);
+ return -ENODATA;
+ }
+ input = sscanf_2_binary(buf_p);
+ if (input < 0) {
+ return -EBFONT;
+ }
+ mutex_lock(&ioexp_p->lock);
+ err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input);
+ mutex_unlock(&ioexp_p->lock);
+ if (err < 0){
+ return err;
+ }
+ return count;
+}
+
+static ssize_t
+store_attr_tx_disable(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_tx_disable,
+ buf_p,
+ count);
+}
+
+static ssize_t
+store_attr_reset(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_reset,
+ buf_p,
+ count);
+}
+
+
+static ssize_t
+store_attr_lpmod(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_lpmod,
+ buf_p,
+ count);
+}
+
+
+static ssize_t
+store_attr_modsel(struct device *dev_p,
+ struct device_attribute *attr_p,
+ const char *buf_p,
+ size_t count){
+
+ struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+ if (!tobj_p) {
+ return -ENODEV;
+ }
+ return _store_ioexp_binary_attr(tobj_p,
+ tobj_p->ioexp_obj_p->set_modsel,
+ buf_p,
+ count);
+}
+
+/* ========== IO Expander attribute: from expander ==========
+ */
+static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL);
+static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL);
+static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL);
+static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable);
+static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset);
+static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod);
+static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel);
+
+/* ========== Functions for module handling ==========
+ */
+static void
+clean_port_obj(void){
+
+ dev_t dev_num;
+ char dev_name[32];
+ struct device *device_p;
+ struct transvr_obj_s *transvr_obj_p;
+ int minor_curr, port_id;
+
+ for (minor_curr=0; minor_curri2c_client_p);
+ kfree(transvr_obj_p);
+ }
+ dev_num = MKDEV(port_major, minor_curr);
+ device_unregister(device_p);
+ device_destroy(swp_class_p, dev_num);
+ }
+ SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+static int
+get_platform_type(void){
+
+ char log_msg[64] = "ERROR";
+
+ platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL);
+ if (!platform_p){
+ snprintf(log_msg, sizeof(log_msg), "kzalloc fail");
+ goto err_get_platform_type_1;
+ }
+ platform_p->id = PLATFORM_SETTINGS;
+ memset(platform_p->name, 0, sizeof(platform_p->name));
+ snprintf(platform_p->name, (sizeof(platform_p->name) - 1),
+ "%s", platform_map.name);
+ snprintf(log_msg, sizeof(log_msg),
+ "User setup platform: %d (%s)",
+ platform_p->id, platform_p->name);
+ SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+ return 0;
+
+err_get_platform_type_1:
+ SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+ return -1;
+}
+
+
+static int
+get_layout_info(void){
+ ioexp_layout = secquoia_ioexp_layout;
+ port_layout = secquoia_port_layout;
+ ioexp_total = ARRAY_SIZE(secquoia_ioexp_layout);
+ port_total = ARRAY_SIZE(secquoia_port_layout);
+
+ SWPS_INFO("Start to initial platform: %d (%s)\n",
+ platform_p->id, platform_p->name);
+ return 0;
+}
+
+/* ========== Functions for register something ==========
+ */
+
+static int
+register_ioexp_attr_sfp_1(struct device *device_p){
+ /* Support machine type:
+ * - SFP : Magnolia
+ */
+ char *err_attr = NULL;
+
+ if (device_create_file(device_p, &dev_attr_present) < 0) {
+ err_attr = "dev_attr_present";
+ goto err_ioexp_sfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_tx_fault) < 0) {
+ err_attr = "dev_attr_tx_fault";
+ goto err_ioexp_sfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_rxlos) < 0) {
+ err_attr = "dev_attr_rxlos";
+ goto err_ioexp_sfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_tx_disable) < 0) {
+ err_attr = "dev_attr_tx_disable";
+ goto err_ioexp_sfp1_attr;
+ }
+ return 0;
+
+err_ioexp_sfp1_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr_sfp_2(struct device *device_p){
+ /* Support machine type:
+ * - SFP28 : Cypress
+ */
+ char *err_attr = NULL;
+
+ if (register_ioexp_attr_sfp_1(device_p) < 0){
+ goto err_ioexp_sfp2_attr;
+ }
+ return 0;
+
+err_ioexp_sfp2_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr_qsfp_1(struct device *device_p){
+ /* Support machine type:
+ * - QSFP : Magnolia, Redwood, Hudson32i
+ * - QSFP+ : Magnolia, Redwood, Hudson32i
+ * - QSFP28: Redwood
+ */
+ char *err_attr = NULL;
+
+ if (device_create_file(device_p, &dev_attr_present) < 0) {
+ err_attr = "dev_attr_present";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_reset) < 0) {
+ err_attr = "dev_attr_reset";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_lpmod) < 0) {
+ err_attr = "dev_attr_lpmod";
+ goto err_ioexp_qsfp1_attr;
+ }
+ if (device_create_file(device_p, &dev_attr_modsel) < 0) {
+ err_attr = "dev_attr_modsel";
+ goto err_ioexp_qsfp1_attr;
+ }
+ return 0;
+
+err_ioexp_qsfp1_attr:
+ SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+ return -1;
+}
+
+static int
+register_ioexp_attr(struct device *device_p,
+ struct transvr_obj_s *transvr_obj){
+
+ char *err_msg = "ERR";
+
+ switch (transvr_obj->ioexp_obj_p->ioexp_type){
+ case IOEXP_TYPE_SEQUOIA_NABC:
+ if (register_ioexp_attr_qsfp_1(device_p) < 0){
+ err_msg = "register_ioexp_attr_qsfp_1 fail";
+ goto err_reg_ioexp_attr;
+ }
+
+ break;
+
+ default:
+ err_msg = "Unknow type";
+ goto err_reg_ioexp_attr;
+ }
+ return 0;
+
+err_reg_ioexp_attr:
+ SWPS_ERR("%s: %s :%d \n",
+ __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type);
+ return -1;
+}
+
+
+static int
+register_port_device(char *dev_name,
+ dev_t dev_num,
+ struct transvr_obj_s *transvr_obj){
+
+ struct device *device_p = NULL;
+ device_p = device_create(swp_class_p, /* struct class *cls */
+ NULL, /* struct device *parent */
+ dev_num, /* dev_t devt */
+ transvr_obj, /* void *private_data */
+ dev_name); /* const char *fmt */
+ if (IS_ERR(device_p)){
+ goto err_regswp_create_dev;
+ }
+ if (register_ioexp_attr(device_p, transvr_obj) < 0){
+ goto err_regswp_reg_attr;
+ }
+ return 0;
+
+err_regswp_reg_attr:
+ device_unregister(device_p);
+ device_destroy(swp_class_p, dev_num);
+err_regswp_create_dev:
+ SWPS_ERR("%s fail! :%s\n", __func__, dev_name);
+ return -1;
+}
+
+
+static int
+register_swp_module(void){
+
+ dev_t port_devt = 0;
+ int dev_total = port_total + 1; /* char_dev for module control */
+
+ if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){
+ SWPS_WARN("Allocate PORT MAJOR failure! \n");
+ goto err_register_swp_module_3;
+ }
+ port_major = MAJOR(port_devt);
+
+ /* Create class object */
+ swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME);
+ if (IS_ERR(swp_class_p)) {
+ SWPS_ERR("Create class failure! \n");
+ goto err_register_swp_module_3;
+ }
+ return 0;
+
+err_register_swp_module_3:
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+ return -1;
+}
+
+
+/* ========== Module initial relate ==========
+ */
+static int
+create_ioexp_objs(void) {
+
+ int i, run_mod;
+
+ /* Clean IOEXP object */
+ clean_ioexp_objs();
+ /* Get running mode */
+ run_mod = IOEXP_MODE_DIRECT;
+ /* Create IOEXP object */
+ for(i=0; i devlen_max) {
+ snprintf(err_msg, sizeof(err_msg),
+ "SWP_DEV_PORT too long!");
+ goto err_initport_create_tranobj;
+ }
+ memset(dev_name, 0, sizeof(dev_name));
+ snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id);
+ /* Create transceiver object */
+ ioexp_obj_p = get_ioexp_obj(ioexp_id);
+ if (!ioexp_obj_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "IOEXP object:%d not exist", ioexp_id);
+ goto err_initport_create_tranobj;
+ }
+ transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p,
+ ioexp_virt_offset, transvr_type,
+ chipset_type, run_mod);
+ if (!transvr_obj_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "Create transceiver object fail :%s", dev_name);
+ goto err_initport_create_tranobj;
+ }
+ /* Setup Lane_ID mapping */
+ i = ARRAY_SIZE(port_layout[minor_curr].lane_id);
+ j = ARRAY_SIZE(transvr_obj_p->lane_id);
+ if (i != j) {
+ snprintf(err_msg, sizeof(err_msg),
+ "Lane_id size inconsistent %d/%d", i, j);
+ goto err_initport_reg_device;
+ }
+ memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int));
+ /* Create and register device object */
+ if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){
+ snprintf(err_msg, sizeof(err_msg),
+ "register_port_device fail");
+ goto err_initport_reg_device;
+ }
+ /* Setup device_ptr of transvr_obj */
+ dev_p = get_swpdev_by_name(dev_name);
+ if (!dev_p){
+ snprintf(err_msg, sizeof(err_msg),
+ "get_swpdev_by_name fail");
+ goto err_initport_reg_device;
+ }
+ transvr_obj_p->transvr_dev_p = dev_p;
+ /* Success */
+ ok_count++;
+ }
+ SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count);
+ return 0;
+
+err_initport_reg_device:
+ kfree(transvr_obj_p);
+err_initport_create_tranobj:
+ clean_port_obj();
+ SWPS_ERR("%s: %s", __func__, err_msg);
+ SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n",
+ port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod);
+ return -1;
+}
+
+static int __init
+swp_module_init(void){
+
+ if (get_platform_type() < 0){
+ goto err_init_out;
+ }
+ if (get_layout_info() < 0){
+ goto err_init_out;
+ }
+ if (register_swp_module() < 0){
+ goto err_init_out;
+ }
+ if (create_ioexp_objs() < 0){
+ goto err_init_ioexp;
+ }
+ if (create_port_objs() < 0){
+ goto err_init_portobj;
+ }
+ if (init_ioexp_objs() < 0){
+ goto err_init_portobj;
+ }
+ SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION);
+ return 0;
+
+
+err_init_portobj:
+ clean_ioexp_objs();
+err_init_ioexp:
+ class_unregister(swp_class_p);
+ class_destroy(swp_class_p);
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+err_init_out:
+ SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION);
+ return -1;
+}
+
+
+static void __exit
+swp_module_exit(void){
+ clean_port_obj();
+ clean_ioexp_objs();
+ class_unregister(swp_class_p);
+ class_destroy(swp_class_p);
+ unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+ SWPS_INFO("Remove Inventec switch-port module success.\n");
+}
+
+
+/* Module information */
+MODULE_AUTHOR(SWP_AUTHOR);
+MODULE_DESCRIPTION(SWP_DESC);
+MODULE_VERSION(SWP_VERSION);
+MODULE_LICENSE(SWP_LICENSE);
+
+module_init(swp_module_init);
+module_exit(swp_module_exit);
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h
new file mode 100644
index 000000000000..3d462ed3c944
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h
@@ -0,0 +1,184 @@
+#ifndef INV_SWPS_H
+#define INV_SWPS_H
+
+#include "transceiver.h"
+#include "io_expander.h"
+
+/* Module settings */
+#define SWP_CLS_NAME "swps"
+#define SWP_DEV_PORT "port"
+#define SWP_DEV_MODCTL "module"
+#define SWP_RESET_PWD "inventec"
+#define SWP_POLLING_PERIOD (300) /* msec */
+#define SWP_POLLING_ENABLE (1)
+#define SWP_AUTOCONFIG_ENABLE (1)
+
+/* Module information */
+#define SWP_AUTHOR "Neil "
+#define SWP_DESC "Inventec port and transceiver driver"
+#define SWP_VERSION "4.2.5"
+#define SWP_LICENSE "GPL"
+
+/* Module status define */
+#define SWP_STATE_NORMAL (0)
+#define SWP_STATE_I2C_DIE (-91)
+
+/* [Note]:
+ * Functions and mechanism for auto-detect platform type is ready,
+ * But HW and BIOS not ready! We need to wait them.
+ * So, please do not use PLATFORM_TYPE_AUTO until they are ready.
+ * (2016.06.13)
+ */
+#define PLATFORM_TYPE_SEQUOIA_GA (171)
+/* Current running platfrom */
+#define PLATFORM_SETTINGS PLATFORM_TYPE_SEQUOIA_GA
+
+/* Define platform flag and kernel version */
+#if (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA)
+ #define SWPS_SEQUOIA (1)
+ #define SWPS_KERN_VER_BF_3_8 (1)
+#endif
+
+
+struct inv_platform_s {
+ int id;
+ char name[64];
+};
+
+struct inv_ioexp_layout_s {
+ int ioexp_id;
+ int ioexp_type;
+ struct ioexp_addr_s addr[4];
+};
+
+struct inv_port_layout_s {
+ int port_id;
+ int chan_id;
+ int ioexp_id;
+ int ioexp_offset;
+ int transvr_type;
+ int chipset_type;
+ int lane_id[8];
+};
+
+
+/* ==========================================
+ * Inventec Platform Settings
+ * ==========================================
+ */
+struct inv_platform_s platform_map = {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" };
+
+/* ==========================================
+ * Sequoia Layout configuration
+ * ==========================================
+ */
+
+struct inv_ioexp_layout_s secquoia_ioexp_layout[] = {
+ /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+ {0, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */
+ {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */
+ {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */
+ },
+ {1, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */
+ {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */
+ {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */
+ },
+ {2, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */
+ {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */
+ {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */
+ },
+ {3, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */
+ {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */
+ {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */
+ },
+ {4, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */
+ {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */
+ {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */
+ },
+ {5, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */
+ {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */
+ {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */
+ },
+ {6, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */
+ {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */
+ {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */
+ },
+ {7, IOEXP_TYPE_SEQUOIA_NABC, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */
+ {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */
+ {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+ },
+};
+
+
+struct inv_port_layout_s secquoia_port_layout[] = {
+ /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+ { 0, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} },
+ { 1, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} },
+ { 2, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
+ { 3, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
+ { 4, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
+ { 5, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
+ { 6, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
+ { 7, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
+ { 8, 18, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
+ { 9, 19, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
+ {10, 20, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
+ {11, 21, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
+ {12, 22, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} },
+ {13, 23, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} },
+ {14, 24, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} },
+ {15, 25, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} },
+ {16, 26, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} },
+ {17, 27, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} },
+ {18, 28, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} },
+ {19, 29, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} },
+ {20, 30, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} },
+ {21, 31, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} },
+ {22, 32, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} },
+ {23, 33, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} },
+ {24, 34, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} },
+ {25, 35, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} },
+ {26, 36, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} },
+ {27, 37, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} },
+ {28, 38, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} },
+ {29, 39, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} },
+ {30, 40, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} },
+ {31, 41, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} },
+ {32, 45, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
+ {33, 44, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} },
+ {34, 43, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
+ {35, 42, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
+ {36, 49, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
+ {37, 48, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
+ {38, 47, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
+ {39, 46, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
+ {40, 53, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
+ {41, 52, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
+ {42, 51, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
+ {43, 50, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+ {44, 57, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} },
+ {45, 56, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} },
+ {46, 55, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} },
+ {47, 54, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} },
+ {48, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} },
+ {49, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} },
+ {50, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} },
+ {51, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} },
+ {52, 65, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} },
+ {53, 64, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} },
+ {54, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} },
+ {55, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} },
+ {56, 69, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} },
+ {57, 68, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} },
+ {58, 67, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} },
+ {59, 66, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} },
+ {60, 73, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} },
+ {61, 72, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} },
+ {62, 71, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} },
+ {63, 70, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} },
+};
+
+
+#endif /* INV_SWPS_H */
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c
new file mode 100644
index 000000000000..231884f3e442
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c
@@ -0,0 +1,1786 @@
+#include
+#include
+#include "io_expander.h"
+
+static struct ioexp_obj_s *ioexp_head_p = NULL;
+static struct ioexp_obj_s *ioexp_tail_p = NULL;
+
+
+/* ========== Register IOEXP layout ==========
+ */
+struct ioexp_map_s ioexp_map_magnolia_nab = {
+
+ .chip_amount = 2,
+ .data_width = 2,
+
+ .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */
+ {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+ {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+ {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+ {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+ {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+ {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+ {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+ },
+ .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */
+ {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+ {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+ {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+ {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+ {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+ {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+ {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+ },
+ .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */
+ {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+ {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+ {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+ {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+ {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+ {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+ {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_magnolia_7ab = {
+
+ .chip_amount = 2,
+ .data_width = 2,
+
+ .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */
+ {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */
+ {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+ {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+ {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+ {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+ {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+ {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+ {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+ {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+ {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */
+ {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */
+ {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */
+ {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */
+ {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */
+ {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */
+ {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */
+ {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */
+ {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */
+ {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */
+ {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */
+ {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */
+ {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */
+ {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */
+ {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */
+ {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */
+ {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */
+ {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */
+ {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */
+ {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */
+ {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */
+ {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */
+ {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */
+ },
+ .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */
+ {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */
+ {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */
+ {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */
+ },
+ .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */
+ {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */
+ {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */
+ {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */
+ {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */
+ {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_cypress_nabc = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */
+ {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+ {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+ {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+ {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+ {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+ {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+ {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+ },
+ .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */
+ {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+ {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+ {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+ {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+ {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+ {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+ {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+ },
+ .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */
+ {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+ {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+ {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+ {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+ {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+ {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+ {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+ },
+ .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */
+ {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */
+ {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */
+ {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */
+ {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */
+ {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */
+ {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */
+ {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */
+ },
+ .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */
+ {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */
+ {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */
+ {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */
+ {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */
+ {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */
+ {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */
+ {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_cypress_7abc = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ },
+ .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */
+ {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+ {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+ {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */
+ {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */
+ {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */
+ },
+ .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */
+ {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+ {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+ {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */
+ {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */
+ {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */
+ },
+ .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */
+ {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+ {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+ {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */
+ {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */
+ {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_tahoe_5a = {
+
+ .chip_amount = 1,
+ .data_width = 2,
+
+ .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ },
+ .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */
+ {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+ {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+ },
+ .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */
+ {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+ {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+ },
+ .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */
+ {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+ {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_tahoe_6abc = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */
+ },
+ .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */
+ {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+ {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+ {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+ {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+ {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+ {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+ {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ },
+ .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */
+ {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+ {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+ {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+ {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+ {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+ {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+ {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+ {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */
+ },
+ .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */
+ {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+ {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+ {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+ {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+ {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+ {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+ {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ },
+};
+
+
+struct ioexp_map_s ioexp_map_sequoia_nabc = {
+
+ .chip_amount = 3,
+ .data_width = 2,
+
+ .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */
+ {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+ {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+ {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+ {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+ {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+ {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+ {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+ },
+ .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */
+ {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+ {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+ {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+ {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+ {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+ {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+ {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+ },
+ .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */
+ {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+ {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+ {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+ {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+ {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+ {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+ {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+ },
+ .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */
+ {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+ {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+ {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+ {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+ {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+ {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+ {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+ },
+};
+
+
+/* ========== Private functions ==========
+ */
+int check_channel_tier_1(void);
+
+struct i2c_client *
+_get_i2c_client(struct ioexp_obj_s *self,
+ int chip_id){
+
+ struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p;
+
+ if (!(i2c_curr_p)){
+ SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__);
+ return NULL;
+ }
+ while (i2c_curr_p){
+ if ((i2c_curr_p->chip_id) == chip_id){
+ return i2c_curr_p->i2c_client_p;
+ }
+ i2c_curr_p = i2c_curr_p->next;
+ }
+ SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id);
+ return NULL;
+}
+
+
+static int
+_common_ioexp_update_one(struct ioexp_obj_s *self,
+ struct ioexp_addr_s *ioexp_addr,
+ int chip_id,
+ int data_width,
+ int show_err,
+ char *caller_name) {
+ int buf = 0;
+ int err = 0;
+ int data_id = 0;
+ int r_offset = 0;
+
+ for(data_id=0; data_idread_offset[data_id];
+ buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset);
+ /* Check error */
+ if (buf < 0) {
+ err = 1;
+ if (show_err) {
+ SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf);
+ SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n",
+ ioexp_addr->chan_id, ioexp_addr->chip_addr,
+ ioexp_addr->read_offset[data_id], caller_name);
+ }
+ continue;
+ }
+ /* Update IOEXP object */
+ self->chip_data[chip_id].data[data_id] = (uint8_t)buf;
+ }
+ if (err) {
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+static int
+common_ioexp_update_all(struct ioexp_obj_s *self,
+ int show_err,
+ char *caller_name){
+
+ int err = 0;
+ int chip_id = 0;
+ int chip_amount = self->ioexp_map_p->chip_amount;
+
+ for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]),
+ chip_id,
+ self->ioexp_map_p->data_width,
+ show_err,
+ caller_name) < 0) {
+ err = 1;
+ }
+ }
+ if (err) {
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+static int
+_common_check_by_mode(struct ioexp_obj_s *self){
+
+ switch (self->mode){
+ case IOEXP_MODE_DIRECT:
+ return self->fsm_4_direct(self);
+
+ case IOEXP_MODE_POLLING:
+ if (self->state >= 0){
+ return 0;
+ }
+ switch (self->state){
+ case STATE_IOEXP_INIT:
+ return ERR_IOEXP_UNINIT;
+ case STATE_IOEXP_ABNORMAL:
+ return ERR_IOEXP_ABNORMAL;
+ default:
+ return ERR_IOEXP_NOSTATE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+_common_get_bit(struct ioexp_obj_s *self,
+ struct ioexp_bitmap_s *bitmap_obj_p,
+ char *func_mane){
+ uint8_t buf;
+ int err_code;
+
+ /* Check and get address */
+ err_code = _common_check_by_mode(self);
+ if (err_code < 0){
+ return err_code;
+ }
+ if (!bitmap_obj_p){
+ SWPS_ERR("Layout config incorrect! :%d :%s\n",
+ self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADCONF;
+ }
+ /* Get data form cache */
+ buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+ return (int)(buf >> bitmap_obj_p->bit_shift & 0x01);
+}
+
+
+static int
+_common_set_bit(struct ioexp_obj_s *self,
+ struct ioexp_bitmap_s *bitmap_obj_p,
+ int input_val,
+ char *func_mane){
+ int err_code, target_offset;
+ uint8_t origin_byte;
+ uint8_t modify_byte;
+
+ /* Check and get address */
+ err_code = _common_check_by_mode(self);
+ if (err_code < 0){
+ return err_code;
+ }
+ if (!bitmap_obj_p){
+ SWPS_ERR("Layout config incorrect! :%d :%s\n",
+ self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADCONF;
+ }
+ /* Prepare write date */
+ origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+ switch (input_val) {
+ case 0:
+ modify_byte = origin_byte;
+ SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift);
+ break;
+ case 1:
+ modify_byte = origin_byte;
+ SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift);
+ break;
+ default:
+ SWPS_ERR("Input value incorrect! :%d :%d :%s\n",
+ input_val, self->ioexp_id, func_mane);
+ return ERR_IOEXP_BADINPUT;
+ }
+ /* Setup i2c client */
+ target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset];
+ /* Write byte to chip via I2C */
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id),
+ target_offset,
+ modify_byte);
+ /* Update or bollback object */
+ if (err_code < 0){
+ self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte;
+ SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n",
+ input_val, self->ioexp_id, func_mane, err_code);
+ return err_code;
+ }
+ self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte;
+ return 0;
+}
+
+
+/* ========== Object public functions ==========
+ */
+int
+common_get_present(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ int UNPLUG = 1;
+ int retval = ERR_IOEXP_UNEXCPT;
+
+ retval = _common_get_bit(self,
+ &(self->ioexp_map_p->map_present[virt_offset]),
+ "common_get_present");
+ if (retval < 0) {
+ /* [Note]
+ * => Transceiver object does not need to handle IOEXP layer issues.
+ */
+ return UNPLUG;
+ }
+ return retval;
+}
+
+
+int
+common_get_tx_fault(struct ioexp_obj_s *self,
+ int virt_offset){
+ /* [Transmit Fault (Tx_Fault)]
+ * A catastrophic laser fault will activate the transmitter signal,
+ * TX_FAULT, and disable the laser. This signal is an open collector
+ * output (pull-up required on the host board). A low signal indicates
+ * normal laser operation and a high signal indicates a fault. The
+ * TX_FAULT will be latched high when a laser fault occurs and is
+ * cleared by toggling the TX_DISABLE input or power cycling the
+ * transceiver. The transmitter fault condition can also be monitored
+ * via the two-wire serial interface.
+ * (address A2, byte 110, bit 2).
+ *
+ * 0: Normal
+ * 1: Abnormal
+ */
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_tx_fault[virt_offset]),
+ "common_get_tx_fault");
+}
+
+
+int
+common_get_rxlos(struct ioexp_obj_s *self,
+ int virt_offset){
+ /* [Receiver Loss of Signal (Rx_LOS)]
+ * The post-amplification IC also includes transition detection circuitry
+ * which monitors the ac level of incoming optical signals and provides a
+ * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical
+ * input results in a low Rx_LOS output while a high Rx_LOS output indicates
+ * an unusable optical input. The Rx_LOS thresholds are factory set so that
+ * a high output indicates a definite optical fault has occurred. Rx_LOS can
+ * also be monitored via the two-wire serial interface
+ * (address A2h, byte 110, bit 1).
+ *
+ * 0: Normal
+ * 1: Abnormal
+ */
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_rxlos[virt_offset]),
+ "common_get_rxlos");
+}
+
+
+int
+common_get_tx_disable(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_tx_disable[virt_offset]),
+ "common_get_tx_disable");
+}
+
+
+int
+common_get_reset(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_reset[virt_offset]),
+ "common_get_reset");
+}
+
+
+int
+common_get_lpmod(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_lpmod[virt_offset]),
+ "common_get_lpmod");
+}
+
+
+int
+common_get_modsel(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_modsel[virt_offset]),
+ "common_get_modsel");
+}
+
+
+int
+common_get_hard_rs0(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_hard_rs0[virt_offset]),
+ "common_get_hard_rs0");
+}
+
+
+int
+common_get_hard_rs1(struct ioexp_obj_s *self,
+ int virt_offset){
+
+ return _common_get_bit(self,
+ &(self->ioexp_map_p->map_hard_rs1[virt_offset]),
+ "common_get_hard_rs1");
+}
+
+
+int
+common_set_tx_disable(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_tx_disable[virt_offset]),
+ input_val,
+ "common_set_tx_disable");
+}
+
+
+int
+common_set_reset(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_reset[virt_offset]),
+ input_val,
+ "common_set_reset");
+}
+
+
+int
+common_set_lpmod(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_lpmod[virt_offset]),
+ input_val,
+ "common_set_lpmod");
+}
+
+
+int
+common_set_modsel(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_modsel[virt_offset]),
+ input_val,
+ "common_set_modsel");
+}
+
+
+int
+common_set_hard_rs0(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_hard_rs0[virt_offset]),
+ input_val,
+ "common_set_hard_rs0");
+}
+
+
+int
+common_set_hard_rs1(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+
+ return _common_set_bit(self,
+ &(self->ioexp_map_p->map_hard_rs1[virt_offset]),
+ input_val,
+ "common_set_hard_rs1");
+}
+
+
+int
+ioexp_get_not_support(struct ioexp_obj_s *self,
+ int virt_offset){
+ return ERR_IOEXP_NOTSUPPORT;
+}
+
+
+int
+ioexp_set_not_support(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+ return ERR_IOEXP_NOTSUPPORT;
+}
+
+
+int
+fake_ioexp_init(struct ioexp_obj_s *self){
+ return 1;
+}
+
+int
+fake_ioexp_update(struct ioexp_obj_s *self){
+ return 1;
+}
+
+
+int
+fake_update_func(struct ioexp_obj_s *self){
+ return 1;
+}
+
+int
+fake_get_func(struct ioexp_obj_s *self,
+ int virt_offset){
+ SWPS_WARN("Someone called fake_get_func\n");
+ return -1;
+}
+
+int
+fake_set_func(struct ioexp_obj_s *self,
+ int virt_offset,
+ int input_val){
+ SWPS_WARN("Someone called fake_set_func\n");
+ return -1;
+}
+
+
+/* ========== Initial functions for IO Expander ==========
+ */
+int
+common_ioexp_init(struct ioexp_obj_s *self) {
+
+ int chip_id, offset, err_code;
+ struct ioexp_addr_s *addr_p;
+
+ /* Setup default value to each physical IO Expander */
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ /* Get address mapping */
+ addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!addr_p){
+ SWPS_ERR("%s: IOEXP config incorrect! :%d \n",
+ __func__, chip_id);
+ return -1;
+ }
+ /* Setup default value */
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+ addr_p->write_offset[offset],
+ addr_p->data_default[offset]);
+ if (err_code < 0){
+ SWPS_ERR("%s: set default fail! :%d \n",
+ __func__, err_code);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ }
+ }
+ /* Check and update info to object */
+ err_code = self->update_all(self, 1, "common_ioexp_init");
+ if (err_code < 0) {
+ SWPS_ERR("%s: update_all() fail! :%d \n",
+ __func__, err_code);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ return 0;
+}
+
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+_is_channel_ready(struct ioexp_obj_s *self){
+
+ int buf = 0;
+ int chip_id = 0; /* Use first chip which be registered */
+ int data_id = 0; /* Use first byte which be registered */
+ struct ioexp_addr_s *ioexp_addr = NULL;
+
+ ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!ioexp_addr){
+ SWPS_ERR("%s: config incorrect!\n", __func__);
+ return ERR_IOEXP_UNEXCPT;
+ }
+ buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id),
+ ioexp_addr->read_offset[data_id]);
+ if (buf >= 0){
+ return 1;
+ }
+ return 0;
+}
+
+int
+_ioexp_init_handler(struct ioexp_obj_s *self){
+
+ int return_val;
+
+ switch (self->mode) {
+ case IOEXP_MODE_DIRECT:
+ return_val = self->init(self);
+ if (return_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ } else {
+ self->state = STATE_IOEXP_NORMAL;
+ }
+ return return_val;
+
+ case IOEXP_MODE_POLLING:
+ /* Check system and channel is ready */
+ if (self->state == STATE_IOEXP_INIT){
+ if (!_is_channel_ready(self)){
+ self->state = STATE_IOEXP_INIT;
+ SWPS_WARN("%s: IOEXP:%d channel not ready.\n",
+ __func__, self->ioexp_id);
+ return 0;
+ }
+ }
+ /* Execute initial callback */
+ return_val = self->init(self);
+ if (return_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ } else {
+ self->state = STATE_IOEXP_NORMAL;
+ }
+ return return_val;
+
+ default:
+ break;
+ }
+ SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+int
+common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){
+
+ int result_val;
+ int show_err = 1;
+ char *func_mane = "common_ioexp_fsm_4_direct";
+
+ switch (self->state){
+ case STATE_IOEXP_INIT:
+ result_val = _ioexp_init_handler(self);
+ /* Exception case: terminate initial procedure */
+ if(result_val < 0){
+ /* Initial fail */
+ return result_val;
+ }
+ if(self->state == STATE_IOEXP_INIT){
+ /* Keep in INIT state, and return error */
+ return ERR_IOEXP_UNINIT;
+ }
+ /* Case: Initial done */
+ return 0;
+
+ case STATE_IOEXP_NORMAL:
+ result_val = self->update_all(self, show_err, func_mane);
+ if (result_val < 0){
+ SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ case STATE_IOEXP_ABNORMAL:
+ result_val = self->update_all(self, show_err, func_mane);
+ if (result_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_ERR("%s: Exception occurs :%d\n",
+ __func__, self->state);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+int
+common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){
+
+ int result_val, i, show_e;
+ int fail_retry = 3;
+ char *func_name = "common_ioexp_fsm_4_polling";
+
+#ifdef DEBUG_SWPS
+ show_e = 1;
+#else
+ show_e = 0;
+#endif
+
+ switch (self->state){
+ case STATE_IOEXP_INIT:
+ result_val = _ioexp_init_handler(self);
+ /* Exception case: terminate initial procedure */
+ if(result_val < 0){
+ /* Initial fail */
+ return result_val;
+ }
+ /* Case: System (Channel) not ready */
+ if(self->state == STATE_IOEXP_INIT){
+ /* Keep in INIT state, wait and retry */
+ return 0;
+ }
+ /* Case: Initial done */
+ SWPS_INFO("IOEXP-%d: initial done. :%d\n",
+ self->ioexp_id, self->ioexp_type);
+ return result_val;
+
+ case STATE_IOEXP_NORMAL:
+ /* Retry mechanism for case of i2c topology not stable */
+ for (i=0; iupdate_all(self, show_e, func_name);
+ if (result_val >= 0) {
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+ }
+ if (check_channel_tier_1() < 0) {
+ SWPS_INFO("%s: detect I2C crash :%d\n",
+ __func__, self->ioexp_id);
+ break;
+ }
+ SWPS_DEBUG("IOEXP-%d: unstable :%d\n",
+ self->ioexp_id, result_val);
+ }
+ SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n",
+ self->ioexp_id, result_val);
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+
+ case STATE_IOEXP_ABNORMAL:
+ result_val = self->update_all(self, show_e, func_name);
+ if (result_val < 0){
+ self->state = STATE_IOEXP_ABNORMAL;
+ return result_val;
+ }
+ SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n",
+ self->ioexp_id, result_val);
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_ERR("IOEXP-%d: Exception occurs :%d\n",
+ self->ioexp_id, self->state);
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+/* ========== Object private functions for check & update ==========
+ */
+int
+common_ioexp_check(struct ioexp_obj_s *self){
+
+ int result;
+
+ if (self->mode != IOEXP_MODE_POLLING){
+ SWPS_ERR("%s: not polling mode :%d\n",
+ __func__, self->mode);
+ return ERR_IOEXP_NOTSUPPORT;
+ }
+ mutex_lock(&self->lock);
+ result = self->fsm_4_polling(self);
+ mutex_unlock(&self->lock);
+ return result;
+}
+
+
+/* ========== Functions for Factory pattern ==========
+ */
+static struct ioexp_map_s *
+get_ioexp_map(int ioexp_type){
+ switch (ioexp_type){
+ case IOEXP_TYPE_MAGINOLIA_NAB:
+ return &ioexp_map_magnolia_nab;
+ case IOEXP_TYPE_MAGINOLIA_7AB:
+ case IOEXP_TYPE_SPRUCE_7AB:
+ return &ioexp_map_magnolia_7ab;
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ return &ioexp_map_redwood_p01p08_p17p24;
+ case IOEXP_TYPE_REDWOOD_P09P16:
+ return &ioexp_map_redwood_p09p16_p25p32;
+ case IOEXP_TYPE_HUDSON32IGA_P01P08:
+ return &ioexp_map_hudson32iga_p01p08_p17p24;
+ case IOEXP_TYPE_HUDSON32IGA_P09P16:
+ return &ioexp_map_hudson32iga_p09p16_p25p32;
+ case IOEXP_TYPE_CYPRESS_NABC:
+ return &ioexp_map_cypress_nabc;
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ return &ioexp_map_cypress_7abc;
+ case IOEXP_TYPE_TAHOE_5A:
+ return &ioexp_map_tahoe_5a;
+ case IOEXP_TYPE_TAHOE_6ABC:
+ return &ioexp_map_tahoe_6abc;
+ case IOEXP_TYPE_SEQUOIA_NABC:
+ return &ioexp_map_sequoia_nabc;
+ default:
+ return NULL;
+ }
+}
+
+
+int
+setup_ioexp_ssize_attr(struct ioexp_obj_s *self,
+ struct ioexp_map_s *ioexp_map_p,
+ int ioexp_id,
+ int ioexp_type,
+ int run_mode){
+ switch (run_mode){
+ case IOEXP_MODE_POLLING: /* Direct access device mode */
+ case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */
+ self->mode = run_mode;
+ break;
+ default:
+ SWPS_ERR("%s: non-defined run_mode:%d\n",
+ __func__, run_mode);
+ self->mode = ERR_IOEXP_UNEXCPT;
+ return ERR_IOEXP_UNEXCPT;
+ }
+ self->ioexp_id = ioexp_id;
+ self->ioexp_type = ioexp_type;
+ self->ioexp_map_p = ioexp_map_p;
+ self->state = STATE_IOEXP_INIT;
+ mutex_init(&self->lock);
+ return 0;
+}
+
+
+static int
+setup_addr_mapping(struct ioexp_obj_s *self,
+ struct ioexp_addr_s *addr_map_p){
+ if (!addr_map_p){
+ SWPS_ERR("%s: map is null\n", __func__);
+ return -1;
+ }
+ self->ioexp_map_p->map_addr = addr_map_p;
+ return 0;
+}
+
+
+static int
+setup_ioexp_public_cb(struct ioexp_obj_s *self,
+ int ioexp_type){
+
+ switch (ioexp_type){
+ case IOEXP_TYPE_MAGINOLIA_NAB:
+ self->get_present = common_get_present;
+ self->get_tx_fault = common_get_tx_fault;
+ self->get_rxlos = common_get_rxlos;
+ self->get_tx_disable = common_get_tx_disable;
+ self->get_reset = ioexp_get_not_support;
+ self->get_lpmod = ioexp_get_not_support;
+ self->get_modsel = ioexp_get_not_support;
+ self->get_hard_rs0 = ioexp_get_not_support;
+ self->get_hard_rs1 = ioexp_get_not_support;
+ self->set_tx_disable = common_set_tx_disable;
+ self->set_reset = ioexp_set_not_support;
+ self->set_lpmod = ioexp_set_not_support;
+ self->set_modsel = ioexp_set_not_support;
+ self->set_hard_rs0 = ioexp_set_not_support;
+ self->set_hard_rs1 = ioexp_set_not_support;
+ return 0;
+ case IOEXP_TYPE_CYPRESS_NABC:
+ self->get_present = common_get_present;
+ self->get_tx_fault = common_get_tx_fault;
+ self->get_rxlos = common_get_rxlos;
+ self->get_tx_disable = common_get_tx_disable;
+ self->get_reset = ioexp_get_not_support;
+ self->get_lpmod = ioexp_get_not_support;
+ self->get_modsel = ioexp_get_not_support;
+ self->get_hard_rs0 = common_get_hard_rs0;
+ self->get_hard_rs1 = common_get_hard_rs1;
+ self->set_tx_disable = common_set_tx_disable;
+ self->set_reset = ioexp_set_not_support;
+ self->set_lpmod = ioexp_set_not_support;
+ self->set_modsel = ioexp_set_not_support;
+ self->set_hard_rs0 = common_set_hard_rs0;
+ self->set_hard_rs1 = common_set_hard_rs1;
+ return 0;
+ case IOEXP_TYPE_MAGINOLIA_7AB:
+ case IOEXP_TYPE_SPRUCE_7AB:
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ case IOEXP_TYPE_REDWOOD_P09P16:
+ case IOEXP_TYPE_HUDSON32IGA_P01P08:
+ case IOEXP_TYPE_HUDSON32IGA_P09P16:
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ case IOEXP_TYPE_TAHOE_5A:
+ case IOEXP_TYPE_TAHOE_6ABC:
+ case IOEXP_TYPE_SEQUOIA_NABC:
+ self->get_present = common_get_present;
+ self->get_tx_fault = ioexp_get_not_support;
+ self->get_rxlos = ioexp_get_not_support;
+ self->get_tx_disable = ioexp_get_not_support;
+ self->get_reset = common_get_reset;
+ self->get_lpmod = common_get_lpmod;
+ self->get_modsel = common_get_modsel;
+ self->get_hard_rs0 = ioexp_get_not_support;
+ self->get_hard_rs1 = ioexp_get_not_support;
+ self->set_tx_disable = ioexp_set_not_support;
+ self->set_reset = common_set_reset;
+ self->set_lpmod = common_set_lpmod;
+ self->set_modsel = common_set_modsel;
+ self->set_hard_rs0 = ioexp_set_not_support;
+ self->set_hard_rs1 = ioexp_set_not_support;
+ return 0;
+
+ default:
+ SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+ break;
+ }
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_ioexp_private_cb(struct ioexp_obj_s *self,
+ int ioexp_type){
+
+ switch (ioexp_type){
+ case IOEXP_TYPE_MAGINOLIA_NAB:
+ case IOEXP_TYPE_MAGINOLIA_7AB:
+ case IOEXP_TYPE_SPRUCE_7AB:
+ case IOEXP_TYPE_REDWOOD_P01P08:
+ case IOEXP_TYPE_REDWOOD_P09P16:
+ case IOEXP_TYPE_HUDSON32IGA_P01P08:
+ case IOEXP_TYPE_HUDSON32IGA_P09P16:
+ case IOEXP_TYPE_CYPRESS_NABC:
+ case IOEXP_TYPE_CYPRESS_7ABC:
+ case IOEXP_TYPE_TAHOE_5A:
+ case IOEXP_TYPE_TAHOE_6ABC:
+ case IOEXP_TYPE_SEQUOIA_NABC:
+ self->init = common_ioexp_init;
+ self->check = common_ioexp_check;
+ self->update_all = common_ioexp_update_all;
+ self->fsm_4_direct = common_ioexp_fsm_4_direct;
+ self->fsm_4_polling = common_ioexp_fsm_4_polling;
+ return 0;
+
+ default:
+ SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+ break;
+ }
+ return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_i2c_client_one(struct ioexp_obj_s *self,
+ int chip_id){
+
+ char *err_msg = "ERROR";
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *client = NULL;
+ struct ioexp_i2c_s *i2c_obj_p = NULL;
+ struct ioexp_i2c_s *i2c_curr_p = NULL;
+
+ int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id;
+ adap = i2c_get_adapter(chan_id);
+ if(!adap){
+ err_msg = "Can not get adap!";
+ goto err_ioexp_setup_i2c_1;
+ }
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client){
+ err_msg = "Can not kzalloc client!";
+ goto err_ioexp_setup_i2c_1;
+ }
+ i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL);
+ if (!i2c_obj_p){
+ err_msg = "Can not kzalloc i2c_obj_p!";
+ goto err_ioexp_setup_i2c_2;
+ }
+ client->adapter = adap;
+ client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr;
+ i2c_obj_p->i2c_client_p = client;
+ i2c_obj_p->chip_id = chip_id;
+ i2c_obj_p->next = NULL;
+ if (!self->i2c_head_p){
+ self->i2c_head_p = i2c_obj_p;
+ } else {
+ i2c_curr_p = self->i2c_head_p;
+ while (i2c_curr_p->next){
+ i2c_curr_p = i2c_curr_p->next;
+ }
+ i2c_curr_p->next = i2c_obj_p;
+ }
+ return 0;
+
+err_ioexp_setup_i2c_2:
+ kfree(client);
+err_ioexp_setup_i2c_1:
+ SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id);
+ return -1;
+}
+
+
+static int
+setup_i2c_client(struct ioexp_obj_s* self){
+
+ int result;
+ int chip_id = 0;
+
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ result = setup_i2c_client_one(self, chip_id);
+ if (result < 0){
+ SWPS_ERR("%s fail! :%d\n", __func__, chip_id);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static int
+setup_ioexp_config(struct ioexp_obj_s *self) {
+
+ int chip_id, offset, err_code;
+ struct ioexp_addr_s *addr_p;
+
+ for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+ addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+ if (!addr_p){
+ SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id);
+ return -1;
+ }
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+
+ err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+ addr_p->conf_offset[offset],
+ addr_p->conf_default[offset]);
+
+ if (err_code < 0){
+ SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code);
+ return -2;
+ }
+ }
+ }
+ return 0;
+}
+
+
+struct ioexp_obj_s *
+_create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode){
+
+ struct ioexp_map_s* ioexp_map_p;
+ struct ioexp_obj_s* result_p;
+ struct ioexp_i2c_s *i2c_curr_p;
+ struct ioexp_i2c_s *i2c_next_p;
+
+ /* Get layout */
+ ioexp_map_p = get_ioexp_map(ioexp_type);
+ if (!ioexp_map_p){
+ SWPS_ERR("%s: Invalid ioexp_type\n", __func__);
+ goto err_create_ioexp_fail;
+ }
+ /* Prepare IOEXP object */
+ result_p = kzalloc(sizeof(*result_p), GFP_KERNEL);
+ if (!result_p){
+ SWPS_ERR("%s: kzalloc failure!\n", __func__);
+ goto err_create_ioexp_fail;
+ }
+ /* Prepare static size attributes */
+ if (setup_ioexp_ssize_attr(result_p,
+ ioexp_map_p,
+ ioexp_id,
+ ioexp_type,
+ run_mode) < 0){
+ goto err_create_ioexp_setup_attr_fail;
+ }
+ /* Prepare address mapping */
+ if (setup_addr_mapping(result_p, addr_map_p) < 0){
+ goto err_create_ioexp_setup_attr_fail;
+ }
+ if (setup_i2c_client(result_p) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ /* Prepare call back functions of object */
+ if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){
+ goto err_create_ioexp_setup_i2c_fail;
+ }
+ return result_p;
+
+err_create_ioexp_setup_i2c_fail:
+ i2c_curr_p = result_p->i2c_head_p;
+ i2c_next_p = result_p->i2c_head_p;
+ while (i2c_curr_p){
+ i2c_next_p = i2c_curr_p->next;
+ kfree(i2c_curr_p->i2c_client_p);
+ kfree(i2c_curr_p);
+ i2c_curr_p = i2c_next_p;
+ }
+err_create_ioexp_setup_attr_fail:
+ kfree(result_p);
+err_create_ioexp_fail:
+ SWPS_ERR("%s: fail! :%d :%d \n",
+ __func__, ioexp_id, ioexp_type);
+ return NULL;
+}
+
+
+int
+create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode){
+
+ struct ioexp_obj_s *ioexp_p = NULL;
+
+ ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type,
+ addr_map_p, run_mode);
+ if (!ioexp_p){
+ return -1;
+ }
+ if (ioexp_head_p == NULL){
+ ioexp_head_p = ioexp_p;
+ ioexp_tail_p = ioexp_p;
+ return 0;
+ }
+ ioexp_tail_p->next = ioexp_p;
+ ioexp_tail_p = ioexp_p;
+ return 0;
+}
+
+
+static int
+_init_ioexp_obj(struct ioexp_obj_s* self) {
+
+ char *err_msg = "ERR";
+ char *func_name = "_init_ioexp_obj";
+
+ /* Setup IOEXP configure byte */
+ if (setup_ioexp_config(self) < 0){
+ err_msg = "setup_ioexp_config fail";
+ goto err_init_ioexp_obj;
+ }
+ /* Setup default data */
+ if (_ioexp_init_handler(self) < 0){
+ err_msg = "_ioexp_init_handler fail";
+ goto err_init_ioexp_obj;
+ }
+ /* Update all */
+ if (self->state == STATE_IOEXP_NORMAL){
+ if (self->update_all(self, 1, func_name) < 0){
+ err_msg = "update_all() fail";
+ goto err_init_ioexp_obj;
+ }
+ }
+ return 0;
+
+err_init_ioexp_obj:
+ SWPS_DEBUG("%s: %s\n", __func__, err_msg);
+ return -1;
+}
+
+
+int
+init_ioexp_objs(void){
+ /* Return value:
+ * 0: Success
+ * -1: Detect topology error
+ * -2: SWPS internal error
+ */
+
+ struct ioexp_obj_s *curr_p = ioexp_head_p;
+
+ if (!curr_p) {
+ SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__);
+ return -2;
+ }
+ while (curr_p) {
+ if (_init_ioexp_obj(curr_p) < 0) {
+ SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__);
+ return -1;
+ }
+ curr_p = curr_p->next;
+ }
+ SWPS_DEBUG("%s: done.\n", __func__);
+ return 0;
+}
+
+
+void
+clean_ioexp_objs(void){
+
+ struct ioexp_i2c_s *i2c_curr_p = NULL;
+ struct ioexp_i2c_s *i2c_next_p = NULL;
+ struct ioexp_obj_s *ioexp_next_p = NULL;
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ if (ioexp_head_p == NULL){
+ ioexp_tail_p = NULL;
+ return;
+ }
+ while(ioexp_curr_p){
+ ioexp_next_p = ioexp_curr_p->next;
+ i2c_curr_p = ioexp_curr_p->i2c_head_p;
+ while (i2c_curr_p) {
+ i2c_next_p = i2c_curr_p->next;
+ kfree(i2c_curr_p->i2c_client_p);
+ kfree(i2c_curr_p);
+ i2c_curr_p = i2c_next_p;
+ }
+ kfree(ioexp_curr_p);
+ ioexp_curr_p = ioexp_next_p;
+ }
+ ioexp_tail_p = NULL;
+ SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+int
+check_ioexp_objs(void){
+
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ while (ioexp_curr_p){
+ if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){
+ SWPS_INFO("check IOEXP-%d fail! :%d\n",
+ ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type);
+ return -1;
+ }
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+ return 0;
+}
+
+
+struct ioexp_obj_s *
+get_ioexp_obj(int ioexp_id){
+
+ struct ioexp_obj_s *result_p = NULL;
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ while(ioexp_curr_p){
+ if (ioexp_curr_p->ioexp_id == ioexp_id){
+ result_p = ioexp_curr_p;
+ break;
+ }
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+ return result_p;
+}
+
+
+void
+unlock_ioexp_all(void) {
+
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ while(ioexp_curr_p){
+ mutex_unlock(&ioexp_curr_p->lock);
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+}
+
+
+int
+lock_ioexp_all(void) {
+
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+ while(ioexp_curr_p){
+ mutex_lock(&ioexp_curr_p->lock);
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+ return 0;
+}
+
+
+int
+check_channel_tier_1(void) {
+
+ if ( (!_is_channel_ready(ioexp_head_p)) &&
+ (!_is_channel_ready(ioexp_tail_p)) ){
+ return -1;
+ }
+ return 0;
+}
+
+
+static int
+_scan_channel_tier_1(int force,
+ int show_err) {
+
+ struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+ int ready = 0;
+
+ if (!ioexp_curr_p) {
+ goto err_scan_tier_1_channel;
+ }
+ while(ioexp_curr_p) {
+ ready = _is_channel_ready(ioexp_curr_p);
+ if ((!ready) && (!force)) {
+ goto err_scan_tier_1_channel;
+ }
+ ioexp_curr_p = ioexp_curr_p->next;
+ }
+ return 0;
+
+err_scan_tier_1_channel:
+ if (show_err) {
+ if (ioexp_curr_p) {
+ SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id);
+ } else {
+ SWPS_INFO("%s: IOEXP is null.\n", __func__);
+ }
+ }
+ return -1;
+}
+
+
+static int
+_scan_channel_tier_1_single(void) {
+
+ int ret = 0;
+ int chan_id = 0;
+ int fake_cid = 0;
+ int fake_offs = 0;
+ int fake_addr = 0;
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *client = NULL;
+
+ if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) {
+ return 0;
+ }
+ /* Setup i2c_client */
+ chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id;
+ fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr;
+ adap = i2c_get_adapter((chan_id + 1));
+ if(!adap){
+ SWPS_INFO("%s: Can not get adap!\n", __func__);
+ return 0;
+ }
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (!client){
+ SWPS_INFO("%s: Can not kzalloc client!\n", __func__);
+ return 0;
+ }
+ client->adapter = adap;
+ client->addr = fake_addr;
+ /* Fouce move ioexp ptr to next */
+ ret = i2c_smbus_read_byte_data(client, fake_offs);
+ SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret);
+ kfree(client);
+ return 1;
+}
+
+
+int
+resync_channel_tier_1(void) {
+
+ char *emsg = "ERR";
+
+ if (!ioexp_head_p) {
+ emsg = "ioexp_head_p is NULL";
+ goto err_resync_ioexp_status_1;
+ }
+ /* Run all */
+ if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) {
+ _scan_channel_tier_1_single();
+ } else {
+ _scan_channel_tier_1(1, 0);
+ }
+ /* Check all */
+ if (_scan_channel_tier_1(0, 1) < 0) {
+ emsg = "resync tier-1 channel fail";
+ goto err_resync_ioexp_status_1;
+ }
+ return 0;
+
+err_resync_ioexp_status_1:
+ SWPS_ERR("%s: %s\n", __func__, emsg);
+ return -1;
+}
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h
new file mode 100644
index 000000000000..4e39fcefa620
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h
@@ -0,0 +1,173 @@
+#ifndef IO_EXPANDER_H
+#define IO_EXPANDER_H
+
+#include
+
+
+/* IOEXP type define (SFP series) */
+#define IOEXP_TYPE_MAGINOLIA_NAB (10101)
+#define IOEXP_TYPE_CYPRESS_NABC (10102)
+
+/* IOEXP type define (QSFP series) */
+#define IOEXP_TYPE_MAGINOLIA_7AB (10201)
+#define IOEXP_TYPE_REDWOOD_P01P08 (10202)
+#define IOEXP_TYPE_REDWOOD_P09P16 (10203)
+#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204)
+#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205)
+#define IOEXP_TYPE_SPRUCE_7AB (10206)
+#define IOEXP_TYPE_CYPRESS_7ABC (10207)
+#define IOEXP_TYPE_TAHOE_5A (10208)
+#define IOEXP_TYPE_TAHOE_6ABC (10209)
+#define IOEXP_TYPE_SEQUOIA_NABC (10210)
+
+/* IOEXP mode define */
+#define IOEXP_MODE_POLLING (19000)
+#define IOEXP_MODE_DIRECT (19001)
+
+/* IOEXP state define */
+#define STATE_IOEXP_NORMAL (0)
+#define STATE_IOEXP_INIT (-1)
+#define STATE_IOEXP_ABNORMAL (-2)
+
+/* IOEXP error code define */
+#define ERR_IOEXP_NOTSUPPORT (-100)
+#define ERR_IOEXP_UNINIT (-101)
+#define ERR_IOEXP_BADCONF (-102)
+#define ERR_IOEXP_ABNORMAL (-103)
+#define ERR_IOEXP_NOSTATE (-104)
+#define ERR_IOEXP_BADINPUT (-105)
+#define ERR_IOEXP_UNEXCPT (-199)
+
+
+#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args)
+#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args)
+#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args)
+
+#ifdef DEBUG_SWPS
+# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args)
+#else
+# define SWPS_DEBUG(fmt, args...)
+#endif
+
+
+struct ioexp_addr_s {
+ int chan_id;
+ int chip_addr;
+ int read_offset[8];
+ int write_offset[8];
+ int conf_offset[8];
+ uint8_t data_default[8];
+ uint8_t conf_default[8];
+};
+
+struct ioexp_i2c_s {
+ int chip_id;
+ struct i2c_client *i2c_client_p;
+ struct ioexp_i2c_s *next;
+};
+
+
+struct ioexp_bitmap_s {
+ int chip_id; /* IOEXP chip id */
+ int ioexp_voffset; /* IOEXP virtual offset */
+ int bit_shift;
+};
+
+struct ioexp_map_s {
+ int chip_amount; /* Number of chips that IOEXP object content */
+ int data_width; /* Number of (Read/Write/Config) bytes */
+ struct ioexp_addr_s *map_addr; /* Chip address info */
+ struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */
+ struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */
+ struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */
+ struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */
+ struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */
+ struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */
+};
+
+struct ioexp_data_s {
+ uint8_t data[8];
+};
+
+struct ioexp_obj_s {
+
+ /* ============================
+ * Object public property
+ * ============================
+ */
+ int ioexp_id;
+ int ioexp_type;
+
+ /* ============================
+ * Object private property
+ * ============================
+ */
+ struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */
+ struct ioexp_map_s *ioexp_map_p;
+ struct ioexp_obj_s *next;
+ struct ioexp_i2c_s *i2c_head_p;
+ struct mutex lock;
+ int mode;
+ int state;
+
+ /* ===========================================
+ * Object public functions
+ * ===========================================
+ */
+ int (*get_present)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_reset)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset);
+ int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset);
+ int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+ int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+
+ /* ===========================================
+ * Object private functions
+ * ===========================================
+ */
+ int (*init)(struct ioexp_obj_s *self);
+ int (*check)(struct ioexp_obj_s *self);
+ int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name);
+ int (*fsm_4_direct)(struct ioexp_obj_s* self);
+ int (*fsm_4_polling)(struct ioexp_obj_s* self);
+};
+
+
+struct ioexp_obj_s* get_ioexp_obj(int ioexp_id);
+int create_ioexp_obj(int ioexp_id,
+ int ioexp_type,
+ struct ioexp_addr_s *addr_map_p,
+ int run_mode);
+int init_ioexp_objs(void);
+int check_ioexp_objs(void);
+void clean_ioexp_objs(void);
+
+void unlock_ioexp_all(void);
+int lock_ioexp_all(void);
+
+int check_channel_tier_1(void);
+int resync_channel_tier_1(void);
+
+/* Macro for bit control */
+#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift)))
+#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift)))
+
+
+#endif /* IO_EXPANDER_H */
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c
new file mode 100644
index 000000000000..0bbd78935433
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c
@@ -0,0 +1,8212 @@
+#include
+#include
+#include
+#include
+#include "io_expander.h"
+#include "transceiver.h"
+
+
+/* ========== Register EEPROM address mapping ==========
+ */
+struct eeprom_map_s eeprom_map_sfp = {
+ .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1,
+ .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1,
+ .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1,
+ .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1,
+ .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1,
+ .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1,
+ .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1,
+ .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1,
+ .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1,
+ .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1,
+ .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1,
+ .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1,
+ .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1,
+ .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1,
+ .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2,
+ .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1,
+ .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1,
+ .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1,
+ .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1,
+ .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2,
+ .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1,
+ .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1,
+ .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2,
+ .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8,
+ .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1,
+ .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2,
+ .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1,
+ .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1,
+ .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1,
+ .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2,
+ .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16,
+ .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16,
+ .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4,
+ .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16,
+ .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2,
+ .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2,
+};
+
+struct eeprom_map_s eeprom_map_qsfp = {
+ .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1,
+ .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1,
+ .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1,
+ .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1,
+ .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1,
+ .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1,
+ .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1,
+ .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1,
+ .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1,
+ .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1,
+ .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1,
+ .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1,
+ .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1,
+ .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1,
+ .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3,
+ .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1,
+ .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1,
+ .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1,
+ .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1,
+ .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8,
+ .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1,
+ .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1,
+ .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2,
+ .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8,
+ .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1,
+ .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8,
+ .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1,
+ .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1,
+ .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1,
+ .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8,
+ .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16,
+ .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16,
+ .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2,
+ .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16,
+ .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2,
+ .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2,
+};
+
+struct eeprom_map_s eeprom_map_qsfp28 = {
+ .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1,
+ .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1,
+ .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1,
+ .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1,
+ .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1,
+ .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1,
+ .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1,
+ .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1,
+ .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1,
+ .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1,
+ .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1,
+ .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1,
+ .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1,
+ .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1,
+ .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3,
+ .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1,
+ .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2,
+ .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2,
+ .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1,
+ .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8,
+ .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1,
+ .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1,
+ .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2,
+ .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8,
+ .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1,
+ .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8,
+ .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1,
+ .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2,
+ .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1,
+ .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8,
+ .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16,
+ .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16,
+ .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2,
+ .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16,
+ .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2,
+ .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2,
+};
+
+
+/* ========== Utility Functions ==========
+ */
+static int
+get_bit(uint8_t origin_byte, int bit_shift) {
+ return (int)((origin_byte >> bit_shift) & 0x1);
+}
+
+static int
+transform_word_to_int(uint8_t hight_byte,
+ uint8_t low_byte) {
+ return ((((int)hight_byte) << 8) + (int)low_byte);
+}
+
+void
+alarm_msg_2_user(struct transvr_obj_s *self,
+ char *emsg) {
+
+ SWPS_ERR("%s on %s.\n", emsg, self->swp_name);
+}
+
+
+/* ========== Private functions ==========
+ */
+static int
+_reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+_is_transvr_support_ctle(struct transvr_obj_s *self);
+
+static int
+_transvr_init_handler(struct transvr_obj_s *self);
+
+int
+_transvr_clean_handler(struct transvr_obj_s *self);
+
+int
+_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self);
+
+
+void
+lock_transvr_obj(struct transvr_obj_s *self) {
+
+ mutex_lock(&self->lock);
+ self->curr_page = VAL_TRANSVR_PAGE_FREE;
+}
+
+
+void
+unlock_transvr_obj(struct transvr_obj_s *self) {
+
+ self->curr_page = VAL_TRANSVR_PAGE_FREE;
+ mutex_unlock(&self->lock);
+}
+
+
+static int
+_check_by_mode(struct transvr_obj_s *self,
+ int (*attr_update_func)(struct transvr_obj_s *self, int show_err),
+ char *caller_name){
+
+ int return_val = ERR_TRANSVR_UNEXCPT;
+
+ switch (self->mode){
+ case TRANSVR_MODE_POLLING:
+ switch (self->state){
+ case STATE_TRANSVR_CONNECTED:
+ goto ok_check_by_mode_1;
+ case STATE_TRANSVR_NEW:
+ case STATE_TRANSVR_INIT:
+ return ERR_TRANSVR_UNINIT;
+ case STATE_TRANSVR_DISCONNECTED:
+ return ERR_TRANSVR_UNPLUGGED;
+ case STATE_TRANSVR_UNEXCEPTED:
+ return ERR_TRANSVR_ABNORMAL;
+ case STATE_TRANSVR_ISOLATED:
+ return ERR_TRNASVR_BE_ISOLATED;
+ default:
+ goto err_check_by_mode_1;
+ }
+ goto ok_check_by_mode_1;
+
+ case TRANSVR_MODE_DIRECT:
+ return_val = self->fsm_4_direct(self, caller_name);
+ if (return_val < 0){
+ return return_val;
+ }
+ goto ok_check_by_mode_1;
+
+ default:
+ goto err_check_by_mode_1;
+ }
+ goto ok_check_by_mode_1;
+
+ok_check_by_mode_1:
+ return attr_update_func(self, 0);
+
+err_check_by_mode_1:
+ SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state);
+ return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static void
+_transvr_clean_retry(struct transvr_obj_s *self) {
+ self->retry = 0;
+}
+
+
+static int
+_transvr_handle_retry(struct transvr_obj_s *self, int retry) {
+ /* Return: 0: keep retry
+ * -1: stop retry
+ */
+ if (self->retry == 0) {
+ self->retry = retry;
+ }
+ self->retry -= 1;
+ if (self->retry <= 0) {
+ _transvr_clean_retry(self);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int
+_common_setup_page(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ int len,
+ int show_e) {
+ /* return:
+ * 0 : OK
+ * -1 : EEPROM settings incorrect
+ * -2 : I2C R/W failure
+ * -3 : Undefined case
+ */
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ /* Check */
+ if ((addr < 0) || (offset < 0) || (len < 0)) {
+ emsg = "EEPROM settings incorrect";
+ retval = -1;
+ goto err_common_setup_page;
+ }
+ /* Case1: continue access */
+ if ((self->i2c_client_p->addr == addr) &&
+ (self->curr_page == page)) {
+ return 0;
+ }
+ self->i2c_client_p->addr = addr;
+ /* Case2: select lower page */
+ if (page == -1) {
+ self->curr_page = page;
+ return 0;
+ }
+ /* Case3: select upper page */
+ if (page >= 0) {
+ goto upper_common_setup_page;
+ }
+ /* Unexpected case */
+ show_e = 1;
+ emsg = "Unexpected case";
+ retval = -3;
+ goto err_common_setup_page;
+
+upper_common_setup_page:
+ if (i2c_smbus_write_byte_data(self->i2c_client_p,
+ VAL_TRANSVR_PAGE_SELECT_OFFSET,
+ page) < 0) {
+ emsg = "I2C R/W failure";
+ retval = -2;
+ goto err_common_setup_page;
+ }
+ self->curr_page = page;
+ mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY);
+ return 0;
+
+err_common_setup_page:
+ if (show_e) {
+ SWPS_INFO("%s: %s", __func__, emsg);
+ SWPS_INFO("%s: :0x%02x :%d :%d :%d\n",
+ __func__, addr, page, offset, len);
+ }
+ return retval;
+}
+
+/*
+static int
+_common_setup_password(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offs,
+ uint8_t pwd[4],
+ int show_e) {
+ int i = 0;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ err = _common_setup_page(self, addr, page, offs, 4, show_e);
+ if (err < 0){
+ emsg = "setup EEPROM page fail";
+ goto err_common_setup_password;
+ }
+ for (i=0; i<4; i++) {
+ err = i2c_smbus_write_byte_data(self->i2c_client_p,
+ (offs + i),
+ pwd[i]);
+ if (err < 0){
+ emsg = "I2C R/W fail!";
+ goto err_common_setup_password;
+ }
+ }
+ return 0;
+
+err_common_setup_password:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%d\n", __func__, emsg, err);
+ }
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+*/
+
+static int
+_common_update_uint8_attr(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ int len,
+ uint8_t *buf,
+ char *caller,
+ int show_e){
+
+ int i;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ err = _common_setup_page(self, addr, page, offset, len, show_e);
+ if (err < 0){
+ emsg = "setup EEPROM page fail";
+ goto err_common_update_uint8_attr;
+ }
+ for (i=0; ii2c_client_p, (offset + i));
+ if (err < 0){
+ emsg = "I2C R/W fail!";
+ goto err_common_update_uint8_attr;
+ }
+ buf[i] = err;
+ }
+ return 0;
+
+err_common_update_uint8_attr:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%s :%d\n",
+ __func__, emsg, caller, err);
+ }
+ buf[0] = DEBUG_TRANSVR_HEX_VAL;
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_update_int_attr(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ int len,
+ int *buf,
+ char *caller,
+ int show_e){
+
+ int i;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ err = _common_setup_page(self, addr, page, offset, len, show_e);
+ if (err < 0){
+ emsg = "setup EEPROM page fail";
+ goto err_common_update_int_attr;
+ }
+ for (i=0; ii2c_client_p, (offset + i));
+ if (err < 0){
+ emsg = "I2C R/W fail!";
+ goto err_common_update_int_attr;
+ }
+ buf[i] = (int)err;
+ }
+ return 0;
+
+err_common_update_int_attr:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%s :%d\n",
+ __func__, emsg, caller, err);
+ }
+ buf[0] = DEBUG_TRANSVR_INT_VAL;
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_update_string_attr(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ int len,
+ char buf[],
+ char *caller,
+ int show_e){
+
+ int i;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ err = _common_setup_page(self, addr, page, offset, len, show_e);
+ if (err < 0){
+ emsg = "setup EEPROM page fail";
+ goto err_common_update_string_attr;
+ }
+ for (i=0; ii2c_client_p, (offset + i));
+ if (err < 0){
+ emsg = "I2C R/W fail!";
+ goto err_common_update_string_attr;
+ }
+ buf[i] = (char)err;
+ }
+ return 0;
+
+err_common_update_string_attr:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%s :%d\n",
+ __func__, emsg, caller, err);
+ }
+ buf[0] = 'e';
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_set_uint8_attr(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offset,
+ uint8_t update,
+ uint8_t *buf,
+ char *caller,
+ int show_e){
+ int len = 1;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ if ((*buf) == update){
+ return 0;
+ }
+ err = _common_setup_page(self, addr, page, offset, len, show_e);
+ if (err < 0){
+ emsg = "setup EEPROM page fail";
+ goto err_common_set_uint8_attr_1;
+ }
+ err = i2c_smbus_write_byte_data(self->i2c_client_p,
+ offset,
+ update);
+ if (err < 0){
+ emsg = "I2C R/W fail!";
+ goto err_common_set_uint8_attr_1;
+ }
+ (*buf) = update;
+ return 0;
+
+err_common_set_uint8_attr_1:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%s :%d\n",
+ __func__, emsg, caller, err);
+ }
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_set_uint8_array(struct transvr_obj_s *self,
+ int addr,
+ int page,
+ int offs,
+ int len,
+ uint8_t update[],
+ uint8_t buf[],
+ char *caller,
+ int show_e){
+ int i = 0;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ err = _common_setup_page(self, addr, page, offs, len, show_e);
+ if (err < 0){
+ emsg = "setup EEPROM page fail";
+ goto err_common_set_uint8_attr_1;
+ }
+ for (i=0; ii2c_client_p,
+ (offs + i),
+ update[i]);
+ if (err < 0){
+ emsg = "I2C R/W fail!";
+ goto err_common_set_uint8_attr_1;
+ }
+ buf[i] = update[i];
+ }
+ return 0;
+
+err_common_set_uint8_attr_1:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%s :%d :%d\n",
+ __func__, emsg, caller, err, i);
+ }
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_update_attr_id(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_id,
+ self->eeprom_map_p->page_id,
+ self->eeprom_map_p->offset_id,
+ self->eeprom_map_p->length_id,
+ &(self->id),
+ "_common_update_attr_id",
+ show_err);
+}
+
+
+static int
+_common_update_attr_extended_id(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_ext_id,
+ self->eeprom_map_p->page_ext_id,
+ self->eeprom_map_p->offset_ext_id,
+ self->eeprom_map_p->length_ext_id,
+ &(self->ext_id),
+ "_common_update_attr_extended_id",
+ show_err);
+}
+
+
+static int
+_common_update_attr_connector(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_connector,
+ self->eeprom_map_p->page_connector,
+ self->eeprom_map_p->offset_connector,
+ self->eeprom_map_p->length_connector,
+ &(self->connector),
+ "_common_update_attr_connector",
+ show_err);
+}
+
+
+static int
+_common_update_attr_transvr_comp(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_trancomp,
+ self->eeprom_map_p->page_trancomp,
+ self->eeprom_map_p->offset_trancomp,
+ self->eeprom_map_p->length_trancomp,
+ self->transvr_comp,
+ "_common_update_attr_transvr_comp",
+ show_err);
+}
+
+
+static int
+_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_trancomp_ext,
+ self->eeprom_map_p->page_trancomp_ext,
+ self->eeprom_map_p->offset_trancomp_ext,
+ self->eeprom_map_p->length_trancomp_ext,
+ &(self->transvr_comp_ext),
+ "_common_update_attr_transvr_comp_ext",
+ show_err);
+}
+
+
+static int
+_common_update_attr_vendor_name(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_string_attr(self,
+ self->eeprom_map_p->addr_vendor_name,
+ self->eeprom_map_p->page_vendor_name,
+ self->eeprom_map_p->offset_vendor_name,
+ self->eeprom_map_p->length_vendor_name,
+ self->vendor_name,
+ "_common_update_attr_vendor_name",
+ show_err);
+}
+
+
+static int
+_common_update_attr_vendor_pn(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_string_attr(self,
+ self->eeprom_map_p->addr_vendor_pn,
+ self->eeprom_map_p->page_vendor_pn,
+ self->eeprom_map_p->offset_vendor_pn,
+ self->eeprom_map_p->length_vendor_pn,
+ self->vendor_pn,
+ "_common_update_attr_vendor_pn",
+ show_err);
+}
+
+
+static int
+_common_update_attr_vendor_rev(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_string_attr(self,
+ self->eeprom_map_p->addr_vendor_rev,
+ self->eeprom_map_p->page_vendor_rev,
+ self->eeprom_map_p->offset_vendor_rev,
+ self->eeprom_map_p->length_vendor_rev,
+ self->vendor_rev,
+ "_common_update_attr_vendor_rev",
+ show_err);
+}
+
+
+static int
+_common_update_attr_vendor_sn(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_string_attr(self,
+ self->eeprom_map_p->addr_vendor_sn,
+ self->eeprom_map_p->page_vendor_sn,
+ self->eeprom_map_p->offset_vendor_sn,
+ self->eeprom_map_p->length_vendor_sn,
+ self->vendor_sn,
+ "_common_update_attr_vendor_sn",
+ show_err);
+}
+
+
+static int
+_common_update_attr_br(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_br,
+ self->eeprom_map_p->page_br,
+ self->eeprom_map_p->offset_br,
+ self->eeprom_map_p->length_br,
+ &(self->br),
+ "_common_update_attr_br",
+ show_err);
+}
+
+
+static int
+_common_update_attr_len_smf(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_len_smf,
+ self->eeprom_map_p->page_len_smf,
+ self->eeprom_map_p->offset_len_smf,
+ self->eeprom_map_p->length_len_smf,
+ &(self->len_smf),
+ "_common_update_attr_len_smf",
+ show_err);
+}
+
+
+static int
+_common_update_attr_len_om1(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_len_om1,
+ self->eeprom_map_p->page_len_om1,
+ self->eeprom_map_p->offset_len_om1,
+ self->eeprom_map_p->length_len_om1,
+ &(self->len_om1),
+ "_common_update_attr_len_om1",
+ show_err);
+}
+
+static int
+_common_update_attr_len_om2(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_len_om2,
+ self->eeprom_map_p->page_len_om2,
+ self->eeprom_map_p->offset_len_om2,
+ self->eeprom_map_p->length_len_om2,
+ &(self->len_om2),
+ "_common_update_attr_len_om2",
+ show_err);
+}
+
+static int
+_common_update_attr_len_om3(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_len_om3,
+ self->eeprom_map_p->page_len_om3,
+ self->eeprom_map_p->offset_len_om3,
+ self->eeprom_map_p->length_len_om3,
+ &(self->len_om3),
+ "_common_update_attr_len_om3",
+ show_err);
+}
+
+
+static int
+_common_update_attr_len_om4(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_len_om4,
+ self->eeprom_map_p->page_len_om4,
+ self->eeprom_map_p->offset_len_om4,
+ self->eeprom_map_p->length_len_om4,
+ &(self->len_om4),
+ "_common_update_attr_len_om4",
+ show_err);
+}
+
+
+static int
+_common_update_attr_option(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_option,
+ self->eeprom_map_p->page_option,
+ self->eeprom_map_p->offset_option,
+ self->eeprom_map_p->length_option,
+ self->option,
+ "_common_update_attr_option",
+ show_err);
+}
+
+
+static int
+_common_update_attr_comp_rev(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_comp_rev,
+ self->eeprom_map_p->page_comp_rev,
+ self->eeprom_map_p->offset_comp_rev,
+ self->eeprom_map_p->length_comp_rev,
+ &(self->comp_rev),
+ "_common_update_attr_comp_rev",
+ show_err);
+}
+
+
+static int
+_common_update_attr_diag_type(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_diag_type,
+ self->eeprom_map_p->page_diag_type,
+ self->eeprom_map_p->offset_diag_type,
+ self->eeprom_map_p->length_diag_type,
+ &(self->diag_type),
+ "_common_update_attr_diag_type",
+ show_err);
+}
+
+
+static int
+_common_update_attr_wavelength(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_wavelength,
+ self->eeprom_map_p->page_wavelength,
+ self->eeprom_map_p->offset_wavelength,
+ self->eeprom_map_p->length_wavelength,
+ self->wavelength,
+ "_common_update_attr_wavelength",
+ show_err);
+}
+
+
+int
+_common_get_option_value(struct transvr_obj_s *self,
+ int offset,
+ int bit_shift) {
+ /* SFP:
+ * - option[0] = A0h / 64
+ * - option[1] = A0h / 65
+ * QSFP:
+ * - option[0] = 00h / 193
+ * - option[1] = 00h / 194
+ * - option[2] = 00h / 195
+ */
+ return (self->option[offset] & (1 << bit_shift));
+}
+
+
+static int
+_sfp_update_attr_len_sm(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_len_sm,
+ self->eeprom_map_p->page_len_sm,
+ self->eeprom_map_p->offset_len_sm,
+ self->eeprom_map_p->length_len_sm,
+ &(self->len_sm),
+ "_common_update_attr_len_sm",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_rate_id(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_int_attr(self,
+ self->eeprom_map_p->addr_rate_id,
+ self->eeprom_map_p->page_rate_id,
+ self->eeprom_map_p->offset_rate_id,
+ self->eeprom_map_p->length_rate_id,
+ &(self->rate_id),
+ "_sfp_update_attr_rate_id",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_soft_rs0(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_soft_rs0,
+ self->eeprom_map_p->page_soft_rs0,
+ self->eeprom_map_p->offset_soft_rs0,
+ self->eeprom_map_p->length_soft_rs0,
+ &(self->soft_rs0),
+ "_sfp_update_attr_soft_rs0",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_soft_rs1(struct transvr_obj_s *self,
+ int show_err){
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_soft_rs1,
+ self->eeprom_map_p->page_soft_rs1,
+ self->eeprom_map_p->offset_soft_rs1,
+ self->eeprom_map_p->length_soft_rs1,
+ &(self->soft_rs1),
+ "_sfp_update_attr_soft_rs1",
+ show_err);
+}
+
+
+int
+_sfp_is_diag_support(struct transvr_obj_s *self){
+
+ uint8_t bit_mask = 0xC0; /* 1100 0000 */
+ uint8_t en_val = 0x40; /* 0100 0000 */
+ uint8_t checkval = (self->diag_type & bit_mask);
+
+ if (checkval == en_val) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+_sfp_update_attr_curr_temp(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!(_sfp_is_diag_support(self))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_temp,
+ self->eeprom_map_p->page_temp,
+ self->eeprom_map_p->offset_temp,
+ self->eeprom_map_p->length_temp,
+ self->curr_temp,
+ "_sfp_update_attr_curr_temp",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_voltage(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!(_sfp_is_diag_support(self))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_voltage,
+ self->eeprom_map_p->page_voltage,
+ self->eeprom_map_p->offset_voltage,
+ self->eeprom_map_p->length_voltage,
+ self->curr_voltage,
+ "_sfp_update_attr_curr_voltage",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!(_sfp_is_diag_support(self))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_bias,
+ self->eeprom_map_p->page_tx_bias,
+ self->eeprom_map_p->offset_tx_bias,
+ self->eeprom_map_p->length_tx_bias,
+ self->curr_tx_bias,
+ "_sfp_update_attr_curr_tx_bias",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!(_sfp_is_diag_support(self))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_power,
+ self->eeprom_map_p->page_tx_power,
+ self->eeprom_map_p->offset_tx_power,
+ self->eeprom_map_p->length_tx_power,
+ self->curr_tx_power,
+ "_sfp_update_attr_curr_tx_power",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!(_sfp_is_diag_support(self))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_power,
+ self->eeprom_map_p->page_rx_power,
+ self->eeprom_map_p->offset_rx_power,
+ self->eeprom_map_p->length_rx_power,
+ self->curr_rx_power,
+ "_sfp_update_attr_curr_rx_power",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_rx_em(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_is_transvr_support_ctle(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_em,
+ self->eeprom_map_p->page_rx_em,
+ self->eeprom_map_p->offset_rx_em,
+ self->eeprom_map_p->length_rx_em,
+ self->rx_em,
+ "_sfp_update_attr_rx_em",
+ show_err);
+}
+
+
+static int
+_sfp_update_attr_tx_eq(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_is_transvr_support_ctle(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_eq,
+ self->eeprom_map_p->page_tx_eq,
+ self->eeprom_map_p->offset_tx_eq,
+ self->eeprom_map_p->length_tx_eq,
+ self->tx_eq,
+ "_sfp_update_attr_tx_eq",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_cdr(struct transvr_obj_s *self,
+ int show_err){
+ if (self->type != TRANSVR_TYPE_QSFP_28){
+ self->cdr = DEBUG_TRANSVR_HEX_VAL;
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_cdr,
+ self->eeprom_map_p->page_cdr,
+ self->eeprom_map_p->offset_cdr,
+ self->eeprom_map_p->length_cdr,
+ &(self->cdr),
+ "_common_update_attr_cdr",
+ show_err);
+}
+
+
+static int
+_qsfg_update_attr_extbr(struct transvr_obj_s *self,
+ int show_err) {
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_extbr,
+ self->eeprom_map_p->page_extbr,
+ self->eeprom_map_p->offset_extbr,
+ self->eeprom_map_p->length_extbr,
+ &(self->extbr),
+ "_common_update_attr_extbr",
+ show_err);
+}
+
+
+static int
+_qsfp_is_diag_support(struct transvr_obj_s *self,
+ int diag_type) {
+ /* Input Parm: diag_type
+ * => 1 : temperature
+ * => 2 : voltage
+ * => 3 : tx relate
+ * => 4 : rx relate
+ */
+ uint8_t mask_b2 = 0x04; /* 0000 0100 */
+ uint8_t mask_b3 = 0x08; /* 0000 1000 */
+
+ switch (diag_type) {
+ case 1: /* temperature */
+ case 2: /* voltage */
+ /* Direct access target, because of spec not defined */
+ return 1;
+ case 3:
+ case 4:
+ /* [Note]
+ * Due to lot of transceiver vendor defined it not rigorously and
+ * consider of general support, we seem it as supported if there
+ * are bit-2 OR bit-3 defined by transceiver vendor.
+ */
+ if ( ((self->diag_type & mask_b2) == mask_b2 ) ||
+ ((self->diag_type & mask_b3) == mask_b3 ) ){
+ return 1;
+ }
+ return 0;
+ default:
+ SWPS_INFO("%s: undefined diag_type:%d\n",
+ __func__, diag_type);
+ break;
+ }
+ return 0;
+}
+
+
+int
+_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) {
+ /*
+ * 00h / Byte-195 / Bit-4
+ */
+ int byte = 2;
+ int bit = 4;
+ return _common_get_option_value(self, byte, bit);
+}
+
+
+int
+_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) {
+ /*
+ * 00h / Byte-195 / Bit-3
+ */
+ int byte = 2;
+ int bit = 3;
+ return _common_get_option_value(self, byte, bit);
+}
+
+
+static int
+_qsfp_update_attr_curr_temp(struct transvr_obj_s *self,
+ int show_err){
+ int diag_type = 1;
+
+ if (!(_qsfp_is_diag_support(self, diag_type))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_temp,
+ self->eeprom_map_p->page_temp,
+ self->eeprom_map_p->offset_temp,
+ self->eeprom_map_p->length_temp,
+ self->curr_temp,
+ "_qsfp_update_attr_curr_temp",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self,
+ int show_err){
+ int diag_type = 2;
+
+ if (!(_qsfp_is_diag_support(self, diag_type))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_voltage,
+ self->eeprom_map_p->page_voltage,
+ self->eeprom_map_p->offset_voltage,
+ self->eeprom_map_p->length_voltage,
+ self->curr_voltage,
+ "_qsfp_update_attr_curr_voltage",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self,
+ int show_err){
+ int diag_type = 3;
+
+ if (!(_qsfp_is_diag_support(self, diag_type))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_bias,
+ self->eeprom_map_p->page_tx_bias,
+ self->eeprom_map_p->offset_tx_bias,
+ self->eeprom_map_p->length_tx_bias,
+ self->curr_tx_bias,
+ "_qsfp_update_attr_curr_tx_bias",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self,
+ int show_err){
+ int diag_type = 3;
+
+ if (!(_qsfp_is_diag_support(self, diag_type))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_power,
+ self->eeprom_map_p->page_tx_power,
+ self->eeprom_map_p->offset_tx_power,
+ self->eeprom_map_p->length_tx_power,
+ self->curr_tx_power,
+ "_qsfp_update_attr_curr_tx_power",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self,
+ int show_err){
+ int diag_type = 4;
+
+ if (!(_qsfp_is_diag_support(self, diag_type))) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_power,
+ self->eeprom_map_p->page_rx_power,
+ self->eeprom_map_p->offset_rx_power,
+ self->eeprom_map_p->length_rx_power,
+ self->curr_rx_power,
+ "_qsfp_update_attr_curr_rx_power",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self,
+ int show_err){
+
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_los,
+ self->eeprom_map_p->page_rx_los,
+ self->eeprom_map_p->offset_rx_los,
+ self->eeprom_map_p->length_rx_los,
+ &(self->rx_los),
+ "_qsfp_update_attr_soft_rx_los",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_qsfp_is_implement_tx_disable(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_disable,
+ self->eeprom_map_p->page_tx_disable,
+ self->eeprom_map_p->offset_tx_disable,
+ self->eeprom_map_p->length_tx_disable,
+ &(self->tx_disable),
+ "_qsfp_update_attr_soft_tx_disable",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_qsfp_is_implement_tx_fault(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_fault,
+ self->eeprom_map_p->page_tx_fault,
+ self->eeprom_map_p->offset_tx_fault,
+ self->eeprom_map_p->length_tx_fault,
+ &(self->tx_fault),
+ "_qsfp_update_attr_soft_tx_fault",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_tx_eq(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_is_transvr_support_ctle(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_eq,
+ self->eeprom_map_p->page_tx_eq,
+ self->eeprom_map_p->offset_tx_eq,
+ self->eeprom_map_p->length_tx_eq,
+ self->tx_eq,
+ "_qsfp_update_attr_tx_eq",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_rx_am(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_is_transvr_support_ctle(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_am,
+ self->eeprom_map_p->page_rx_am,
+ self->eeprom_map_p->offset_rx_am,
+ self->eeprom_map_p->length_rx_am,
+ self->rx_am,
+ "_qsfp_update_attr_rx_am",
+ show_err);
+}
+
+
+static int
+_qsfp_update_attr_rx_em(struct transvr_obj_s *self,
+ int show_err){
+
+ if (!_is_transvr_support_ctle(self)) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ return _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_em,
+ self->eeprom_map_p->page_rx_em,
+ self->eeprom_map_p->offset_rx_em,
+ self->eeprom_map_p->length_rx_em,
+ self->rx_em,
+ "_qsfp_update_attr_rx_em",
+ show_err);
+}
+
+
+int
+_common_update_attr_all(struct transvr_obj_s *self,
+ int show_err){
+
+ char *err_str = "err";
+
+ if (_common_update_attr_id(self, show_err) < 0) {
+ err_str = "_common_update_attr_id";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_extended_id(self, show_err) < 0) {
+ err_str = "_common_update_attr_extended_id";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_connector(self, show_err) < 0) {
+ err_str = "_common_update_attr_connector";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_transvr_comp(self, show_err) < 0) {
+ err_str = "_common_update_attr_transvr_comp";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) {
+ err_str = "_common_update_attr_transvr_comp_ext";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_vendor_name(self, show_err) < 0) {
+ err_str = "_common_update_attr_vendor_name";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_vendor_pn(self, show_err) < 0) {
+ err_str = "_common_update_attr_vendor_pn";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_vendor_rev(self, show_err) < 0) {
+ err_str = "_common_update_attr_vendor_rev";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_vendor_sn(self, show_err) < 0) {
+ err_str = "_common_update_attr_vendor_sn";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_br(self, show_err) < 0) {
+ err_str = "_common_update_attr_br";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_len_smf(self, show_err) < 0) {
+ err_str = "_common_update_attr_len_smf";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_len_om1(self, show_err) < 0) {
+ err_str = "_common_update_attr_len_om1";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_len_om2(self, show_err) < 0) {
+ err_str = "_common_update_attr_len_om2";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_len_om3(self, show_err) < 0) {
+ err_str = "_common_update_attr_len_om3";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_len_om4(self, show_err) < 0) {
+ err_str = "_common_update_attr_len_om4";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_option(self, show_err) < 0) {
+ err_str = "_common_update_attr_option";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_comp_rev(self, show_err) < 0) {
+ err_str = "_common_update_attr_comp_rev";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_diag_type(self, show_err) < 0) {
+ err_str = "_common_update_attr_diag_type";
+ goto err_common_update_attr_all;
+ }
+ if (_common_update_attr_wavelength(self, show_err) < 0) {
+ err_str = "_common_update_attr_wavelength";
+ goto err_common_update_attr_all;
+ }
+ return 0;
+
+err_common_update_attr_all:
+ if (show_err){
+ SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name);
+ }
+ return -1;
+}
+
+
+int
+_sfp_update_attr_all(struct transvr_obj_s *self,
+ int show_err){
+
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+
+ if (_common_update_attr_all(self, show_err) < 0){
+ err_str = "_common_update_attr_all";
+ goto err_sfp_update_attr_all;
+ }
+ if (_sfp_update_attr_len_sm(self, show_err) < 0) {
+ err_str = "_sfp_update_attr_len_sm";
+ goto err_sfp_update_attr_all;
+ }
+ if (_sfp_update_attr_rate_id(self, show_err) < 0) {
+ err_str = "_sfp_update_attr_rate_id";
+ goto err_sfp_update_attr_all;
+ }
+ if ((self->rate_id) > 0) {
+ if (_sfp_update_attr_soft_rs0(self, show_err) < 0) {
+ err_str = "_sfp_update_attr_soft_rs0";
+ goto err_sfp_update_attr_all;
+ }
+ if (_sfp_update_attr_soft_rs1(self, show_err) < 0) {
+ err_str = "_sfp_update_attr_soft_rs1";
+ goto err_sfp_update_attr_all;
+ }
+ }
+ return 0;
+
+err_sfp_update_attr_all:
+ if (show_err){
+ SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name);
+ }
+ return -1;
+}
+
+
+int
+_qsfp_update_attr_all(struct transvr_obj_s *self,
+ int show_err){
+
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+
+ if (_common_update_attr_all(self, show_err) < 0){
+ err_str = "_common_update_attr_all";
+ goto err_qsfp_update_attr_all;
+ }
+ if (_qsfg_update_attr_extbr(self, show_err) < 0) {
+ err_str = "_qsfg_update_attr_extbr";
+ goto err_qsfp_update_attr_all;
+ }
+ if (self->type == TRANSVR_TYPE_QSFP_28) {
+ if (_qsfp_update_attr_cdr(self, 1) < 0) {
+ err_str = "_qsfp_update_attr_cdr";
+ goto err_qsfp_update_attr_all;
+ }
+ }
+ return 0;
+
+err_qsfp_update_attr_all:
+ if (show_err){
+ SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name);
+ }
+ return -1;
+}
+
+
+/* ========== Object functions for common type ==========
+ */
+int
+_common_count_temp(uint8_t high_byte,
+ uint8_t low_byte,
+ char *buf_p) {
+ int sign = 0;
+ int high = 0;
+ int low = 0;
+ int lmax = 8;
+
+ /* Count high */
+ sign = get_bit(high_byte,7);
+ SWP_BIT_CLEAR(high_byte, 7);
+ high = (int)high_byte;
+ if (sign == 1) {
+ high = 0 - high;
+ }
+ /* Count low */
+ low = (get_bit(low_byte, 7) * 500);
+ low += (get_bit(low_byte, 6) * 250);
+ low += (get_bit(low_byte, 5) * 125);
+ low += (get_bit(low_byte, 4) * 62);
+ low = (low / 100);
+ /* Integrate High and Low */
+ return snprintf(buf_p, lmax, "%d.%d\n", high, low);
+}
+
+
+int
+_common_count_voltage(uint8_t high_byte,
+ uint8_t low_byte,
+ char *buf_p) {
+ /* [Note]:
+ * Internally measured transceiver supply voltage. Represented
+ * as a 16 bit unsigned integer with the voltage defined as the
+ * full 16 bit value (0-65535) with LSB equal to 100 uVolt,
+ * yielding a total range of 0 to +6.55 Volts. Practical
+ * considerations to be defined by transceiver manufacturer will
+ * tend to limit the actual bounds of the supply voltage measurement.
+ * Accuracy is vendor specific but must be better than 3% of the
+ * manufacturer's nominal value over specified operating temperature
+ * and voltage. Note that in some transceivers, transmitter supply
+ * voltage and receiver supply voltage are isolated. In that case,
+ * only one supply is monitored. Refer to the device specification
+ * for more detail.
+ */
+ int total = 0;
+ int lmax = 8;
+ int val_i = 0;
+ int val_f = 0;
+ /* unit: 100 uV (1mV=1000uV) */
+ total = transform_word_to_int(high_byte, low_byte);
+ val_i = ((total/10) / 1000);
+ val_f = ((total/10) - (val_i*1000));
+ /* Return Unit: 1 Volt */
+ return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f);
+}
+
+
+int
+_common_count_tx_bias(uint8_t high_byte,
+ uint8_t low_byte,
+ char *buf_p) {
+ /* [Note]
+ * Measured TX bias current in uA. Represented as a 16 bit unsigned
+ * integer with the current defined as the full 16 bit value (0-65535)
+ * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA.
+ * Accuracy is vendor specific but must be better than 10% of the
+ * manufacturer's nominal value over specified operating temperature
+ * and voltage.
+ */
+ int total = 0;
+ int lmax = 8;
+ int val_i = 0;
+ int val_f = 0;
+ /* unit: 2 uA (1mA=1000uA) */
+ total = transform_word_to_int(high_byte, low_byte);
+ val_i = ((total*2) / 1000);
+ val_f = (((total*2) - (val_i*1000)) / 100);
+ /* Return Unit: 1 mA */
+ return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f);
+}
+
+
+int
+_common_count_tx_power(uint8_t high_byte,
+ uint8_t low_byte,
+ char *buf_p) {
+ /* [Note]
+ * Measured TX output power in mW. Represented as a 16 bit unsigned
+ * integer with the power defined as the full 16 bit value (0-65535)
+ * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW
+ * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of
+ * laser monitor photodiode current. It is factory calibrated to absolute
+ * units using the most representative fiber output type. Accuracy is
+ * vendor specific but must be better than 3dB over specified temperature
+ * and voltage. Data is not valid when the transmitter is disabled.
+ */
+ int total = 0;
+ int lmax = 8;
+ int val_i = 0;
+ int val_f = 0;
+ /* unit: 0.1 uW (1mW=1000uW) */
+ total = transform_word_to_int(high_byte, low_byte);
+ val_i = ((total/10) / 1000);
+ val_f = ((total/10) - (val_i*1000));
+ /* Return Unit: 1 mW */
+ return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f);
+}
+
+
+int
+_common_count_rx_power(uint8_t high_byte,
+ uint8_t low_byte,
+ char *buf_p) {
+ /* [Note]
+ * Measured RX received optical power in mW. Value can represent either
+ * average received power or OMA depending upon how bit 3 of byte 92 (A0h)
+ * is set. Represented as a 16 bit unsigned integer with the power defined
+ * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a
+ * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is
+ * dependent upon the exact optical wavelength. For the vendor specified
+ * wavelength, accuracy shall be better than 3dB over specified temperature
+ * and voltage.
+ */
+ int total = 0;
+ int lmax = 8;
+ int val_i = 0;
+ int val_f = 0;
+ /* unit: 0.1 uW (1mW=1000uW) */
+ total = transform_word_to_int(high_byte, low_byte);
+ val_i = ((total/10) / 1000);
+ val_f = ((total/10) - (val_i*1000));
+ /* Return Unit: 1 mW */
+ return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f);
+}
+
+
+int
+_common_count_wavelength(struct transvr_obj_s *self,
+ uint8_t high_byte,
+ uint8_t low_byte) {
+ /* [Note]
+ * SFP : uint 1 um.
+ * QSFP: unit 0.05 um.
+ */
+ int total = 0;
+
+ total = transform_word_to_int(high_byte, low_byte);
+ switch (self->type) {
+ case TRANSVR_TYPE_SFP:
+ return total;
+
+ case TRANSVR_TYPE_QSFP:
+ case TRANSVR_TYPE_QSFP_PLUS:
+ case TRANSVR_TYPE_QSFP_28:
+ return (total/20);
+
+ default:
+ break;
+ }
+ return ERR_TRANSVR_UNDEFINED;
+}
+
+
+int
+common_get_id(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_id,
+ "common_get_id");
+ if (err_code < 0){
+ return err_code;
+ }
+ /* Transform to INT to show error case */
+ return (int)self->id;
+}
+
+
+int
+common_get_ext_id(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_extended_id,
+ "common_get_ext_id");
+ if (err_code < 0){
+ return err_code;
+ }
+ /* Transform to INT to show error case */
+ return (int)self->ext_id;
+}
+
+
+int
+common_get_connector(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_connector,
+ "common_get_connector");
+ if (err_code < 0){
+ return err_code;
+ }
+ /* Transform to INT to show error case */
+ return (int)self->connector;
+}
+
+
+int
+common_get_vendor_name(struct transvr_obj_s *self, char *buf){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name);
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_vendor_name,
+ "common_get_vendor_name");
+ memset(buf, 0, LEN_TRANSVR_M_STR);
+ if (err < 0){
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+ }
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name);
+}
+
+
+int
+common_get_vendor_pn(struct transvr_obj_s *self, char *buf) {
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn);
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_vendor_pn,
+ "common_get_vendor_pn");
+ memset(buf, 0, LEN_TRANSVR_M_STR);
+ if (err < 0){
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+ }
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn);
+}
+
+
+int
+common_get_vendor_rev(struct transvr_obj_s *self, char *buf) {
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev);
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_vendor_rev,
+ "common_get_vendor_rev");
+ memset(buf, 0, LEN_TRANSVR_M_STR);
+ if (err < 0){
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+ }
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev);
+}
+
+
+int
+common_get_vendor_sn(struct transvr_obj_s *self, char *buf) {
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn);
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_vendor_sn,
+ "common_get_vendor_sn");
+ memset(buf, 0, LEN_TRANSVR_M_STR);
+ if (err < 0){
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+ }
+ return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn);
+}
+
+
+int
+common_get_br(struct transvr_obj_s *self){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return (int)self->br;
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_br,
+ "common_get_br");
+ if (err < 0){
+ return err;
+ }
+ /* Transform to INT to show error case */
+ return (int)self->br;
+}
+
+
+int
+common_get_len_smf(struct transvr_obj_s *self){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return self->len_smf;
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_len_smf,
+ "common_get_len_smf");
+ if (err < 0){
+ return err;
+ }
+ return self->len_smf;
+}
+
+
+int
+common_get_len_om1(struct transvr_obj_s *self){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return self->len_om1;
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_len_om1,
+ "common_get_len_om1");
+ if (err < 0){
+ return err;
+ }
+ return self->len_om1;
+}
+
+
+int
+common_get_len_om2(struct transvr_obj_s *self){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return self->len_om2;
+ }
+
+ err = _check_by_mode(self,
+ &_common_update_attr_len_om2,
+ "common_get_len_om2");
+ if (err < 0){
+ return err;
+ }
+ return self->len_om2;
+}
+
+
+int
+common_get_len_om3(struct transvr_obj_s *self){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return self->len_om3;
+ }
+
+ err = _check_by_mode(self,
+ &_common_update_attr_len_om3,
+ "common_get_len_om3");
+ if (err < 0){
+ return err;
+ }
+ return self->len_om3;
+}
+
+
+int
+common_get_len_om4(struct transvr_obj_s *self){
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ if (self->state == STATE_TRANSVR_CONNECTED &&
+ self->mode == TRANSVR_MODE_POLLING &&
+ TRANSVR_INFO_CACHE_ENABLE) {
+ return self->len_om4;
+ }
+ err = _check_by_mode(self,
+ &_common_update_attr_len_om4,
+ "common_get_len_om4");
+ if (err < 0){
+ return err;
+ }
+ return self->len_om4;
+}
+
+
+int
+common_get_comp_extended(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_transvr_comp_ext,
+ "common_get_comp_extended");
+ if (err_code < 0){
+ return err_code;
+ }
+ return self->transvr_comp_ext;
+}
+
+
+int
+common_get_comp_rev(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_comp_rev,
+ "common_get_comp_rev");
+ if (err_code < 0){
+ return err_code;
+ }
+ return self->comp_rev;
+}
+
+
+int
+common_get_info(struct transvr_obj_s *self){
+
+ if (self->state != STATE_TRANSVR_CONNECTED) {
+ return self->state;
+ }
+ return self->info;
+}
+
+
+int
+_common_get_if_lane(struct transvr_obj_s *self,
+ char *result){
+ int i = 0;
+ int tmp_val = 0;
+ char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL;
+
+ memset(result, 0, LEN_TRANSVR_M_STR);
+
+ for (i=0; ilane_id); i++) {
+ tmp_val = self->lane_id[i];
+ if (tmp_val < 1) {
+ break;
+ }
+ memset(tmp_str, 0, LEN_TRANSVR_M_STR);
+ if (i == 0) {
+ snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val);
+ } else {
+ snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val);
+ }
+ strncat(result, tmp_str, LEN_TRANSVR_M_STR);
+ }
+ if (i == 0) {
+ return EVENT_TRANSVR_TASK_FAIL;
+ }
+ return 0;
+}
+
+
+int
+common_get_if_lane(struct transvr_obj_s *self,
+ char *buf_p){
+
+ char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL;
+
+ if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) {
+ return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL);
+ }
+ if (_common_get_if_lane(self, tmp_str) < 0) {
+ return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL);
+ }
+ return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str);
+}
+
+
+int
+sfp_get_len_sm(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_sfp_update_attr_len_sm,
+ "sfp_get_len_sm");
+ if (err_code < 0){
+ return err_code;
+ }
+ return self->len_sm;
+}
+
+
+int
+sfp_get_rate_id(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_sfp_update_attr_rate_id,
+ "sfp_get_rate_id");
+ if (err_code < 0){
+ return err_code;
+ }
+ return self->rate_id;
+}
+
+
+int
+sfp_get_soft_rs0(struct transvr_obj_s *self){
+ /* Note:
+ * SFP Soft Rate_Select Select [aka. "RS(0)"] address
+ * A2h, offset: 110, bit 3 (begin form 0)
+ */
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ int bit_shift = 3;
+ uint8_t result = 0x00;
+ uint8_t bitmask = (1 << bit_shift);
+
+ /* Check rate identifier is supported */
+ err_code = self->get_rate_id(self);
+ if (err_code <= 0) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ /* Update and check */
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_soft_rs0,
+ "sfp_get_soft_rs0");
+ if (err_code <0){
+ return err_code;
+ }
+ result = (self->soft_rs0 & bitmask);
+ if (result == bitmask) {
+ return 1;
+ }
+ if (result == 0) {
+ return 0;
+ }
+ return ERR_TRANSVR_UNEXCPT;
+}
+
+
+int
+sfp_get_soft_rs1(struct transvr_obj_s *self){
+ /* Note:
+ * SFP Soft RS(1) Select address
+ * A2h, offset: 118, bit 3 (begin form 0)
+ */
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ int bit_shift = 3;
+ uint8_t result = 0x00;
+ uint8_t bitmask = (1 << bit_shift);
+
+ /* Check rate identifier is supported */
+ err_code = self->get_rate_id(self);
+ if (err_code <= 0) {
+ return ERR_TRANSVR_NOTSUPPORT;
+ }
+ /* Update and check */
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_soft_rs1,
+ "sfp_get_soft_rs1");
+ if (err_code <0){
+ return err_code;
+ }
+ result = (self->soft_rs1 & bitmask);
+ if (result == bitmask) {
+ return 1;
+ }
+ if (result == 0) {
+ return 0;
+ }
+ return ERR_TRANSVR_UNEXCPT;
+}
+
+
+int
+sfp_get_transvr_temp(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_curr_temp,
+ "sfp_get_transvr_temp");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return _common_count_temp(self->curr_temp[0],
+ self->curr_temp[1],
+ buf_p);
+}
+
+
+int
+sfp_get_transvr_voltage(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_curr_voltage,
+ "sfp_get_transvr_voltage");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 Volt */
+ return _common_count_voltage(self->curr_voltage[0],
+ self->curr_voltage[1],
+ buf_p);
+}
+
+
+int
+sfp_get_transvr_tx_bias(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_curr_tx_bias,
+ "sfp_get_transvr_tx_bias");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 mA */
+ return _common_count_tx_bias(self->curr_tx_bias[0],
+ self->curr_tx_bias[1],
+ buf_p);
+}
+
+
+int
+sfp_get_transvr_tx_power(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_curr_tx_power,
+ "sfp_get_transvr_tx_power");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 mW */
+ return _common_count_tx_power(self->curr_tx_power[0],
+ self->curr_tx_power[1],
+ buf_p);
+}
+
+
+int
+sfp_get_transvr_rx_power(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_sfp_update_attr_curr_rx_power,
+ "sfp_get_transvr_rx_power");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 mW */
+ return _common_count_rx_power(self->curr_rx_power[0],
+ self->curr_rx_power[0],
+ buf_p);
+}
+
+
+int
+sfp_get_transvr_rx_em(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int limt = 8;
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ err = _check_by_mode(self,
+ &_sfp_update_attr_rx_em,
+ "sfp_get_transvr_rx_em");
+ if (err < 0) {
+ return snprintf(buf_p, limt, "%d\n", err);
+ }
+ if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]);
+}
+
+
+int
+sfp_get_transvr_tx_eq(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int limt = 8;
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ err = _check_by_mode(self,
+ &_sfp_update_attr_tx_eq,
+ "sfp_get_transvr_tx_eq");
+ if (err < 0) {
+ return snprintf(buf_p, limt, "%d\n", err);
+ }
+ if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]);
+}
+
+
+int
+_sfp_get_comp_extended(struct transvr_obj_s *self) {
+ /* Address: A0h / 36
+ * Reference: SFF-8024 TABLE 4-4
+ */
+ if ((self->state == STATE_TRANSVR_CONNECTED) ||
+ (self->state == STATE_TRANSVR_INIT) ) {
+ return (int)(self->transvr_comp_ext);
+ }
+ return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+__sfp_get_comp_attr(struct transvr_obj_s *self,
+ int array_offset) {
+ /* SFP Specification Compliance: A0h / 3-10
+ * transvr_comp[0-7] = 3 - 10
+ */
+ if ((self->state == STATE_TRANSVR_CONNECTED) ||
+ (self->state == STATE_TRANSVR_INIT) ) {
+ return (int)(self->transvr_comp[array_offset]);
+ }
+ return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) {
+ /* transvr_comp[0] = address A0h / 3
+ *
+ * 3 7: 10G Base-ER
+ * 3 6: 10GBASE-LRM
+ * 3 5: 10GBASE-LR
+ * 3 4: 10GBASE-SR
+ */
+ int bitmask = 0xf0; /* 11110000 */
+ return (__sfp_get_comp_attr(self, 0) & bitmask);
+}
+
+
+int
+_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) {
+ /* transvr_comp[3] = address A0h / 6
+ *
+ * 6 7: BASE-PX *3
+ * 6 6: BASE-BX10 *3
+ * 6 5: 100BASE-FX
+ * 6 4: 100BASE-LX/LX10
+ * 6 3: 1000BASE-T
+ * 6 2: 1000BASE-CX
+ * 6 1: 1000BASE-LX *3
+ * 6 0: 1000BASE-SX
+ */
+ return __sfp_get_comp_attr(self, 3);
+}
+
+
+int
+_sfp_get_cable_tech(struct transvr_obj_s *self) {
+ /* transvr_comp[5] = address A0h / 8
+ *
+ * 8 3: Active Cable *8
+ * 8 2: Passive Cable *8
+ */
+ int bitmask = 0x0c; /* 00001100 */
+ return (__sfp_get_comp_attr(self, 5) & bitmask);
+}
+
+
+int
+sfp_get_comp_eth_1(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_transvr_comp,
+ "sfp_get_comp_eth_1");
+ if (err_code < 0){
+ return err_code;
+ }
+ return _sfp_get_comp_1g_eth_comp(self);
+}
+
+
+int
+sfp_get_comp_eth_10(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_transvr_comp,
+ "sfp_get_comp_eth_10");
+ if (err_code < 0){
+ return err_code;
+ }
+ return _sfp_get_comp_10g_eth_comp(self);
+}
+
+
+int
+_sfp_get_connector_type(struct transvr_obj_s *self) {
+ /* Address: A0h / 2
+ * Reference: SFF-8024 TABLE 4-3
+ */
+ if ((self->state == STATE_TRANSVR_CONNECTED) ||
+ (self->state == STATE_TRANSVR_INIT) ) {
+ return (int)(self->connector);
+ }
+ return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+sfp_get_wavelength(struct transvr_obj_s *self,
+ char *buf_p) {
+ /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472)
+ * [Addr] A0h, Bytes 60-61
+ * [Note] For optical variants, as defined by having zero's in A0h Byte 8
+ * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output
+ * wavelength at room temperature. 16 bit value with byte 60 as high
+ * order byte and byte 61 as low order byte. The laser wavelength is
+ * equal to the 16 bit integer value in nm. This field allows the user
+ * to read the laser wavelength directly, so it is not necessary to
+ * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table
+ * 5-3). This also allows specification of wavelengths not covered
+ * in the Transceiver Codes, such as those used in coarse WDM systems.
+ *
+ * For passive and active cable variants, a value of 00h for both A0h
+ * Byte 60 and Byte 61 denotes laser wavelength or cable specification
+ * compliance is unspecified.
+ */
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_common_update_attr_wavelength,
+ "common_get_wavelength");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* unit: 1 um */
+ return snprintf(buf_p, lmax, "%d\n",
+ _common_count_wavelength(self,
+ self->wavelength[0],
+ self->wavelength[1]));
+}
+
+
+int
+__qsfp_get_power_cls(struct transvr_obj_s *self,
+ int direct_access){
+
+ int err_code;
+ uint8_t detect_val;
+
+ /* Detect and Update power class attribute */
+ if (direct_access){
+ err_code = _check_by_mode(self,
+ &_common_update_attr_extended_id,
+ "__qsfp_get_power_cls");
+ } else {
+ err_code = self->ext_id;
+ }
+ if (err_code <0){
+ return err_code;
+ }
+ if (err_code == DEBUG_TRANSVR_HEX_VAL){
+ return ERR_TRANSVR_UPDATE_FAIL;
+ }
+ /* Clean data */
+ detect_val = self->ext_id;
+ SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */
+ SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */
+ SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */
+ SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */
+ /* Identify power class */
+ switch (detect_val) {
+ case 0: /* Class_1: 00000000 */
+ return 1;
+ case 64: /* Class_2: 01000000 */
+ return 2;
+ case 128: /* Class_3: 10000000 */
+ return 3;
+ case 192: /* Class_4: 11000000 */
+ return 4;
+ case 1: /* Class_5: 00000001 */
+ case 193: /* Class_5: 11000001 */
+ return 5;
+ case 2: /* Class_6: 00000010 */
+ case 194: /* Class_6: 11000010 */
+ return 6;
+ case 3: /* Class_7: 00000011 */
+ case 195: /* Class_7: 11000011 */
+ return 7;
+ default:
+ break;
+ }
+ SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val);
+ return ERR_TRANSVR_UNDEFINED;
+}
+
+
+int
+qsfp_get_power_cls(struct transvr_obj_s *self) {
+ return __qsfp_get_power_cls(self, 1);
+}
+
+
+int
+__qsfp_get_cdr_present(struct transvr_obj_s *self,
+ int direct_access){
+
+ int retval;
+ int BIT_SHIFT = 2;
+ int BIT_MASK = 0x3;
+
+ /* Detect and Update power class attribute */
+ if (direct_access) {
+ retval = _check_by_mode(self,
+ &_common_update_attr_extended_id,
+ "__qsfp_get_cdr_present");
+ if (retval < 0){
+ return retval;
+ }
+ }
+ retval = self->ext_id;
+ if (retval == DEBUG_TRANSVR_HEX_VAL){
+ return ERR_TRANSVR_UPDATE_FAIL;
+ }
+ /* Clean data and return */
+ return (int)(retval >> BIT_SHIFT & BIT_MASK);
+}
+
+
+int
+qsfp_get_cdr_present(struct transvr_obj_s *self) {
+ return __qsfp_get_cdr_present(self, 1);
+}
+
+
+int
+qsfp_get_cdr(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_qsfp_update_attr_cdr,
+ "qsfp_get_cdr");
+ if (err_code <0){
+ return err_code;
+ }
+
+ return self->cdr;
+}
+
+
+int
+__qsfp_get_comp_attr(struct transvr_obj_s *self,
+ int array_offset) {
+ /* QSFP Specification Compliance: 00h / 131-138
+ * transvr_comp[0-7] = 131 - 138
+ */
+ if ((self->state == STATE_TRANSVR_CONNECTED) ||
+ (self->state == STATE_TRANSVR_INIT) ) {
+ return (int)(self->transvr_comp[array_offset]);
+ }
+ return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) {
+ /* transvr_comp[0] = address 00h / 131
+ *
+ * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance
+ * Codes are maintained in the Transceiver Management section of SFF-
+ * 8024.
+ * 131 6: 10GBASE-LRM
+ * 131 5: 10GBASE-LR
+ * 131 4: 10GBASE-SR
+ * 131 3: 40GBASE-CR4
+ * 131 2: 40GBASE-SR4
+ * 131 1: 40GBASE-LR4
+ * 131 0: 40G Active Cable (XLPPI)
+ */
+ return __qsfp_get_comp_attr(self, 0);
+}
+
+
+int
+_qsfp_get_comp_sonet(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 132 7-3: Reserved
+ * 132 2: OC 48, long reach
+ * 132 1: OC 48, intermediate reach
+ * 132 0: OC 48 short reach
+ */
+ return __qsfp_get_comp_attr(self, 1);
+}
+
+
+int
+_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 133 7: SAS 24.0 Gb/s
+ * 133 6: SAS 12.0 Gb/s
+ * 133 5: SAS 6.0 Gb/s
+ * 133 4: SAS 3.0 Gb/s
+ * 133 3-0: Reserved
+ */
+ return __qsfp_get_comp_attr(self, 2);
+}
+
+
+int
+_qsfp_get_comp_ethernet(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 134 7-4: Reserved
+ * 134 3: 1000BASE-T
+ * 134 2: 1000BASE-CX
+ * 134 1: 1000BASE-LX
+ * 134 0: 1000BASE-SX
+ */
+ return __qsfp_get_comp_attr(self, 3);
+}
+
+
+int
+_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 135 7: Very long distance (V)
+ * 135 6: Short distance (S)
+ * 135 5: Intermediate distance (I)
+ * 135 4: Long distance (L)
+ * 135 3: Medium (M)
+ */
+ int mask = 0xFC; /* 11111100 */
+ return (__qsfp_get_comp_attr(self, 4) & mask);
+}
+
+
+int
+_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 135 2: Reserved
+ * 135 1: Longwave laser (LC)
+ * 135 0: Electrical inter-enclosure (EL)
+ *
+ * 136 7: Electrical intra-enclosure
+ * 136 6: Shortwave laser w/o OFC (SN)
+ * 136 5: Shortwave laser w OFC (SL)
+ * 136 4: Longwave Laser (LL)
+ * 136 3-0: Reserved
+ *
+ * return value = [bit 8-15:addr 135][bit 0-7:addr 136]
+ */
+ int mask_135 = 7; /* 00000111 */
+ int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135);
+ int val_136 = __qsfp_get_comp_attr(self, 5);
+ return ((val_135 << 7) + val_136);
+}
+
+
+int
+_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 137 7: Twin Axial Pair (TW)
+ * 137 6: Shielded Twisted Pair (TP)
+ * 137 5: Miniature Coax (MI)
+ * 137 4: Video Coax (TV)
+ * 137 3: Multi-mode 62.5 m (M6)
+ * 137 2: Multi-mode 50 m (M5)
+ * 137 1: Multi-mode 50 um (OM3)
+ * 137 0: Single Mode (SM)
+ */
+ return __qsfp_get_comp_attr(self, 6);
+}
+
+
+int
+_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) {
+ /* transvr_comp[1] = address 00h / 132
+ *
+ * 138 7: 1200 MBps (per channel)
+ * 138 6: 800 MBps
+ * 138 5: 1600 MBps (per channel)
+ * 138 4: 400 MBps
+ * 138 3: 3200 MBps (per channel)
+ * 138 2: 200 MBps
+ * 138 1: Extended: See section 6.3.23. The Extended Specification
+ * Compliance Codes are maintained in the Transceiver Management
+ * section of SFF-8024.
+ * 138 0: 100 MBps
+ */
+ return __qsfp_get_comp_attr(self, 7);
+}
+
+
+int
+_qsfp_get_comp_extended(struct transvr_obj_s *self) {
+ /* Address: 00h / 192
+ * Reference: SFF-8024 TABLE 4-4
+ */
+ if ((self->state == STATE_TRANSVR_CONNECTED) ||
+ (self->state == STATE_TRANSVR_INIT) ) {
+ return (int)(self->transvr_comp_ext);
+ }
+ return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+qsfp_get_comp_eth(struct transvr_obj_s *self){
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_transvr_comp,
+ "qsfp_get_comp_eth");
+ if (err_code < 0){
+ return err_code;
+ }
+ return _qsfp_get_comp_ethernet(self);
+}
+
+
+int
+qsfp_get_comp_10_40(struct transvr_obj_s *self) {
+
+ int err_code = _check_by_mode(self,
+ &_common_update_attr_transvr_comp,
+ "qsfp_get_comp_10_40");
+ if (err_code < 0){
+ return err_code;
+ }
+ return _qsfp_get_comp_10_40_100_ethernet(self);
+}
+
+
+int
+_qsfp_get_connector_type(struct transvr_obj_s *self) {
+ /* Address: 00h / 130
+ * Reference: SFF-8024 TABLE 4-3
+ */
+ if ((self->state == STATE_TRANSVR_CONNECTED) ||
+ (self->state == STATE_TRANSVR_INIT) ) {
+ return (int)(self->connector);
+ }
+ return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+qsfp_get_transvr_temp(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_curr_temp,
+ "qsfp_get_transvr_temp");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return _common_count_temp(self->curr_temp[0],
+ self->curr_temp[1],
+ buf_p);
+}
+
+
+int
+qsfp_get_transvr_voltage(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_curr_voltage,
+ "qsfp_get_transvr_voltage");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 Volt */
+ return _common_count_voltage(self->curr_voltage[0],
+ self->curr_voltage[1],
+ buf_p);
+}
+
+
+int
+qsfp_get_transvr_tx_eq(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int limt = 8;
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ err = _check_by_mode(self,
+ &_qsfp_update_attr_tx_eq,
+ "qsfp_get_transvr_tx_eq");
+ if (err < 0) {
+ return snprintf(buf_p, limt, "%d\n", err);
+ }
+ if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return snprintf(buf_p, limt, "0x%02x%02x\n",
+ self->tx_eq[0], self->tx_eq[1]);
+}
+
+
+int
+qsfp_get_transvr_rx_am(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int limt = 8;
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ err = _check_by_mode(self,
+ &_qsfp_update_attr_rx_am,
+ "qsfp_get_transvr_rx_am");
+ if (err < 0) {
+ return snprintf(buf_p, limt, "%d\n", err);
+ }
+ if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return snprintf(buf_p, limt, "0x%02x%02x\n",
+ self->rx_am[0], self->rx_am[1]);
+}
+
+
+int
+qsfp_get_transvr_rx_em(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int limt = 8;
+ int err = DEBUG_TRANSVR_INT_VAL;
+
+ err = _check_by_mode(self,
+ &_qsfp_update_attr_rx_em,
+ "qsfp_get_transvr_rx_em");
+ if (err < 0) {
+ return snprintf(buf_p, limt, "%d\n", err);
+ }
+ if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ return snprintf(buf_p, limt, "0x%02x%02x\n",
+ self->rx_em[0], self->rx_em[1]);
+}
+
+
+int
+_qsfp_get_channel_diag(uint8_t *data_array,
+ int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p),
+ char *ch_name,
+ char *result_p) {
+ int i, high, low;
+ int len_max = 128;
+ char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL,
+ DEBUG_TRANSVR_STR_VAL,
+ DEBUG_TRANSVR_STR_VAL,
+ DEBUG_TRANSVR_STR_VAL };
+
+ for (i=0; i<4; i++) {
+ high = (i*2);
+ low = ((i*2) + 1);
+ count_func(data_array[high], data_array[low], ch_buf[i]);
+ }
+ return snprintf(result_p, len_max,
+ "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s",
+ ch_name, 1, ch_buf[0],
+ ch_name, 2, ch_buf[1],
+ ch_name, 3, ch_buf[2],
+ ch_name, 4, ch_buf[3]);
+}
+
+
+int
+qsfp_get_soft_rx_los(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int mask = 0x0f; /* Bit 0 ~ Bit 3 */
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_soft_rx_los,
+ "qsfp_get_soft_rx_los");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask));
+}
+
+
+int
+qsfp_get_soft_tx_disable(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int mask = 0x0f; /* Bit 0 ~ Bit 3 */
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_soft_tx_disable,
+ "qsfp_get_soft_tx_disable");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask));
+}
+
+
+int
+qsfp_get_soft_tx_fault(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int mask = 0x0f; /* Bit 0 ~ Bit 3 */
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_soft_tx_fault,
+ "qsfp_get_soft_tx_fault");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask));
+}
+
+
+int
+qsfp_get_auto_tx_disable(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) {
+ return snprintf(buf_p, LEN_TRANSVR_S_STR,
+ "%d\n", ERR_TRANSVR_FUNC_DISABLE);
+ }
+ return snprintf(buf_p, LEN_TRANSVR_S_STR,
+ "0x%02x\n", self->auto_tx_disable);
+}
+
+
+int
+qsfp_get_transvr_tx_bias(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ char *ch_name = "TX";
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_curr_tx_bias,
+ "qsfp_get_transvr_tx_bias");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 mA */
+ return _qsfp_get_channel_diag(self->curr_tx_bias,
+ _common_count_tx_bias,
+ ch_name,
+ buf_p);
+}
+
+
+int
+qsfp_get_transvr_tx_power(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ char *ch_name = "TX";
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_curr_tx_power,
+ "qsfp_get_transvr_tx_power");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 mW */
+ return _qsfp_get_channel_diag(self->curr_tx_power,
+ _common_count_tx_power,
+ ch_name,
+ buf_p);
+}
+
+
+int
+qsfp_get_transvr_rx_power(struct transvr_obj_s *self,
+ char *buf_p) {
+
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ char *ch_name = "RX";
+
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_curr_rx_power,
+ "qsfp_get_transvr_rx_power");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* Return Unit: 1 mW */
+ return _qsfp_get_channel_diag(self->curr_rx_power,
+ _common_count_rx_power,
+ ch_name,
+ buf_p);
+}
+
+
+int
+qsfp_get_wavelength(struct transvr_obj_s *self,
+ char *buf_p) {
+ /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636)
+ * [Addr] 00h 186-187
+ * [Note]
+ * For optical free side devices, this parameter identifies the nominal
+ * transmitter output wavelength at room temperature. This parameter is
+ * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as
+ * low order byte. The laser wavelength is equal to the 16-bit integer value
+ * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate
+ * to cover all relevant wavelengths yet provide enough resolution for all
+ * expected DWDM applications. For accurate representation of controlled
+ * wavelength applications, this value should represent the center of the
+ * guaranteed wavelength range.
+ * If the free side device is identified as copper cable these registers will
+ * be used to define the cable attenuation. An indication of 0 dB attenuation
+ * refers to the case where the attenuation is not known or is unavailable.
+ * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB.
+ * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB.
+ */
+ int lmax = 8;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _check_by_mode(self,
+ &_common_update_attr_wavelength,
+ "common_get_wavelength");
+ if (err_code < 0) {
+ return snprintf(buf_p, lmax, "%d\n", err_code);
+ }
+ if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) {
+ return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+ }
+ /* unit: 1 um */
+ return snprintf(buf_p, lmax, "%d\n",
+ _common_count_wavelength(self,
+ self->wavelength[0],
+ self->wavelength[1]));
+}
+
+
+/* Public Function for Setup Features
+ */
+static int
+__sfp_set_soft_rs(struct transvr_obj_s *self,
+ int input_val,
+ int address,
+ int page,
+ int offset,
+ int bit_shift,
+ uint8_t *attr_p,
+ char *caller,
+ int show_err) {
+
+ int retval = ERR_TRANSVR_UNEXCPT;
+ int err_code = ERR_TRANSVR_UNEXCPT;
+ char *err_msg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t update_val = (*attr_p);
+
+ switch (input_val) {
+ case 0:
+ SWP_BIT_CLEAR(update_val, bit_shift);
+ break;
+ case 1:
+ SWP_BIT_SET(update_val, bit_shift);
+ break;
+ default:
+ retval = ERR_TRANSVR_UNEXCPT;
+ err_code = ERR_TRANSVR_UNEXCPT;
+ err_msg = "Exception occurs";
+ goto err_private_sfp_set_soft_rs_1;
+ }
+ err_code = _common_set_uint8_attr(self,
+ address,
+ page,
+ offset,
+ update_val,
+ attr_p,
+ caller,
+ show_err);
+ if (err_code < 0) {
+ retval = err_code;
+ err_msg = "Write data via i2c fail!";
+ goto err_private_sfp_set_soft_rs_1;
+ }
+ (*attr_p) = update_val;
+ return 0;
+
+err_private_sfp_set_soft_rs_1:
+ if (show_err) {
+ SWPS_INFO("%s: %s :%d :%s\n :%d\n",
+ __func__, err_msg, err_code, self->swp_name, input_val);
+ }
+ return retval;
+}
+
+
+static int
+_sfp_set_soft_rs(struct transvr_obj_s *self,
+ int input_val,
+ int address,
+ int page,
+ int offset,
+ int bit_shift,
+ int (*attr_update_func)(struct transvr_obj_s *self, int show_err),
+ uint8_t *attr_p,
+ char *caller,
+ int show_err) {
+
+ int retval = ERR_TRANSVR_UNEXCPT;
+ int err_code = ERR_TRANSVR_UNEXCPT;
+ char *err_msg = DEBUG_TRANSVR_STR_VAL;
+
+ /* Check input value */
+ if ((input_val != 0) && (input_val != 1)){
+ retval = ERR_TRANSVR_BADINPUT;
+ err_code = ERR_TRANSVR_BADINPUT;
+ err_msg = "Input range incorrect!";
+ goto err_common_sfp_set_soft_rs_1;
+ }
+ /* Check rate identifier is supported */
+ err_code = self->get_rate_id(self);
+ if (err_code <= 0) {
+ switch (err_code) {
+ case 0:
+ retval = ERR_TRANSVR_NOTSUPPORT;
+ err_msg = "Not support this feature";
+ break;
+ case ERR_TRANSVR_UNINIT:
+ retval = ERR_TRANSVR_UNINIT;
+ err_msg = "Check CDR present fail!";
+ break;
+ case ERR_TRANSVR_UNPLUGGED:
+ retval = ERR_TRANSVR_UNPLUGGED;
+ err_msg = "Transceiver unplugged!";
+ break;
+ default:
+ retval = err_code;
+ err_msg = "Check Rate_ID fail!";
+ break;
+ }
+ goto err_common_sfp_set_soft_rs_1;
+ }
+ /* Check and update */
+ err_code = _check_by_mode(self,
+ attr_update_func,
+ caller);
+ if ( (err_code < 0) ||
+ ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){
+ retval = err_code;
+ err_msg = "Get current value fail!";
+ goto err_common_sfp_set_soft_rs_1;
+ }
+ /* Generate and update value */
+ return __sfp_set_soft_rs(self,
+ input_val,
+ address,
+ page,
+ offset,
+ bit_shift,
+ attr_p,
+ caller,
+ show_err);
+
+err_common_sfp_set_soft_rs_1:
+ if (show_err) {
+ SWPS_INFO("%s: %s :%d :%s\n :%d\n",
+ __func__, err_msg, err_code, self->swp_name, input_val);
+ }
+ return retval;
+}
+
+
+int
+sfp_set_soft_rs0(struct transvr_obj_s *self,
+ int input_val) {
+ /* Note:
+ * SFP Soft Rate_Select Select RX ["RS(0)"] address
+ * A2h, offset: 110, bit 3
+ */
+ int bit_shift = 3;
+ int show_err = 1;
+ return _sfp_set_soft_rs(self,
+ input_val,
+ self->eeprom_map_p->addr_soft_rs0,
+ self->eeprom_map_p->page_soft_rs0,
+ self->eeprom_map_p->offset_soft_rs0,
+ bit_shift,
+ &_sfp_update_attr_soft_rs0,
+ &(self->soft_rs0),
+ "sfp_set_soft_rs0",
+ show_err);
+}
+
+
+int
+sfp_set_soft_rs1(struct transvr_obj_s *self,
+ int input_val) {
+ /* Note:
+ * SFP Soft Rate_Select Select RX ["RS(1)"] address
+ * A2h, offset: 118, bit 3
+ */
+ int bit_shift = 3;
+ int show_err = 1;
+ return _sfp_set_soft_rs(self,
+ input_val,
+ self->eeprom_map_p->addr_soft_rs1,
+ self->eeprom_map_p->page_soft_rs1,
+ self->eeprom_map_p->offset_soft_rs1,
+ bit_shift,
+ &_sfp_update_attr_soft_rs1,
+ &(self->soft_rs1),
+ "sfp_set_soft_rs1",
+ show_err);
+}
+
+
+int
+__sfp_set_tx_eq(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t setv = DEBUG_TRANSVR_HEX_VAL;
+
+ if ((input < 0) || (input > 0xFF)) {
+ emsg = "input incorrect";
+ err = ERR_TRANSVR_BADINPUT;
+ goto err_sfp_set_tx_eq;
+ }
+ setv = (uint8_t)input;
+ if (self->tx_eq[0] == setv) {
+ return 0;
+ }
+ err = _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_eq,
+ self->eeprom_map_p->page_tx_eq,
+ self->eeprom_map_p->offset_tx_eq,
+ setv,
+ &(self->tx_eq[0]),
+ "_sfp_set_tx_eq",
+ show_e);
+ if (err < 0) {
+ emsg = "set_uint8_attr fail";
+ goto err_sfp_set_tx_eq;
+ }
+ return 0;
+
+err_sfp_set_tx_eq:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%d\n", __func__, emsg, input);
+ }
+ return err;
+}
+
+
+int
+_sfp_set_tx_eq(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ uint8_t tmp;
+ int i = 0;
+ int retry = 3;
+
+ for (i=0; itx_eq[0];
+ if (_sfp_update_attr_tx_eq(self, show_e) < 0){
+ continue;
+ }
+ if (self->tx_eq[0] == tmp){
+ return 0;
+ }
+ }
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+int
+sfp_set_tx_eq(struct transvr_obj_s *self,
+ int input) {
+
+ int err = _check_by_mode(self,
+ &_sfp_update_attr_tx_eq,
+ "sfp_set_tx_eq");
+ if (err < 0) {
+ SWPS_DEBUG("%s: check fail :%d\n", __func__, err);
+ return err;
+ }
+ return _sfp_set_tx_eq(self, input, 1);
+}
+
+
+int
+__sfp_set_rx_em(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t setv = DEBUG_TRANSVR_HEX_VAL;
+
+ if ((input < 0) || (input > 0xFF)) {
+ emsg = "input incorrect";
+ err = ERR_TRANSVR_BADINPUT;
+ goto err_sfp_set_rx_em;
+ }
+ setv = (uint8_t)input;
+ if (self->rx_em[0] == setv) {
+ return 0;
+ }
+ err = _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_rx_em,
+ self->eeprom_map_p->page_rx_em,
+ self->eeprom_map_p->offset_rx_em,
+ setv,
+ &(self->rx_em[0]),
+ "_sfp_set_rx_em",
+ show_e);
+ if (err < 0) {
+ emsg = "set_uint8_attr fail";
+ goto err_sfp_set_rx_em;
+ }
+ return 0;
+
+err_sfp_set_rx_em:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%d\n", __func__, emsg, input);
+ }
+ return err;
+}
+
+
+int
+_sfp_set_rx_em(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ uint8_t tmp;
+ int i = 0;
+ int retry = 3;
+
+ for (i=0; irx_em[0];
+ if (_sfp_update_attr_rx_em(self, show_e) < 0){
+ continue;
+ }
+ if (self->rx_em[0] == tmp){
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+int
+sfp_set_rx_em(struct transvr_obj_s *self,
+ int input) {
+
+ int err = _check_by_mode(self,
+ &_sfp_update_attr_rx_em,
+ "sfp_set_rx_em");
+ if (err < 0) {
+ SWPS_DEBUG("%s: check fail :%d\n", __func__, err);
+ return err;
+ }
+ return _sfp_set_rx_em(self, input, 1);
+}
+
+
+static int
+__qsfp_set_cdr(struct transvr_obj_s *self,
+ int input_val,
+ int show_err) {
+
+ uint8_t update_val;
+ int CDR_FEATURE_SUPPORTED = 0x3;
+ int retval = ERR_TRANSVR_UNEXCPT;
+ int err_code = ERR_TRANSVR_UNEXCPT;
+ char *err_msg = DEBUG_TRANSVR_STR_VAL;
+ char *func_name = "__qsfp_set_cdr";
+
+ /* Check input value */
+ if ((input_val < 0) || (input_val > 0xff)){
+ retval = ERR_TRANSVR_BADINPUT;
+ err_code = ERR_TRANSVR_BADINPUT;
+ err_msg = "Input range incorrect!";
+ goto err_qsfp_set_cdr_1;
+ }
+ update_val = (uint8_t)input_val;
+ /* Check CDR supported by transceiver */
+ err_code = qsfp_get_cdr_present(self);
+ if (err_code < 0) {
+ retval = err_code;
+ switch (err_code) {
+ case ERR_TRANSVR_UNINIT:
+ err_msg = "Check CDR present fail!";
+ break;
+ case ERR_TRANSVR_UNPLUGGED:
+ err_msg = "Transceiver unplugged!";
+ break;
+ default:
+ err_msg = "Check CDR present fail!";
+ break;
+ }
+ goto err_qsfp_set_cdr_1;
+ }
+ if (err_code != CDR_FEATURE_SUPPORTED) {
+ retval = ERR_TRANSVR_NOTSUPPORT;
+ err_msg = "This transceiver not support CDR!";
+ goto err_qsfp_set_cdr_1;
+ }
+ /* Check and update */
+ err_code = _check_by_mode(self,
+ &_qsfp_update_attr_cdr,
+ func_name);
+ if ( (err_code < 0) ||
+ (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){
+ retval = err_code;
+ err_msg = "Get current value fail!";
+ goto err_qsfp_set_cdr_1;
+ }
+ /* Write input value to transceiver */
+ return _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_cdr,
+ self->eeprom_map_p->page_cdr,
+ self->eeprom_map_p->offset_cdr,
+ update_val,
+ &(self->cdr),
+ func_name,
+ show_err);
+
+err_qsfp_set_cdr_1:
+ if (show_err) {
+ SWPS_INFO("%s: %s :%d :%s\n :%d\n",
+ __func__, err_msg, err_code, self->swp_name, input_val);
+ }
+ return retval;
+}
+
+
+int
+qsfp_set_cdr(struct transvr_obj_s *self,
+ int input_val) {
+ return __qsfp_set_cdr(self, input_val, 1);
+}
+
+
+int
+qsfp_set_soft_tx_disable(struct transvr_obj_s *self,
+ int input_val) {
+
+ int show_err = 1;
+ int in_max = 0xf; /* 1111 */
+ int in_min = 0x0; /* 0000 */
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ int update_val = DEBUG_TRANSVR_INT_VAL;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ retval = _check_by_mode(self,
+ &_qsfp_update_attr_soft_tx_disable,
+ "qsfp_set_soft_tx_disable");
+ if (retval < 0) {
+ snprintf(err_msg, 63, "Not ready. err:%d", retval);
+ goto err_qsfp_set_soft_tx_disable;
+ }
+ if ((input_val > in_max) ||
+ (input_val < in_min) ){
+ retval = ERR_TRANSVR_BADINPUT;
+ snprintf(err_msg, 63, "Input value:%d incorrect!", input_val);
+ goto err_qsfp_set_soft_tx_disable;
+ }
+ if ((self->tx_disable & 0x0f) == input_val) {
+ return 0;
+ }
+ update_val = ((self->tx_disable & 0xf0) & input_val);
+ retval = _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_disable,
+ self->eeprom_map_p->page_tx_disable,
+ self->eeprom_map_p->offset_tx_disable,
+ input_val,
+ &(self->tx_disable),
+ "qsfp_set_tx_disable",
+ show_err);
+ if (retval < 0) {
+ snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval);
+ goto err_qsfp_set_soft_tx_disable;
+ }
+ return 0;
+
+err_qsfp_set_soft_tx_disable:
+ SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name);
+ return retval;
+}
+
+
+int
+_qsfp_set_auto_tx_disable(struct transvr_obj_s *self,
+ uint8_t update) {
+
+ uint8_t tx_enable = 0x0;
+ int show_e = 1;
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ /* Handle timing issues */
+ if (update != tx_enable) {
+ /* Note:
+ * Because there are some txvr has timing issues,
+ * therefore we need to execute reset cycle first.
+ * (enable -> other settings)
+ */
+ err = _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_disable,
+ self->eeprom_map_p->page_tx_disable,
+ self->eeprom_map_p->offset_tx_disable,
+ tx_enable,
+ &(self->tx_disable),
+ "_qsfp_set_auto_tx_disable",
+ show_e);
+ if (err < 0) {
+ emsg = "I2C set reset value fail";
+ goto err_qsfp_set_auto_tx_disable;
+ }
+ mdelay(10);
+ }
+ /* Setup target value */
+ err = _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_disable,
+ self->eeprom_map_p->page_tx_disable,
+ self->eeprom_map_p->offset_tx_disable,
+ self->auto_tx_disable,
+ &(self->tx_disable),
+ "_qsfp_set_auto_tx_disable",
+ show_e);
+ if (err < 0) {
+ emsg = "I2C set target value fail";
+ goto err_qsfp_set_auto_tx_disable;
+ }
+ /* Check and update */
+ err = _common_update_uint8_attr(self,
+ self->eeprom_map_p->addr_tx_disable,
+ self->eeprom_map_p->page_tx_disable,
+ self->eeprom_map_p->offset_tx_disable,
+ self->eeprom_map_p->length_tx_disable,
+ &(self->tx_disable),
+ "_qsfp_set_auto_tx_disable",
+ show_e);
+ if (err < 0) {
+ emsg = "I2C get value fail";
+ goto err_qsfp_set_auto_tx_disable;
+ }
+ if (self->tx_disable != update) {
+ emsg = "data not become effective";
+ goto err_qsfp_set_auto_tx_disable;
+ }
+ return 0;
+
+err_qsfp_set_auto_tx_disable:
+ SWPS_DEBUG("%s: %s :%s\n",
+ __func__, emsg, self->swp_name);
+ return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+int
+qsfp_set_auto_tx_disable(struct transvr_obj_s *self,
+ int input_val) {
+
+ int in_max = 0xf; /* 1111 */
+ int in_min = 0x0; /* 0000 */
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+ /* Update settings*/
+ if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) {
+ emsg = "User disable auto tx_disable";
+ self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE;
+ goto out_qsfp_set_auto_tx_disable;
+ }
+ if ((input_val > in_max) || (input_val < in_min) ){
+ SWPS_INFO("%s: Input value:%d incorrect! :%s\n",
+ __func__, input_val, self->swp_name);
+ return ERR_TRANSVR_BADINPUT;
+ }
+ self->auto_tx_disable = input_val;
+ /* Check current soft tx_disable */
+ retval = _check_by_mode(self,
+ &_qsfp_update_attr_soft_tx_disable,
+ "qsfp_set_auto_tx_disable");
+ switch (retval) {
+ case 0:
+ break;
+ case ERR_TRANSVR_UNPLUGGED:
+ emsg = "Doesn't need to update";
+ goto out_qsfp_set_auto_tx_disable;
+ default:
+ SWPS_INFO("%s: setup fail :%d :%s\n",
+ __func__, retval, self->swp_name);
+ return retval;
+ }
+ return _qsfp_set_auto_tx_disable(self, input_val);
+
+out_qsfp_set_auto_tx_disable:
+ SWPS_DEBUG("%s: %s :%s :%d\n :%d",
+ __func__, emsg, self->swp_name, input_val, retval);
+ return 0;
+}
+
+
+int
+__qsfp_set_tx_eq(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+ /* [Note]
+ * 0x
+ */
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t setv[2] = {0x00, 0x00};
+
+ if ((input < 0) || (input > 0xFFFF)) {
+ emsg = "input incorrect";
+ err = ERR_TRANSVR_BADINPUT;
+ goto err_qsfp_set_tx_eq;
+ }
+ setv[0] = (uint8_t)((input & 0xFF00) >> 8);
+ setv[1] = (uint8_t)(input & 0xFF);
+ if ((self->tx_eq[0] == setv[0]) &&
+ (self->tx_eq[1] == setv[1]) ) {
+ return 0;
+ }
+ err = _common_set_uint8_array(self,
+ self->eeprom_map_p->addr_tx_eq,
+ self->eeprom_map_p->page_tx_eq,
+ self->eeprom_map_p->offset_tx_eq,
+ self->eeprom_map_p->length_tx_eq,
+ setv,
+ self->tx_eq,
+ "_qsfp_set_tx_eq",
+ show_e);
+ if (err < 0) {
+ emsg = "set_uint8_array fail";
+ goto err_qsfp_set_tx_eq;
+ }
+ return 0;
+
+err_qsfp_set_tx_eq:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%d\n", __func__, emsg, input);
+ }
+ return err;
+}
+
+
+int
+_qsfp_set_tx_eq(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ int i = 0;
+ int retry = 3;
+ uint8_t tmp[2];
+
+ for (i=0; itx_eq[0];
+ tmp[1] = self->tx_eq[1];
+ if (_qsfp_update_attr_tx_eq(self, show_e) < 0){
+ continue;
+ }
+ if ((self->tx_eq[0] == tmp[0]) &&
+ (self->tx_eq[1] == tmp[1]) ){
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+int
+qsfp_set_tx_eq(struct transvr_obj_s *self,
+ int input) {
+
+ int err = _check_by_mode(self,
+ &_qsfp_update_attr_tx_eq,
+ "qsfp_set_tx_eq");
+ if (err < 0) {
+ SWPS_DEBUG("%s: check fail :%d\n", __func__, err);
+ return err;
+ }
+ return _qsfp_set_tx_eq(self, input, 1);
+}
+
+
+int
+__qsfp_set_rx_am(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+ /* [Note]
+ * 0x
+ */
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t setv[2] = {0x00, 0x00};
+
+ if ((input < 0) || (input > 0xFFFF)) {
+ emsg = "input incorrect";
+ err = ERR_TRANSVR_BADINPUT;
+ goto err_qsfp_set_rx_am;
+ }
+ setv[0] = (uint8_t)((input & 0xFF00) >> 8);
+ setv[1] = (uint8_t)(input & 0xFF);
+ if ((self->rx_am[0] == setv[0]) &&
+ (self->rx_am[1] == setv[1]) ) {
+ return 0;
+ }
+ err = _common_set_uint8_array(self,
+ self->eeprom_map_p->addr_rx_am,
+ self->eeprom_map_p->page_rx_am,
+ self->eeprom_map_p->offset_rx_am,
+ self->eeprom_map_p->length_rx_am,
+ setv,
+ self->rx_am,
+ "_qsfp_set_rx_am",
+ show_e);
+ if (err < 0) {
+ emsg = "set_uint8_array fail";
+ goto err_qsfp_set_rx_am;
+ }
+ return 0;
+
+err_qsfp_set_rx_am:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%d\n", __func__, emsg, input);
+ }
+ return err;
+}
+
+
+int
+_qsfp_set_rx_am(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ int i = 0;
+ int retry = 3;
+ uint8_t tmp[2];
+
+ for (i=0; irx_am[0];
+ tmp[1] = self->rx_am[1];
+ if (_qsfp_update_attr_rx_am(self, show_e) < 0){
+ continue;
+ }
+ if ((self->rx_am[0] == tmp[0]) &&
+ (self->rx_am[1] == tmp[1]) ){
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+int
+qsfp_set_rx_am(struct transvr_obj_s *self,
+ int input) {
+
+ int err = _check_by_mode(self,
+ &_qsfp_update_attr_rx_am,
+ "qsfp_set_rx_am");
+ if (err < 0) {
+ SWPS_DEBUG("%s: check fail :%d\n", __func__, err);
+ return err;
+ }
+ return _qsfp_set_rx_am(self, input, 1);
+}
+
+
+int
+__qsfp_set_rx_em(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+ /* [Note]
+ * 0x
+ */
+ int err = DEBUG_TRANSVR_INT_VAL;
+ char *emsg = DEBUG_TRANSVR_STR_VAL;
+ uint8_t setv[2] = {0x00, 0x00};
+
+ if ((input < 0) || (input > 0xFFFF)) {
+ emsg = "input incorrect";
+ err = ERR_TRANSVR_BADINPUT;
+ goto err_qsfp_set_rx_em;
+ }
+ setv[0] = (uint8_t)((input & 0xFF00) >> 8);
+ setv[1] = (uint8_t)(input & 0xFF);
+ if ((self->rx_em[0] == setv[0]) &&
+ (self->rx_em[1] == setv[1]) ) {
+ return 0;
+ }
+ err = _common_set_uint8_array(self,
+ self->eeprom_map_p->addr_rx_em,
+ self->eeprom_map_p->page_rx_em,
+ self->eeprom_map_p->offset_rx_em,
+ self->eeprom_map_p->length_rx_em,
+ setv,
+ self->rx_em,
+ "_qsfp_set_rx_em",
+ show_e);
+ if (err < 0) {
+ emsg = "set_uint8_array fail";
+ goto err_qsfp_set_rx_em;
+ }
+ return 0;
+
+err_qsfp_set_rx_em:
+ if (show_e) {
+ SWPS_INFO("%s: %s :%d\n", __func__, emsg, input);
+ }
+ return err;
+}
+
+
+int
+_qsfp_set_rx_em(struct transvr_obj_s *self,
+ int input,
+ int show_e) {
+
+ int i = 0;
+ int retry = 3;
+ uint8_t tmp[2];
+
+ for (i=0; irx_em[0];
+ tmp[1] = self->rx_em[1];
+ if (_qsfp_update_attr_rx_em(self, show_e) < 0){
+ continue;
+ }
+ if ((self->rx_em[0] == tmp[0]) &&
+ (self->rx_em[1] == tmp[1]) ){
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+int
+qsfp_set_rx_em(struct transvr_obj_s *self,
+ int input) {
+
+ int err = _check_by_mode(self,
+ &_qsfp_update_attr_rx_em,
+ "qsfp_set_rx_em");
+ if (err < 0) {
+ SWPS_DEBUG("%s: check fail :%d\n", __func__, err);
+ return err;
+ }
+ return _qsfp_set_rx_em(self, input, 1);
+}
+
+
+int
+common_transvr_dump(struct transvr_obj_s* self){
+
+ char *type_name = "Undefined";
+
+ if (TRANSVR_INFO_DUMP_ENABLE != 1) {
+ return 0;
+ }
+ switch (self->type) {
+ case TRANSVR_TYPE_SFP:
+ type_name = STR_TRANSVR_SFP;
+ break;
+ case TRANSVR_TYPE_QSFP:
+ type_name = STR_TRANSVR_QSFP;
+ break;
+ case TRANSVR_TYPE_QSFP_PLUS:
+ type_name = STR_TRANSVR_QSFP_PLUS;
+ break;
+ case TRANSVR_TYPE_QSFP_28:
+ type_name = STR_TRANSVR_QSFP28;
+ break;
+ case TRANSVR_TYPE_FAKE:
+ type_name = "FAKE";
+ goto ok_common_transvr_dump;
+ case TRANSVR_TYPE_UNPLUGGED:
+ type_name = "UNPLUGGED";
+ goto err_common_transvr_dump;
+ case TRANSVR_TYPE_INCONSISTENT:
+ type_name = "INCONSISTENT";
+ goto err_common_transvr_dump;
+ case TRANSVR_TYPE_ERROR:
+ type_name = "ERROR";
+ goto err_common_transvr_dump;
+
+ default:
+ type_name = "UNEXPECTED";
+ goto err_common_transvr_dump;
+ }
+ printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name);
+ printk(KERN_INFO " |- :%s\n", type_name);
+ printk(KERN_INFO " |- :%s\n", self->vendor_name);
+ printk(KERN_INFO " |- :%s\n", self->vendor_pn);
+ printk(KERN_INFO " |- :%s\n", self->vendor_rev);
+ printk(KERN_INFO " |- :%s\n", self->vendor_sn);
+ printk(KERN_INFO " |- :0x%02x\n", self->br);
+ printk(KERN_INFO " |- :0x%02x\n", self->comp_rev);
+ printk(KERN_INFO " |- :%d\n", self->len_om1);
+ printk(KERN_INFO " |- :%d\n", self->len_om2);
+ printk(KERN_INFO " |- :%d\n", self->len_om3);
+ printk(KERN_INFO " |- :%d\n", self->len_om4);
+ return 0;
+
+ok_common_transvr_dump:
+ SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name);
+ return 0;
+
+err_common_transvr_dump:
+ SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name);
+ return -1;
+}
+
+
+int
+sfp_transvr_dump(struct transvr_obj_s* self) {
+
+ if (TRANSVR_INFO_DUMP_ENABLE != 1) {
+ return 0;
+ }
+ if (common_transvr_dump(self) < 0) {
+ return -1;
+ }
+ printk(KERN_INFO " |- :%d\n", self->len_sm);
+ printk(KERN_INFO " |- :%d\n", self->len_smf);
+ printk(KERN_INFO " '- :0x%02x\n", self->rate_id);
+ return 0;
+}
+
+
+int
+qsfp_transvr_dump(struct transvr_obj_s* self) {
+
+ if (TRANSVR_INFO_DUMP_ENABLE != 1) {
+ return 0;
+ }
+ if (common_transvr_dump(self) < 0) {
+ return -1;
+ }
+ printk(KERN_INFO " |- :%d\n", self->len_smf);
+ printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0));
+ return 0;
+}
+
+
+int
+fake_transvr_dump(struct transvr_obj_s* self) {
+
+ printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name);
+ printk(KERN_INFO " |- :FAKE\n");
+ printk(KERN_INFO " |- :FAKE_VENDER_NAME\n");
+ printk(KERN_INFO " |- :FAKE_VENDER_PN\n");
+ printk(KERN_INFO " |- :FAKE_VENDER_REV\n");
+ printk(KERN_INFO " |- :FAKE_VENDER_SN\n");
+ printk(KERN_INFO " |- :0x99\n");
+ printk(KERN_INFO " |- :99\n");
+ printk(KERN_INFO " |- :99\n");
+ printk(KERN_INFO " |- :99\n");
+ printk(KERN_INFO " |- :99\n");
+ printk(KERN_INFO " |- :99\n");
+ printk(KERN_INFO " |- :99\n");
+ printk(KERN_INFO " '- :0x99\n");
+ return 0;
+}
+
+
+/* ========== Object functions for fake type ==========
+ */
+int
+fake_transvr_update(struct transvr_obj_s *self,
+ int show_err){
+ self->state = STATE_TRANSVR_CONNECTED;
+ return 0;
+}
+
+
+int
+fake_get_binary(struct transvr_obj_s *self){
+ return 1;
+}
+
+int
+fake_get_int(struct transvr_obj_s *self){
+ return 99;
+}
+
+
+int
+fake_get_hex(struct transvr_obj_s *self){
+ return 0x0f;
+}
+
+
+int
+fake_get_str(struct transvr_obj_s *self, char *buf) {
+ return snprintf(buf, 16, "fake_get_str\n");
+}
+
+
+int
+fake_set_int(struct transvr_obj_s *self, int input){
+ SWPS_INFO("%s: %d\n", __func__, input);
+ return 0;
+}
+
+
+int
+fake_set_hex(struct transvr_obj_s *self, int input){
+ SWPS_INFO("%s: 0x%02x\n", __func__, input);
+ return 0;
+}
+
+
+/* ========== Object functions for unsupported ==========
+ */
+int
+unsupported_get_func(struct transvr_obj_s *self){
+ return ERR_TRANSVR_NOTSUPPORT;
+}
+
+
+int
+unsupported_get_func2(struct transvr_obj_s *self,
+ char *buf_p) {
+ int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT);
+ return len;
+}
+
+
+int
+unsupported_set_func(struct transvr_obj_s *self,
+ int input_val){
+ return ERR_TRANSVR_NOTSUPPORT;
+}
+
+
+
+/* ========== Object functions for long term task ==========
+ *
+ * [Note]
+ * SWPS transceiver worker is likely the green-thread (coroutine).
+ * Due to resource and performance considerations. SWPS run all
+ * features in one kthread at the same time, and handle by it self.
+ */
+
+/* For Transceiver Task Handling
+ */
+static struct transvr_worker_s *
+transvr_task_get(struct transvr_obj_s *self,
+ char *func_name) {
+
+ struct transvr_worker_s *curr_p = self->worker_p;
+
+ while(curr_p != NULL){
+ if (strcmp((curr_p->func_name), func_name) == 0 ) {
+ return curr_p;
+ }
+ curr_p = curr_p->next_p;
+ }
+ return NULL;
+}
+
+
+static struct transvr_worker_s*
+transvr_task_creat(struct transvr_obj_s *self,
+ int (*main_task)(struct transvr_worker_s *task),
+ int (*post_task)(struct transvr_worker_s *task),
+ char *caller) {
+
+ struct transvr_worker_s *task_p = NULL;
+ struct transvr_worker_s *curr_p = NULL;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ /* Check task not exist */
+ task_p = transvr_task_get(self, caller);
+ if (task_p) {
+ snprintf(err_msg, sizeof(err_msg), "Task already created!");
+ goto err_transvr_task_creat;
+ }
+ /* Create task worker */
+ task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL);
+ if (!task_p){
+ snprintf(err_msg, sizeof(err_msg), "kzalloc fail");
+ goto err_transvr_task_creat;
+ }
+ /* Setup task data */
+ task_p->transvr_p = self;
+ task_p->next_p = NULL;
+ task_p->trigger_time = 0;
+ task_p->retry = 1;
+ task_p->state = STATE_T_TASK_INIT;
+ task_p->main_task = main_task;
+ task_p->post_task = post_task;
+ task_p->p_data = NULL;
+ snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller);
+ /* Setup Link List */
+ if (self->worker_p) {
+ curr_p = self->worker_p;
+ while(curr_p->next_p != NULL) {
+ curr_p = curr_p->next_p;
+ }
+ curr_p->next_p = task_p;
+ task_p->pre_p = curr_p;
+ } else {
+ self->worker_p = task_p;
+ task_p->pre_p = NULL;
+ }
+ return task_p;
+
+err_transvr_task_creat:
+ SWPS_ERR("%s: %s :%s :%s\n",
+ __func__, err_msg, caller, self->swp_name);
+ return NULL;
+}
+
+
+static void
+transvr_task_free_one(struct transvr_worker_s *task_p){
+
+ struct transvr_worker_s *pre_p = NULL;
+ struct transvr_worker_s *next_p = NULL;
+
+ if (task_p) {
+ pre_p = task_p->pre_p;
+ next_p = task_p->next_p;
+
+ if ((pre_p) && (next_p)) {
+ pre_p->next_p = next_p;
+ next_p->pre_p = pre_p;
+
+ } else if ((!pre_p) && (next_p)) {
+ next_p->pre_p = NULL;
+
+ } else if ((pre_p) && (!next_p)) {
+ pre_p->next_p = NULL;
+
+ } else if ((!pre_p) && (!next_p)) {
+ task_p->transvr_p->worker_p = NULL;
+ } else {
+ SWPS_ERR("%s: Unexcept case!\n :%s",
+ __func__, task_p->transvr_p->swp_name);
+ }
+ kfree(task_p->p_data);
+ kfree(task_p);
+ }
+}
+
+
+static void
+transvr_task_free_all(struct transvr_obj_s *self) {
+
+ struct transvr_worker_s *curr_p = NULL;
+ struct transvr_worker_s *next_p = NULL;
+
+ if (self->worker_p) {
+ curr_p = self->worker_p;
+ while(curr_p) {
+ next_p = curr_p->next_p;
+ transvr_task_free_one(curr_p);
+ curr_p = next_p;
+ }
+ self->worker_p = NULL;
+ }
+}
+
+
+static int
+_transvr_task_run_main(struct transvr_worker_s *task_p) {
+
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ if (!task_p){
+ snprintf(err_msg, sizeof(err_msg), "main_task is NULL!");
+ goto main_transvr_task_err;
+ }
+ if ((task_p->trigger_time) == 0){
+ goto main_transvr_task_run;
+ }
+ if (time_before(jiffies, task_p->trigger_time)){
+ goto main_transvr_task_wait;
+ }
+ goto main_transvr_task_run;
+
+main_transvr_task_run:
+ if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) {
+ task_p->retry -= 1;
+ }
+ retval = task_p->main_task(task_p);
+ if (retval < 0) {
+ if (task_p->retry > 0) {
+ task_p->state = STATE_T_TASK_WAIT;
+ return EVENT_TRANSVR_TASK_WAIT;
+ }
+ snprintf(err_msg, sizeof(err_msg), "Run main_task fail!");
+ goto main_transvr_task_err;
+ }
+ goto main_transvr_task_identify;
+
+main_transvr_task_identify:
+ switch (retval) {
+ case EVENT_TRANSVR_TASK_WAIT:
+ task_p->state = STATE_T_TASK_WAIT;
+ return EVENT_TRANSVR_TASK_WAIT;
+
+ case EVENT_TRANSVR_TASK_DONE:
+ task_p->state = STATE_T_TASK_DONE;
+ return EVENT_TRANSVR_TASK_DONE;
+
+ default:
+ break;
+ }
+ snprintf(err_msg, sizeof(err_msg), "Run main_task fail!");
+ goto main_transvr_task_err;
+
+main_transvr_task_wait:
+ task_p->state = STATE_T_TASK_WAIT;
+ return EVENT_TRANSVR_TASK_WAIT;
+
+main_transvr_task_err:
+ task_p->state = STATE_T_TASK_FAIL;
+ SWPS_INFO("%s: %s :%d :%s\n",
+ __func__, err_msg, retval, task_p->transvr_p->swp_name);
+ return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+static int
+_transvr_task_run_post(struct transvr_worker_s *task_p) {
+
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ if ((task_p->post_task) == NULL) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ switch (task_p->state) {
+ case STATE_T_TASK_WAIT:
+ case STATE_T_TASK_INIT:
+ goto post_transvr_task_wait;
+
+ case STATE_T_TASK_DONE:
+ case STATE_T_TASK_FAIL:
+ goto post_transvr_task_run;
+
+ default:
+ break;
+ }
+ snprintf(err_msg, sizeof(err_msg), "Unexcept task state");
+ goto post_transvr_task_err;
+
+post_transvr_task_run:
+ task_p->post_task(task_p);
+ return EVENT_TRANSVR_TASK_DONE;
+
+post_transvr_task_wait:
+ return EVENT_TRANSVR_TASK_WAIT;
+
+post_transvr_task_err:
+ SWPS_INFO("%s: %s :%d :%s\n",
+ __func__, err_msg, task_p->state, task_p->transvr_p->swp_name);
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+static int
+transvr_task_run_one(struct transvr_worker_s *task_p) {
+
+ int retval_main = DEBUG_TRANSVR_INT_VAL;
+ int retval_post = DEBUG_TRANSVR_INT_VAL;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+ retval_main = _transvr_task_run_main(task_p);
+ if (retval_main < 0) {
+ snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!");
+ goto err_transvr_task_run_one;
+ }
+ retval_post = _transvr_task_run_post(task_p);
+ if (retval_post < 0) {
+ snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!");
+ goto err_transvr_task_run_one;
+ }
+ return retval_main;
+
+err_transvr_task_run_one:
+ SWPS_INFO("%s: %s :%d :%d :%s :%s\n",
+ __func__, err_msg, retval_main, retval_post,
+ task_p->func_name, task_p->transvr_p->swp_name);
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+static int
+transvr_task_run_all(struct transvr_obj_s *self) {
+
+ int haserr = 0;
+ int retval = DEBUG_TRANSVR_INT_VAL;
+ struct transvr_worker_s *curr_p = NULL;
+ struct transvr_worker_s *next_p = NULL;
+
+ if ((self->worker_p) == NULL) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ curr_p = self->worker_p;
+ while (curr_p != NULL) {
+ next_p = curr_p->next_p;
+ retval = transvr_task_run_one(curr_p);
+ if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) {
+ curr_p = next_p;
+ continue;
+ }
+ switch (retval) {
+ case EVENT_TRANSVR_TASK_WAIT:
+ break;
+ case EVENT_TRANSVR_TASK_DONE:
+ transvr_task_free_one(curr_p);
+ break;
+ case EVENT_TRANSVR_TASK_FAIL:
+
+ default:
+ haserr = 1;
+ transvr_task_free_one(curr_p);
+ break;
+ }
+ curr_p = next_p;
+ }
+ if (haserr) {
+ return EVENT_TRANSVR_TASK_FAIL;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+static void
+transvr_task_set_delay(struct transvr_worker_s *task_p,
+ unsigned long delay_msec) {
+
+ task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000)));
+}
+
+
+static void
+transvr_task_set_retry(struct transvr_worker_s *task_p,
+ unsigned long retry_times) {
+
+ task_p->retry = retry_times;
+}
+
+
+/* For Transceiver Post Task
+ */
+int
+taskfunc_post_do_nothing(struct transvr_worker_s *task_p) {
+
+ return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) {
+
+ struct transvr_obj_s* tp = task_p->transvr_p;
+
+ switch (task_p->state) {
+ case STATE_T_TASK_INIT:
+ case STATE_T_TASK_WAIT:
+ return EVENT_TRANSVR_TASK_WAIT;
+
+ case STATE_T_TASK_DONE:
+ tp->state = STATE_TRANSVR_CONNECTED;
+ tp->send_uevent(tp, KOBJ_ADD);
+ return EVENT_TRANSVR_TASK_DONE;
+
+ case STATE_T_TASK_FAIL:
+ tp->state = STATE_TRANSVR_UNEXCEPTED;
+ return EVENT_TRANSVR_TASK_FAIL;
+
+ default:
+ break;
+ }
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+/* For Transceiver Main Task
+ */
+int
+_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p,
+ int input_val,
+ int address,
+ int page,
+ int offset,
+ int bit_shift,
+ uint8_t *attr_p,
+ char *caller) {
+
+ int show_err = 0;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+ char *func_str = "_taskfunc_sfp_setup_soft_rs";
+
+ err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0);
+ if (err_code < 0) {
+ err_str = "Get current soft_rs0 fail!";
+ goto err_taskfunc_sfp_setup_soft_rs_1;
+ }
+ err_code = __sfp_set_soft_rs(task_p->transvr_p,
+ input_val,
+ address,
+ page,
+ offset,
+ bit_shift,
+ attr_p,
+ caller,
+ show_err);
+ if (err_code < 0) {
+ err_str = "Get current soft_rs0 fail!";
+ goto err_taskfunc_sfp_setup_soft_rs_1;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_sfp_setup_soft_rs_1:
+ if ((task_p->retry) == 0) {
+ SWPS_INFO("%s: %s :%s :%d :%d\n",
+ func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code);
+ }
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p,
+ int input_val,
+ int (*get_func)(struct ioexp_obj_s *self, int virt_offset),
+ int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) {
+
+ int err_val = EVENT_TRANSVR_EXCEP_EXCEP;
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+
+ err_val = get_func(task_p->transvr_p->ioexp_obj_p,
+ task_p->transvr_p->ioexp_virt_offset);
+
+ if (err_val < 0) {
+ if (err_val == ERR_IOEXP_NOTSUPPORT) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ err_str = "Get current hard_rs fail!";
+ goto err_p_taskfunc_sfp_setup_hard_rs_1;
+ }
+ if (err_val == input_val) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ err_val = set_func(task_p->transvr_p->ioexp_obj_p,
+ task_p->transvr_p->ioexp_virt_offset,
+ input_val);
+ if (err_val < 0) {
+ err_str = "Setup hard_rs fail!";
+ goto err_p_taskfunc_sfp_setup_hard_rs_1;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_p_taskfunc_sfp_setup_hard_rs_1:
+ if ((task_p->retry) == 0) {
+ SWPS_INFO("%s: %s :%s :%d :%d\n",
+ __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val);
+ }
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p,
+ int input_val) {
+
+ return __taskfunc_sfp_setup_hard_rs(task_p,
+ input_val,
+ task_p->transvr_p->ioexp_obj_p->get_hard_rs0,
+ task_p->transvr_p->ioexp_obj_p->set_hard_rs0);
+}
+
+
+int
+_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p,
+ int input_val) {
+
+ return __taskfunc_sfp_setup_hard_rs(task_p,
+ input_val,
+ task_p->transvr_p->ioexp_obj_p->get_hard_rs1,
+ task_p->transvr_p->ioexp_obj_p->set_hard_rs1);
+}
+
+
+int
+_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p,
+ int input_val) {
+
+ int bit_shift = 3;
+ int old_val = DEBUG_TRANSVR_INT_VAL;
+ int err_val = EVENT_TRANSVR_EXCEP_EXCEP;
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+ char *func_str = "_taskfunc_sfp_setup_rs0";
+
+ err_val = _taskfunc_sfp_setup_hard_rs0(task_p,
+ input_val);
+ if (err_val < 0) {
+ err_str = "Setup hard_rs0 fail!";
+ goto err_private_taskfunc_sfp_setup_rs0_1;
+ }
+ old_val = err_val;
+ err_val = _taskfunc_sfp_setup_soft_rs(task_p,
+ input_val,
+ task_p->transvr_p->eeprom_map_p->addr_soft_rs0,
+ task_p->transvr_p->eeprom_map_p->page_soft_rs0,
+ task_p->transvr_p->eeprom_map_p->offset_soft_rs0,
+ bit_shift,
+ &(task_p->transvr_p->soft_rs0),
+ func_str);
+ if (err_val < 0) {
+ err_str = "Setup soft_rs0 fail!";
+ goto err_private_taskfunc_sfp_setup_rs0_1;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_private_taskfunc_sfp_setup_rs0_1:
+ if ((task_p->retry) == 0) {
+ SWPS_INFO("%s: %s :%s :%d :%d\n",
+ func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val);
+ }
+ _taskfunc_sfp_setup_hard_rs0(task_p, old_val);
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p,
+ int input_val) {
+
+ int bit_shift = 3;
+ int old_val = DEBUG_TRANSVR_INT_VAL;
+ int err_val = EVENT_TRANSVR_EXCEP_EXCEP;
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+ char *func_str = "_taskfunc_sfp_setup_rs1";
+
+ err_val = _taskfunc_sfp_setup_hard_rs1(task_p,
+ input_val);
+ if (err_val < 0) {
+ err_str = "Setup hard_rs1 fail!";
+ goto err_private_taskfunc_sfp_setup_rs1_1;
+ }
+ old_val = err_val;
+ err_val = _taskfunc_sfp_setup_soft_rs(task_p,
+ input_val,
+ task_p->transvr_p->eeprom_map_p->addr_soft_rs1,
+ task_p->transvr_p->eeprom_map_p->page_soft_rs1,
+ task_p->transvr_p->eeprom_map_p->offset_soft_rs1,
+ bit_shift,
+ &(task_p->transvr_p->soft_rs1),
+ func_str);
+ if (err_val < 0) {
+ err_str = "Setup soft_rs1 fail!";
+ goto err_private_taskfunc_sfp_setup_rs1_1;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_private_taskfunc_sfp_setup_rs1_1:
+ if ((task_p->retry) == 0) {
+ SWPS_INFO("%s: %s :%s :%d :%d\n",
+ func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val);
+ }
+ _taskfunc_sfp_setup_hard_rs1(task_p, old_val);
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) {
+ /* SFF-8431 (8/4/2G Rx Rate_Select only) */
+ int update_val = 1;
+
+ return _taskfunc_sfp_setup_rs0(task_p, update_val);
+}
+
+
+
+int
+taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) {
+ /* SFF-8431 (8/4/2G Tx Rate_Select only) */
+ int update_val = 1;
+
+ return _taskfunc_sfp_setup_rs1(task_p, update_val);
+}
+
+
+int
+taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) {
+ /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */
+ int update_rs0 = 1;
+ int update_rs1 = 1;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+
+ err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0);
+ if (err_code < 0) {
+ return err_code;
+ }
+ return _taskfunc_sfp_setup_rs1(task_p, update_rs1);
+}
+
+
+int
+taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) {
+
+ /* Not all of platform support 0x56 for transceiver
+ * external PHY, Support list as below:
+ * => 1. Magnolia-PVT (PS: EVT & DVT not ready)
+ */
+ int ext_phy_addr = 0x56;
+ int ext_phy_page = -1;
+ int ext_phy_offs = 0x11;
+ int ext_phy_len = 1;
+ int lstate_mask = 0x04; /* 00000100 */
+ int show_err = 0;
+ int fail_retry = 5;
+ int fail_delay = 1000; /* msec */
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL;
+ char err_str[64] = DEBUG_TRANSVR_STR_VAL;
+ int *tmp_p = NULL;
+ char *func_name = "taskfunc_sfp_handle_1g_rj45";
+
+ if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) &&
+ (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) {
+ goto err_taskfunc_sfp_handle_1g_rj45_1;
+ }
+ err_code = _common_update_uint8_attr(task_p->transvr_p,
+ ext_phy_addr,
+ ext_phy_page,
+ ext_phy_offs,
+ ext_phy_len,
+ &detect_val,
+ func_name,
+ show_err);
+ if ( (err_code < 0) ||
+ (detect_val == DEBUG_TRANSVR_HEX_VAL) ) {
+ snprintf(err_str, sizeof(err_str), "Detect external link status fail");
+ goto err_taskfunc_sfp_handle_1g_rj45_2;
+ }
+ if ((detect_val & lstate_mask) == lstate_mask) {
+ goto ok_taskfunc_sfp_handle_1g_rj45_link_up;
+ }
+ goto ok_taskfunc_sfp_handle_1g_rj45_link_down;
+
+ok_taskfunc_sfp_handle_1g_rj45_link_up:
+ /* Filter out noise */
+ if (!(task_p->p_data)) {
+ tmp_p = kzalloc(sizeof(int), GFP_KERNEL);
+ if (!tmp_p) {
+ snprintf(err_str, sizeof(err_str), "kzalloc p_data fail");
+ goto err_taskfunc_sfp_handle_1g_rj45_2;
+ }
+ *tmp_p = TRANSVR_CLASS_BASE_T_1000_up;
+ task_p->p_data = tmp_p;
+ goto ok_taskfunc_sfp_handle_1g_rj45_done;
+ }
+ if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) {
+ kfree(task_p->p_data);
+ task_p->p_data = NULL;
+ snprintf(err_str, sizeof(err_str), "Internal error");
+ goto err_taskfunc_sfp_handle_1g_rj45_2;
+ }
+ task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up;
+ kfree(task_p->p_data);
+ task_p->p_data = NULL;
+ goto ok_taskfunc_sfp_handle_1g_rj45_done;
+
+ok_taskfunc_sfp_handle_1g_rj45_link_down:
+ if (task_p->p_data) {
+ kfree(task_p->p_data);
+ task_p->p_data = NULL;
+ }
+ task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000;
+ goto ok_taskfunc_sfp_handle_1g_rj45_done;
+
+ok_taskfunc_sfp_handle_1g_rj45_done:
+ if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) {
+ transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER);
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_sfp_handle_1g_rj45_1:
+ snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.",
+ task_p->transvr_p->info);
+ SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name);
+ transvr_task_set_retry(task_p, 0);
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_sfp_handle_1g_rj45_2:
+ if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) {
+ transvr_task_set_retry(task_p, fail_retry);
+ }
+ if ((task_p->retry) == 0) {
+ /* Error case:
+ * => In this case, SWPS will stop external Link state monitor features
+ * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up.
+ * Upper layer will see it always Linkup that because of these type of
+ * transceiver has external phy, BCM chip see it as Loopback transceiver.
+ */
+ SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n",
+ task_p->transvr_p->swp_name);
+ task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up;
+ return EVENT_TRANSVR_TASK_DONE;
+ } else {
+ transvr_task_set_delay(task_p, fail_delay);
+ }
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self,
+ int setup_val) {
+
+ int curr_val = DEBUG_TRANSVR_INT_VAL;
+ int err_val = DEBUG_TRANSVR_INT_VAL;
+ char *err_msg = DEBUG_TRANSVR_STR_VAL;
+
+ curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p,
+ self->ioexp_virt_offset);
+ if (curr_val < 0){
+ err_msg = "Get current value fail!";
+ goto err_private_taskfunc_qsfp_setup_power_mod_1;
+ }
+ if (curr_val == setup_val){
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p,
+ self->ioexp_virt_offset,
+ setup_val);
+ if (err_val < 0){
+ err_msg = "Setup power mode fail!";
+ goto err_private_taskfunc_qsfp_setup_power_mod_1;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_private_taskfunc_qsfp_setup_power_mod_1:
+ SWPS_INFO("%s: %s :%d :%d :%d\n",
+ __func__, err_msg, err_val, curr_val, setup_val);
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) {
+
+ int i = 0;
+ int retry = 5;
+ int delay_ms = 100;
+
+ if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) {
+ return EVENT_TRANSVR_TASK_DONE;
+ }
+ for (i=0; itransvr_p,
+ task_p->transvr_p->auto_tx_disable)
+ == EVENT_TRANSVR_TASK_DONE) {
+ goto ok_taskfunc_qsfp_handle_tx_disable;
+ }
+ mdelay(delay_ms);
+ }
+ SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n",
+ task_p->transvr_p->swp_name,
+ task_p->transvr_p->auto_tx_disable);
+ return EVENT_TRANSVR_INIT_FAIL;
+
+ok_taskfunc_qsfp_handle_tx_disable:
+ SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n",
+ task_p->transvr_p->swp_name,
+ task_p->transvr_p->auto_tx_disable);
+ return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) {
+
+ int err = DEBUG_TRANSVR_INT_VAL;
+ int HIGH_POWER_MODE = 0;
+
+ /* Handle power mode */
+ err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p,
+ HIGH_POWER_MODE);
+ if (err < 0) {
+ SWPS_INFO("%s: setup hpmod fail :%d :%s\n",
+ __func__, err, task_p->transvr_p->swp_name);
+ return err;
+ }
+ /* Handle auto tx_disable
+ * [Note]
+ * => Because there are some transceiver have timing issues or
+ * setup sequence issues, therefore we handle auto tx_disable
+ * after handle power mode.
+ */
+ mdelay(100);
+ return taskfunc_qsfp_handle_tx_disable(task_p);
+}
+
+
+int
+taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) {
+
+ int LOW_POWER_MODE = 1;
+ return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p,
+ LOW_POWER_MODE);
+}
+
+
+static int
+initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) {
+
+ int task_retry = 3;
+ int err_code = DEBUG_TRANSVR_INT_VAL;
+ char *err_str = DEBUG_TRANSVR_STR_VAL;
+ char *func_str = "sfp_handle_multi_rate_mode";
+ struct transvr_worker_s *task_p = NULL;
+
+ switch (self->rate_id) {
+ case 0x00: /* Unspecified */
+ case 0x03: /* Unspecified */
+ case 0x05: /* Unspecified */
+ case 0x07: /* Unspecified */
+ case 0x09: /* Unspecified */
+ case 0x0B: /* Unspecified */
+ case 0x0D: /* Unspecified */
+ case 0x0F: /* Unspecified */
+ goto sfp_handle_multi_rate_mode_4_unspecified;
+
+ case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */
+ task_p = transvr_task_creat(self,
+ taskfunc_sfp_setup_SFF8431_case1,
+ taskfunc_post_handle_task_state,
+ func_str);
+ goto sfp_handle_multi_rate_mode_4_sff8431;
+
+ case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */
+ task_p = transvr_task_creat(self,
+ taskfunc_sfp_setup_SFF8431_case2,
+ taskfunc_post_handle_task_state,
+ func_str);
+ goto sfp_handle_multi_rate_mode_4_sff8431;
+
+ case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */
+ task_p = transvr_task_creat(self,
+ taskfunc_sfp_setup_SFF8431_case3,
+ taskfunc_post_handle_task_state,
+ func_str);
+ goto sfp_handle_multi_rate_mode_4_sff8431;
+
+ case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */
+ err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)";
+ goto sfp_handle_multi_rate_mode_4_not_support;
+
+ case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only)
+ * High=16G only, Low=8G/4G
+ */
+ err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)";
+ goto sfp_handle_multi_rate_mode_4_not_support;
+
+ case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)
+ * High=16G only, Low=8G/4G
+ */
+ err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)";
+ goto sfp_handle_multi_rate_mode_4_not_support;
+
+ case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)
+ * High=32G only, Low = 16G/8G
+ */
+ err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)";
+ goto sfp_handle_multi_rate_mode_4_not_support;
+
+ case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or
+ * locking modes of the internal signal conditioner, retimer
+ * or CDR, according to the logic table defined in Table 10-2,
+ * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) =
+ * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft
+ * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate
+ * Select RS(1), Table 10-1) is 1.
+ */
+ err_str = "cable type: 0x0E";
+ goto sfp_handle_multi_rate_mode_4_not_support;
+
+ default:
+ err_str = "cable type: UNKNOW";
+ goto sfp_handle_multi_rate_mode_4_not_support;
+ }
+
+sfp_handle_multi_rate_mode_4_sff8431:
+ if (!task_p) {
+ err_str = "Create task fail!";
+ goto sfp_handle_multi_rate_mode_4_fail_1;
+ }
+ transvr_task_set_retry(task_p, task_retry);
+ return EVENT_TRANSVR_TASK_WAIT;
+
+sfp_handle_multi_rate_mode_4_unspecified:
+ return EVENT_TRANSVR_TASK_DONE;
+
+sfp_handle_multi_rate_mode_4_not_support:
+ SWPS_INFO("%s: Does not support %s :%s :0x%02x\n",
+ func_str, err_str, self->swp_name, self->rate_id);
+ return EVENT_TRANSVR_TASK_DONE;
+
+sfp_handle_multi_rate_mode_4_fail_1:
+ SWPS_INFO("%s: %s :%s :0x%02x, :%d\n",
+ func_str, err_str, self->swp_name, self->rate_id, err_code);
+ return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+static int
+initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) {
+
+ struct transvr_worker_s *task_p = NULL;
+ int detect_cls = DEBUG_TRANSVR_INT_VAL;
+ char err_str[64] = DEBUG_TRANSVR_STR_VAL;
+ char *func_str = "initfunc_sfp_handle_1g_rj45";
+
+
+ if (self->info == TRANSVR_CLASS_BASE_T_1000) {
+ task_p = transvr_task_creat(self,
+ taskfunc_sfp_handle_1g_rj45,
+ taskfunc_post_do_nothing,
+ func_str);
+ if (!task_p) {
+ snprintf(err_str, sizeof(err_str), "Create task fail");
+ goto err_initfunc_sfp_handle_1g_rj45;
+ }
+ transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER);
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_initfunc_sfp_handle_1g_rj45:
+ SWPS_INFO("%s: %s :%s :%d\n",
+ __func__, err_str, self->swp_name, detect_cls);
+ return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+static int
+initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) {
+
+ int err_code = EVENT_TRANSVR_EXCEP_INIT;
+ int power_class = DEBUG_TRANSVR_INT_VAL;
+ int hpmod_retry = 3;
+ int lpower_config = 1;
+ char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+ unsigned long hpmod_delay = 500; /* msec */
+ struct transvr_worker_s *task_p = NULL;
+
+ /* Handle power mode for IOEXP */
+ power_class = __qsfp_get_power_cls(self, 0);
+ switch (power_class) {
+ case 1: /* Case: Low power mode (Class = 1) */
+ err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config);
+ if (err_code < 0){
+ snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code);
+ goto err_initfunc_qsfp_handle_power_mode;
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+ case 2: /* Case: High power mode (Class > 1) */
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ task_p = transvr_task_creat(self,
+ taskfunc_qsfp_set_hpmod,
+ taskfunc_post_handle_task_state,
+ "transvr_init_qsfp");
+ if (!task_p) {
+ snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code);
+ goto err_initfunc_qsfp_handle_power_mode;
+ }
+ transvr_task_set_retry(task_p, hpmod_retry);
+ transvr_task_set_delay(task_p, hpmod_delay);
+ return EVENT_TRANSVR_TASK_WAIT;
+
+ default:
+ break;
+ }
+ snprintf(err_msg, sizeof(err_msg), "Exception case");
+ goto err_initfunc_qsfp_handle_power_mode;
+
+err_initfunc_qsfp_handle_power_mode:
+ SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name);
+ return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+int
+initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) {
+
+ uint8_t DEFAULT_VAL_CDR = 0xff;
+ int CDR_FUNC_EXISTED = 0x3;
+ int show_err = 1;
+ int err_val = EVENT_TRANSVR_TASK_FAIL;
+ char *err_msg = DEBUG_TRANSVR_STR_VAL;
+ char *func_str = "initfunc_qsfp28_handle_cdr";
+
+ err_val = __qsfp_get_cdr_present(self, 0);
+ if ( (err_val < 0) ||
+ (err_val == DEBUG_TRANSVR_HEX_VAL) ) {
+ err_msg = "detect cdr_present fail!";
+ goto err_taskfunc_qsfp_handle_cdr_1;
+ }
+ if (err_val == CDR_FUNC_EXISTED) {
+ err_val = _common_set_uint8_attr(self,
+ self->eeprom_map_p->addr_cdr,
+ self->eeprom_map_p->addr_cdr,
+ self->eeprom_map_p->offset_cdr,
+ DEFAULT_VAL_CDR,
+ &(self->cdr),
+ func_str,
+ show_err);
+ if (err_val < 0) {
+ err_msg = "set CDR fail!";
+ goto err_taskfunc_qsfp_handle_cdr_1;
+ }
+ }
+ return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_qsfp_handle_cdr_1:
+ SWPS_INFO("%s: %s :%d :%s\n",
+ func_str, err_msg, err_val, self->swp_name);
+ return EVENT_TRANSVR_INIT_FAIL;
+}
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+is_plugged(struct transvr_obj_s *self){
+
+ int limit = 63;
+ int present = DEBUG_TRANSVR_INT_VAL;
+ char emsg[64] = DEBUG_TRANSVR_STR_VAL;
+ struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p;
+
+ if (!ioexp_p) {
+ snprintf(emsg, limit, "ioexp_p is null!");
+ goto err_is_plugged_1;
+ }
+ present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset);
+ switch (present){
+ case 0:
+ return 1;
+ case 1:
+ return 0;
+ case ERR_IOEXP_UNINIT:
+ snprintf(emsg, limit, "ioexp_p not ready!");
+ goto err_is_plugged_1;
+ default:
+ if (ioexp_p->state == STATE_IOEXP_INIT){
+ snprintf(emsg, limit, "ioexp_p not ready!");
+ goto err_is_plugged_1;
+ }
+ break;
+ }
+ SWPS_INFO("%s: Exception case! :%d