mirror of
				https://github.com/Telecominfraproject/ols-nos.git
				synced 2025-10-29 17:22:33 +00:00 
			
		
		
		
	two platforms supporting S3IP SYSFS (TCS8400, TCS9400) (#12386)
Why I did it Add two platform that support s3IP framework How I did it Add two platforms supporting S3IP SYSFS (TCS8400, TCS9400) How to verify it Manual test
This commit is contained in:
		
							
								
								
									
										574
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/TCS8400-24CC8CD/TCS8400-24CC8CD.yml
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										574
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/TCS8400-24CC8CD/TCS8400-24CC8CD.yml
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,574 @@ | ||||
| # | ||||
| # BCM56880 128x100g port configuration. | ||||
| # | ||||
| # configuration yaml file | ||||
| #   device: | ||||
| #       <unit>: | ||||
| #           <table>: | ||||
| #               ? | ||||
| #                   <key_fld_1>: <value> | ||||
| #                   <key_fld_2>: <value> | ||||
| #                   ... | ||||
| #                   <key_fld_n>: <value> | ||||
| #               : | ||||
| #                   <data_fld_1>: <value> | ||||
| #                   <data_fld_2>: <value> | ||||
| #                   ... | ||||
| #                   <data_fld_n>: <value> | ||||
| # | ||||
| # $Copyright: (c) 2019 Broadcom. | ||||
| # Broadcom Proprietary and Confidential. All rights reserved.$ | ||||
| # | ||||
|  | ||||
| --- | ||||
| bcm_device: | ||||
|     0: | ||||
|         global: | ||||
|             bcm_tunnel_term_compatible_mode: 1 | ||||
|             # Multicast group allocated by brcm-sai, setting "vlan_flooding_l2mc_num_reserved=0"  | ||||
|             vlan_flooding_l2mc_num_reserved: 0 | ||||
|             shared_block_mask_section: uc_bc | ||||
|             sai_tunnel_support: 1 | ||||
|             l3_alpm_template: 1 | ||||
|             l3_alpm2_bnk_threshold: 100 | ||||
|             uft_mode: 1 | ||||
|             l3_enable: 1 | ||||
|             l2_hitbit_enable: 1 | ||||
|             pktio_mode: 1 | ||||
|             skip_protocol_default_entries: 1 | ||||
|             ifa_enable: 1 | ||||
| ... | ||||
|  | ||||
| --- | ||||
| bcm_device: | ||||
|     0: | ||||
|         port: | ||||
|             "*": | ||||
|                 encap_mode: IEEE | ||||
|                 dport_map_enable: 1 | ||||
|             11: | ||||
|                 dport_map_port: 1 | ||||
|             13: | ||||
|                 dport_map_port: 2 | ||||
|             20: | ||||
|                 dport_map_port: 3 | ||||
|             22: | ||||
|                 dport_map_port: 4 | ||||
|             24: | ||||
|                 dport_map_port: 5 | ||||
|             26: | ||||
|                 dport_map_port: 6 | ||||
|             28: | ||||
|                 dport_map_port: 7 | ||||
|             30: | ||||
|                 dport_map_port: 8 | ||||
|             3: | ||||
|                 dport_map_port: 9 | ||||
|             5: | ||||
|                 dport_map_port: 10 | ||||
|             7: | ||||
|                 dport_map_port: 11 | ||||
|             9: | ||||
|                 dport_map_port: 12 | ||||
|             40: | ||||
|                 dport_map_port: 13 | ||||
|             42: | ||||
|                 dport_map_port: 14 | ||||
|             44: | ||||
|                 dport_map_port: 15 | ||||
|             46: | ||||
|                 dport_map_port: 16 | ||||
|             48: | ||||
|                 dport_map_port: 17 | ||||
|             50: | ||||
|                 dport_map_port: 18 | ||||
|             64: | ||||
|                 dport_map_port: 19 | ||||
|             66: | ||||
|                 dport_map_port: 20 | ||||
|             68: | ||||
|                 dport_map_port: 21 | ||||
|             70: | ||||
|                 dport_map_port: 22 | ||||
|             72: | ||||
|                 dport_map_port: 23 | ||||
|             74: | ||||
|                 dport_map_port: 24 | ||||
|             1: | ||||
|                 dport_map_port: 25 | ||||
|             15: | ||||
|                 dport_map_port: 26 | ||||
|             32: | ||||
|                 dport_map_port: 27 | ||||
|             34: | ||||
|                 dport_map_port: 28 | ||||
|             52: | ||||
|                 dport_map_port: 29 | ||||
|             54: | ||||
|                 dport_map_port: 30 | ||||
|             60: | ||||
|                 dport_map_port: 31 | ||||
|             62: | ||||
|                 dport_map_port: 32 | ||||
|  | ||||
| ... | ||||
|  | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         DEVICE_CONFIG: | ||||
|             # CORE CLOCK FREQUENCY | ||||
|             CORE_CLK_FREQ: CLK_1350MHZ | ||||
|             # PP CLOCK FREQUENCY | ||||
|             PP_CLK_FREQ: CLK_1350MHZ | ||||
| ... | ||||
|  | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         PC_PM_CORE: | ||||
|             ? | ||||
|                 PC_PM_ID: 1 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x73510624 | ||||
|                     RX_LANE_MAP: 0x46270513 | ||||
|                     TX_POLARITY_FLIP: 0xa | ||||
|                     RX_POLARITY_FLIP: 0x17 | ||||
|             ? | ||||
|                 PC_PM_ID: 2 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x52317046 | ||||
|                     RX_LANE_MAP: 0x31247056 | ||||
|                     TX_POLARITY_FLIP: 0x90 | ||||
|                     RX_POLARITY_FLIP: 0x47 | ||||
|             ? | ||||
|                 PC_PM_ID: 3 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x23104567 | ||||
|                     RX_LANE_MAP: 0x64752310 | ||||
|                     TX_POLARITY_FLIP: 0x29 | ||||
|                     RX_POLARITY_FLIP: 0x5a | ||||
|             ? | ||||
|                 PC_PM_ID: 4 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x23104567 | ||||
|                     RX_LANE_MAP: 0x64752310 | ||||
|                     TX_POLARITY_FLIP: 0x29 | ||||
|                     RX_POLARITY_FLIP: 0x5a | ||||
|             ? | ||||
|                 PC_PM_ID: 5 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x25047361 | ||||
|                     RX_LANE_MAP: 0x10452736 | ||||
|                     TX_POLARITY_FLIP: 0xf5 | ||||
|                     RX_POLARITY_FLIP: 0xc0 | ||||
|             ? | ||||
|                 PC_PM_ID: 6 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x45763210 | ||||
|                     RX_LANE_MAP: 0x13026457 | ||||
|                     TX_POLARITY_FLIP: 0xa | ||||
|                     RX_POLARITY_FLIP: 0xf9 | ||||
|             ? | ||||
|                 PC_PM_ID: 7 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x45763210 | ||||
|                     RX_LANE_MAP: 0x13026457 | ||||
|                     TX_POLARITY_FLIP: 0xa | ||||
|                     RX_POLARITY_FLIP: 0xf9 | ||||
|             ? | ||||
|                 PC_PM_ID: 8 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x45673210 | ||||
|                     RX_LANE_MAP: 0x13026457 | ||||
|                     TX_POLARITY_FLIP: 0x4a | ||||
|                     RX_POLARITY_FLIP: 0xf3 | ||||
|             ? | ||||
|                 PC_PM_ID: 9 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x02476531 | ||||
|                     RX_LANE_MAP: 0x05261734 | ||||
|                     TX_POLARITY_FLIP: 0xdf | ||||
|                     RX_POLARITY_FLIP: 0x84 | ||||
|             ? | ||||
|                 PC_PM_ID: 10 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x37065241 | ||||
|                     RX_LANE_MAP: 0x04175263 | ||||
|                     TX_POLARITY_FLIP: 0x36 | ||||
|                     RX_POLARITY_FLIP: 0x39 | ||||
|             ? | ||||
|                 PC_PM_ID: 11 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x54762301 | ||||
|                     RX_LANE_MAP: 0x13025467 | ||||
|                     TX_POLARITY_FLIP: 0x70 | ||||
|                     RX_POLARITY_FLIP: 0x6f | ||||
|             ? | ||||
|                 PC_PM_ID: 12 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x73125046 | ||||
|                     RX_LANE_MAP: 0x21437056 | ||||
|                     TX_POLARITY_FLIP: 0x78 | ||||
|                     RX_POLARITY_FLIP: 0x5c | ||||
|             ? | ||||
|                 PC_PM_ID: 13 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x32104567 | ||||
|                     RX_LANE_MAP: 0x64572310 | ||||
|                     TX_POLARITY_FLIP: 0xd6 | ||||
|                     RX_POLARITY_FLIP: 0xad | ||||
|             ? | ||||
|                 PC_PM_ID: 14 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x03172465 | ||||
|                     RX_LANE_MAP: 0x45173620 | ||||
|                     TX_POLARITY_FLIP: 0xed | ||||
|                     RX_POLARITY_FLIP: 0x36 | ||||
|             ? | ||||
|                 PC_PM_ID: 15 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x36175042 | ||||
|                     RX_LANE_MAP: 0x04176253 | ||||
|                     TX_POLARITY_FLIP: 0x10 | ||||
|                     RX_POLARITY_FLIP: 0xfa | ||||
|             ? | ||||
|                 PC_PM_ID: 16 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x74615203 | ||||
|                     RX_LANE_MAP: 0x51704236 | ||||
|                     TX_POLARITY_FLIP: 0x5f | ||||
|                     RX_POLARITY_FLIP: 0x56 | ||||
|             ? | ||||
|                 PC_PM_ID: 17 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x26374051 | ||||
|                     RX_LANE_MAP: 0x37046251 | ||||
|                     TX_POLARITY_FLIP: 0xaa | ||||
|                     RX_POLARITY_FLIP: 0x21 | ||||
|             ? | ||||
|                 PC_PM_ID: 18 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x45672310 | ||||
|                     RX_LANE_MAP: 0x32105476 | ||||
|                     TX_POLARITY_FLIP: 0x15 | ||||
|                     RX_POLARITY_FLIP: 0x92 | ||||
|             ? | ||||
|                 PC_PM_ID: 19 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x70465321 | ||||
|                     RX_LANE_MAP: 0x63107542 | ||||
|                     TX_POLARITY_FLIP: 0xe6 | ||||
|                     RX_POLARITY_FLIP: 0xf2 | ||||
|             ? | ||||
|                 PC_PM_ID: 20 | ||||
|                 CORE_INDEX: 0 | ||||
|             : | ||||
|                     TX_LANE_MAP_AUTO: 0 | ||||
|                     RX_LANE_MAP_AUTO: 0 | ||||
|                     TX_POLARITY_FLIP_AUTO: 0 | ||||
|                     RX_POLARITY_FLIP_AUTO: 0 | ||||
|                     TX_LANE_MAP: 0x23015476 | ||||
|                     RX_LANE_MAP: 0x64752301 | ||||
|                     TX_POLARITY_FLIP: 0x50 | ||||
|                     RX_POLARITY_FLIP: 0x6c | ||||
| ... | ||||
|  | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         PC_PORT_PHYS_MAP: | ||||
|             ? | ||||
|                 # CPU port | ||||
|                 PORT_ID: 0 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 0 | ||||
|             ? | ||||
|                 PORT_ID: 1 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 1 | ||||
|             ? | ||||
|                 PORT_ID: 3 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 9 | ||||
|             ? | ||||
|                 PORT_ID: 5 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 13 | ||||
|             ? | ||||
|                 PORT_ID: 7 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 17 | ||||
|             ? | ||||
|                 PORT_ID: 9 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 21 | ||||
|             ? | ||||
|                 PORT_ID: 11 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 25 | ||||
|             ? | ||||
|                 PORT_ID: 13 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 29 | ||||
|             ? | ||||
|                 PORT_ID: 15 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 33 | ||||
|             ? | ||||
|                 PORT_ID: 20 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 41 | ||||
|             ? | ||||
|                 PORT_ID: 22 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 45 | ||||
|             ? | ||||
|                 PORT_ID: 24 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 49 | ||||
|             ? | ||||
|                 PORT_ID: 26 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 53 | ||||
|             ? | ||||
|                 PORT_ID: 28 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 57 | ||||
|             ? | ||||
|                 PORT_ID: 30 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 61 | ||||
|             ? | ||||
|                 PORT_ID: 32 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 65 | ||||
|             ? | ||||
|                 PORT_ID: 34 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 73 | ||||
|             ? | ||||
|                 PORT_ID: 40 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 81 | ||||
|             ? | ||||
|                 PORT_ID: 42 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 85 | ||||
|             ? | ||||
|                 PORT_ID: 44 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 89 | ||||
|             ? | ||||
|                 PORT_ID: 46 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 93 | ||||
|             ? | ||||
|                 PORT_ID: 48 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 97 | ||||
|             ? | ||||
|                 PORT_ID: 50 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 101 | ||||
|             ? | ||||
|                 PORT_ID: 52 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 105 | ||||
|             ? | ||||
|                 PORT_ID: 54 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 113 | ||||
|             ? | ||||
|                 PORT_ID: 60 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 121 | ||||
|             ? | ||||
|                 PORT_ID: 62 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 129 | ||||
|             ? | ||||
|                 PORT_ID: 64 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 137 | ||||
|             ? | ||||
|                 PORT_ID: 66 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 141 | ||||
|             ? | ||||
|                 PORT_ID: 68 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 145 | ||||
|             ? | ||||
|                 PORT_ID: 70 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 149 | ||||
|             ? | ||||
|                 PORT_ID: 72 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 153 | ||||
|             ? | ||||
|                 PORT_ID: 74 | ||||
|             : | ||||
|                 PC_PHYS_PORT_ID: 157 | ||||
|  | ||||
| ... | ||||
|  | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         PC_PORT: | ||||
|             ? | ||||
|                 PORT_ID: 0 | ||||
|             : | ||||
|                 ENABLE: 0 | ||||
|                 SPEED: 10000 | ||||
|                 NUM_LANES: 1 | ||||
|             ? | ||||
|                 PORT_ID: [3, 5, 7, 9, 11, 13,  | ||||
|                           20, 22, 24, 26, 28, 30,  | ||||
|                           40, 42, 44, 46, 48, 50,  | ||||
|                           64, 66, 68, 70, 72, 74] | ||||
|             : | ||||
|                 ENABLE: 0 | ||||
|                 SPEED: 200000 | ||||
|                 FEC_MODE: PC_FEC_RS544_2XN | ||||
|                 NUM_LANES: 4 | ||||
|                 LINK_TRAINING: 0 | ||||
|                 MAX_FRAME_SIZE: 9416 | ||||
|             ? | ||||
|                 PORT_ID: [1, 15, 32, 34, 52, 54, 60, 62] | ||||
|             : | ||||
|                 ENABLE: 0 | ||||
|                 SPEED: 400000 | ||||
|                 FEC_MODE: PC_FEC_RS544_2XN | ||||
|                 NUM_LANES: 8 | ||||
|                 LINK_TRAINING: 0 | ||||
|                 MAX_FRAME_SIZE: 9416 | ||||
| ... | ||||
|  | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         TM_SCHEDULER_CONFIG: | ||||
|             NUM_MC_Q: NUM_MC_Q_4 | ||||
| ... | ||||
|  | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         FP_CONFIG: | ||||
|             FP_ING_OPERMODE: GLOBAL_PIPE_AWARE | ||||
| ... | ||||
| --- | ||||
| device: | ||||
|     0: | ||||
|         PORT_PROPERTY: | ||||
|             ? | ||||
|                 PORT_ID: 19 | ||||
|             : | ||||
|                 PORT_TYPE: 1 | ||||
|                 PORT_PARSER: 5 | ||||
|                 EGR_PORT_PROPERTY: 2 | ||||
|             ? | ||||
|                 PORT_ID: 59 | ||||
|             : | ||||
|                 PORT_TYPE: 1 | ||||
|                 PORT_PARSER: 5 | ||||
|                 EGR_PORT_PROPERTY: 2 | ||||
| ... | ||||
							
								
								
									
										33
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/TCS8400-24CC8CD/port_config.ini
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										33
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/TCS8400-24CC8CD/port_config.ini
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| # name          lanes                                alias               index      speed | ||||
| Ethernet1       25,26,27,28                          Eth200GE0/1         1          200000 | ||||
| Ethernet2       29,30,31,32                          Eth200GE0/2         2          200000 | ||||
| Ethernet3       41,42,43,44                          Eth200GE0/3         3          200000 | ||||
| Ethernet4       45,46,47,48                          Eth200GE0/4         4          200000 | ||||
| Ethernet5       49,50,51,52                          Eth200GE0/5         5          200000 | ||||
| Ethernet6       53,54,55,56                          Eth200GE0/6         6          200000 | ||||
| Ethernet7       57,58,59,60                          Eth200GE0/7         7          200000 | ||||
| Ethernet8       61,62,63,64                          Eth200GE0/8         8          200000 | ||||
| Ethernet9       9,10,11,12                           Eth200GE0/9         9          200000 | ||||
| Ethernet10      13,14,15,16                          Eth200GE0/10        10         200000 | ||||
| Ethernet11      17,18,19,20                          Eth200GE0/11        11         200000 | ||||
| Ethernet12      21,22,23,24                          Eth200GE0/12        12         200000 | ||||
| Ethernet13      81,82,83,84                          Eth200GE0/13        13         200000 | ||||
| Ethernet14      85,86,87,88                          Eth200GE0/14        14         200000 | ||||
| Ethernet15      89,90,91,92                          Eth200GE0/15        15         200000 | ||||
| Ethernet16      93,94,95,96                          Eth200GE0/16        16         200000 | ||||
| Ethernet17      97,98,99,100                         Eth200GE0/17        17         200000 | ||||
| Ethernet18      101,102,103,104                      Eth200GE0/18        18         200000 | ||||
| Ethernet19      137,138,139,140                      Eth200GE0/19        19         200000 | ||||
| Ethernet20      141,142,143,144                      Eth200GE0/20        20         200000 | ||||
| Ethernet21      145,146,147,148                      Eth200GE0/21        21         200000 | ||||
| Ethernet22      149,150,151,152                      Eth200GE0/22        22         200000 | ||||
| Ethernet23      153,154,155,156                      Eth200GE0/23        23         200000 | ||||
| Ethernet24      157,158,159,160                      Eth200GE0/24        24         200000 | ||||
| Ethernet25      1,2,3,4,5,6,7,8                      Eth400GE0/25        25         400000 | ||||
| Ethernet26      33,34,35,36,37,38,39,40              Eth400GE0/26        26         400000 | ||||
| Ethernet27      65,66,67,68,69,70,71,72              Eth400GE0/27        27         400000 | ||||
| Ethernet28      73,74,75,76,77,78,79,80              Eth400GE0/28        28         400000 | ||||
| Ethernet29      105,106,107,108,109,110,111,112      Eth400GE0/29        29         400000 | ||||
| Ethernet30      113,114,115,116,117,118,119,120      Eth400GE0/30        30         400000 | ||||
| Ethernet31      121,122,123,124,125,126,127,128      Eth400GE0/31        31         400000 | ||||
| Ethernet32      129,130,131,132,133,134,135,136      Eth400GE0/32        32         400000 | ||||
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/TCS8400-24CC8CD/sai.profile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/TCS8400-24CC8CD/sai.profile
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/TCS8400-24CC8CD.yml | ||||
							
								
								
									
										268
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/config_db.TCS8400-24CC8CD.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										268
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/config_db.TCS8400-24CC8CD.json
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,268 @@ | ||||
| { | ||||
|     "DEVICE_METADATA": { | ||||
|         "localhost": { | ||||
|             "hwsku": "TCS8400-24CC8CD", | ||||
|             "platform": "x86_64-tencent_tcs8400-r0", | ||||
|             "mac": "58:69:6c:f1:23:12", | ||||
|             "hostname": "sonic" | ||||
|         } | ||||
|     }, | ||||
|     "PORT": { | ||||
|         "Ethernet1": { | ||||
|             "lanes": "25,26,27,28", | ||||
|             "alias": "Eth200GE0/1", | ||||
|             "index": "1", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet2": { | ||||
|             "lanes": "29,30,31,32", | ||||
|             "alias": "Eth200GE0/2", | ||||
|             "index": "2", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet3": { | ||||
|             "lanes": "41,42,43,44", | ||||
|             "alias": "Eth200GE0/3", | ||||
|             "index": "3", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet4": { | ||||
|             "lanes": "45,46,47,48", | ||||
|             "alias": "Eth200GE0/4", | ||||
|             "index": "4", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet5": { | ||||
|             "lanes": "49,50,51,52", | ||||
|             "alias": "Eth200GE0/5", | ||||
|             "index": "5", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet6": { | ||||
|             "lanes": "53,54,55,56", | ||||
|             "alias": "Eth200GE0/6", | ||||
|             "index": "6", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet7": { | ||||
|             "lanes": "57,58,59,60", | ||||
|             "alias": "Eth200GE0/7", | ||||
|             "index": "7", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet8": { | ||||
|             "lanes": "61,62,63,64", | ||||
|             "alias": "Eth200GE0/8", | ||||
|             "index": "8", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet9": { | ||||
|             "lanes": "9,10,11,12", | ||||
|             "alias": "Eth200GE0/9", | ||||
|             "index": "9", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet10": { | ||||
|             "lanes": "13,14,15,16", | ||||
|             "alias": "Eth200GE0/10", | ||||
|             "index": "10", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet11": { | ||||
|             "lanes": "17,18,19,20", | ||||
|             "alias": "Eth200GE0/11", | ||||
|             "index": "11", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet12": { | ||||
|             "lanes": "21,22,23,24", | ||||
|             "alias": "Eth200GE0/12", | ||||
|             "index": "12", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet13": { | ||||
|             "lanes": "81,82,83,84", | ||||
|             "alias": "Eth200GE0/13", | ||||
|             "index": "13", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet14": { | ||||
|             "lanes": "85,86,87,88", | ||||
|             "alias": "Eth200GE0/14", | ||||
|             "index": "14", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet15": { | ||||
|             "lanes": "89,90,91,92", | ||||
|             "alias": "Eth200GE0/15", | ||||
|             "index": "15", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet16": { | ||||
|             "lanes": "93,94,95,96", | ||||
|             "alias": "Eth200GE0/16", | ||||
|             "index": "16", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet17": { | ||||
|             "lanes": "97,98,99,100", | ||||
|             "alias": "Eth200GE0/17", | ||||
|             "index": "17", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet18": { | ||||
|             "lanes": "101,102,103,104", | ||||
|             "alias": "Eth200GE0/18", | ||||
|             "index": "18", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet19": { | ||||
|             "lanes": "137,138,139,140", | ||||
|             "alias": "Eth200GE0/19", | ||||
|             "index": "19", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet20": { | ||||
|             "lanes": "141,142,143,144", | ||||
|             "alias": "Eth200GE0/20", | ||||
|             "index": "20", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet21": { | ||||
|             "lanes": "145,146,147,148", | ||||
|             "alias": "Eth200GE0/21", | ||||
|             "index": "21", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet22": { | ||||
|             "lanes": "149,150,151,152", | ||||
|             "alias": "Eth200GE0/22", | ||||
|             "index": "22", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet23": { | ||||
|             "lanes": "153,154,155,156", | ||||
|             "alias": "Eth200GE0/23", | ||||
|             "index": "23", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet24": { | ||||
|             "lanes": "157,158,159,160", | ||||
|             "alias": "Eth200GE0/24", | ||||
|             "index": "24", | ||||
|             "speed": "200000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet25": { | ||||
|             "lanes": "1,2,3,4,5,6,7,8", | ||||
|             "alias": "Eth400GE0/25", | ||||
|             "index": "25", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet26": { | ||||
|             "lanes": "33,34,35,36,37,38,39,40", | ||||
|             "alias": "Eth400GE0/26", | ||||
|             "index": "26", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet27": { | ||||
|             "lanes": "65,66,67,68,69,70,71,72", | ||||
|             "alias": "Eth400GE0/27", | ||||
|             "index": "27", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet28": { | ||||
|             "lanes": "73,74,75,76,77,78,79,80", | ||||
|             "alias": "Eth400GE0/28", | ||||
|             "index": "28", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet29": { | ||||
|             "lanes": "105,106,107,108,109,110,111,112", | ||||
|             "alias": "Eth400GE0/29", | ||||
|             "index": "29", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet30": { | ||||
|             "lanes": "113,114,115,116,117,118,119,120", | ||||
|             "alias": "Eth400GE0/30", | ||||
|             "index": "30", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet31": { | ||||
|             "lanes": "121,122,123,124,125,126,127,128", | ||||
|             "alias": "Eth400GE0/31", | ||||
|             "index": "31", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         }, | ||||
|         "Ethernet32": { | ||||
|             "lanes": "129,130,131,132,133,134,135,136", | ||||
|             "alias": "Eth400GE0/32", | ||||
|             "index": "32", | ||||
|             "speed": "400000", | ||||
|             "admin_status": "up", | ||||
|             "mtu": "9100" | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										85
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/cpu.cint
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										85
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/cpu.cint
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| cint_reset(); | ||||
|  | ||||
| int cint_field_group_create(int unit, bcm_field_group_t grp) | ||||
| { | ||||
|     int rv; | ||||
|  | ||||
|     bcm_field_qset_t    qset; | ||||
|     bcm_field_aset_t    aset; | ||||
|  | ||||
|     BCM_FIELD_QSET_INIT(qset); | ||||
|     BCM_FIELD_QSET_ADD(qset,bcmFieldQualifyDstMac); | ||||
|     BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyStageIngress); | ||||
|  | ||||
|     BCM_FIELD_ASET_INIT(aset); | ||||
|     BCM_FIELD_ASET_ADD(aset, bcmFieldActionCopyToCpu);  | ||||
|  | ||||
|     rv = bcm_field_group_create_mode_id(unit, qset, 103, bcmFieldGroupModeAuto, grp); | ||||
|     if (rv != BCM_E_NONE) { | ||||
|         printf("bcm_field_group_create_mode_id failed, rv = %d\r\n", rv); | ||||
|         return -1; | ||||
|     } | ||||
|     printf("cint_field_group_create success!!!, rv = %d\r\n", rv); | ||||
|  | ||||
|     bcm_field_group_dump(unit,grp);    | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int cint_field_entry_create1(int unit, bcm_field_group_t grp,bcm_field_entry_t entry) | ||||
| { | ||||
|     int rv; | ||||
|     bcm_mac_t dst_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||||
|     bcm_mac_t mac_mask = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||||
| 	 | ||||
|     rv = bcm_field_entry_create_id(unit, grp, entry);     | ||||
|     if (rv != BCM_E_NONE) { | ||||
|         printf("bcm_field_entry_create_id failed, rv = %d\r\n", rv); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     rv =bcm_field_qualify_DstMac(unit, entry, dst_mac, mac_mask); | ||||
|     if (rv != BCM_E_NONE) { | ||||
|         printf("bcm_field_qualify_DstMac failed,ret = %d\r\n", rv); | ||||
|         bcm_field_entry_destroy(unit, entry); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     rv = bcm_field_action_add(unit, entry, bcmFieldActionCopyToCpu, 1, 0); | ||||
|     if (rv != BCM_E_NONE) { | ||||
|         printf("bcm_field_action_add failed, rv = %d \r\n", rv); | ||||
|         bcm_field_entry_destroy(unit, entry); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     rv = bcm_field_action_add(unit, entry, bcmFieldActionDrop, 1, 0); | ||||
|     if (rv != BCM_E_NONE) { | ||||
|         printf("bcm_field_action_add failed, rv = %d \r\n", rv); | ||||
|         bcm_field_entry_destroy(unit, entry); | ||||
|         return -1; | ||||
|     } | ||||
| 	 | ||||
|     rv = bcm_field_entry_install(unit, entry); | ||||
|     if (rv != BCM_E_NONE) { | ||||
|         printf("bcm_field_entry_install failed,ret = %d\r\n", rv); | ||||
|         bcm_field_entry_destroy(unit, entry); | ||||
|         return -1; | ||||
|     }   | ||||
|  | ||||
|     printf("********************* BEGIN ****************************\r\n"); | ||||
|     bcm_field_entry_dump(unit, entry); | ||||
|     printf("*********************** END ****************************\r\n"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| cint_field_group_create(0,5); | ||||
| cint_field_entry_create1(0,5,2048); | ||||
|  | ||||
| //bcm_field_entry_destroy(0, 2048); | ||||
| //bcm_field_group_destroy(0, 5); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/custom_led.bin
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/custom_led.bin
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/default_sku
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/default_sku
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| TCS8400-24CC8CD t1 | ||||
							
								
								
									
										349
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/dev.xml
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										349
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/dev.xml
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,349 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- | ||||
|       ### type    1 result/1000 | ||||
|           type    2 result/100 | ||||
|           type    3 read bit | ||||
|      ### property need check must add int front | ||||
| --> | ||||
| <catalog> | ||||
|     <fans> | ||||
|         <fan id="fan1" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan1/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan1/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan1/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/35-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan1/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan1/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan2" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan2/present"       type="4" decode="fanpresent" default="1" /> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan2/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan2/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/34-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan2/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan2/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan3" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan3/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan3/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan3/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/33-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan3/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan3/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan4" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan4/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan4/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan4/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/32-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan4/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan4/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan5" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan5/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan5/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan5/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/31-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan5/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan5/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan6" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan6/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan6/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan6/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/30-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan6/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan6/motor1/speed"/> | ||||
|         </fan> | ||||
|     </fans> | ||||
|     <temps> | ||||
|         <temp id="air_inlet_TL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/40-004f/hwmon/*/temp1_input" type="1" addend="-3"/> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/40-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/40-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_inlet_BL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/39-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/39-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/39-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_outlet_L" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/36-0048/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/36-0048/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/36-0048/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_outlet_R" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/36-0049/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/36-0049/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/36-0049/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_hotlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/40-004e/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/40-004e/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/40-004e/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_PACKAGE0" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/39-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/39-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/39-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_PACKAGE1" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/40-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/40-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/40-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|     </temps> | ||||
|     <psus> | ||||
|         <psu id="psu1" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu1/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu1/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/41-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/41-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/41-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/41-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu2" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu2/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu2/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/42-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/42-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/42-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/42-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|     </psus> | ||||
|     <dcdcs> | ||||
|         <dcdc id="VDD5V_CLK_MCU" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.345" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.840" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD3.3_CLK" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.560" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.220" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD1.0V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.049" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.950" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.903" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.720" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_BOARD_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.499" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.170" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.272" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.150" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD_CORE" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.950" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.670" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="ANALOG0.75V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.800" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.700" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.259" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDDO1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.937" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.750" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_ANA1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in11_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.276" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.150" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_ANA1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in12_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.910" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.730" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFP56_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in13_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.595" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.250" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFP56_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in14_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.601" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.260" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFPDD_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in15_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.565" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.230" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFPDD_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in16_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.564" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.220" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD5.0V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.429" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.910" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="SW_VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.284" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.160" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD2.5V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="2.620" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="2.370" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CONNECT_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.437" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.110" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.700" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.300" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD3.3_STBY" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.489" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.160" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="SSD_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.475" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VCCIN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0060/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.879" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.700" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P1V05" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0060/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.103" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.000" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P1V2_VDDQ" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-006c/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.258" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P2V5_VPP" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-006c/hwmon/hwmon*/in4_input" type="6" coefficient="1.124" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="2.632" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="2.380" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P3V3_STBY" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0043/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.476" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P5V_AUX_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0043/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.229" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.730" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P1V7_VCCSCFUSESUS_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0043/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.789" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.620" /> | ||||
|         </dcdc> | ||||
|     </dcdcs> | ||||
|     <mactemps> | ||||
|         <mactemp id="MAC_DIE_0" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp1_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_1" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp2_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_2" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp3_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_3" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp4_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_4" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp5_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_5" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp6_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_6" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp7_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_7" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp8_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_8" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp9_input"  type="1"/> | ||||
|         </mactemp> | ||||
|     </mactemps> | ||||
|     <macpowers> | ||||
|         <macpower id="MAC_Core" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/43-005b/hwmon/hwmon*/power1_input"  type="5"/> | ||||
|         </macpower> | ||||
|         <macpower id="MAC_Analog" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/43-005b/hwmon/hwmon*/power2_input"  type="5"/> | ||||
|         </macpower> | ||||
|     </macpowers> | ||||
|     <cpus location="/sys/class/hwmon/hwmon0"/> | ||||
|     <decode> | ||||
|     <fanpresent> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </fanpresent> | ||||
|     <fanstatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </fanstatus> | ||||
|     <psucheck> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </psucheck> | ||||
|     <psustatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </psustatus> | ||||
|     <psutype> | ||||
|         <code key="DPS-1300AB-6" value="PSA1300CRPS-F"/> | ||||
|         <code key="GW-CRPS1300D" value="PSA1300CRPS-F"/> | ||||
|         <code key="DPS-1300AB-11" value="PSA1300CRPS-R"/> | ||||
|         <code key="CRPS1300D3R" value="PSA1300CRPS-R"/> | ||||
|     </psutype> | ||||
|     <fan_display_name> | ||||
|         <code key="FAN24K4056-F" value="FAN24K4056-F"/> | ||||
|         <code key="FAN24K4056S-F" value="FAN24K4056-F"/> | ||||
|         <code key="FAN24K4056S-R" value="FAN24K4056-R"/> | ||||
|     </fan_display_name> | ||||
|     <slotpresent> | ||||
|         <code key="1" value="ABSENT"/> | ||||
|         <code key="0" value="PRESENT"/> | ||||
|     </slotpresent> | ||||
|     </decode> | ||||
| </catalog> | ||||
|  | ||||
|  | ||||
							
								
								
									
										349
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/dev_0x407b.xml
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										349
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/dev_0x407b.xml
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,349 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- | ||||
|       ### type    1 result/1000 | ||||
|           type    2 result/100 | ||||
|           type    3 read bit | ||||
|      ### property need check must add int front | ||||
| --> | ||||
| <catalog> | ||||
|     <fans> | ||||
|         <fan id="fan1" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan1/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan1/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan1/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/35-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan1/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan1/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan2" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan2/present"       type="4" decode="fanpresent" default="1" /> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan2/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan2/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/34-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan2/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan2/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan3" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan3/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan3/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan3/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/33-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan3/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan3/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan4" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan4/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan4/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan4/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/32-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan4/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan4/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan5" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan5/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan5/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan5/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/31-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan5/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan5/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan6" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan6/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan6/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan6/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/30-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan6/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan6/motor1/speed"/> | ||||
|         </fan> | ||||
|     </fans> | ||||
|     <temps> | ||||
|         <temp id="air_inlet_TL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/40-004f/hwmon/*/temp1_input" type="1" addend="-3"/> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/40-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/40-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_inlet_BL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/39-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/39-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/39-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_outlet_L" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/36-0048/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/36-0048/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/36-0048/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_outlet_R" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/36-0049/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/36-0049/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/36-0049/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="air_hotlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/40-004e/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/40-004e/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst"       location="/sys/bus/i2c/devices/40-004e/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_PACKAGE0" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/39-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/39-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/39-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_PACKAGE1" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/40-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/40-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/40-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|     </temps> | ||||
|     <psus> | ||||
|         <psu id="psu1" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu1/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu1/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/41-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/41-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/41-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/41-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/41-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu2" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu2/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu2/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/42-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/42-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/42-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/42-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/42-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|     </psus> | ||||
|     <dcdcs> | ||||
|         <dcdc id="VDD5V_CLK_MCU" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.345" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.840" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD3.3_CLK" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.560" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.220" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD1.0V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.049" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.950" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.903" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.720" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_BOARD_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.499" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.170" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.272" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.150" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD_CORE" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.950" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.670" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="ANALOG0.75V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.800" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.700" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.259" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDDO1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.937" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.750" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_ANA1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in11_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.276" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.150" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_ANA1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in12_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.910" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.730" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFP56_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in13_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.595" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.250" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFP56_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in14_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.601" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.260" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFPDD_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in15_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.565" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.230" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="QSFPDD_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/45-005b/hwmon/hwmon*/in16_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.564" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.220" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD5.0V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.429" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.910" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CONNECT_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.437" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.110" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.700" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.300" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VDD3.3_STBY" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.489" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.160" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="SSD_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.475" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="PHY_VDD1V0" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.050" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.950" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="ODD_PHY_M" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/24-005b/hwmon/hwmon*/in11_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.444" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.116" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="VCCIN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0060/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.879" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.700" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P1V05" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0060/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.103" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.000" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P1V2_VDDQ" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-006c/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.258" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P2V5_VPP" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-006c/hwmon/hwmon*/in4_input" type="6" coefficient="1.124" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="2.632" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="2.380" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P3V3_STBY" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0043/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.476" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P5V_AUX_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0043/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.229" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.730" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="P1V7_VCCSCFUSESUS_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/25-0043/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.789" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.620" /> | ||||
|         </dcdc> | ||||
|     </dcdcs> | ||||
|     <mactemps> | ||||
|         <mactemp id="MAC_DIE_0" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp1_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_1" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp2_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_2" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp3_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_3" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp4_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_4" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp5_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_5" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp6_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_6" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp7_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_7" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp8_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_8" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/44-0044/hwmon/hwmon*/temp9_input"  type="1"/> | ||||
|         </mactemp> | ||||
|     </mactemps> | ||||
|     <macpowers> | ||||
|         <macpower id="MAC_Core" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/43-005b/hwmon/hwmon*/power1_input"  type="5"/> | ||||
|         </macpower> | ||||
|         <macpower id="MAC_Analog" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/43-005b/hwmon/hwmon*/power2_input"  type="5"/> | ||||
|         </macpower> | ||||
|     </macpowers> | ||||
|     <cpus location="/sys/class/hwmon/hwmon0"/> | ||||
|     <decode> | ||||
|     <fanpresent> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </fanpresent> | ||||
|     <fanstatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </fanstatus> | ||||
|     <psucheck> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </psucheck> | ||||
|     <psustatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </psustatus> | ||||
|     <psutype> | ||||
|         <code key="DPS-1300AB-6" value="PSA1300CRPS-F"/> | ||||
|         <code key="GW-CRPS1300D" value="PSA1300CRPS-F"/> | ||||
|         <code key="DPS-1300AB-11" value="PSA1300CRPS-R"/> | ||||
|         <code key="CRPS1300D3R" value="PSA1300CRPS-R"/> | ||||
|     </psutype> | ||||
|     <fan_display_name> | ||||
|         <code key="FAN24K4056-F" value="FAN24K4056-F"/> | ||||
|         <code key="FAN24K4056S-F" value="FAN24K4056-F"/> | ||||
|         <code key="FAN24K4056S-R" value="FAN24K4056-R"/> | ||||
|     </fan_display_name> | ||||
|     <slotpresent> | ||||
|         <code key="1" value="ABSENT"/> | ||||
|         <code key="0" value="PRESENT"/> | ||||
|     </slotpresent> | ||||
|     </decode> | ||||
| </catalog> | ||||
|  | ||||
|  | ||||
							
								
								
									
										953
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/fru.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										953
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/fru.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,953 @@ | ||||
| #!/usr/bin/python3 | ||||
| import collections | ||||
| from bitarray import bitarray | ||||
| from datetime import datetime, timedelta | ||||
|  | ||||
|  | ||||
| __DEBUG__ = "N" | ||||
|  | ||||
|  | ||||
| class FruException(Exception): | ||||
|     def __init__(self, message='fruerror', code=-100): | ||||
|         err = 'errcode: {0} message:{1}'.format(code, message) | ||||
|         Exception.__init__(self, err) | ||||
|         self.code = code | ||||
|         self.message = message | ||||
|  | ||||
|  | ||||
| def e_print(err): | ||||
|     print("ERROR: " + err) | ||||
|  | ||||
|  | ||||
| def d_print(debug_info): | ||||
|     if(__DEBUG__ == "Y"): | ||||
|         print(debug_info) | ||||
|  | ||||
|  | ||||
| class FruUtil(): | ||||
|     @staticmethod | ||||
|     def decodeLength(value): | ||||
|         a = bitarray(8) | ||||
|         a.setall(True) | ||||
|         a[0:1] = 0 | ||||
|         a[1:2] = 0 | ||||
|         x = ord(a.tobytes()) | ||||
|         return x & ord(value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def minToData(): | ||||
|         starttime = datetime(1996, 1, 1, 0, 0, 0) | ||||
|         endtime = datetime.now() | ||||
|         seconds = (endtime - starttime).total_seconds() | ||||
|         mins = seconds // 60 | ||||
|         m = int(round(mins)) | ||||
|         return m | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTimeFormat(): | ||||
|         return datetime.now().strftime('%Y-%m-%d') | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTypeLength(value): | ||||
|         if value is None or len(value) == 0: | ||||
|             return 0 | ||||
|         a = bitarray(8) | ||||
|         a.setall(False) | ||||
|         a[0:1] = 1 | ||||
|         a[1:2] = 1 | ||||
|         x = ord(a.tobytes()) | ||||
|         return x | len(value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def checksum(b): | ||||
|         result = 0 | ||||
|         for i in range(len(b)): | ||||
|             result += ord(b[i]) | ||||
|         return (0x100 - (result & 0xff)) & 0xff | ||||
|  | ||||
|  | ||||
| class BaseArea(object): | ||||
|     SUGGESTED_SIZE_COMMON_HEADER = 8 | ||||
|     SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 | ||||
|     SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 | ||||
|     SUGGESTED_SIZE_BOARD_INFO_AREA = 80 | ||||
|     SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 | ||||
|  | ||||
|     INITVALUE = b'\x00' | ||||
|     resultvalue = INITVALUE * 256 | ||||
|     COMMON_HEAD_VERSION = b'\x01' | ||||
|     __childList = None | ||||
|  | ||||
|     def __init__(self, name="", size=0, offset=0): | ||||
|         self.__childList = [] | ||||
|         self._offset = offset | ||||
|         self.name = name | ||||
|         self._size = size | ||||
|         self._isPresent = False | ||||
|         self._data = b'\x00' * size | ||||
|         self.__dataoffset = 0 | ||||
|  | ||||
|     @property | ||||
|     def childList(self): | ||||
|         return self.__childList | ||||
|  | ||||
|     @childList.setter | ||||
|     def childList(self, value): | ||||
|         self.__childList = value | ||||
|  | ||||
|     @property | ||||
|     def offset(self): | ||||
|         return self._offset | ||||
|  | ||||
|     @offset.setter | ||||
|     def offset(self, value): | ||||
|         self._offset = value | ||||
|  | ||||
|     @property | ||||
|     def size(self): | ||||
|         return self._size | ||||
|  | ||||
|     @size.setter | ||||
|     def size(self, value): | ||||
|         self._size = value | ||||
|  | ||||
|     @property | ||||
|     def data(self): | ||||
|         return self._data | ||||
|  | ||||
|     @data.setter | ||||
|     def data(self, value): | ||||
|         self._data = value | ||||
|  | ||||
|     @property | ||||
|     def isPresent(self): | ||||
|         return self._isPresent | ||||
|  | ||||
|     @isPresent.setter | ||||
|     def isPresent(self, value): | ||||
|         self._isPresent = value | ||||
|  | ||||
|  | ||||
| class InternalUseArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class ChassisInfoArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class BoardInfoArea(BaseArea): | ||||
|     _boardTime = None | ||||
|     _fields = None | ||||
|     _mfg_date = None | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "version             : %x\n" \ | ||||
|                     "length              : %d \n" \ | ||||
|                     "language            : %x \n" \ | ||||
|                     "mfg_date            : %s \n" \ | ||||
|                     "boardManufacturer   : %s \n" \ | ||||
|                     "boardProductName    : %s \n" \ | ||||
|                     "boardSerialNumber   : %s \n" \ | ||||
|                     "boardPartNumber     : %s \n" \ | ||||
|                     "fruFileId           : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (ord(self.boardversion), self.size, | ||||
|                               self.language, self.getMfgRealData(), | ||||
|                               self.boardManufacturer, self.boardProductName, | ||||
|                               self.boardSerialNumber, self.boardPartNumber, | ||||
|                               self.fruFileId) | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 tmpstr += "boardextra%d         : %s \n" % (i, valtmpval) | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         return tmpstr | ||||
|  | ||||
|     def todict(self): | ||||
|         dic = collections.OrderedDict() | ||||
|         dic["boardversion"] = ord(self.boardversion) | ||||
|         dic["boardlength"] = self.size | ||||
|         dic["boardlanguage"] = self.language | ||||
|         dic["boardmfg_date"] = self.getMfgRealData() | ||||
|         dic["boardManufacturer"] = self.boardManufacturer | ||||
|         dic["boardProductName"] = self.boardProductName | ||||
|         dic["boardSerialNumber"] = self.boardSerialNumber | ||||
|         dic["boardPartNumber"] = self.boardPartNumber | ||||
|         dic["boardfruFileId"] = self.fruFileId | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 dic[valtmp] = valtmpval | ||||
|             else: | ||||
|                 break | ||||
|         return dic | ||||
|  | ||||
|     def decodedata(self): | ||||
|         index = 0 | ||||
|         self.areaversion = self.data[index] | ||||
|         index += 1 | ||||
|         d_print("decode length :%d class size:%d" % | ||||
|                 ((ord(self.data[index]) * 8), self.size)) | ||||
|         index += 2 | ||||
|  | ||||
|         timetmp = self.data[index: index + 3] | ||||
|         self.mfg_date = ord(timetmp[0]) | ( | ||||
|             ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) | ||||
|         d_print("decode getMfgRealData :%s" % self.getMfgRealData()) | ||||
|         index += 3 | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardManufacturer = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardManufacturer:%s" % self.boardManufacturer) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardProductName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardProductName:%s" % self.boardProductName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardSerialNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardPartNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardPartNumber:%s" % self.boardPartNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.fruFileId = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode fruFileId:%s" % self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if self.data[index] != chr(0xc1): | ||||
|                 templen = FruUtil.decodeLength(self.data[index]) | ||||
|                 tmpval = self.data[index + 1: index + templen + 1] | ||||
|                 setattr(self, valtmp, tmpval) | ||||
|                 index += templen + 1 | ||||
|                 d_print("decode boardextra%d:%s" % (i, tmpval)) | ||||
|             else: | ||||
|                 break | ||||
|         return | ||||
|  | ||||
|     def recalcute(self): | ||||
|         d_print("boardInfoArea version:%x" % ord(self.boardversion)) | ||||
|         d_print("boardInfoArea length:%d" % self.size) | ||||
|         d_print("boardInfoArea language:%x" % self.language) | ||||
|         self.mfg_date = FruUtil.minToData() | ||||
|         d_print("boardInfoArea mfg_date:%x" % self.mfg_date) | ||||
|  | ||||
|         self.data = chr(ord(self.boardversion)) + \ | ||||
|             chr(self.size // 8) + chr(self.language) | ||||
|  | ||||
|         self.data += chr(self.mfg_date & 0xFF) | ||||
|         self.data += chr((self.mfg_date >> 8) & 0xFF) | ||||
|         self.data += chr((self.mfg_date >> 16) & 0xFF) | ||||
|  | ||||
|         d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) | ||||
|         typelength = FruUtil.getTypeLength(self.boardManufacturer) | ||||
|         self.data += chr(typelength) | ||||
|         self.data += self.boardManufacturer | ||||
|  | ||||
|         d_print("boardInfoArea boardProductName:%s" % self.boardProductName) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardProductName)) | ||||
|         self.data += self.boardProductName | ||||
|  | ||||
|         d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) | ||||
|         self.data += self.boardSerialNumber | ||||
|  | ||||
|         d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) | ||||
|         self.data += self.boardPartNumber | ||||
|  | ||||
|         d_print("boardInfoArea fruFileId:%s" % self.fruFileId) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.fruFileId)) | ||||
|         self.data += self.fruFileId | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) | ||||
|                 self.data += chr(FruUtil.getTypeLength(valtmpval)) | ||||
|                 if valtmpval is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     self.data += valtmpval | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         self.data += chr(0xc1) | ||||
|  | ||||
|         if len(self.data) > (self.size - 1): | ||||
|             incr = (len(self.data) - self.size) // 8 + 1 | ||||
|             self.size += incr * 8 | ||||
|  | ||||
|         self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] | ||||
|         d_print("self data:%d" % len(self.data)) | ||||
|         d_print("self size:%d" % self.size) | ||||
|         d_print("adjust size:%d" % (self.size - len(self.data) - 1)) | ||||
|         self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) | ||||
|  | ||||
|         # checksum | ||||
|         checksum = FruUtil.checksum(self.data) | ||||
|         d_print("board info checksum:%x" % checksum) | ||||
|         self.data += chr(checksum) | ||||
|  | ||||
|     def getMfgRealData(self): | ||||
|         starttime = datetime(1996, 1, 1, 0, 0, 0) | ||||
|         mactime = starttime + timedelta(minutes=self.mfg_date) | ||||
|         return mactime | ||||
|  | ||||
|     @property | ||||
|     def language(self): | ||||
|         self._language = 25 | ||||
|         return self._language | ||||
|  | ||||
|     @property | ||||
|     def mfg_date(self): | ||||
|         return self._mfg_date | ||||
|  | ||||
|     @mfg_date.setter | ||||
|     def mfg_date(self, val): | ||||
|         self._mfg_date = val | ||||
|  | ||||
|     @property | ||||
|     def boardversion(self): | ||||
|         self._boardversion = self.COMMON_HEAD_VERSION | ||||
|         return self._boardversion | ||||
|  | ||||
|     @property | ||||
|     def fruFileId(self): | ||||
|         return self._FRUFileID | ||||
|  | ||||
|     @fruFileId.setter | ||||
|     def fruFileId(self, val): | ||||
|         self._FRUFileID = val | ||||
|  | ||||
|     @property | ||||
|     def boardPartNumber(self): | ||||
|         return self._boardPartNumber | ||||
|  | ||||
|     @boardPartNumber.setter | ||||
|     def boardPartNumber(self, val): | ||||
|         self._boardPartNumber = val | ||||
|  | ||||
|     @property | ||||
|     def boardSerialNumber(self): | ||||
|         return self._boardSerialNumber | ||||
|  | ||||
|     @boardSerialNumber.setter | ||||
|     def boardSerialNumber(self, val): | ||||
|         self._boardSerialNumber = val | ||||
|  | ||||
|     @property | ||||
|     def boardProductName(self): | ||||
|         return self._boradProductName | ||||
|  | ||||
|     @boardProductName.setter | ||||
|     def boardProductName(self, val): | ||||
|         self._boradProductName = val | ||||
|  | ||||
|     @property | ||||
|     def boardManufacturer(self): | ||||
|         return self._boardManufacturer | ||||
|  | ||||
|     @boardManufacturer.setter | ||||
|     def boardManufacturer(self, val): | ||||
|         self._boardManufacturer = val | ||||
|  | ||||
|     @property | ||||
|     def boardTime(self): | ||||
|         return self._boardTime | ||||
|  | ||||
|     @boardTime.setter | ||||
|     def boardTime(self, val): | ||||
|         self._boardTime = val | ||||
|  | ||||
|     @property | ||||
|     def fields(self): | ||||
|         return self._fields | ||||
|  | ||||
|     @fields.setter | ||||
|     def fields(self, val): | ||||
|         self._fields = val | ||||
|  | ||||
|  | ||||
| class ProductInfoArea(BaseArea): | ||||
|     _productManufacturer = None | ||||
|     _productAssetTag = None | ||||
|     _FRUFileID = None | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "version             : %x\n" \ | ||||
|                     "length              : %d \n" \ | ||||
|                     "language            : %x \n" \ | ||||
|                     "productManufacturer : %s \n" \ | ||||
|                     "productName         : %s \n" \ | ||||
|                     "productPartModelName: %s \n" \ | ||||
|                     "productVersion      : %s \n" \ | ||||
|                     "productSerialNumber : %s \n" \ | ||||
|                     "productAssetTag     : %s \n" \ | ||||
|                     "fruFileId           : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (ord(self.areaversion), self.size, | ||||
|                               self.language, self.productManufacturer, | ||||
|                               self.productName, self.productPartModelName, | ||||
|                               self.productVersion, self.productSerialNumber, | ||||
|                               self.productAssetTag, self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 tmpstr += "productextra%d       : %s \n" % (i, valtmpval) | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         return tmpstr | ||||
|  | ||||
|     def todict(self): | ||||
|         dic = collections.OrderedDict() | ||||
|         dic["productversion"] = ord(self.areaversion) | ||||
|         dic["productlength"] = self.size | ||||
|         dic["productlanguage"] = self.language | ||||
|         dic["productManufacturer"] = self.productManufacturer | ||||
|         dic["productName"] = self.productName | ||||
|         dic["productPartModelName"] = self.productPartModelName | ||||
|         dic["productVersion"] = int(self.productVersion, 16) | ||||
|         dic["productSerialNumber"] = self.productSerialNumber | ||||
|         dic["productAssetTag"] = self.productAssetTag | ||||
|         dic["productfruFileId"] = self.fruFileId | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 dic[valtmp] = valtmpval | ||||
|             else: | ||||
|                 break | ||||
|         return dic | ||||
|  | ||||
|     def decodedata(self): | ||||
|         index = 0 | ||||
|         self.areaversion = self.data[index]  # 0 | ||||
|         index += 1 | ||||
|         d_print("decode length %d" % (ord(self.data[index]) * 8)) | ||||
|         d_print("class size %d" % self.size) | ||||
|         index += 2 | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productManufacturer = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productManufacturer:%s" % self.productManufacturer) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productName:%s" % self.productName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productPartModelName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productPartModelName:%s" % self.productPartModelName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productVersion = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productVersion:%s" % self.productVersion) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productSerialNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productSerialNumber:%s" % self.productSerialNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productAssetTag = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productAssetTag:%s" % self.productAssetTag) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.fruFileId = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode fruFileId:%s" % self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if self.data[index] != chr(0xc1) and index < self.size - 1: | ||||
|                 templen = FruUtil.decodeLength(self.data[index]) | ||||
|                 if templen == 0: | ||||
|                     break | ||||
|                 tmpval = self.data[index + 1: index + templen + 1] | ||||
|                 d_print("decode boardextra%d:%s" % (i, tmpval)) | ||||
|                 setattr(self, valtmp, tmpval) | ||||
|                 index += templen + 1 | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|     @property | ||||
|     def productVersion(self): | ||||
|         return self._productVersion | ||||
|  | ||||
|     @productVersion.setter | ||||
|     def productVersion(self, name): | ||||
|         self._productVersion = name | ||||
|  | ||||
|     @property | ||||
|     def areaversion(self): | ||||
|         self._areaversion = self.COMMON_HEAD_VERSION | ||||
|         return self._areaversion | ||||
|  | ||||
|     @areaversion.setter | ||||
|     def areaversion(self, name): | ||||
|         self._areaversion = name | ||||
|  | ||||
|     @property | ||||
|     def language(self): | ||||
|         self._language = 25 | ||||
|         return self._language | ||||
|  | ||||
|     @property | ||||
|     def productManufacturer(self): | ||||
|         return self._productManufacturer | ||||
|  | ||||
|     @productManufacturer.setter | ||||
|     def productManufacturer(self, name): | ||||
|         self._productManufacturer = name | ||||
|  | ||||
|     @property | ||||
|     def productName(self): | ||||
|         return self._productName | ||||
|  | ||||
|     @productName.setter | ||||
|     def productName(self, name): | ||||
|         self._productName = name | ||||
|  | ||||
|     @property | ||||
|     def productPartModelName(self): | ||||
|         return self._productPartModelName | ||||
|  | ||||
|     @productPartModelName.setter | ||||
|     def productPartModelName(self, name): | ||||
|         self._productPartModelName = name | ||||
|  | ||||
|     @property | ||||
|     def productSerialNumber(self): | ||||
|         return self._productSerialNumber | ||||
|  | ||||
|     @productSerialNumber.setter | ||||
|     def productSerialNumber(self, name): | ||||
|         self._productSerialNumber = name | ||||
|  | ||||
|     @property | ||||
|     def productAssetTag(self): | ||||
|         return self._productAssetTag | ||||
|  | ||||
|     @productAssetTag.setter | ||||
|     def productAssetTag(self, name): | ||||
|         self._productAssetTag = name | ||||
|  | ||||
|     @property | ||||
|     def fruFileId(self): | ||||
|         return self._FRUFileID | ||||
|  | ||||
|     @fruFileId.setter | ||||
|     def fruFileId(self, name): | ||||
|         self._FRUFileID = name | ||||
|  | ||||
|     def recalcute(self): | ||||
|         d_print("product version:%x" % ord(self.areaversion)) | ||||
|         d_print("product length:%d" % self.size) | ||||
|         d_print("product language:%x" % self.language) | ||||
|         self.data = chr(ord(self.areaversion)) + \ | ||||
|             chr(self.size // 8) + chr(self.language) | ||||
|  | ||||
|         typelength = FruUtil.getTypeLength(self.productManufacturer) | ||||
|         self.data += chr(typelength) | ||||
|         self.data += self.productManufacturer | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productName)) | ||||
|         self.data += self.productName | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) | ||||
|         self.data += self.productPartModelName | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productVersion)) | ||||
|         self.data += self.productVersion | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) | ||||
|         self.data += self.productSerialNumber | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) | ||||
|         if self.productAssetTag is not None: | ||||
|             self.data += self.productAssetTag | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.fruFileId)) | ||||
|         self.data += self.fruFileId | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) | ||||
|                 self.data += chr(FruUtil.getTypeLength(valtmpval)) | ||||
|                 if valtmpval is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     self.data += valtmpval | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         self.data += chr(0xc1) | ||||
|         if len(self.data) > (self.size - 1): | ||||
|             incr = (len(self.data) - self.size) // 8 + 1 | ||||
|             self.size += incr * 8 | ||||
|         d_print("self.data:%d" % len(self.data)) | ||||
|         d_print("self.size:%d" % self.size) | ||||
|  | ||||
|         self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] | ||||
|         self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) | ||||
|         checksum = FruUtil.checksum(self.data) | ||||
|         d_print("board info checksum:%x" % checksum) | ||||
|         self.data += chr(checksum) | ||||
|  | ||||
|  | ||||
| class MultiRecordArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class Field(object): | ||||
|  | ||||
|     def __init__(self, fieldType="ASCII", fieldData=""): | ||||
|         self.fieldData = fieldData | ||||
|         self.fieldType = fieldType | ||||
|  | ||||
|     @property | ||||
|     def data(self): | ||||
|         return self._data | ||||
|  | ||||
|     @property | ||||
|     def fieldType(self): | ||||
|         return self._fieldType | ||||
|  | ||||
|     @property | ||||
|     def fieldData(self): | ||||
|         return self._fieldData | ||||
|  | ||||
|  | ||||
| class ipmifru(BaseArea): | ||||
|     _BoardInfoArea = None | ||||
|     _ProductInfoArea = None | ||||
|     _InternalUseArea = None | ||||
|     _ChassisInfoArea = None | ||||
|     _multiRecordArea = None | ||||
|     _productinfoAreaOffset = BaseArea.INITVALUE | ||||
|     _boardInfoAreaOffset = BaseArea.INITVALUE | ||||
|     _internalUserAreaOffset = BaseArea.INITVALUE | ||||
|     _chassicInfoAreaOffset = BaseArea.INITVALUE | ||||
|     _multiRecordAreaOffset = BaseArea.INITVALUE | ||||
|     _bindata = None | ||||
|     _bodybin = None | ||||
|     _version = BaseArea.COMMON_HEAD_VERSION | ||||
|     _zeroCheckSum = None | ||||
|     _frusize = 256 | ||||
|  | ||||
|     def __str__(self): | ||||
|         tmpstr = "" | ||||
|         if self.boardInfoArea.isPresent: | ||||
|             tmpstr += "\nboardinfoarea: \n" | ||||
|             tmpstr += self.boardInfoArea.__str__() | ||||
|         if self.productInfoArea.isPresent: | ||||
|             tmpstr += "\nproductinfoarea: \n" | ||||
|             tmpstr += self.productInfoArea.__str__() | ||||
|         return tmpstr | ||||
|  | ||||
|     def decodeBin(self, eeprom): | ||||
|         commonHead = eeprom[0:8] | ||||
|         d_print("decode version %x" % ord(commonHead[0])) | ||||
|         if ord(self.COMMON_HEAD_VERSION) != ord(commonHead[0]): | ||||
|             raise FruException("HEAD VERSION error,not Fru format!", -10) | ||||
|         if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): | ||||
|             strtemp = "check header checksum error [cal:%02x data:%02x]" % ( | ||||
|                 FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) | ||||
|             raise FruException(strtemp, -3) | ||||
|         if ord(commonHead[1]) != ord(self.INITVALUE): | ||||
|             d_print("Internal Use Area is present") | ||||
|             self.internalUseArea = InternalUseArea( | ||||
|                 name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) | ||||
|             self.internalUseArea.isPresent = True | ||||
|             self.internalUserAreaOffset = ord(commonHead[1]) | ||||
|             self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( | ||||
|                 self.internalUserAreaOffset * 8 + self.internalUseArea.size)] | ||||
|         if ord(commonHead[2]) != ord(self.INITVALUE): | ||||
|             d_print("Chassis Info Area is present") | ||||
|             self.chassisInfoArea = ChassisInfoArea( | ||||
|                 name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) | ||||
|             self.chassisInfoArea.isPresent = True | ||||
|             self.chassicInfoAreaOffset = ord(commonHead[2]) | ||||
|             self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( | ||||
|                 self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] | ||||
|         if ord(commonHead[3]) != ord(self.INITVALUE): | ||||
|             self.boardInfoArea = BoardInfoArea( | ||||
|                 name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) | ||||
|             self.boardInfoArea.isPresent = True | ||||
|             self.boardInfoAreaOffset = ord(commonHead[3]) | ||||
|             self.boardInfoArea.size = ord( | ||||
|                 eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 | ||||
|             d_print("Board Info Area is present size:%d" % | ||||
|                     (self.boardInfoArea.size)) | ||||
|             self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( | ||||
|                 self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] | ||||
|             if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): | ||||
|                 strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" %  \ | ||||
|                     (FruUtil.checksum( | ||||
|                         self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:])) | ||||
|                 raise FruException(strtmp, -3) | ||||
|             self.boardInfoArea.decodedata() | ||||
|         if ord(commonHead[4]) != ord(self.INITVALUE): | ||||
|             d_print("Product Info Area is present") | ||||
|             self.productInfoArea = ProductInfoArea( | ||||
|                 name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) | ||||
|             self.productInfoArea.isPresent = True | ||||
|             self.productinfoAreaOffset = ord(commonHead[4]) | ||||
|             d_print("length offset value: %02x" % | ||||
|                     ord(eeprom[self.productinfoAreaOffset * 8 + 1])) | ||||
|             self.productInfoArea.size = ord( | ||||
|                 eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 | ||||
|             d_print("Product Info Area is present size:%d" % | ||||
|                     (self.productInfoArea.size)) | ||||
|  | ||||
|             self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( | ||||
|                 self.productinfoAreaOffset * 8 + self.productInfoArea.size)] | ||||
|             if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): | ||||
|                 strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( | ||||
|                     FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) | ||||
|                 raise FruException(strtmp, -3) | ||||
|             self.productInfoArea.decodedata() | ||||
|         if ord(commonHead[5]) != ord(self.INITVALUE): | ||||
|             self.multiRecordArea = MultiRecordArea( | ||||
|                 name="MultiRecord record Area ") | ||||
|             d_print("MultiRecord record present") | ||||
|             self.multiRecordArea.isPresent = True | ||||
|             self.multiRecordAreaOffset = ord(commonHead[5]) | ||||
|             self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( | ||||
|                 self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] | ||||
|  | ||||
|     def initDefault(self): | ||||
|         self.version = self.COMMON_HEAD_VERSION | ||||
|         self.internalUserAreaOffset = self.INITVALUE | ||||
|         self.chassicInfoAreaOffset = self.INITVALUE | ||||
|         self.boardInfoAreaOffset = self.INITVALUE | ||||
|         self.productinfoAreaOffset = self.INITVALUE | ||||
|         self.multiRecordAreaOffset = self.INITVALUE | ||||
|         self.PAD = self.INITVALUE | ||||
|         self.zeroCheckSum = self.INITVALUE | ||||
|         self.offset = self.SUGGESTED_SIZE_COMMON_HEADER | ||||
|         self.productInfoArea = None | ||||
|         self.internalUseArea = None | ||||
|         self.boardInfoArea = None | ||||
|         self.chassisInfoArea = None | ||||
|         self.multiRecordArea = None | ||||
|         # self.recalcute() | ||||
|  | ||||
|     @property | ||||
|     def version(self): | ||||
|         return self._version | ||||
|  | ||||
|     @version.setter | ||||
|     def version(self, name): | ||||
|         self._version = name | ||||
|  | ||||
|     @property | ||||
|     def internalUserAreaOffset(self): | ||||
|         return self._internalUserAreaOffset | ||||
|  | ||||
|     @internalUserAreaOffset.setter | ||||
|     def internalUserAreaOffset(self, obj): | ||||
|         self._internalUserAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def chassicInfoAreaOffset(self): | ||||
|         return self._chassicInfoAreaOffset | ||||
|  | ||||
|     @chassicInfoAreaOffset.setter | ||||
|     def chassicInfoAreaOffset(self, obj): | ||||
|         self._chassicInfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def productinfoAreaOffset(self): | ||||
|         return self._productinfoAreaOffset | ||||
|  | ||||
|     @productinfoAreaOffset.setter | ||||
|     def productinfoAreaOffset(self, obj): | ||||
|         self._productinfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def boardInfoAreaOffset(self): | ||||
|         return self._boardInfoAreaOffset | ||||
|  | ||||
|     @boardInfoAreaOffset.setter | ||||
|     def boardInfoAreaOffset(self, obj): | ||||
|         self._boardInfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def multiRecordAreaOffset(self): | ||||
|         return self._multiRecordAreaOffset | ||||
|  | ||||
|     @multiRecordAreaOffset.setter | ||||
|     def multiRecordAreaOffset(self, obj): | ||||
|         self._multiRecordAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def zeroCheckSum(self): | ||||
|         return self._zeroCheckSum | ||||
|  | ||||
|     @zeroCheckSum.setter | ||||
|     def zeroCheckSum(self, obj): | ||||
|         self._zeroCheckSum = obj | ||||
|  | ||||
|     @property | ||||
|     def productInfoArea(self): | ||||
|         return self._ProductInfoArea | ||||
|  | ||||
|     @productInfoArea.setter | ||||
|     def productInfoArea(self, obj): | ||||
|         self._ProductInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def internalUseArea(self): | ||||
|         return self._InternalUseArea | ||||
|  | ||||
|     @internalUseArea.setter | ||||
|     def internalUseArea(self, obj): | ||||
|         self.internalUseArea = obj | ||||
|  | ||||
|     @property | ||||
|     def boardInfoArea(self): | ||||
|         return self._BoardInfoArea | ||||
|  | ||||
|     @boardInfoArea.setter | ||||
|     def boardInfoArea(self, obj): | ||||
|         self._BoardInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def chassisInfoArea(self): | ||||
|         return self._ChassisInfoArea | ||||
|  | ||||
|     @chassisInfoArea.setter | ||||
|     def chassisInfoArea(self, obj): | ||||
|         self._ChassisInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def multiRecordArea(self): | ||||
|         return self._multiRecordArea | ||||
|  | ||||
|     @multiRecordArea.setter | ||||
|     def multiRecordArea(self, obj): | ||||
|         self._multiRecordArea = obj | ||||
|  | ||||
|     @property | ||||
|     def bindata(self): | ||||
|         return self._bindata | ||||
|  | ||||
|     @bindata.setter | ||||
|     def bindata(self, obj): | ||||
|         self._bindata = obj | ||||
|  | ||||
|     @property | ||||
|     def bodybin(self): | ||||
|         return self._bodybin | ||||
|  | ||||
|     @bodybin.setter | ||||
|     def bodybin(self, obj): | ||||
|         self._bodybin = obj | ||||
|  | ||||
|     def recalcuteCommonHead(self): | ||||
|         self.bindata = "" | ||||
|         self.offset = self.SUGGESTED_SIZE_COMMON_HEADER | ||||
|         d_print("common Header %d" % self.offset) | ||||
|         d_print("fru eeprom size  %d" % self._frusize) | ||||
|         if self.internalUseArea is not None and self.internalUseArea.isPresent: | ||||
|             self.internalUserAreaOffset = self.offset // 8 | ||||
|             self.offset += self.internalUseArea.size | ||||
|             d_print("internalUseArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: | ||||
|             self.chassicInfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.chassisInfoArea.size | ||||
|             d_print("chassisInfoArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.boardInfoArea is not None and self.boardInfoArea.isPresent: | ||||
|             self.boardInfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.boardInfoArea.size | ||||
|             d_print("boardInfoArea is present offset:%d" % self.offset) | ||||
|             d_print("boardInfoArea is present size:%d" % | ||||
|                     self.boardInfoArea.size) | ||||
|  | ||||
|         if self.productInfoArea is not None and self.productInfoArea.isPresent: | ||||
|             self.productinfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.productInfoArea.size | ||||
|             d_print("productInfoArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.multiRecordArea is not None and self.multiRecordArea.isPresent: | ||||
|             self.multiRecordAreaOffset = self.offset // 8 | ||||
|             d_print("multiRecordArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.internalUserAreaOffset == self.INITVALUE: | ||||
|             self.internalUserAreaOffset = 0 | ||||
|         if self.productinfoAreaOffset == self.INITVALUE: | ||||
|             self.productinfoAreaOffset = 0 | ||||
|         if self.chassicInfoAreaOffset == self.INITVALUE: | ||||
|             self.chassicInfoAreaOffset = 0 | ||||
|         if self.boardInfoAreaOffset == self.INITVALUE: | ||||
|             self.boardInfoAreaOffset = 0 | ||||
|         if self.multiRecordAreaOffset == self.INITVALUE: | ||||
|             self.multiRecordAreaOffset = 0 | ||||
|  | ||||
|         self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset | ||||
|                              - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff | ||||
|         d_print("zerochecksum:%x" % self.zeroCheckSum) | ||||
|         self.data = "" | ||||
|         self.data += chr(self.version[0]) + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( | ||||
|             self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + chr(self.INITVALUE[0]) + chr(self.zeroCheckSum) | ||||
|  | ||||
|         self.bindata = self.data + self.bodybin | ||||
|         totallen = len(self.bindata) | ||||
|         d_print("totallen %d" % totallen) | ||||
|         if (totallen < self._frusize): | ||||
|             self.bindata = self.bindata.ljust(self._frusize, chr(self.INITVALUE[0])) | ||||
|         else: | ||||
|             raise FruException('bin data more than %d' % self._frusize, -2) | ||||
|  | ||||
|     def recalcutebin(self): | ||||
|         self.bodybin = "" | ||||
|         if self.internalUseArea is not None and self.internalUseArea.isPresent: | ||||
|             d_print("internalUseArea present") | ||||
|             self.bodybin += self.internalUseArea.data | ||||
|         if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: | ||||
|             d_print("chassisInfoArea present") | ||||
|             self.bodybin += self.chassisInfoArea.data | ||||
|         if self.boardInfoArea is not None and self.boardInfoArea.isPresent: | ||||
|             d_print("boardInfoArea present") | ||||
|             self.boardInfoArea.recalcute() | ||||
|             self.bodybin += self.boardInfoArea.data | ||||
|         if self.productInfoArea is not None and self.productInfoArea.isPresent: | ||||
|             d_print("productInfoAreapresent") | ||||
|             self.productInfoArea.recalcute() | ||||
|             self.bodybin += self.productInfoArea.data | ||||
|         if self.multiRecordArea is not None and self.multiRecordArea.isPresent: | ||||
|             d_print("multiRecordArea present") | ||||
|             self.bodybin += self.productInfoArea.data | ||||
|  | ||||
|     def recalcute(self, fru_eeprom_size=256): | ||||
|         self._frusize = fru_eeprom_size | ||||
|         self.recalcutebin() | ||||
|         self.recalcuteCommonHead() | ||||
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/installer.conf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/installer.conf
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| CONSOLE_SPEED=115200 | ||||
							
								
								
									
										6
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/led_proc_init.soc
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/led_proc_init.soc
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,6 @@ | ||||
|  | ||||
| led auto on | ||||
|  | ||||
| led start | ||||
|  | ||||
| linkscan SwPortBitMap=all | ||||
							
								
								
									
										431
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/monitor.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										431
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/monitor.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,431 @@ | ||||
| #!/usr/bin/python3 | ||||
| #   * onboard temperature sensors | ||||
| #   * FAN trays | ||||
| #   * PSU | ||||
| # | ||||
| import os | ||||
| import xml.etree.ElementTree as ET | ||||
| import glob | ||||
| from fru import ipmifru | ||||
| from decimal import Decimal | ||||
|  | ||||
|  | ||||
| MAILBOX_DIR = "/sys/bus/i2c/devices/" | ||||
| BOARD_ID_PATH = "/sys/module/ruijie_common/parameters/dfd_my_type" | ||||
|  | ||||
| CONFIG_NAME = "dev.xml" | ||||
|  | ||||
| def byteTostr(val): | ||||
|     strtmp = '' | ||||
|     for i in range(len(val)): | ||||
|         strtmp += chr(val[i]) | ||||
|     return strtmp | ||||
|  | ||||
|  | ||||
| def typeTostr(val): | ||||
|     if isinstance(val, bytes): | ||||
|         strtmp = byteTostr(val) | ||||
|         return strtmp | ||||
|     return val | ||||
|  | ||||
|  | ||||
| def get_board_id(): | ||||
|     if not os.path.exists(BOARD_ID_PATH): | ||||
|         return "NA" | ||||
|     with open(BOARD_ID_PATH) as fd: | ||||
|         id_str = fd.read().strip() | ||||
|     return "0x%x" % (int(id_str, 10)) | ||||
|  | ||||
|  | ||||
| def dev_file_read(path, offset, read_len): | ||||
|     retval = "ERR" | ||||
|     val_list = [] | ||||
|     msg = "" | ||||
|     ret = "" | ||||
|     fd = -1 | ||||
|  | ||||
|     if not os.path.exists(path): | ||||
|         return False, "%s %s not found" % (retval, path) | ||||
|  | ||||
|     try: | ||||
|         fd = os.open(path, os.O_RDONLY) | ||||
|         os.lseek(fd, offset, os.SEEK_SET) | ||||
|         ret = os.read(fd, read_len) | ||||
|         for item in ret: | ||||
|             val_list.append(item) | ||||
|     except Exception as e: | ||||
|         msg = str(e) | ||||
|         return False, "%s %s" % (retval, msg) | ||||
|     finally: | ||||
|         if fd > 0: | ||||
|             os.close(fd) | ||||
|     return True, val_list | ||||
|  | ||||
|  | ||||
| def getPMCreg(location): | ||||
|     retval = 'ERR' | ||||
|     if (not os.path.isfile(location)): | ||||
|         return "%s %s  notfound"% (retval , location) | ||||
|     try: | ||||
|         with open(location, 'r') as fd: | ||||
|             retval = fd.read() | ||||
|     except Exception as error: | ||||
|         return "ERR %s" % str(error) | ||||
|  | ||||
|     retval = retval.rstrip('\r\n') | ||||
|     retval = retval.lstrip(" ") | ||||
|     return retval | ||||
|  | ||||
|  | ||||
| # Get a mailbox register | ||||
| def get_pmc_register(reg_name): | ||||
|     retval = 'ERR' | ||||
|     mb_reg_file = reg_name | ||||
|     filepath = glob.glob(mb_reg_file) | ||||
|     if(len(filepath) == 0): | ||||
|         return "%s %s  notfound"% (retval , mb_reg_file) | ||||
|     mb_reg_file = filepath[0] | ||||
|     if (not os.path.isfile(mb_reg_file)): | ||||
|         #print mb_reg_file,  'not found !' | ||||
|         return "%s %s  notfound"% (retval , mb_reg_file) | ||||
|     try: | ||||
|         with open(mb_reg_file, 'rb') as fd: | ||||
|             retval = fd.read() | ||||
|         retval = typeTostr(retval) | ||||
|     except Exception as error: | ||||
|         retval = "%s %s read failed, msg: %s" % (retval, mb_reg_file, str(error)) | ||||
|  | ||||
|     retval = retval.rstrip('\r\n') | ||||
|     retval = retval.lstrip(" ") | ||||
|     return retval | ||||
|  | ||||
|  | ||||
| class checktype(): | ||||
|     def __init__(self, test1): | ||||
|         self.test1 = test1 | ||||
|  | ||||
|     @staticmethod | ||||
|     def check(name,location, bit, value, tips , err1): | ||||
|         psu_status = int(get_pmc_register(location),16) | ||||
|         val = (psu_status & (1<< bit)) >> bit | ||||
|         if (val != value): | ||||
|             err1["errmsg"] = tips | ||||
|             err1["code"] = -1 | ||||
|             return -1 | ||||
|         else: | ||||
|             err1["errmsg"] = "none" | ||||
|             err1["code"] = 0 | ||||
|             return 0 | ||||
|  | ||||
|     @staticmethod | ||||
|     def getValue(location, bit , type, coefficient = 1, addend = 0): | ||||
|         try: | ||||
|             value_t = get_pmc_register(location) | ||||
|             if value_t.startswith("ERR") : | ||||
|                 return value_t | ||||
|             if (type == 1): | ||||
|                 return float('%.1f' % ((float(value_t)/1000) + addend)) | ||||
|             elif (type == 2): | ||||
|                 return float('%.1f' % (float(value_t)/100)) | ||||
|             elif (type == 3): | ||||
|                 psu_status = int(value_t,16) | ||||
|                 return (psu_status & (1<< bit)) >> bit | ||||
|             elif (type == 4): | ||||
|                 return int(value_t,10) | ||||
|             elif (type == 5): | ||||
|                 return float('%.1f' % (float(value_t)/1000/1000)) | ||||
|             elif (type == 6): | ||||
|                 return Decimal(float(value_t)*coefficient/1000).quantize(Decimal('0.000')) | ||||
|             else: | ||||
|                 return value_t | ||||
|         except Exception as e: | ||||
|             value_t = "ERR %s" % str(e) | ||||
|             return value_t | ||||
|  | ||||
|     #######temp | ||||
|     @staticmethod | ||||
|     def getTemp(self, name, location , ret_t): | ||||
|         ret2 = self.getValue(location + "temp1_input" ," " ,1); | ||||
|         ret3 = self.getValue(location + "temp1_max" ," ", 1); | ||||
|         ret4 = self.getValue(location + "temp1_max_hyst" ," ", 1); | ||||
|         ret_t["temp1_input"] = ret2 | ||||
|         ret_t["temp1_max"] = ret3 | ||||
|         ret_t["temp1_max_hyst"] = ret4 | ||||
|  | ||||
|     @staticmethod | ||||
|     def getLM75(name, location, result): | ||||
|         c1=checktype | ||||
|         r1={} | ||||
|         c1.getTemp(c1, name, location, r1) | ||||
|         result[name] = r1 | ||||
|  | ||||
|     ##########fanFRU | ||||
|     @staticmethod | ||||
|     def decodeBinByValue(retval): | ||||
|         fru = ipmifru() | ||||
|         fru.decodeBin(retval) | ||||
|         return fru | ||||
|  | ||||
|     @staticmethod | ||||
|     def printbinvalue(b): | ||||
|         index = 0 | ||||
|         print("     ",) | ||||
|         for width in range(16): | ||||
|             print("%02x " % width,) | ||||
|         print("") | ||||
|         for i in range(0, len(b)): | ||||
|             if index % 16 == 0: | ||||
|                 print(" ") | ||||
|                 print(" %02x  " % i,) | ||||
|             print("%02x " % ord(b[i]),) | ||||
|             index += 1 | ||||
|         print("") | ||||
|  | ||||
|     @staticmethod | ||||
|     def getfruValue(prob_t, root, val): | ||||
|         try: | ||||
|             ret, binval_bytes = dev_file_read(val, 0, 256) | ||||
|             if ret == False: | ||||
|                 return binval_bytes | ||||
|             binval = byteTostr(binval_bytes) | ||||
|             fanpro = {} | ||||
|             ret = checktype.decodeBinByValue(binval) | ||||
|             fanpro['fan_type']  = ret.productInfoArea.productName | ||||
|             fanpro['hw_version']  = ret.productInfoArea.productVersion | ||||
|             fanpro['sn']  = ret.productInfoArea.productSerialNumber | ||||
|             fanpro['fanid']  = ret.productInfoArea.productextra2 | ||||
|             fan_display_name_dict = status.getDecodValue(root, "fan_display_name") | ||||
|             fan_name = fanpro['fan_type'].strip() | ||||
|             if len(fan_display_name_dict) == 0: | ||||
|                 return fanpro | ||||
|             if fan_name not in fan_display_name_dict.keys(): | ||||
|                 prob_t['errcode']= -1 | ||||
|                 prob_t['errmsg'] = '%s'%  ("ERR fan name: %s not support" % fan_name) | ||||
|             else: | ||||
|                 fanpro['fan_type'] = fan_display_name_dict[fan_name] | ||||
|             return fanpro | ||||
|         except Exception as error: | ||||
|             return "ERR " + str(error) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getslotfruValue(val): | ||||
|         try: | ||||
|             binval = checktype.getValue(val, 0 , 0) | ||||
|             if binval.startswith("ERR"): | ||||
|                 return binval | ||||
|             slotpro = {} | ||||
|             ret = checktype.decodeBinByValue(binval) | ||||
|             slotpro['slot_type']  = ret.boardInfoArea.boardProductName | ||||
|             slotpro['hw_version']  = ret.boardInfoArea.boardextra1 | ||||
|             slotpro['sn']  = ret.boardInfoArea.boardSerialNumber | ||||
|             return slotpro | ||||
|         except Exception as error: | ||||
|             return "ERR " + str(error) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getpsufruValue(prob_t, root, val): | ||||
|         try: | ||||
|             psu_match = False | ||||
|             binval = checktype.getValue(val, 0 , 0) | ||||
|             if binval.startswith("ERR"): | ||||
|                 return binval | ||||
|             psupro = {} | ||||
|             ret = checktype.decodeBinByValue(binval) | ||||
|             psupro['type1']  = ret.productInfoArea.productPartModelName | ||||
|             psupro['sn']  = ret.productInfoArea.productSerialNumber | ||||
|             psupro['hw_version'] = ret.productInfoArea.productVersion | ||||
|             psu_dict = status.getDecodValue(root, "psutype") | ||||
|             psupro['type1'] = psupro['type1'].strip() | ||||
|             if len(psu_dict) == 0: | ||||
|                 return psupro | ||||
|             for psu_name in psu_dict.keys(): | ||||
|                 if psu_name in psupro['type1']: | ||||
|                     psupro['type1'] = psu_dict[psu_name] | ||||
|                     psu_match = True | ||||
|                     break | ||||
|             if psu_match is not True: | ||||
|                 prob_t['errcode']= -1 | ||||
|                 prob_t['errmsg'] = '%s'%  ("ERR psu name: %s not support" % psupro['type1']) | ||||
|             return psupro | ||||
|         except Exception as error: | ||||
|             return "ERR " + str(error) | ||||
|  | ||||
| class status(): | ||||
|     def __init__(self, productname): | ||||
|         self.productname = productname | ||||
|  | ||||
|     @staticmethod | ||||
|     def getETroot(filename): | ||||
|         tree = ET.parse(filename) | ||||
|         root = tree.getroot() | ||||
|         return root; | ||||
|  | ||||
|     @staticmethod | ||||
|     def getDecodValue(collection, decode): | ||||
|         decodes = collection.find('decode') | ||||
|         testdecode = decodes.find(decode) | ||||
|         test={} | ||||
|         if testdecode is None: | ||||
|             return test | ||||
|         for neighbor in testdecode.iter('code'): | ||||
|             test[neighbor.attrib["key"]]=neighbor.attrib["value"] | ||||
|         return test | ||||
|  | ||||
|     @staticmethod | ||||
|     def getfileValue(location): | ||||
|         return checktype.getValue(location," "," ") | ||||
|  | ||||
|     @staticmethod | ||||
|     def getETValue(a, filename, tagname): | ||||
|         root = status.getETroot(filename) | ||||
|         for neighbor in root.iter(tagname): | ||||
|             prob_t = {} | ||||
|             prob_t = neighbor.attrib | ||||
|             prob_t['errcode']= 0 | ||||
|             prob_t['errmsg'] = '' | ||||
|             for pros in neighbor.iter("property"): | ||||
|                 ret = dict(list(neighbor.attrib.items()) + list(pros.attrib.items())) | ||||
|                 if ret.get('e2type') == 'fru' and ret.get("name") == "fru": | ||||
|                     fruval = checktype.getfruValue(prob_t, root, ret["location"]) | ||||
|                     if  isinstance(fruval, str) and fruval.startswith("ERR"): | ||||
|                         prob_t['errcode']= -1 | ||||
|                         prob_t['errmsg']= fruval | ||||
|                         break | ||||
|                     else: | ||||
|                         prob_t.update(fruval) | ||||
|                         continue | ||||
|  | ||||
|                 if ret.get("name") == "psu" and ret.get('e2type') == 'fru': | ||||
|                     psuval = checktype.getpsufruValue(prob_t, root, ret["location"]) | ||||
|                     if  isinstance(psuval, str) and psuval.startswith("ERR"): | ||||
|                         prob_t['errcode']= -1 | ||||
|                         prob_t['errmsg']= psuval | ||||
|                         break | ||||
|                     else: | ||||
|                         prob_t.update(psuval) | ||||
|                         continue | ||||
|  | ||||
|                 if ret.get("gettype") == "config": | ||||
|                     prob_t[ret["name"]] = ret["value"] | ||||
|                     continue | ||||
|  | ||||
|                 if ('type' not in ret.keys()): | ||||
|                     val = "0"; | ||||
|                 else: | ||||
|                     val = ret["type"] | ||||
|                 if ('bit' not in ret.keys()): | ||||
|                     bit = "0"; | ||||
|                 else: | ||||
|                     bit = ret["bit"] | ||||
|                 if ('coefficient' not in ret.keys()): | ||||
|                     coefficient = 1; | ||||
|                 else: | ||||
|                     coefficient = float(ret["coefficient"]) | ||||
|                 if ('addend' not in ret.keys()): | ||||
|                     addend = 0; | ||||
|                 else: | ||||
|                     addend = float(ret["addend"]) | ||||
|  | ||||
|                 s = checktype.getValue(ret["location"], int(bit),int(val), coefficient, addend) | ||||
|                 if  isinstance(s, str) and s.startswith("ERR"): | ||||
|                     prob_t['errcode']= -1 | ||||
|                     prob_t['errmsg']= s | ||||
|                     break | ||||
|                 if ('default' in ret.keys()): | ||||
|                     rt = status.getDecodValue(root,ret['decode']) | ||||
|                     prob_t['errmsg']= rt[str(s)] | ||||
|                     if str(s) != ret["default"]: | ||||
|                         prob_t['errcode']= -1 | ||||
|                         break | ||||
|                 else: | ||||
|                     if ('decode' in ret.keys()): | ||||
|                         rt = status.getDecodValue(root,ret['decode']) | ||||
|                         if(ret['decode'] == "psutype" and s.replace("\x00","").rstrip() not in rt.keys()): | ||||
|                                 prob_t['errcode']= -1 | ||||
|                                 prob_t['errmsg'] = '%s' %  ("ERR psu name: %s not support" % (s.replace("\x00","").rstrip())) | ||||
|                         else: | ||||
|                             s = rt[str(s).replace("\x00","").rstrip()] | ||||
|                 name = ret["name"] | ||||
|                 prob_t[name]=str(s) | ||||
|             a.append(prob_t) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getCPUValue(a, filename, tagname): | ||||
|         root = status.getETroot(filename) | ||||
|         for neighbor in root.iter(tagname): | ||||
|             location =  neighbor.attrib["location"] | ||||
|         L=[] | ||||
|         for dirpath, dirnames, filenames in os.walk(location): | ||||
|             for file in filenames : | ||||
|                 if file.endswith("input"): | ||||
|                     L.append(os.path.join(dirpath, file)) | ||||
|             L =sorted(L,reverse=False) | ||||
|         for i in range(len(L)): | ||||
|             prob_t = {} | ||||
|             prob_t["name"] = getPMCreg("%s/temp%d_label"%(location,i+1)) | ||||
|             prob_t["temp"] = float(getPMCreg("%s/temp%d_input"%(location,i+1)))/1000 | ||||
|             prob_t["alarm"] = float(getPMCreg("%s/temp%d_crit_alarm"%(location,i+1)))/1000 | ||||
|             prob_t["crit"] = float(getPMCreg("%s/temp%d_crit"%(location,i+1)))/1000 | ||||
|             prob_t["max"] = float(getPMCreg("%s/temp%d_max"%(location,i+1)))/1000 | ||||
|             a.append(prob_t) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getFileName(): | ||||
|         fpath = os.path.dirname(os.path.realpath(__file__)) | ||||
|         board_id = get_board_id() | ||||
|         dev_id_xml = fpath + "/" + "dev_%s.xml" % board_id | ||||
|         if os.path.exists(dev_id_xml): | ||||
|              return dev_id_xml | ||||
|         return  fpath + "/"+ CONFIG_NAME | ||||
|  | ||||
|     @staticmethod | ||||
|     def getFan(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "fan" | ||||
|         status.getvalue(ret, _filename, _tagname) | ||||
|  | ||||
|  | ||||
|     @staticmethod | ||||
|     def checkFan(ret): | ||||
|         _filename = status.getFileName() | ||||
|        # _filename = "/usr/local/bin/" + status.getFileName() | ||||
|         _tagname = "fan" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTemp(ret): | ||||
|         _filename = status.getFileName() | ||||
|        #_filename = "/usr/local/bin/" + status.getFileName() | ||||
|         _tagname = "temp" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getPsu(ret): | ||||
|         _filename = status.getFileName() | ||||
|        # _filename = "/usr/local/bin/" + status.getFileName() | ||||
|         _tagname = "psu" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getcputemp(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "cpus" | ||||
|         status.getCPUValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getDcdc(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "dcdc" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getmactemp(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "mactemp" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getmacpower(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "macpower" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/platform_asic
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/platform_asic
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| broadcom | ||||
| @@ -0,0 +1,2 @@ | ||||
| SYNCD_SHM_SIZE=1g | ||||
| is_ltsw_chip=1 | ||||
							
								
								
									
										17
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/prbs.cint
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								device/tencent/x86_64-tencent_tcs8400-r0/prbs.cint
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| void set_port_prbs(int unit_port, int enable){ | ||||
|     int status; | ||||
|     bcm_port_control_set(0, unit_port, bcmPortControlPrbsPolynomial, 6);    | ||||
|     bcm_port_control_set(0, unit_port, bcmPortControlPrbsRxEnable, 0); | ||||
|     bcm_port_control_set(0, unit_port, bcmPortControlPrbsTxEnable, 0); | ||||
|     if(enable == 1){ | ||||
|         bcm_port_control_set(0, unit_port, bcmPortControlPrbsRxEnable, 1); | ||||
|         bcm_port_control_set(0, unit_port, bcmPortControlPrbsTxEnable, 1); | ||||
|         bcm_port_control_get(0, unit_port, bcmPortControlPrbsRxStatus, &status); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int get_port_prbs_result(int unit_port){ | ||||
|     int status; | ||||
|     bcm_port_control_get(0, unit_port, bcmPortControlPrbsRxStatus, &status); | ||||
|     return status; | ||||
| } | ||||
							
								
								
									
										1783
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/TCS9400-128CC/TCS9400-128CC.yml
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1783
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/TCS9400-128CC/TCS9400-128CC.yml
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										128
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/TCS9400-128CC/port_config.ini
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										128
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/TCS9400-128CC/port_config.ini
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| # name                  lanes                     alias                index      speed | ||||
| Ethernet1               81,82,83,84               Eth200GE0/1          1          200000 | ||||
| Ethernet2               83,84,85,86               Eth200GE0/2          2          200000 | ||||
| Ethernet3               89,90,91,92               Eth200GE0/3          3          200000 | ||||
| Ethernet4               91,92,93,94               Eth200GE0/4          4          200000 | ||||
| Ethernet5               93,94,95,96               Eth200GE0/5          5          200000 | ||||
| Ethernet6               95,96,97,98               Eth200GE0/6          6          200000 | ||||
| Ethernet7               85,86,87,88               Eth200GE0/7          7          200000 | ||||
| Ethernet8               87,88,89,90               Eth200GE0/8          8          200000 | ||||
| Ethernet9               41,42,43,44               Eth200GE0/9          9          200000 | ||||
| Ethernet10              43,44,45,46               Eth200GE0/10         10         200000 | ||||
| Ethernet11              37,38,39,40               Eth200GE0/11         11         200000 | ||||
| Ethernet12              39,40,41,42               Eth200GE0/12         12         200000 | ||||
| Ethernet13              45,46,47,48               Eth200GE0/13         13         200000 | ||||
| Ethernet14              47,48,49,50               Eth200GE0/14         14         200000 | ||||
| Ethernet15              33,34,35,36               Eth200GE0/15         15         200000 | ||||
| Ethernet16              35,36,37,38               Eth200GE0/16         16         200000 | ||||
| Ethernet17              221,222,223,224           Eth200GE0/17         17         200000 | ||||
| Ethernet18              223,224,225,226           Eth200GE0/18         18         200000 | ||||
| Ethernet19              209,210,211,212           Eth200GE0/19         19         200000 | ||||
| Ethernet20              211,212,213,214           Eth200GE0/20         20         200000 | ||||
| Ethernet21              217,218,219,220           Eth200GE0/21         21         200000 | ||||
| Ethernet22              219,220,221,222           Eth200GE0/22         22         200000 | ||||
| Ethernet23              213,214,215,216           Eth200GE0/23         23         200000 | ||||
| Ethernet24              215,216,217,218           Eth200GE0/24         24         200000 | ||||
| Ethernet25              165,166,167,168           Eth200GE0/25         25         200000 | ||||
| Ethernet26              167,168,169,170           Eth200GE0/26         26         200000 | ||||
| Ethernet27              173,174,175,176           Eth200GE0/27         27         200000 | ||||
| Ethernet28              175,176,177,178           Eth200GE0/28         28         200000 | ||||
| Ethernet29              161,162,163,164           Eth200GE0/29         29         200000 | ||||
| Ethernet30              163,164,165,166           Eth200GE0/30         30         200000 | ||||
| Ethernet31              169,170,171,172           Eth200GE0/31         31         200000 | ||||
| Ethernet32              171,172,173,174           Eth200GE0/32         32         200000 | ||||
| Ethernet33              9,10,11,12                Eth200GE0/33         33         200000 | ||||
| Ethernet34              11,12,13,14               Eth200GE0/34         34         200000 | ||||
| Ethernet35              13,14,15,16               Eth200GE0/35         35         200000 | ||||
| Ethernet36              15,16,17,18               Eth200GE0/36         36         200000 | ||||
| Ethernet37              21,22,23,24               Eth200GE0/37         37         200000 | ||||
| Ethernet38              23,24,25,26               Eth200GE0/38         38         200000 | ||||
| Ethernet39              29,30,31,32               Eth200GE0/39         39         200000 | ||||
| Ethernet40              31,32,33,34               Eth200GE0/40         40         200000 | ||||
| Ethernet41              101,102,103,104           Eth200GE0/41         41         200000 | ||||
| Ethernet42              103,104,105,106           Eth200GE0/42         42         200000 | ||||
| Ethernet43              109,110,111,112           Eth200GE0/43         43         200000 | ||||
| Ethernet44              111,112,113,114           Eth200GE0/44         44         200000 | ||||
| Ethernet45              113,114,115,116           Eth200GE0/45         45         200000 | ||||
| Ethernet46              115,116,117,118           Eth200GE0/46         46         200000 | ||||
| Ethernet47              117,118,119,120           Eth200GE0/47         47         200000 | ||||
| Ethernet48              119,120,121,122           Eth200GE0/48         48         200000 | ||||
| Ethernet49              137,138,139,140           Eth200GE0/49         49         200000 | ||||
| Ethernet50              139,140,141,142           Eth200GE0/50         50         200000 | ||||
| Ethernet51              141,142,143,144           Eth200GE0/51         51         200000 | ||||
| Ethernet52              143,144,145,146           Eth200GE0/52         52         200000 | ||||
| Ethernet53              145,146,147,148           Eth200GE0/53         53         200000 | ||||
| Ethernet54              147,148,149,150           Eth200GE0/54         54         200000 | ||||
| Ethernet55              153,154,155,156           Eth200GE0/55         55         200000 | ||||
| Ethernet56              155,156,157,158           Eth200GE0/56         56         200000 | ||||
| Ethernet57              225,226,227,228           Eth200GE0/57         57         200000 | ||||
| Ethernet58              227,228,229,230           Eth200GE0/58         58         200000 | ||||
| Ethernet59              233,234,235,236           Eth200GE0/59         59         200000 | ||||
| Ethernet60              235,236,237,238           Eth200GE0/60         60         200000 | ||||
| Ethernet61              241,242,243,244           Eth200GE0/61         61         200000 | ||||
| Ethernet62              243,244,245,246           Eth200GE0/62         62         200000 | ||||
| Ethernet63              245,246,247,248           Eth200GE0/63         63         200000 | ||||
| Ethernet64              247,248,249,250           Eth200GE0/64         64         200000 | ||||
| Ethernet65              5,6,7,8                   Eth200GE0/65         65         200000 | ||||
| Ethernet66              7,8,9,10                  Eth200GE0/66         66         200000 | ||||
| Ethernet67              1,2,3,4                   Eth200GE0/67         67         200000 | ||||
| Ethernet68              3,4,5,6                   Eth200GE0/68         68         200000 | ||||
| Ethernet69              17,18,19,20               Eth200GE0/69         69         200000 | ||||
| Ethernet70              19,20,21,22               Eth200GE0/70         70         200000 | ||||
| Ethernet71              25,26,27,28               Eth200GE0/71         71         200000 | ||||
| Ethernet72              27,28,29,30               Eth200GE0/72         72         200000 | ||||
| Ethernet73              97,98,99,100              Eth200GE0/73         73         200000 | ||||
| Ethernet74              99,100,101,102            Eth200GE0/74         74         200000 | ||||
| Ethernet75              105,106,107,108           Eth200GE0/75         75         200000 | ||||
| Ethernet76              107,108,109,110           Eth200GE0/76         76         200000 | ||||
| Ethernet77              125,126,127,128           Eth200GE0/77         77         200000 | ||||
| Ethernet78              127,128,129,130           Eth200GE0/78         78         200000 | ||||
| Ethernet79              121,122,123,124           Eth200GE0/79         79         200000 | ||||
| Ethernet80              123,124,125,126           Eth200GE0/80         80         200000 | ||||
| Ethernet81              133,134,135,136           Eth200GE0/81         81         200000 | ||||
| Ethernet82              135,136,137,138           Eth200GE0/82         82         200000 | ||||
| Ethernet83              129,130,131,132           Eth200GE0/83         83         200000 | ||||
| Ethernet84              131,132,133,134           Eth200GE0/84         84         200000 | ||||
| Ethernet85              149,150,151,152           Eth200GE0/85         85         200000 | ||||
| Ethernet86              151,152,153,154           Eth200GE0/86         86         200000 | ||||
| Ethernet87              157,158,159,160           Eth200GE0/87         87         200000 | ||||
| Ethernet88              159,160,161,162           Eth200GE0/88         88         200000 | ||||
| Ethernet89              229,230,231,232           Eth200GE0/89         89         200000 | ||||
| Ethernet90              231,232,233,234           Eth200GE0/90         90         200000 | ||||
| Ethernet91              237,238,239,240           Eth200GE0/91         91         200000 | ||||
| Ethernet92              239,240,241,242           Eth200GE0/92         92         200000 | ||||
| Ethernet93              253,254,255,256           Eth200GE0/93         93         200000 | ||||
| Ethernet94              255,256,257,258           Eth200GE0/94         94         200000 | ||||
| Ethernet95              249,250,251,252           Eth200GE0/95         95         200000 | ||||
| Ethernet96              251,252,253,254           Eth200GE0/96         96         200000 | ||||
| Ethernet97              65,66,67,68               Eth200GE0/97         97         200000 | ||||
| Ethernet98              67,68,69,70               Eth200GE0/98         98         200000 | ||||
| Ethernet99              73,74,75,76               Eth200GE0/99         99         200000 | ||||
| Ethernet100             75,76,77,78               Eth200GE0/100        100        200000 | ||||
| Ethernet101             69,70,71,72               Eth200GE0/101        101        200000 | ||||
| Ethernet102             71,72,73,74               Eth200GE0/102        102        200000 | ||||
| Ethernet103             77,78,79,80               Eth200GE0/103        103        200000 | ||||
| Ethernet104             79,80,81,82               Eth200GE0/104        104        200000 | ||||
| Ethernet105             57,58,59,60               Eth200GE0/105        105        200000 | ||||
| Ethernet106             59,60,61,62               Eth200GE0/106        106        200000 | ||||
| Ethernet107             53,54,55,56               Eth200GE0/107        107        200000 | ||||
| Ethernet108             55,56,57,58               Eth200GE0/108        108        200000 | ||||
| Ethernet109             61,62,63,64               Eth200GE0/109        109        200000 | ||||
| Ethernet110             63,64,65,66               Eth200GE0/110        110        200000 | ||||
| Ethernet111             49,50,51,52               Eth200GE0/111        111        200000 | ||||
| Ethernet112             51,52,53,54               Eth200GE0/112        112        200000 | ||||
| Ethernet113             205,206,207,208           Eth200GE0/113        113        200000 | ||||
| Ethernet114             207,208,209,210           Eth200GE0/114        114        200000 | ||||
| Ethernet115             193,194,195,196           Eth200GE0/115        115        200000 | ||||
| Ethernet116             195,196,197,198           Eth200GE0/116        116        200000 | ||||
| Ethernet117             201,202,203,204           Eth200GE0/117        117        200000 | ||||
| Ethernet118             203,204,205,206           Eth200GE0/118        118        200000 | ||||
| Ethernet119             197,198,199,200           Eth200GE0/119        119        200000 | ||||
| Ethernet120             199,200,201,202           Eth200GE0/120        120        200000 | ||||
| Ethernet121             177,178,179,180           Eth200GE0/121        121        200000 | ||||
| Ethernet122             179,180,181,182           Eth200GE0/122        122        200000 | ||||
| Ethernet123             185,186,187,188           Eth200GE0/123        123        200000 | ||||
| Ethernet124             187,188,189,190           Eth200GE0/124        124        200000 | ||||
| Ethernet125             181,182,183,184           Eth200GE0/125        125        200000 | ||||
| Ethernet126             183,184,185,186           Eth200GE0/126        126        200000 | ||||
| Ethernet127             189,190,191,192           Eth200GE0/127        127        200000 | ||||
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/TCS9400-128CC/sai.profile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/TCS9400-128CC/sai.profile
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/TCS9400-128CC.yml | ||||
							
								
								
									
										1028
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/config_db.TCS9400-128CC.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1028
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/config_db.TCS9400-128CC.json
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/custom_led.bin
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/custom_led.bin
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/default_sku
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/default_sku
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| TCS9400-128CC t1 | ||||
							
								
								
									
										572
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/dev.xml
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										572
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/dev.xml
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,572 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- | ||||
|       ### type    1 result/1000 | ||||
|           type    2 result/100 | ||||
|           type    3 read bit | ||||
|      ### property need check must add int front | ||||
| --> | ||||
| <catalog> | ||||
|     <fans> | ||||
|         <fan id="fan1" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan1/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan1/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan1/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/90-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan1/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan1/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan2" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan2/present"       type="4" decode="fanpresent" default="1" /> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan2/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan2/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/98-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan2/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan2/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan3" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan3/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan3/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan3/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/91-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan3/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan3/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan4" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan4/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan4/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan4/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/99-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan4/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan4/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan5" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan5/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan5/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan5/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/92-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan5/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan5/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan6" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan6/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan6/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan6/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/100-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan6/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan6/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan7" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan7/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan7/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan7/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/93-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan7/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan7/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan8" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan8/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan8/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan8/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/101-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan8/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan8/motor1/speed"/> | ||||
|         </fan> | ||||
|     </fans> | ||||
|     <temps> | ||||
|         <temp id="air_inlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/107-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/107-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/107-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Uport_air_inlet_L" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/64-004f/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/64-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/64-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Uport_air_inlet_R" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/63-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/63-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/63-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Dport_air_inlet_L" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/114-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/114-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/114-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Dport_air_inlet_R" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/115-004f/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/115-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/115-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_air_inlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/69-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/69-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/69-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Base_air_inlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/109-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/109-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/109-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_air_outlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/70-004f/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/70-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/70-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_TEMPDIODE0" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/71-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/71-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/71-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_TEMPDIODE1" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/72-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/72-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/72-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_UL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/88-0048/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/88-0048/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/88-0048/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_UR" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/89-0049/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/89-0049/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/89-0049/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_DL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/96-0048/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/96-0048/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/96-0048/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_DR" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/97-0049/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/97-0049/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/97-0049/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|     </temps> | ||||
|     <psus> | ||||
|         <psu id="psu1" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu1/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu1/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/79-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/79-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/79-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/79-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu2" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu2/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu2/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/80-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/80-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/80-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/80-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu3" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu3/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu3/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/82-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/82-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/82-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/82-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu4" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu4/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu4/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/81-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/81-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/81-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/81-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|     </psus> | ||||
|     <dcdcs> | ||||
|         <dcdc id="MAC_VDD_ANALOG1" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.809" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.731" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.0V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.071" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.969" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.8V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.890" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.710" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.2V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_SW_VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD5V_CLK_MCU" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.334" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.826" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD5V_VR" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.334" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.826" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD3.3_CLK" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.486" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.154" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDDO1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in11_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.901" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.719" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDDO1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in12_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD_CORE" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in13_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.950" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.700" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD_ANALOG" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in14_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.809" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.731" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.2V_MAC" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in15_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_AVDD1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in16_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.890" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.710" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_SW_VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_VDD2.5V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="2.615" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="2.365" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.444" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.116" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_SSD_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_VCCIN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0060/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.950" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.600" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P1V05" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0060/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.100" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.000" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P1V2_VDDQ" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-006c/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.160" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P2V5_VPP" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-006c/hwmon/hwmon*/in4_input" type="6" coefficient="1.124" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="2.750" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="2.375" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P3V3_STBY" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0043/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P5V_AUX_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0043/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.500" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.250" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P1V7_VCCSCFUSESUS_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0043/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.785" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.615" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD1.0V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.061" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.959" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD1.8V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.901" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.719" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD1.2V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_C" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_D" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD3.3_MON" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD1.0V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.061" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.959" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD1.8V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.901" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.719" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD1.2V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_C" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_D" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD3.3_MON" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in0/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in1/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_C" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in2/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_D" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in3/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_E" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in4/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_F" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in5/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_G" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in6/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_H" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in7/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|     </dcdcs> | ||||
|     <mactemps> | ||||
|         <mactemp id="MAC_DIE_0" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp1_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_1" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp2_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_2" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp3_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_3" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp4_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_4" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp5_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_5" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp6_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_6" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp7_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_7" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp8_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_8" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp9_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_9" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp10_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_10" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp11_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_11" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp12_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_12" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp13_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_13" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp14_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_14" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp15_input"  type="1"/> | ||||
|         </mactemp> | ||||
|     </mactemps> | ||||
|     <macpowers> | ||||
|         <macpower id="MAC_Core" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/75-0010/hwmon/*/power1_input"  type="5"/> | ||||
|         </macpower> | ||||
|         <macpower id="MAC_Analog" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/76-005a/hwmon/*/power3_input"  type="5"/> | ||||
|         </macpower> | ||||
|     </macpowers> | ||||
|     <cpus location="/sys/class/hwmon/hwmon0"/> | ||||
|     <decode> | ||||
|     <fanpresent> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </fanpresent> | ||||
|     <fanstatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </fanstatus> | ||||
|     <psucheck> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </psucheck> | ||||
|     <psustatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </psustatus> | ||||
|     <psutype> | ||||
|         <code key="DPS-1300AB-6" value="PSA1300CRPS-F"/> | ||||
|         <code key="GW-CRPS1300D" value="PSA1300CRPS-F"/> | ||||
|         <code key="DPS-1300AB-11" value="PSA1300CRPS-R"/> | ||||
|         <code key="CRPS1300D3R" value="PSA1300CRPS-R"/> | ||||
|     </psutype> | ||||
|     <fan_display_name> | ||||
|         <code key="FAN12K8080-F" value="FAN12K8080-F"/> | ||||
|     </fan_display_name> | ||||
|     <slotpresent> | ||||
|         <code key="1" value="ABSENT"/> | ||||
|         <code key="0" value="PRESENT"/> | ||||
|     </slotpresent> | ||||
|     </decode> | ||||
| </catalog> | ||||
|  | ||||
|  | ||||
							
								
								
									
										572
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/dev_0x407c.xml
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										572
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/dev_0x407c.xml
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,572 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- | ||||
|       ### type    1 result/1000 | ||||
|           type    2 result/100 | ||||
|           type    3 read bit | ||||
|      ### property need check must add int front | ||||
| --> | ||||
| <catalog> | ||||
|     <fans> | ||||
|         <fan id="fan1" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan1/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan1/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan1/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/90-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan1/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan1/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan2" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan2/present"       type="4" decode="fanpresent" default="1" /> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan2/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan2/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/98-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan2/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan2/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan3" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan3/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan3/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan3/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/91-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan3/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan3/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan4" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan4/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan4/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan4/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/99-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan4/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan4/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan5" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan5/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan5/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan5/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/92-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan5/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan5/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan6" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan6/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan6/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan6/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/100-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan6/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan6/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan7" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan7/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan7/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan7/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/93-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan7/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan7/motor1/speed"/> | ||||
|         </fan> | ||||
|         <fan id="fan8" > | ||||
|             <property name="present" location="/sys/rg_plat/fan/fan8/present"       type="4" decode="fanpresent" default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/fan/fan8/motor0/status" type="4" decode="fanstatus"  default="1"/> | ||||
|             <property name="status2" location="/sys/rg_plat/fan/fan8/motor1/status" type="4" decode="fanstatus"  default="1"/> | ||||
|     		<property name="fru" e2type="fru"  location="/sys/bus/i2c/devices/101-0050/eeprom"/> | ||||
|             <property name="rotor1_speed" location="/sys/rg_plat/fan/fan8/motor0/speed"/> | ||||
|             <property name="rotor2_speed" location="/sys/rg_plat/fan/fan8/motor1/speed"/> | ||||
|         </fan> | ||||
|     </fans> | ||||
|     <temps> | ||||
|         <temp id="air_inlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/107-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/107-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/107-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Uport_air_inlet_L" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/64-004f/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/64-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/64-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Uport_air_inlet_R" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/63-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/63-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/63-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Dport_air_inlet_L" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/114-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/114-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/114-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Dport_air_inlet_R" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/115-004f/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/115-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/115-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_air_inlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/69-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/69-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/69-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="Base_air_inlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/109-004b/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/109-004b/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/109-004b/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_air_outlet" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/70-004f/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/70-004f/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/70-004f/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_TEMPDIODE0" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/71-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/71-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/71-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="MAC_TEMPDIODE1" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/72-004c/hwmon/*/temp2_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/72-004c/hwmon/*/temp2_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/72-004c/hwmon/*/temp2_crit_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_UL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/88-0048/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/88-0048/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/88-0048/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_UR" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/89-0049/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/89-0049/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/89-0049/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_DL" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/96-0048/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/96-0048/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/96-0048/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|         <temp id="FCB_air_outlet_DR" > | ||||
|             <property name="temp1_input" location="/sys/bus/i2c/devices/97-0049/hwmon/*/temp1_input" type="1" /> | ||||
|             <property name="temp1_max"     location="/sys/bus/i2c/devices/97-0049/hwmon/*/temp1_max" type="1" /> | ||||
|             <property name="temp1_max_hyst" location="/sys/bus/i2c/devices/97-0049/hwmon/*/temp1_max_hyst" type="1"/> | ||||
|         </temp> | ||||
|     </temps> | ||||
|     <psus> | ||||
|         <psu id="psu1" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu1/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu1/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/79-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/79-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/79-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/79-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/79-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu2" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu2/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu2/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/80-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/80-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/80-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/80-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/80-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu3" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu3/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu3/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/82-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/82-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/82-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/82-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/82-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|         <psu id="psu4" > | ||||
|             <property name="present" location="/sys/rg_plat/psu/psu4/present" type="4" decode="psucheck"  default="1"/> | ||||
|             <property name="status"  location="/sys/rg_plat/psu/psu4/output"  type="4" decode="psustatus" default="1"/> | ||||
|             <property name="psu" e2type="fru"  location="/sys/bus/i2c/devices/81-0050/eeprom"/> | ||||
|             <property name="in_current"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/curr1_input" type="1" /> | ||||
|             <property name="in_voltage"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/in1_input"  type="1"/> | ||||
|             <property name="out_voltage"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/in2_input" type="1" /> | ||||
|             <property name="out_current"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/curr2_input" type="1" /> | ||||
|             <property name="temp"    location="/sys/bus/i2c/devices/81-0058/hwmon/*/temp1_input" type="1"/> | ||||
|             <property name="fan_speed"     location="/sys/bus/i2c/devices/81-0058/hwmon/*/fan1_input" /> | ||||
|             <property name="in_power"      location="/sys/bus/i2c/devices/81-0058/hwmon/*/power1_input"  type="5"/> | ||||
|             <property name="out_power"     location="/sys/bus/i2c/devices/81-0058/hwmon/*/power2_input"  type="5"/> | ||||
|         </psu> | ||||
|     </psus> | ||||
|     <dcdcs> | ||||
|         <dcdc id="MAC_VDD_ANALOG1" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.809" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.731" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.0V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.071" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.969" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.8V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.890" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.710" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.2V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_SW_VDD1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD5V_CLK_MCU" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.334" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.826" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD5V_VR" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.334" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.826" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD3.3_CLK" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.486" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.154" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDDO1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in11_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.901" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.719" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDDO1.2V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in12_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD_CORE" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in13_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.950" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.700" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD_ANALOG" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in14_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="0.809" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.731" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_VDD1.2V_MAC" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in15_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_AVDD1.8V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/73-005b/hwmon/hwmon*/in16_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.890" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.710" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_SW_VDD1.0V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.050" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.950" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.444" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.116" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_SW_OVDD" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.444" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.116" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="BASE_SSD_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/105-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_VCCIN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0060/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.950" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.600" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P1V05" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0060/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.100" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.000" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P1V2_VDDQ" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-006c/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.160" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P2V5_VPP" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-006c/hwmon/hwmon*/in4_input" type="6" coefficient="1.124" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="2.750" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="2.375" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P3V3_STBY" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0043/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P5V_AUX_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0043/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="5.500" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="4.250" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="CPU_P1V7_VCCSCFUSESUS_IN" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/106-0043/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.785" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.615" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD1.0V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.061" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.959" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD1.8V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.901" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.719" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD1.2V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_C" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_QSFP56_VDD3.3V_D" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD3.3_MON" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="UPORT_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/62-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD1.0V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in1_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.061" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="0.959" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD1.8V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in2_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.901" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.719" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD1.2V_FPGA" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in3_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="1.260" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="1.140" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD3.3V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in4_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in5_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in6_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_C" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in7_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_QSFP56_VDD3.3V_D" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in8_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD3.3_MON" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in9_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.465" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.135" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="DPORT_VDD12V" > | ||||
|             <property name="dcdc_input" location="/sys/bus/i2c/devices/113-005b/hwmon/hwmon*/in10_input" type="6" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="12.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="11.400" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_A" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in0/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_B" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in1/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_C" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in2/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_D" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in3/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_E" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in4/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_F" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in5/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_G" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in6/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|         <dcdc id="MAC_QSFPDD_VDD3.3V_H" > | ||||
|             <property name="dcdc_input" location="/sys/rg_plat/sensor/in7/in_input" type="0" /> | ||||
|             <property name="dcdc_max"   gettype="config" value="3.600" /> | ||||
|             <property name="dcdc_min"   gettype="config" value="3.200" /> | ||||
|         </dcdc> | ||||
|     </dcdcs> | ||||
|     <mactemps> | ||||
|         <mactemp id="MAC_DIE_0" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp1_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_1" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp2_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_2" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp3_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_3" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp4_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_4" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp5_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_5" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp6_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_6" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp7_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_7" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp8_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_8" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp9_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_9" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp10_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_10" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp11_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_11" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp12_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_12" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp13_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_13" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp14_input"  type="1"/> | ||||
|         </mactemp> | ||||
|         <mactemp id="MAC_DIE_14" > | ||||
|             <property name="temp_input" location="/sys/bus/i2c/devices/74-0044/hwmon/hwmon*/temp15_input"  type="1"/> | ||||
|         </mactemp> | ||||
|     </mactemps> | ||||
|     <macpowers> | ||||
|         <macpower id="MAC_Core" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/75-0010/hwmon/*/power1_input"  type="5"/> | ||||
|         </macpower> | ||||
|         <macpower id="MAC_Analog" > | ||||
|             <property name="power_input" location="/sys/bus/i2c/devices/76-005a/hwmon/*/power3_input"  type="5"/> | ||||
|         </macpower> | ||||
|     </macpowers> | ||||
|     <cpus location="/sys/class/hwmon/hwmon0"/> | ||||
|     <decode> | ||||
|     <fanpresent> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </fanpresent> | ||||
|     <fanstatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </fanstatus> | ||||
|     <psucheck> | ||||
|         <code key="1" value="PRESENT"/> | ||||
|         <code key="0" value="ABSENT"/> | ||||
|     </psucheck> | ||||
|     <psustatus> | ||||
|         <code key="1" value="OK"/> | ||||
|         <code key="0" value="NOT OK"/> | ||||
|     </psustatus> | ||||
|     <psutype> | ||||
|         <code key="DPS-1300AB-6" value="PSA1300CRPS-F"/> | ||||
|         <code key="GW-CRPS1300D" value="PSA1300CRPS-F"/> | ||||
|         <code key="DPS-1300AB-11" value="PSA1300CRPS-R"/> | ||||
|         <code key="CRPS1300D3R" value="PSA1300CRPS-R"/> | ||||
|     </psutype> | ||||
|     <fan_display_name> | ||||
|         <code key="FAN12K8080-F" value="FAN12K8080-F"/> | ||||
|     </fan_display_name> | ||||
|     <slotpresent> | ||||
|         <code key="1" value="ABSENT"/> | ||||
|         <code key="0" value="PRESENT"/> | ||||
|     </slotpresent> | ||||
|     </decode> | ||||
| </catalog> | ||||
|  | ||||
|  | ||||
							
								
								
									
										953
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/fru.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										953
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/fru.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,953 @@ | ||||
| #!/usr/bin/python3 | ||||
| import collections | ||||
| from bitarray import bitarray | ||||
| from datetime import datetime, timedelta | ||||
|  | ||||
|  | ||||
| __DEBUG__ = "N" | ||||
|  | ||||
|  | ||||
| class FruException(Exception): | ||||
|     def __init__(self, message='fruerror', code=-100): | ||||
|         err = 'errcode: {0} message:{1}'.format(code, message) | ||||
|         Exception.__init__(self, err) | ||||
|         self.code = code | ||||
|         self.message = message | ||||
|  | ||||
|  | ||||
| def e_print(err): | ||||
|     print("ERROR: " + err) | ||||
|  | ||||
|  | ||||
| def d_print(debug_info): | ||||
|     if(__DEBUG__ == "Y"): | ||||
|         print(debug_info) | ||||
|  | ||||
|  | ||||
| class FruUtil(): | ||||
|     @staticmethod | ||||
|     def decodeLength(value): | ||||
|         a = bitarray(8) | ||||
|         a.setall(True) | ||||
|         a[0:1] = 0 | ||||
|         a[1:2] = 0 | ||||
|         x = ord(a.tobytes()) | ||||
|         return x & ord(value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def minToData(): | ||||
|         starttime = datetime(1996, 1, 1, 0, 0, 0) | ||||
|         endtime = datetime.now() | ||||
|         seconds = (endtime - starttime).total_seconds() | ||||
|         mins = seconds // 60 | ||||
|         m = int(round(mins)) | ||||
|         return m | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTimeFormat(): | ||||
|         return datetime.now().strftime('%Y-%m-%d') | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTypeLength(value): | ||||
|         if value is None or len(value) == 0: | ||||
|             return 0 | ||||
|         a = bitarray(8) | ||||
|         a.setall(False) | ||||
|         a[0:1] = 1 | ||||
|         a[1:2] = 1 | ||||
|         x = ord(a.tobytes()) | ||||
|         return x | len(value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def checksum(b): | ||||
|         result = 0 | ||||
|         for i in range(len(b)): | ||||
|             result += ord(b[i]) | ||||
|         return (0x100 - (result & 0xff)) & 0xff | ||||
|  | ||||
|  | ||||
| class BaseArea(object): | ||||
|     SUGGESTED_SIZE_COMMON_HEADER = 8 | ||||
|     SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 | ||||
|     SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 | ||||
|     SUGGESTED_SIZE_BOARD_INFO_AREA = 80 | ||||
|     SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 | ||||
|  | ||||
|     INITVALUE = b'\x00' | ||||
|     resultvalue = INITVALUE * 256 | ||||
|     COMMON_HEAD_VERSION = b'\x01' | ||||
|     __childList = None | ||||
|  | ||||
|     def __init__(self, name="", size=0, offset=0): | ||||
|         self.__childList = [] | ||||
|         self._offset = offset | ||||
|         self.name = name | ||||
|         self._size = size | ||||
|         self._isPresent = False | ||||
|         self._data = b'\x00' * size | ||||
|         self.__dataoffset = 0 | ||||
|  | ||||
|     @property | ||||
|     def childList(self): | ||||
|         return self.__childList | ||||
|  | ||||
|     @childList.setter | ||||
|     def childList(self, value): | ||||
|         self.__childList = value | ||||
|  | ||||
|     @property | ||||
|     def offset(self): | ||||
|         return self._offset | ||||
|  | ||||
|     @offset.setter | ||||
|     def offset(self, value): | ||||
|         self._offset = value | ||||
|  | ||||
|     @property | ||||
|     def size(self): | ||||
|         return self._size | ||||
|  | ||||
|     @size.setter | ||||
|     def size(self, value): | ||||
|         self._size = value | ||||
|  | ||||
|     @property | ||||
|     def data(self): | ||||
|         return self._data | ||||
|  | ||||
|     @data.setter | ||||
|     def data(self, value): | ||||
|         self._data = value | ||||
|  | ||||
|     @property | ||||
|     def isPresent(self): | ||||
|         return self._isPresent | ||||
|  | ||||
|     @isPresent.setter | ||||
|     def isPresent(self, value): | ||||
|         self._isPresent = value | ||||
|  | ||||
|  | ||||
| class InternalUseArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class ChassisInfoArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class BoardInfoArea(BaseArea): | ||||
|     _boardTime = None | ||||
|     _fields = None | ||||
|     _mfg_date = None | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "version             : %x\n" \ | ||||
|                     "length              : %d \n" \ | ||||
|                     "language            : %x \n" \ | ||||
|                     "mfg_date            : %s \n" \ | ||||
|                     "boardManufacturer   : %s \n" \ | ||||
|                     "boardProductName    : %s \n" \ | ||||
|                     "boardSerialNumber   : %s \n" \ | ||||
|                     "boardPartNumber     : %s \n" \ | ||||
|                     "fruFileId           : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (ord(self.boardversion), self.size, | ||||
|                               self.language, self.getMfgRealData(), | ||||
|                               self.boardManufacturer, self.boardProductName, | ||||
|                               self.boardSerialNumber, self.boardPartNumber, | ||||
|                               self.fruFileId) | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 tmpstr += "boardextra%d         : %s \n" % (i, valtmpval) | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         return tmpstr | ||||
|  | ||||
|     def todict(self): | ||||
|         dic = collections.OrderedDict() | ||||
|         dic["boardversion"] = ord(self.boardversion) | ||||
|         dic["boardlength"] = self.size | ||||
|         dic["boardlanguage"] = self.language | ||||
|         dic["boardmfg_date"] = self.getMfgRealData() | ||||
|         dic["boardManufacturer"] = self.boardManufacturer | ||||
|         dic["boardProductName"] = self.boardProductName | ||||
|         dic["boardSerialNumber"] = self.boardSerialNumber | ||||
|         dic["boardPartNumber"] = self.boardPartNumber | ||||
|         dic["boardfruFileId"] = self.fruFileId | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 dic[valtmp] = valtmpval | ||||
|             else: | ||||
|                 break | ||||
|         return dic | ||||
|  | ||||
|     def decodedata(self): | ||||
|         index = 0 | ||||
|         self.areaversion = self.data[index] | ||||
|         index += 1 | ||||
|         d_print("decode length :%d class size:%d" % | ||||
|                 ((ord(self.data[index]) * 8), self.size)) | ||||
|         index += 2 | ||||
|  | ||||
|         timetmp = self.data[index: index + 3] | ||||
|         self.mfg_date = ord(timetmp[0]) | ( | ||||
|             ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) | ||||
|         d_print("decode getMfgRealData :%s" % self.getMfgRealData()) | ||||
|         index += 3 | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardManufacturer = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardManufacturer:%s" % self.boardManufacturer) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardProductName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardProductName:%s" % self.boardProductName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardSerialNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardPartNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardPartNumber:%s" % self.boardPartNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.fruFileId = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode fruFileId:%s" % self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if self.data[index] != chr(0xc1): | ||||
|                 templen = FruUtil.decodeLength(self.data[index]) | ||||
|                 tmpval = self.data[index + 1: index + templen + 1] | ||||
|                 setattr(self, valtmp, tmpval) | ||||
|                 index += templen + 1 | ||||
|                 d_print("decode boardextra%d:%s" % (i, tmpval)) | ||||
|             else: | ||||
|                 break | ||||
|         return | ||||
|  | ||||
|     def recalcute(self): | ||||
|         d_print("boardInfoArea version:%x" % ord(self.boardversion)) | ||||
|         d_print("boardInfoArea length:%d" % self.size) | ||||
|         d_print("boardInfoArea language:%x" % self.language) | ||||
|         self.mfg_date = FruUtil.minToData() | ||||
|         d_print("boardInfoArea mfg_date:%x" % self.mfg_date) | ||||
|  | ||||
|         self.data = chr(ord(self.boardversion)) + \ | ||||
|             chr(self.size // 8) + chr(self.language) | ||||
|  | ||||
|         self.data += chr(self.mfg_date & 0xFF) | ||||
|         self.data += chr((self.mfg_date >> 8) & 0xFF) | ||||
|         self.data += chr((self.mfg_date >> 16) & 0xFF) | ||||
|  | ||||
|         d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) | ||||
|         typelength = FruUtil.getTypeLength(self.boardManufacturer) | ||||
|         self.data += chr(typelength) | ||||
|         self.data += self.boardManufacturer | ||||
|  | ||||
|         d_print("boardInfoArea boardProductName:%s" % self.boardProductName) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardProductName)) | ||||
|         self.data += self.boardProductName | ||||
|  | ||||
|         d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) | ||||
|         self.data += self.boardSerialNumber | ||||
|  | ||||
|         d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) | ||||
|         self.data += self.boardPartNumber | ||||
|  | ||||
|         d_print("boardInfoArea fruFileId:%s" % self.fruFileId) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.fruFileId)) | ||||
|         self.data += self.fruFileId | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) | ||||
|                 self.data += chr(FruUtil.getTypeLength(valtmpval)) | ||||
|                 if valtmpval is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     self.data += valtmpval | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         self.data += chr(0xc1) | ||||
|  | ||||
|         if len(self.data) > (self.size - 1): | ||||
|             incr = (len(self.data) - self.size) // 8 + 1 | ||||
|             self.size += incr * 8 | ||||
|  | ||||
|         self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] | ||||
|         d_print("self data:%d" % len(self.data)) | ||||
|         d_print("self size:%d" % self.size) | ||||
|         d_print("adjust size:%d" % (self.size - len(self.data) - 1)) | ||||
|         self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) | ||||
|  | ||||
|         # checksum | ||||
|         checksum = FruUtil.checksum(self.data) | ||||
|         d_print("board info checksum:%x" % checksum) | ||||
|         self.data += chr(checksum) | ||||
|  | ||||
|     def getMfgRealData(self): | ||||
|         starttime = datetime(1996, 1, 1, 0, 0, 0) | ||||
|         mactime = starttime + timedelta(minutes=self.mfg_date) | ||||
|         return mactime | ||||
|  | ||||
|     @property | ||||
|     def language(self): | ||||
|         self._language = 25 | ||||
|         return self._language | ||||
|  | ||||
|     @property | ||||
|     def mfg_date(self): | ||||
|         return self._mfg_date | ||||
|  | ||||
|     @mfg_date.setter | ||||
|     def mfg_date(self, val): | ||||
|         self._mfg_date = val | ||||
|  | ||||
|     @property | ||||
|     def boardversion(self): | ||||
|         self._boardversion = self.COMMON_HEAD_VERSION | ||||
|         return self._boardversion | ||||
|  | ||||
|     @property | ||||
|     def fruFileId(self): | ||||
|         return self._FRUFileID | ||||
|  | ||||
|     @fruFileId.setter | ||||
|     def fruFileId(self, val): | ||||
|         self._FRUFileID = val | ||||
|  | ||||
|     @property | ||||
|     def boardPartNumber(self): | ||||
|         return self._boardPartNumber | ||||
|  | ||||
|     @boardPartNumber.setter | ||||
|     def boardPartNumber(self, val): | ||||
|         self._boardPartNumber = val | ||||
|  | ||||
|     @property | ||||
|     def boardSerialNumber(self): | ||||
|         return self._boardSerialNumber | ||||
|  | ||||
|     @boardSerialNumber.setter | ||||
|     def boardSerialNumber(self, val): | ||||
|         self._boardSerialNumber = val | ||||
|  | ||||
|     @property | ||||
|     def boardProductName(self): | ||||
|         return self._boradProductName | ||||
|  | ||||
|     @boardProductName.setter | ||||
|     def boardProductName(self, val): | ||||
|         self._boradProductName = val | ||||
|  | ||||
|     @property | ||||
|     def boardManufacturer(self): | ||||
|         return self._boardManufacturer | ||||
|  | ||||
|     @boardManufacturer.setter | ||||
|     def boardManufacturer(self, val): | ||||
|         self._boardManufacturer = val | ||||
|  | ||||
|     @property | ||||
|     def boardTime(self): | ||||
|         return self._boardTime | ||||
|  | ||||
|     @boardTime.setter | ||||
|     def boardTime(self, val): | ||||
|         self._boardTime = val | ||||
|  | ||||
|     @property | ||||
|     def fields(self): | ||||
|         return self._fields | ||||
|  | ||||
|     @fields.setter | ||||
|     def fields(self, val): | ||||
|         self._fields = val | ||||
|  | ||||
|  | ||||
| class ProductInfoArea(BaseArea): | ||||
|     _productManufacturer = None | ||||
|     _productAssetTag = None | ||||
|     _FRUFileID = None | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "version             : %x\n" \ | ||||
|                     "length              : %d \n" \ | ||||
|                     "language            : %x \n" \ | ||||
|                     "productManufacturer : %s \n" \ | ||||
|                     "productName         : %s \n" \ | ||||
|                     "productPartModelName: %s \n" \ | ||||
|                     "productVersion      : %s \n" \ | ||||
|                     "productSerialNumber : %s \n" \ | ||||
|                     "productAssetTag     : %s \n" \ | ||||
|                     "fruFileId           : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (ord(self.areaversion), self.size, | ||||
|                               self.language, self.productManufacturer, | ||||
|                               self.productName, self.productPartModelName, | ||||
|                               self.productVersion, self.productSerialNumber, | ||||
|                               self.productAssetTag, self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 tmpstr += "productextra%d       : %s \n" % (i, valtmpval) | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         return tmpstr | ||||
|  | ||||
|     def todict(self): | ||||
|         dic = collections.OrderedDict() | ||||
|         dic["productversion"] = ord(self.areaversion) | ||||
|         dic["productlength"] = self.size | ||||
|         dic["productlanguage"] = self.language | ||||
|         dic["productManufacturer"] = self.productManufacturer | ||||
|         dic["productName"] = self.productName | ||||
|         dic["productPartModelName"] = self.productPartModelName | ||||
|         dic["productVersion"] = int(self.productVersion, 16) | ||||
|         dic["productSerialNumber"] = self.productSerialNumber | ||||
|         dic["productAssetTag"] = self.productAssetTag | ||||
|         dic["productfruFileId"] = self.fruFileId | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 dic[valtmp] = valtmpval | ||||
|             else: | ||||
|                 break | ||||
|         return dic | ||||
|  | ||||
|     def decodedata(self): | ||||
|         index = 0 | ||||
|         self.areaversion = self.data[index]  # 0 | ||||
|         index += 1 | ||||
|         d_print("decode length %d" % (ord(self.data[index]) * 8)) | ||||
|         d_print("class size %d" % self.size) | ||||
|         index += 2 | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productManufacturer = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productManufacturer:%s" % self.productManufacturer) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productName:%s" % self.productName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productPartModelName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productPartModelName:%s" % self.productPartModelName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productVersion = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productVersion:%s" % self.productVersion) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productSerialNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productSerialNumber:%s" % self.productSerialNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productAssetTag = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productAssetTag:%s" % self.productAssetTag) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.fruFileId = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode fruFileId:%s" % self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if self.data[index] != chr(0xc1) and index < self.size - 1: | ||||
|                 templen = FruUtil.decodeLength(self.data[index]) | ||||
|                 if templen == 0: | ||||
|                     break | ||||
|                 tmpval = self.data[index + 1: index + templen + 1] | ||||
|                 d_print("decode boardextra%d:%s" % (i, tmpval)) | ||||
|                 setattr(self, valtmp, tmpval) | ||||
|                 index += templen + 1 | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|     @property | ||||
|     def productVersion(self): | ||||
|         return self._productVersion | ||||
|  | ||||
|     @productVersion.setter | ||||
|     def productVersion(self, name): | ||||
|         self._productVersion = name | ||||
|  | ||||
|     @property | ||||
|     def areaversion(self): | ||||
|         self._areaversion = self.COMMON_HEAD_VERSION | ||||
|         return self._areaversion | ||||
|  | ||||
|     @areaversion.setter | ||||
|     def areaversion(self, name): | ||||
|         self._areaversion = name | ||||
|  | ||||
|     @property | ||||
|     def language(self): | ||||
|         self._language = 25 | ||||
|         return self._language | ||||
|  | ||||
|     @property | ||||
|     def productManufacturer(self): | ||||
|         return self._productManufacturer | ||||
|  | ||||
|     @productManufacturer.setter | ||||
|     def productManufacturer(self, name): | ||||
|         self._productManufacturer = name | ||||
|  | ||||
|     @property | ||||
|     def productName(self): | ||||
|         return self._productName | ||||
|  | ||||
|     @productName.setter | ||||
|     def productName(self, name): | ||||
|         self._productName = name | ||||
|  | ||||
|     @property | ||||
|     def productPartModelName(self): | ||||
|         return self._productPartModelName | ||||
|  | ||||
|     @productPartModelName.setter | ||||
|     def productPartModelName(self, name): | ||||
|         self._productPartModelName = name | ||||
|  | ||||
|     @property | ||||
|     def productSerialNumber(self): | ||||
|         return self._productSerialNumber | ||||
|  | ||||
|     @productSerialNumber.setter | ||||
|     def productSerialNumber(self, name): | ||||
|         self._productSerialNumber = name | ||||
|  | ||||
|     @property | ||||
|     def productAssetTag(self): | ||||
|         return self._productAssetTag | ||||
|  | ||||
|     @productAssetTag.setter | ||||
|     def productAssetTag(self, name): | ||||
|         self._productAssetTag = name | ||||
|  | ||||
|     @property | ||||
|     def fruFileId(self): | ||||
|         return self._FRUFileID | ||||
|  | ||||
|     @fruFileId.setter | ||||
|     def fruFileId(self, name): | ||||
|         self._FRUFileID = name | ||||
|  | ||||
|     def recalcute(self): | ||||
|         d_print("product version:%x" % ord(self.areaversion)) | ||||
|         d_print("product length:%d" % self.size) | ||||
|         d_print("product language:%x" % self.language) | ||||
|         self.data = chr(ord(self.areaversion)) + \ | ||||
|             chr(self.size // 8) + chr(self.language) | ||||
|  | ||||
|         typelength = FruUtil.getTypeLength(self.productManufacturer) | ||||
|         self.data += chr(typelength) | ||||
|         self.data += self.productManufacturer | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productName)) | ||||
|         self.data += self.productName | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) | ||||
|         self.data += self.productPartModelName | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productVersion)) | ||||
|         self.data += self.productVersion | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) | ||||
|         self.data += self.productSerialNumber | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) | ||||
|         if self.productAssetTag is not None: | ||||
|             self.data += self.productAssetTag | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.fruFileId)) | ||||
|         self.data += self.fruFileId | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) | ||||
|                 self.data += chr(FruUtil.getTypeLength(valtmpval)) | ||||
|                 if valtmpval is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     self.data += valtmpval | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         self.data += chr(0xc1) | ||||
|         if len(self.data) > (self.size - 1): | ||||
|             incr = (len(self.data) - self.size) // 8 + 1 | ||||
|             self.size += incr * 8 | ||||
|         d_print("self.data:%d" % len(self.data)) | ||||
|         d_print("self.size:%d" % self.size) | ||||
|  | ||||
|         self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] | ||||
|         self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) | ||||
|         checksum = FruUtil.checksum(self.data) | ||||
|         d_print("board info checksum:%x" % checksum) | ||||
|         self.data += chr(checksum) | ||||
|  | ||||
|  | ||||
| class MultiRecordArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class Field(object): | ||||
|  | ||||
|     def __init__(self, fieldType="ASCII", fieldData=""): | ||||
|         self.fieldData = fieldData | ||||
|         self.fieldType = fieldType | ||||
|  | ||||
|     @property | ||||
|     def data(self): | ||||
|         return self._data | ||||
|  | ||||
|     @property | ||||
|     def fieldType(self): | ||||
|         return self._fieldType | ||||
|  | ||||
|     @property | ||||
|     def fieldData(self): | ||||
|         return self._fieldData | ||||
|  | ||||
|  | ||||
| class ipmifru(BaseArea): | ||||
|     _BoardInfoArea = None | ||||
|     _ProductInfoArea = None | ||||
|     _InternalUseArea = None | ||||
|     _ChassisInfoArea = None | ||||
|     _multiRecordArea = None | ||||
|     _productinfoAreaOffset = BaseArea.INITVALUE | ||||
|     _boardInfoAreaOffset = BaseArea.INITVALUE | ||||
|     _internalUserAreaOffset = BaseArea.INITVALUE | ||||
|     _chassicInfoAreaOffset = BaseArea.INITVALUE | ||||
|     _multiRecordAreaOffset = BaseArea.INITVALUE | ||||
|     _bindata = None | ||||
|     _bodybin = None | ||||
|     _version = BaseArea.COMMON_HEAD_VERSION | ||||
|     _zeroCheckSum = None | ||||
|     _frusize = 256 | ||||
|  | ||||
|     def __str__(self): | ||||
|         tmpstr = "" | ||||
|         if self.boardInfoArea.isPresent: | ||||
|             tmpstr += "\nboardinfoarea: \n" | ||||
|             tmpstr += self.boardInfoArea.__str__() | ||||
|         if self.productInfoArea.isPresent: | ||||
|             tmpstr += "\nproductinfoarea: \n" | ||||
|             tmpstr += self.productInfoArea.__str__() | ||||
|         return tmpstr | ||||
|  | ||||
|     def decodeBin(self, eeprom): | ||||
|         commonHead = eeprom[0:8] | ||||
|         d_print("decode version %x" % ord(commonHead[0])) | ||||
|         if ord(self.COMMON_HEAD_VERSION) != ord(commonHead[0]): | ||||
|             raise FruException("HEAD VERSION error,not Fru format!", -10) | ||||
|         if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): | ||||
|             strtemp = "check header checksum error [cal:%02x data:%02x]" % ( | ||||
|                 FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) | ||||
|             raise FruException(strtemp, -3) | ||||
|         if ord(commonHead[1]) != ord(self.INITVALUE): | ||||
|             d_print("Internal Use Area is present") | ||||
|             self.internalUseArea = InternalUseArea( | ||||
|                 name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) | ||||
|             self.internalUseArea.isPresent = True | ||||
|             self.internalUserAreaOffset = ord(commonHead[1]) | ||||
|             self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( | ||||
|                 self.internalUserAreaOffset * 8 + self.internalUseArea.size)] | ||||
|         if ord(commonHead[2]) != ord(self.INITVALUE): | ||||
|             d_print("Chassis Info Area is present") | ||||
|             self.chassisInfoArea = ChassisInfoArea( | ||||
|                 name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) | ||||
|             self.chassisInfoArea.isPresent = True | ||||
|             self.chassicInfoAreaOffset = ord(commonHead[2]) | ||||
|             self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( | ||||
|                 self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] | ||||
|         if ord(commonHead[3]) != ord(self.INITVALUE): | ||||
|             self.boardInfoArea = BoardInfoArea( | ||||
|                 name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) | ||||
|             self.boardInfoArea.isPresent = True | ||||
|             self.boardInfoAreaOffset = ord(commonHead[3]) | ||||
|             self.boardInfoArea.size = ord( | ||||
|                 eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 | ||||
|             d_print("Board Info Area is present size:%d" % | ||||
|                     (self.boardInfoArea.size)) | ||||
|             self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( | ||||
|                 self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] | ||||
|             if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): | ||||
|                 strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" %  \ | ||||
|                     (FruUtil.checksum( | ||||
|                         self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:])) | ||||
|                 raise FruException(strtmp, -3) | ||||
|             self.boardInfoArea.decodedata() | ||||
|         if ord(commonHead[4]) != ord(self.INITVALUE): | ||||
|             d_print("Product Info Area is present") | ||||
|             self.productInfoArea = ProductInfoArea( | ||||
|                 name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) | ||||
|             self.productInfoArea.isPresent = True | ||||
|             self.productinfoAreaOffset = ord(commonHead[4]) | ||||
|             d_print("length offset value: %02x" % | ||||
|                     ord(eeprom[self.productinfoAreaOffset * 8 + 1])) | ||||
|             self.productInfoArea.size = ord( | ||||
|                 eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 | ||||
|             d_print("Product Info Area is present size:%d" % | ||||
|                     (self.productInfoArea.size)) | ||||
|  | ||||
|             self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( | ||||
|                 self.productinfoAreaOffset * 8 + self.productInfoArea.size)] | ||||
|             if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): | ||||
|                 strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( | ||||
|                     FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) | ||||
|                 raise FruException(strtmp, -3) | ||||
|             self.productInfoArea.decodedata() | ||||
|         if ord(commonHead[5]) != ord(self.INITVALUE): | ||||
|             self.multiRecordArea = MultiRecordArea( | ||||
|                 name="MultiRecord record Area ") | ||||
|             d_print("MultiRecord record present") | ||||
|             self.multiRecordArea.isPresent = True | ||||
|             self.multiRecordAreaOffset = ord(commonHead[5]) | ||||
|             self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( | ||||
|                 self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] | ||||
|  | ||||
|     def initDefault(self): | ||||
|         self.version = self.COMMON_HEAD_VERSION | ||||
|         self.internalUserAreaOffset = self.INITVALUE | ||||
|         self.chassicInfoAreaOffset = self.INITVALUE | ||||
|         self.boardInfoAreaOffset = self.INITVALUE | ||||
|         self.productinfoAreaOffset = self.INITVALUE | ||||
|         self.multiRecordAreaOffset = self.INITVALUE | ||||
|         self.PAD = self.INITVALUE | ||||
|         self.zeroCheckSum = self.INITVALUE | ||||
|         self.offset = self.SUGGESTED_SIZE_COMMON_HEADER | ||||
|         self.productInfoArea = None | ||||
|         self.internalUseArea = None | ||||
|         self.boardInfoArea = None | ||||
|         self.chassisInfoArea = None | ||||
|         self.multiRecordArea = None | ||||
|         # self.recalcute() | ||||
|  | ||||
|     @property | ||||
|     def version(self): | ||||
|         return self._version | ||||
|  | ||||
|     @version.setter | ||||
|     def version(self, name): | ||||
|         self._version = name | ||||
|  | ||||
|     @property | ||||
|     def internalUserAreaOffset(self): | ||||
|         return self._internalUserAreaOffset | ||||
|  | ||||
|     @internalUserAreaOffset.setter | ||||
|     def internalUserAreaOffset(self, obj): | ||||
|         self._internalUserAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def chassicInfoAreaOffset(self): | ||||
|         return self._chassicInfoAreaOffset | ||||
|  | ||||
|     @chassicInfoAreaOffset.setter | ||||
|     def chassicInfoAreaOffset(self, obj): | ||||
|         self._chassicInfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def productinfoAreaOffset(self): | ||||
|         return self._productinfoAreaOffset | ||||
|  | ||||
|     @productinfoAreaOffset.setter | ||||
|     def productinfoAreaOffset(self, obj): | ||||
|         self._productinfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def boardInfoAreaOffset(self): | ||||
|         return self._boardInfoAreaOffset | ||||
|  | ||||
|     @boardInfoAreaOffset.setter | ||||
|     def boardInfoAreaOffset(self, obj): | ||||
|         self._boardInfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def multiRecordAreaOffset(self): | ||||
|         return self._multiRecordAreaOffset | ||||
|  | ||||
|     @multiRecordAreaOffset.setter | ||||
|     def multiRecordAreaOffset(self, obj): | ||||
|         self._multiRecordAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def zeroCheckSum(self): | ||||
|         return self._zeroCheckSum | ||||
|  | ||||
|     @zeroCheckSum.setter | ||||
|     def zeroCheckSum(self, obj): | ||||
|         self._zeroCheckSum = obj | ||||
|  | ||||
|     @property | ||||
|     def productInfoArea(self): | ||||
|         return self._ProductInfoArea | ||||
|  | ||||
|     @productInfoArea.setter | ||||
|     def productInfoArea(self, obj): | ||||
|         self._ProductInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def internalUseArea(self): | ||||
|         return self._InternalUseArea | ||||
|  | ||||
|     @internalUseArea.setter | ||||
|     def internalUseArea(self, obj): | ||||
|         self.internalUseArea = obj | ||||
|  | ||||
|     @property | ||||
|     def boardInfoArea(self): | ||||
|         return self._BoardInfoArea | ||||
|  | ||||
|     @boardInfoArea.setter | ||||
|     def boardInfoArea(self, obj): | ||||
|         self._BoardInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def chassisInfoArea(self): | ||||
|         return self._ChassisInfoArea | ||||
|  | ||||
|     @chassisInfoArea.setter | ||||
|     def chassisInfoArea(self, obj): | ||||
|         self._ChassisInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def multiRecordArea(self): | ||||
|         return self._multiRecordArea | ||||
|  | ||||
|     @multiRecordArea.setter | ||||
|     def multiRecordArea(self, obj): | ||||
|         self._multiRecordArea = obj | ||||
|  | ||||
|     @property | ||||
|     def bindata(self): | ||||
|         return self._bindata | ||||
|  | ||||
|     @bindata.setter | ||||
|     def bindata(self, obj): | ||||
|         self._bindata = obj | ||||
|  | ||||
|     @property | ||||
|     def bodybin(self): | ||||
|         return self._bodybin | ||||
|  | ||||
|     @bodybin.setter | ||||
|     def bodybin(self, obj): | ||||
|         self._bodybin = obj | ||||
|  | ||||
|     def recalcuteCommonHead(self): | ||||
|         self.bindata = "" | ||||
|         self.offset = self.SUGGESTED_SIZE_COMMON_HEADER | ||||
|         d_print("common Header %d" % self.offset) | ||||
|         d_print("fru eeprom size  %d" % self._frusize) | ||||
|         if self.internalUseArea is not None and self.internalUseArea.isPresent: | ||||
|             self.internalUserAreaOffset = self.offset // 8 | ||||
|             self.offset += self.internalUseArea.size | ||||
|             d_print("internalUseArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: | ||||
|             self.chassicInfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.chassisInfoArea.size | ||||
|             d_print("chassisInfoArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.boardInfoArea is not None and self.boardInfoArea.isPresent: | ||||
|             self.boardInfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.boardInfoArea.size | ||||
|             d_print("boardInfoArea is present offset:%d" % self.offset) | ||||
|             d_print("boardInfoArea is present size:%d" % | ||||
|                     self.boardInfoArea.size) | ||||
|  | ||||
|         if self.productInfoArea is not None and self.productInfoArea.isPresent: | ||||
|             self.productinfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.productInfoArea.size | ||||
|             d_print("productInfoArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.multiRecordArea is not None and self.multiRecordArea.isPresent: | ||||
|             self.multiRecordAreaOffset = self.offset // 8 | ||||
|             d_print("multiRecordArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.internalUserAreaOffset == self.INITVALUE: | ||||
|             self.internalUserAreaOffset = 0 | ||||
|         if self.productinfoAreaOffset == self.INITVALUE: | ||||
|             self.productinfoAreaOffset = 0 | ||||
|         if self.chassicInfoAreaOffset == self.INITVALUE: | ||||
|             self.chassicInfoAreaOffset = 0 | ||||
|         if self.boardInfoAreaOffset == self.INITVALUE: | ||||
|             self.boardInfoAreaOffset = 0 | ||||
|         if self.multiRecordAreaOffset == self.INITVALUE: | ||||
|             self.multiRecordAreaOffset = 0 | ||||
|  | ||||
|         self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset | ||||
|                              - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff | ||||
|         d_print("zerochecksum:%x" % self.zeroCheckSum) | ||||
|         self.data = "" | ||||
|         self.data += chr(self.version[0]) + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( | ||||
|             self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + chr(self.INITVALUE[0]) + chr(self.zeroCheckSum) | ||||
|  | ||||
|         self.bindata = self.data + self.bodybin | ||||
|         totallen = len(self.bindata) | ||||
|         d_print("totallen %d" % totallen) | ||||
|         if (totallen < self._frusize): | ||||
|             self.bindata = self.bindata.ljust(self._frusize, chr(self.INITVALUE[0])) | ||||
|         else: | ||||
|             raise FruException('bin data more than %d' % self._frusize, -2) | ||||
|  | ||||
|     def recalcutebin(self): | ||||
|         self.bodybin = "" | ||||
|         if self.internalUseArea is not None and self.internalUseArea.isPresent: | ||||
|             d_print("internalUseArea present") | ||||
|             self.bodybin += self.internalUseArea.data | ||||
|         if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: | ||||
|             d_print("chassisInfoArea present") | ||||
|             self.bodybin += self.chassisInfoArea.data | ||||
|         if self.boardInfoArea is not None and self.boardInfoArea.isPresent: | ||||
|             d_print("boardInfoArea present") | ||||
|             self.boardInfoArea.recalcute() | ||||
|             self.bodybin += self.boardInfoArea.data | ||||
|         if self.productInfoArea is not None and self.productInfoArea.isPresent: | ||||
|             d_print("productInfoAreapresent") | ||||
|             self.productInfoArea.recalcute() | ||||
|             self.bodybin += self.productInfoArea.data | ||||
|         if self.multiRecordArea is not None and self.multiRecordArea.isPresent: | ||||
|             d_print("multiRecordArea present") | ||||
|             self.bodybin += self.productInfoArea.data | ||||
|  | ||||
|     def recalcute(self, fru_eeprom_size=256): | ||||
|         self._frusize = fru_eeprom_size | ||||
|         self.recalcutebin() | ||||
|         self.recalcuteCommonHead() | ||||
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/installer.conf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/installer.conf
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| CONSOLE_SPEED=115200 | ||||
							
								
								
									
										6
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/led_proc_init.soc
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/led_proc_init.soc
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,6 @@ | ||||
|  | ||||
| led auto on | ||||
|  | ||||
| led start | ||||
|  | ||||
| linkscan SwPortBitMap=all | ||||
							
								
								
									
										431
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/monitor.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										431
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/monitor.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,431 @@ | ||||
| #!/usr/bin/python3 | ||||
| #   * onboard temperature sensors | ||||
| #   * FAN trays | ||||
| #   * PSU | ||||
| # | ||||
| import os | ||||
| import xml.etree.ElementTree as ET | ||||
| import glob | ||||
| from fru import ipmifru | ||||
| from decimal import Decimal | ||||
|  | ||||
|  | ||||
| MAILBOX_DIR = "/sys/bus/i2c/devices/" | ||||
| BOARD_ID_PATH = "/sys/module/ruijie_common/parameters/dfd_my_type" | ||||
|  | ||||
| CONFIG_NAME = "dev.xml" | ||||
|  | ||||
| def byteTostr(val): | ||||
|     strtmp = '' | ||||
|     for i in range(len(val)): | ||||
|         strtmp += chr(val[i]) | ||||
|     return strtmp | ||||
|  | ||||
|  | ||||
| def typeTostr(val): | ||||
|     if isinstance(val, bytes): | ||||
|         strtmp = byteTostr(val) | ||||
|         return strtmp | ||||
|     return val | ||||
|  | ||||
|  | ||||
| def get_board_id(): | ||||
|     if not os.path.exists(BOARD_ID_PATH): | ||||
|         return "NA" | ||||
|     with open(BOARD_ID_PATH) as fd: | ||||
|         id_str = fd.read().strip() | ||||
|     return "0x%x" % (int(id_str, 10)) | ||||
|  | ||||
|  | ||||
| def dev_file_read(path, offset, read_len): | ||||
|     retval = "ERR" | ||||
|     val_list = [] | ||||
|     msg = "" | ||||
|     ret = "" | ||||
|     fd = -1 | ||||
|  | ||||
|     if not os.path.exists(path): | ||||
|         return False, "%s %s not found" % (retval, path) | ||||
|  | ||||
|     try: | ||||
|         fd = os.open(path, os.O_RDONLY) | ||||
|         os.lseek(fd, offset, os.SEEK_SET) | ||||
|         ret = os.read(fd, read_len) | ||||
|         for item in ret: | ||||
|             val_list.append(item) | ||||
|     except Exception as e: | ||||
|         msg = str(e) | ||||
|         return False, "%s %s" % (retval, msg) | ||||
|     finally: | ||||
|         if fd > 0: | ||||
|             os.close(fd) | ||||
|     return True, val_list | ||||
|  | ||||
|  | ||||
| def getPMCreg(location): | ||||
|     retval = 'ERR' | ||||
|     if (not os.path.isfile(location)): | ||||
|         return "%s %s  notfound"% (retval , location) | ||||
|     try: | ||||
|         with open(location, 'r') as fd: | ||||
|             retval = fd.read() | ||||
|     except Exception as error: | ||||
|         return "ERR %s" % str(error) | ||||
|  | ||||
|     retval = retval.rstrip('\r\n') | ||||
|     retval = retval.lstrip(" ") | ||||
|     return retval | ||||
|  | ||||
|  | ||||
| # Get a mailbox register | ||||
| def get_pmc_register(reg_name): | ||||
|     retval = 'ERR' | ||||
|     mb_reg_file = reg_name | ||||
|     filepath = glob.glob(mb_reg_file) | ||||
|     if(len(filepath) == 0): | ||||
|         return "%s %s  notfound"% (retval , mb_reg_file) | ||||
|     mb_reg_file = filepath[0] | ||||
|     if (not os.path.isfile(mb_reg_file)): | ||||
|         #print mb_reg_file,  'not found !' | ||||
|         return "%s %s  notfound"% (retval , mb_reg_file) | ||||
|     try: | ||||
|         with open(mb_reg_file, 'rb') as fd: | ||||
|             retval = fd.read() | ||||
|         retval = typeTostr(retval) | ||||
|     except Exception as error: | ||||
|         retval = "%s %s read failed, msg: %s" % (retval, mb_reg_file, str(error)) | ||||
|  | ||||
|     retval = retval.rstrip('\r\n') | ||||
|     retval = retval.lstrip(" ") | ||||
|     return retval | ||||
|  | ||||
|  | ||||
| class checktype(): | ||||
|     def __init__(self, test1): | ||||
|         self.test1 = test1 | ||||
|  | ||||
|     @staticmethod | ||||
|     def check(name,location, bit, value, tips , err1): | ||||
|         psu_status = int(get_pmc_register(location),16) | ||||
|         val = (psu_status & (1<< bit)) >> bit | ||||
|         if (val != value): | ||||
|             err1["errmsg"] = tips | ||||
|             err1["code"] = -1 | ||||
|             return -1 | ||||
|         else: | ||||
|             err1["errmsg"] = "none" | ||||
|             err1["code"] = 0 | ||||
|             return 0 | ||||
|  | ||||
|     @staticmethod | ||||
|     def getValue(location, bit , type, coefficient = 1, addend = 0): | ||||
|         try: | ||||
|             value_t = get_pmc_register(location) | ||||
|             if value_t.startswith("ERR") : | ||||
|                 return value_t | ||||
|             if (type == 1): | ||||
|                 return float('%.1f' % ((float(value_t)/1000) + addend)) | ||||
|             elif (type == 2): | ||||
|                 return float('%.1f' % (float(value_t)/100)) | ||||
|             elif (type == 3): | ||||
|                 psu_status = int(value_t,16) | ||||
|                 return (psu_status & (1<< bit)) >> bit | ||||
|             elif (type == 4): | ||||
|                 return int(value_t,10) | ||||
|             elif (type == 5): | ||||
|                 return float('%.1f' % (float(value_t)/1000/1000)) | ||||
|             elif (type == 6): | ||||
|                 return Decimal(float(value_t)*coefficient/1000).quantize(Decimal('0.000')) | ||||
|             else: | ||||
|                 return value_t | ||||
|         except Exception as e: | ||||
|             value_t = "ERR %s" % str(e) | ||||
|             return value_t | ||||
|  | ||||
|     #######temp | ||||
|     @staticmethod | ||||
|     def getTemp(self, name, location , ret_t): | ||||
|         ret2 = self.getValue(location + "temp1_input" ," " ,1); | ||||
|         ret3 = self.getValue(location + "temp1_max" ," ", 1); | ||||
|         ret4 = self.getValue(location + "temp1_max_hyst" ," ", 1); | ||||
|         ret_t["temp1_input"] = ret2 | ||||
|         ret_t["temp1_max"] = ret3 | ||||
|         ret_t["temp1_max_hyst"] = ret4 | ||||
|  | ||||
|     @staticmethod | ||||
|     def getLM75(name, location, result): | ||||
|         c1=checktype | ||||
|         r1={} | ||||
|         c1.getTemp(c1, name, location, r1) | ||||
|         result[name] = r1 | ||||
|  | ||||
|     ##########fanFRU | ||||
|     @staticmethod | ||||
|     def decodeBinByValue(retval): | ||||
|         fru = ipmifru() | ||||
|         fru.decodeBin(retval) | ||||
|         return fru | ||||
|  | ||||
|     @staticmethod | ||||
|     def printbinvalue(b): | ||||
|         index = 0 | ||||
|         print("     ",) | ||||
|         for width in range(16): | ||||
|             print("%02x " % width,) | ||||
|         print("") | ||||
|         for i in range(0, len(b)): | ||||
|             if index % 16 == 0: | ||||
|                 print(" ") | ||||
|                 print(" %02x  " % i,) | ||||
|             print("%02x " % ord(b[i]),) | ||||
|             index += 1 | ||||
|         print("") | ||||
|  | ||||
|     @staticmethod | ||||
|     def getfruValue(prob_t, root, val): | ||||
|         try: | ||||
|             ret, binval_bytes = dev_file_read(val, 0, 256) | ||||
|             if ret == False: | ||||
|                 return binval_bytes | ||||
|             binval = byteTostr(binval_bytes) | ||||
|             fanpro = {} | ||||
|             ret = checktype.decodeBinByValue(binval) | ||||
|             fanpro['fan_type']  = ret.productInfoArea.productName | ||||
|             fanpro['hw_version']  = ret.productInfoArea.productVersion | ||||
|             fanpro['sn']  = ret.productInfoArea.productSerialNumber | ||||
|             fanpro['fanid']  = ret.productInfoArea.productextra2 | ||||
|             fan_display_name_dict = status.getDecodValue(root, "fan_display_name") | ||||
|             fan_name = fanpro['fan_type'].strip() | ||||
|             if len(fan_display_name_dict) == 0: | ||||
|                 return fanpro | ||||
|             if fan_name not in fan_display_name_dict.keys(): | ||||
|                 prob_t['errcode']= -1 | ||||
|                 prob_t['errmsg'] = '%s'%  ("ERR fan name: %s not support" % fan_name) | ||||
|             else: | ||||
|                 fanpro['fan_type'] = fan_display_name_dict[fan_name] | ||||
|             return fanpro | ||||
|         except Exception as error: | ||||
|             return "ERR " + str(error) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getslotfruValue(val): | ||||
|         try: | ||||
|             binval = checktype.getValue(val, 0 , 0) | ||||
|             if binval.startswith("ERR"): | ||||
|                 return binval | ||||
|             slotpro = {} | ||||
|             ret = checktype.decodeBinByValue(binval) | ||||
|             slotpro['slot_type']  = ret.boardInfoArea.boardProductName | ||||
|             slotpro['hw_version']  = ret.boardInfoArea.boardextra1 | ||||
|             slotpro['sn']  = ret.boardInfoArea.boardSerialNumber | ||||
|             return slotpro | ||||
|         except Exception as error: | ||||
|             return "ERR " + str(error) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getpsufruValue(prob_t, root, val): | ||||
|         try: | ||||
|             psu_match = False | ||||
|             binval = checktype.getValue(val, 0 , 0) | ||||
|             if binval.startswith("ERR"): | ||||
|                 return binval | ||||
|             psupro = {} | ||||
|             ret = checktype.decodeBinByValue(binval) | ||||
|             psupro['type1']  = ret.productInfoArea.productPartModelName | ||||
|             psupro['sn']  = ret.productInfoArea.productSerialNumber | ||||
|             psupro['hw_version'] = ret.productInfoArea.productVersion | ||||
|             psu_dict = status.getDecodValue(root, "psutype") | ||||
|             psupro['type1'] = psupro['type1'].strip() | ||||
|             if len(psu_dict) == 0: | ||||
|                 return psupro | ||||
|             for psu_name in psu_dict.keys(): | ||||
|                 if psu_name in psupro['type1']: | ||||
|                     psupro['type1'] = psu_dict[psu_name] | ||||
|                     psu_match = True | ||||
|                     break | ||||
|             if psu_match is not True: | ||||
|                 prob_t['errcode']= -1 | ||||
|                 prob_t['errmsg'] = '%s'%  ("ERR psu name: %s not support" % psupro['type1']) | ||||
|             return psupro | ||||
|         except Exception as error: | ||||
|             return "ERR " + str(error) | ||||
|  | ||||
| class status(): | ||||
|     def __init__(self, productname): | ||||
|         self.productname = productname | ||||
|  | ||||
|     @staticmethod | ||||
|     def getETroot(filename): | ||||
|         tree = ET.parse(filename) | ||||
|         root = tree.getroot() | ||||
|         return root; | ||||
|  | ||||
|     @staticmethod | ||||
|     def getDecodValue(collection, decode): | ||||
|         decodes = collection.find('decode') | ||||
|         testdecode = decodes.find(decode) | ||||
|         test={} | ||||
|         if testdecode is None: | ||||
|             return test | ||||
|         for neighbor in testdecode.iter('code'): | ||||
|             test[neighbor.attrib["key"]]=neighbor.attrib["value"] | ||||
|         return test | ||||
|  | ||||
|     @staticmethod | ||||
|     def getfileValue(location): | ||||
|         return checktype.getValue(location," "," ") | ||||
|  | ||||
|     @staticmethod | ||||
|     def getETValue(a, filename, tagname): | ||||
|         root = status.getETroot(filename) | ||||
|         for neighbor in root.iter(tagname): | ||||
|             prob_t = {} | ||||
|             prob_t = neighbor.attrib | ||||
|             prob_t['errcode']= 0 | ||||
|             prob_t['errmsg'] = '' | ||||
|             for pros in neighbor.iter("property"): | ||||
|                 ret = dict(list(neighbor.attrib.items()) + list(pros.attrib.items())) | ||||
|                 if ret.get('e2type') == 'fru' and ret.get("name") == "fru": | ||||
|                     fruval = checktype.getfruValue(prob_t, root, ret["location"]) | ||||
|                     if  isinstance(fruval, str) and fruval.startswith("ERR"): | ||||
|                         prob_t['errcode']= -1 | ||||
|                         prob_t['errmsg']= fruval | ||||
|                         break | ||||
|                     else: | ||||
|                         prob_t.update(fruval) | ||||
|                         continue | ||||
|  | ||||
|                 if ret.get("name") == "psu" and ret.get('e2type') == 'fru': | ||||
|                     psuval = checktype.getpsufruValue(prob_t, root, ret["location"]) | ||||
|                     if  isinstance(psuval, str) and psuval.startswith("ERR"): | ||||
|                         prob_t['errcode']= -1 | ||||
|                         prob_t['errmsg']= psuval | ||||
|                         break | ||||
|                     else: | ||||
|                         prob_t.update(psuval) | ||||
|                         continue | ||||
|  | ||||
|                 if ret.get("gettype") == "config": | ||||
|                     prob_t[ret["name"]] = ret["value"] | ||||
|                     continue | ||||
|  | ||||
|                 if ('type' not in ret.keys()): | ||||
|                     val = "0"; | ||||
|                 else: | ||||
|                     val = ret["type"] | ||||
|                 if ('bit' not in ret.keys()): | ||||
|                     bit = "0"; | ||||
|                 else: | ||||
|                     bit = ret["bit"] | ||||
|                 if ('coefficient' not in ret.keys()): | ||||
|                     coefficient = 1; | ||||
|                 else: | ||||
|                     coefficient = float(ret["coefficient"]) | ||||
|                 if ('addend' not in ret.keys()): | ||||
|                     addend = 0; | ||||
|                 else: | ||||
|                     addend = float(ret["addend"]) | ||||
|  | ||||
|                 s = checktype.getValue(ret["location"], int(bit),int(val), coefficient, addend) | ||||
|                 if  isinstance(s, str) and s.startswith("ERR"): | ||||
|                     prob_t['errcode']= -1 | ||||
|                     prob_t['errmsg']= s | ||||
|                     break | ||||
|                 if ('default' in ret.keys()): | ||||
|                     rt = status.getDecodValue(root,ret['decode']) | ||||
|                     prob_t['errmsg']= rt[str(s)] | ||||
|                     if str(s) != ret["default"]: | ||||
|                         prob_t['errcode']= -1 | ||||
|                         break | ||||
|                 else: | ||||
|                     if ('decode' in ret.keys()): | ||||
|                         rt = status.getDecodValue(root,ret['decode']) | ||||
|                         if(ret['decode'] == "psutype" and s.replace("\x00","").rstrip() not in rt.keys()): | ||||
|                                 prob_t['errcode']= -1 | ||||
|                                 prob_t['errmsg'] = '%s' %  ("ERR psu name: %s not support" % (s.replace("\x00","").rstrip())) | ||||
|                         else: | ||||
|                             s = rt[str(s).replace("\x00","").rstrip()] | ||||
|                 name = ret["name"] | ||||
|                 prob_t[name]=str(s) | ||||
|             a.append(prob_t) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getCPUValue(a, filename, tagname): | ||||
|         root = status.getETroot(filename) | ||||
|         for neighbor in root.iter(tagname): | ||||
|             location =  neighbor.attrib["location"] | ||||
|         L=[] | ||||
|         for dirpath, dirnames, filenames in os.walk(location): | ||||
|             for file in filenames : | ||||
|                 if file.endswith("input"): | ||||
|                     L.append(os.path.join(dirpath, file)) | ||||
|             L =sorted(L,reverse=False) | ||||
|         for i in range(len(L)): | ||||
|             prob_t = {} | ||||
|             prob_t["name"] = getPMCreg("%s/temp%d_label"%(location,i+1)) | ||||
|             prob_t["temp"] = float(getPMCreg("%s/temp%d_input"%(location,i+1)))/1000 | ||||
|             prob_t["alarm"] = float(getPMCreg("%s/temp%d_crit_alarm"%(location,i+1)))/1000 | ||||
|             prob_t["crit"] = float(getPMCreg("%s/temp%d_crit"%(location,i+1)))/1000 | ||||
|             prob_t["max"] = float(getPMCreg("%s/temp%d_max"%(location,i+1)))/1000 | ||||
|             a.append(prob_t) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getFileName(): | ||||
|         fpath = os.path.dirname(os.path.realpath(__file__)) | ||||
|         board_id = get_board_id() | ||||
|         dev_id_xml = fpath + "/" + "dev_%s.xml" % board_id | ||||
|         if os.path.exists(dev_id_xml): | ||||
|              return dev_id_xml | ||||
|         return  fpath + "/"+ CONFIG_NAME | ||||
|  | ||||
|     @staticmethod | ||||
|     def getFan(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "fan" | ||||
|         status.getvalue(ret, _filename, _tagname) | ||||
|  | ||||
|  | ||||
|     @staticmethod | ||||
|     def checkFan(ret): | ||||
|         _filename = status.getFileName() | ||||
|        # _filename = "/usr/local/bin/" + status.getFileName() | ||||
|         _tagname = "fan" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTemp(ret): | ||||
|         _filename = status.getFileName() | ||||
|        #_filename = "/usr/local/bin/" + status.getFileName() | ||||
|         _tagname = "temp" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getPsu(ret): | ||||
|         _filename = status.getFileName() | ||||
|        # _filename = "/usr/local/bin/" + status.getFileName() | ||||
|         _tagname = "psu" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getcputemp(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "cpus" | ||||
|         status.getCPUValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getDcdc(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "dcdc" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getmactemp(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "mactemp" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getmacpower(ret): | ||||
|         _filename = status.getFileName() | ||||
|         _tagname = "macpower" | ||||
|         status.getETValue(ret, _filename, _tagname) | ||||
							
								
								
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/platform_asic
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								device/tencent/x86_64-tencent_tcs9400-r0/platform_asic
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| broadcom | ||||
| @@ -0,0 +1,2 @@ | ||||
| SYNCD_SHM_SIZE=1g | ||||
| is_ltsw_chip=1 | ||||
							
								
								
									
										4
									
								
								platform/broadcom/one-image.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										4
									
								
								platform/broadcom/one-image.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -81,7 +81,9 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ | ||||
|                                $(RAGILE_RA_B6910_64C_PLATFORM_MODULE) \ | ||||
|                                $(RAGILE_RA_B6510_32C_PLATFORM_MODULE) \ | ||||
|                                $(RAGILE_RA_B6920_4S_PLATFORM_MODULE) \ | ||||
|                                $(NOKIA_IXR7250_PLATFORM_MODULE) | ||||
|                                $(NOKIA_IXR7250_PLATFORM_MODULE) \ | ||||
|                                $(TENCENT_TCS8400_PLATFORM_MODULE) \ | ||||
|                                $(TENCENT_TCS9400_PLATFORM_MODULE) | ||||
| $(SONIC_ONE_IMAGE)_LAZY_BUILD_INSTALLS = $(BRCM_OPENNSL_KERNEL) $(BRCM_DNX_OPENNSL_KERNEL) | ||||
| ifeq ($(INSTALL_DEBUG_TOOLS),y) | ||||
| $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) | ||||
|   | ||||
							
								
								
									
										8
									
								
								platform/broadcom/platform-modules-tencent.dep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								platform/broadcom/platform-modules-tencent.dep
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| MPATH       := $($(TENCENT_TCS8400_PLATFORM_MODULE)_SRC_PATH) | ||||
| DEP_FILES   := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-tencent.mk platform/broadcom/platform-modules-tencent.dep    | ||||
| DEP_FILES   += $(SONIC_COMMON_BASE_FILES_LIST) | ||||
| DEP_FILES   += $(shell git ls-files $(MPATH)) | ||||
|  | ||||
| $(TENCENT_TCS8400_PLATFORM_MODULE)_CACHE_MODE  := GIT_CONTENT_SHA  | ||||
| $(TENCENT_TCS8400_PLATFORM_MODULE)_DEP_FLAGS   := $(SONIC_COMMON_FLAGS_LIST) | ||||
| $(TENCENT_TCS8400_PLATFORM_MODULE)_DEP_FILES   := $(DEP_FILES) | ||||
							
								
								
									
										18
									
								
								platform/broadcom/platform-modules-tencent.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								platform/broadcom/platform-modules-tencent.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| # Tencent platform modules | ||||
| TENCENT_TCS8400_PLATFORM_MODULE_VERSION = 1.0 | ||||
| export TENCENT_TCS8400_PLATFORM_MODULE_VERSION | ||||
|  | ||||
| TENCENT_TCS8400_PLATFORM_MODULE = platform-modules-ruijie-tcs8400_$(TENCENT_TCS8400_PLATFORM_MODULE_VERSION)_amd64.deb | ||||
| $(TENCENT_TCS8400_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-tencent | ||||
| $(TENCENT_TCS8400_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) | ||||
| $(TENCENT_TCS8400_PLATFORM_MODULE)_PLATFORM = x86_64-tencent_tcs8400-r0 | ||||
| SONIC_DPKG_DEBS += $(TENCENT_TCS8400_PLATFORM_MODULE) | ||||
| SONIC_STRETCH_DEBS += $(TENCENT_TCS8400_PLATFORM_MODULE) | ||||
|  | ||||
| ## TCS9400 | ||||
| TENCENT_TCS9400_PLATFORM_MODULE_VERSION = 1.0 | ||||
| export TENCENT_TCS9400_PLATFORM_MODULE_VERSION | ||||
|  | ||||
| TENCENT_TCS9400_PLATFORM_MODULE = platform-modules-ruijie-tcs9400_$(TENCENT_TCS9400_PLATFORM_MODULE_VERSION)_amd64.deb | ||||
| $(TENCENT_TCS9400_PLATFORM_MODULE)_PLATFORM = x86_64-tencent_tcs9400-r0 | ||||
| $(eval $(call add_extra_package,$(TENCENT_TCS8400_PLATFORM_MODULE),$(TENCENT_TCS9400_PLATFORM_MODULE))) | ||||
							
								
								
									
										1
									
								
								platform/broadcom/rules.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										1
									
								
								platform/broadcom/rules.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -15,6 +15,7 @@ include $(PLATFORM_PATH)/platform-modules-juniper.mk | ||||
| #include $(PLATFORM_PATH)/platform-modules-brcm-xlr-gts.mk | ||||
| #include $(PLATFORM_PATH)/platform-modules-ruijie.mk | ||||
| #include $(PLATFORM_PATH)/platform-modules-ragile.mk | ||||
| #include $(PLATFORM_PATH)/platform-modules-tencent.mk | ||||
| include $(PLATFORM_PATH)/docker-syncd-brcm.mk | ||||
| include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk | ||||
| include $(PLATFORM_PATH)/docker-saiserver-brcm.mk | ||||
|   | ||||
							
								
								
									
										15
									
								
								platform/broadcom/sonic-platform-modules-tencent/LICENSE
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								platform/broadcom/sonic-platform-modules-tencent/LICENSE
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| Copyright (C) 2016  Microsoft, Inc | ||||
| Copyright (C) 2022  Ruijie Network Corporation | ||||
| 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. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License | ||||
| along with this program; if not, write to the Free Software | ||||
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | ||||
							
								
								
									
										37
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/Makefile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										37
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/Makefile
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| PWD		= $(shell pwd) | ||||
| CC ?=gcc | ||||
| INSTALL_MOD_DIR ?=extra | ||||
| KVERSION   ?= $(shell uname -r) | ||||
| KERNEL_SRC ?=  /lib/modules/$(KVERSION) | ||||
| EXTRA_CFLAGS:= -I$(M)/include | ||||
| EXTRA_CFLAGS+= -Wall | ||||
| SUB_BUILD_DIR = $(PWD)/build | ||||
| DIR_KERNEL_SRC = $(PWD)/modules | ||||
| SCRIPT_DIR = $(PWD)/script | ||||
| SERVICE_DIR = $(PWD)/service | ||||
| BLACK_DRIVER_CONF_DIR = $(PWD)/modprobe_conf | ||||
|  | ||||
| modules_build_dir = $(DIR_KERNEL_SRC)/build | ||||
|  | ||||
| INSTALL_MODULE_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) | ||||
| INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin | ||||
| INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system | ||||
| INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3/dist-packages | ||||
| INSTALL_BLACK_DRIVER = $(SUB_BUILD_DIR)/etc/modprobe.d | ||||
|  | ||||
| all: | ||||
| 	$(MAKE) -C $(DIR_KERNEL_SRC) | ||||
| 	@if [ ! -d ${INSTALL_MODULE_DIR} ]; then mkdir -p ${INSTALL_MODULE_DIR} ;fi | ||||
| 	@if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi | ||||
| 	@if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi | ||||
| 	@if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi | ||||
| 	@if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi | ||||
| 	@if [ -d $(PWD)/sonic_platform/ ]; then cp -rf $(PWD)/sonic_platform ${INSTALL_LIB_DIR} ;fi | ||||
| 	cp -r $(modules_build_dir)/*.ko $(INSTALL_MODULE_DIR) | ||||
| 	cp -r $(SCRIPT_DIR)/*  $(INSTALL_SCRIPT_DIR) | ||||
| 	cp -r $(SERVICE_DIR)/*  $(INSTALL_SERVICE_DIR) | ||||
| 	@if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi | ||||
| 	@if [ ! -d ${INSTALL_BLACK_DRIVER} ]; then mkdir -p ${INSTALL_BLACK_DRIVER} ;fi | ||||
| 	cp -r  $(BLACK_DRIVER_CONF_DIR)/*  $(INSTALL_BLACK_DRIVER) | ||||
| clean: | ||||
| 	rm -rf $(SUB_BUILD_DIR) | ||||
| @@ -0,0 +1,167 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import os | ||||
| import syslog | ||||
| import copy | ||||
|  | ||||
| from plat_hal.baseutil import baseutil | ||||
|  | ||||
| HYST_DEBUG_FILE = "/etc/.hysteresis_debug_flag" | ||||
|  | ||||
| HYSTERROR   = 1 | ||||
| HYSTDEBUG   = 2 | ||||
|  | ||||
| debuglevel = 0 | ||||
|  | ||||
| def hyst_debug(s): | ||||
|     if HYSTDEBUG & debuglevel: | ||||
|         syslog.openlog("FANCONTROL-HYST", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_DEBUG, s) | ||||
|  | ||||
| def hyst_error(s): | ||||
|     if HYSTERROR & debuglevel: | ||||
|         syslog.openlog("FANCONTROL-HYST", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_ERR, s) | ||||
|  | ||||
| class hysteresis(object): | ||||
|     __config = None | ||||
|     __hyst_config = None | ||||
|  | ||||
|     def __init__(self): | ||||
|         self.__config = baseutil.get_monitor_config() | ||||
|         self.__hyst_config = copy.deepcopy(self.__config.get("hyst", {})) | ||||
|         # init check | ||||
|         errcnt = 0 | ||||
|         errmsg = "" | ||||
|         self.debug_init() | ||||
|         for temp_hyst_conf in self.__hyst_config.values(): | ||||
|             if temp_hyst_conf["flag"] == 0: | ||||
|                 continue | ||||
|             for i in range(temp_hyst_conf["temp_min"], temp_hyst_conf["temp_max"] + 1): | ||||
|                 if i not in temp_hyst_conf["rising"]: | ||||
|                     errcnt -= 1 | ||||
|                     msg = "%s hyst config error, temp value %d not in rising curve;" % (temp_hyst_conf["name"], i) | ||||
|                     hyst_error(msg) | ||||
|                     errmsg += msg | ||||
|                 if i not in temp_hyst_conf["descending"]: | ||||
|                     errcnt -= 1 | ||||
|                     msg = "%s hyst config error, temp value %d not in descending curve;" %(temp_hyst_conf["name"], i) | ||||
|                     hyst_error(msg) | ||||
|                     errmsg += msg | ||||
|         if errcnt < 0: | ||||
|             raise KeyError(errmsg) | ||||
|  | ||||
|     def debug_init(self): | ||||
|             global debuglevel | ||||
|             if os.path.exists(HYST_DEBUG_FILE): | ||||
|                 debuglevel = debuglevel | HYSTDEBUG | HYSTERROR | ||||
|             else: | ||||
|                 debuglevel = debuglevel & ~(HYSTDEBUG | HYSTERROR) | ||||
|  | ||||
|     def get_temp_hyst_conf(self, temp_name): | ||||
|         temp_hyst_conf = self.__hyst_config.get(temp_name) | ||||
|         return temp_hyst_conf | ||||
|  | ||||
|     def get_temp_update(self, hyst_para, current_temp): | ||||
|         temp = hyst_para["value"] | ||||
|         if temp is None: | ||||
|             return None | ||||
|         temp.append(current_temp) | ||||
|         del temp[0] | ||||
|         return temp | ||||
|  | ||||
|     def duty_to_pwm(self, duty): | ||||
|         pwm = int(round(float(duty) * 255 / 100)) | ||||
|         return pwm | ||||
|  | ||||
|     def pwm_to_duty(self, pwm): | ||||
|         duty = int(round(float(pwm) * 100 / 255)) | ||||
|         return duty | ||||
|  | ||||
|     def calc_hyst_val(self, temp_name, temp_list): | ||||
|  | ||||
|         temp_hyst_conf = self.get_temp_hyst_conf(temp_name) | ||||
|         hyst_min = temp_hyst_conf["hyst_min"] | ||||
|         hyst_max = temp_hyst_conf["hyst_max"] | ||||
|         temp_min = temp_hyst_conf["temp_min"] | ||||
|         temp_max = temp_hyst_conf["temp_max"] | ||||
|         rising = temp_hyst_conf["rising"] | ||||
|         descending = temp_hyst_conf["descending"] | ||||
|         last_hyst_value = temp_hyst_conf["last_hyst_value"] | ||||
|         current_temp = temp_list[1] | ||||
|         last_temp = temp_list[0] | ||||
|  | ||||
|         hyst_debug("calc_hyst_val, temp_name: %s, current_temp: %s, last_temp: %s, last_hyst_value: %s" % | ||||
|             (temp_name, current_temp, last_temp, last_hyst_value)) | ||||
|  | ||||
|         if current_temp < temp_min: | ||||
|             hyst_debug("%s current_temp %s less than temp_min %s, set min hyst value: %s" % | ||||
|                 (temp_name, current_temp, temp_min, hyst_min)) | ||||
|             return hyst_min | ||||
|  | ||||
|         if current_temp > temp_max: | ||||
|             hyst_debug("%s current_temp %s more than temp_max %s, set max hyst value: %s" % | ||||
|                 (temp_name, current_temp, temp_max, hyst_max)) | ||||
|             return hyst_max | ||||
|  | ||||
|         if last_temp is None: # first time | ||||
|             hyst_value = rising[current_temp] | ||||
|             hyst_debug("last_temp is None, it's first hysteresis, using rising hyst value: %s" % hyst_value) | ||||
|             return hyst_value | ||||
|  | ||||
|         if current_temp == last_temp: # temp unchanging | ||||
|             hyst_debug("current_temp equal last_temp, keep last hyst value: %s" % last_hyst_value) | ||||
|             return last_hyst_value | ||||
|  | ||||
|         if current_temp > last_temp: | ||||
|             calc_hyst_value = rising[current_temp] | ||||
|             if calc_hyst_value < last_hyst_value: | ||||
|                 hyst_value = last_hyst_value | ||||
|             else: | ||||
|                 hyst_value = calc_hyst_value | ||||
|             hyst_debug("temp rising, last_hyst_value: %s, calc_hyst_value: %s, set hyst value: %s" % | ||||
|                 (last_hyst_value, calc_hyst_value, hyst_value)) | ||||
|             return hyst_value | ||||
|  | ||||
|         calc_hyst_value = descending[current_temp] | ||||
|         if calc_hyst_value > last_hyst_value: | ||||
|             hyst_value = last_hyst_value | ||||
|         else: | ||||
|             hyst_value = calc_hyst_value | ||||
|         hyst_debug("temp descending, last_hyst_value: %s, calc_hyst_value: %s, set hyst value: %s" % | ||||
|             (last_hyst_value, calc_hyst_value, hyst_value)) | ||||
|         return hyst_value | ||||
|  | ||||
|     def cacl(self, temp_name, current_temp): | ||||
|         self.debug_init() | ||||
|         try: | ||||
|             temp_hyst_conf = self.get_temp_hyst_conf(temp_name) | ||||
|             if temp_hyst_conf is None: | ||||
|                 hyst_debug("get %s hysteresis config failed" % temp_name) | ||||
|                 return None | ||||
|  | ||||
|             flag = temp_hyst_conf["flag"] | ||||
|             if flag != 1: | ||||
|                 hyst_debug("%s hysteresis flag == 0, skip" % temp_name) | ||||
|                 return None | ||||
|  | ||||
|             temp = self.get_temp_update(temp_hyst_conf, current_temp) | ||||
|             if temp is None: | ||||
|                 hyst_debug("get %s update failed" % temp_name) | ||||
|                 return None | ||||
|  | ||||
|             value = self.calc_hyst_val(temp_name, temp) | ||||
|  | ||||
|             temp_hyst_conf["last_hyst_value"] = value | ||||
|  | ||||
|             type = temp_hyst_conf["type"] | ||||
|             if type == "duty": | ||||
|                 pwm = self.duty_to_pwm(value) | ||||
|             else: | ||||
|                 pwm = value | ||||
|  | ||||
|             hyst_debug("temp_name: %s, current_temp: %s, set pwm 0x%x" % (temp_name, current_temp, pwm)) | ||||
|             return pwm | ||||
|         except Exception as e: | ||||
|             hyst_error("temp_name: %s calc hysteresis pwm error, msg: %s" % (temp_name, str(e))) | ||||
|             return None | ||||
|  | ||||
| @@ -0,0 +1,104 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import os | ||||
| import syslog | ||||
|  | ||||
| from plat_hal.baseutil import baseutil | ||||
|  | ||||
| OPENLOOP_DEBUG_FILE = "/etc/.openloop_debug_flag" | ||||
|  | ||||
| OPENLOOPERROR = 1 | ||||
| OPENLOOPDEBUG = 2 | ||||
|  | ||||
| debuglevel = 0 | ||||
|  | ||||
|  | ||||
| def openloop_debug(s): | ||||
|     if OPENLOOPDEBUG & debuglevel: | ||||
|         syslog.openlog("FANCONTROL-OPENLOOP", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_DEBUG, s) | ||||
|  | ||||
|  | ||||
| def openloop_error(s): | ||||
|     if OPENLOOPERROR & debuglevel: | ||||
|         syslog.openlog("FANCONTROL-OPENLOOP", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_ERR, s) | ||||
|  | ||||
|  | ||||
| class openloop(object): | ||||
|     __config = None | ||||
|     __openloop_config = None | ||||
|  | ||||
|     def __init__(self): | ||||
|         self.__config = baseutil.get_monitor_config() | ||||
|         self.__openloop_config = self.__config["openloop"] | ||||
|  | ||||
|     def debug_init(self): | ||||
|         global debuglevel | ||||
|         if os.path.exists(OPENLOOP_DEBUG_FILE): | ||||
|             debuglevel = debuglevel | OPENLOOPDEBUG | OPENLOOPERROR | ||||
|         else: | ||||
|             debuglevel = debuglevel & ~(OPENLOOPDEBUG | OPENLOOPERROR) | ||||
|  | ||||
|     def get_para(self, type): | ||||
|         para = self.__openloop_config.get(type) | ||||
|         return para | ||||
|  | ||||
|     def linear_cacl(self, temp): | ||||
|         self.debug_init() | ||||
|         openloop_para = self.get_para("linear") | ||||
|         if openloop_para is None: | ||||
|             openloop_debug("linear openloop: get para failed") | ||||
|             return None | ||||
|  | ||||
|         K = openloop_para["K"] | ||||
|         tin_min = openloop_para["tin_min"] | ||||
|         pwm_min = openloop_para["pwm_min"] | ||||
|         pwm_max = openloop_para["pwm_max"] | ||||
|         flag = openloop_para["flag"] | ||||
|  | ||||
|         if flag != 1: | ||||
|             openloop_debug("linear openloop: flag == 0") | ||||
|             return None | ||||
|  | ||||
|         if temp <= tin_min: | ||||
|             openloop_debug("linear openloop: temp = %d less than tin_min[%d]" % (temp, tin_min)) | ||||
|             return pwm_min | ||||
|  | ||||
|         pwm = int(pwm_min + (temp - tin_min) * K) | ||||
|         openloop_debug("linear openloop: cacl_pwm = 0x%x" % pwm) | ||||
|  | ||||
|         pwm = min(pwm, pwm_max) | ||||
|         pwm = max(pwm, pwm_min) | ||||
|         openloop_debug("linear openloop: temp = %d, pwm = 0x%x" % (temp, pwm)) | ||||
|         return pwm | ||||
|  | ||||
|     def curve_cacl(self, temp): | ||||
|         self.debug_init() | ||||
|         openloop_para = self.get_para("curve") | ||||
|         if openloop_para is None: | ||||
|             openloop_debug("curve openloop: get para failed") | ||||
|             return None | ||||
|  | ||||
|         a = openloop_para["a"] | ||||
|         b = openloop_para["b"] | ||||
|         c = openloop_para["c"] | ||||
|         tin_min = openloop_para["tin_min"] | ||||
|         pwm_min = openloop_para["pwm_min"] | ||||
|         pwm_max = openloop_para["pwm_max"] | ||||
|         flag = openloop_para["flag"] | ||||
|  | ||||
|         if flag != 1: | ||||
|             openloop_debug("curve openloop: flag == 0") | ||||
|             return None | ||||
|  | ||||
|         if temp <= tin_min: | ||||
|             openloop_debug("curve openloop: temp = %d less than tin_min[%d]" % (temp, tin_min)) | ||||
|             return pwm_min | ||||
|  | ||||
|         pwm = int(a * temp * temp + b * temp + c) | ||||
|         openloop_debug("curve openloop: cacl_pwm = 0x%x" % pwm) | ||||
|  | ||||
|         pwm = min(pwm, pwm_max) | ||||
|         pwm = max(pwm, pwm_min) | ||||
|         openloop_debug("curve openloop: temp = %d, pwm = 0x%x" % (temp, pwm)) | ||||
|         return pwm | ||||
							
								
								
									
										106
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/algorithm/pid.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										106
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/algorithm/pid.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import os | ||||
| import syslog | ||||
| import copy | ||||
|  | ||||
| from plat_hal.baseutil import baseutil | ||||
|  | ||||
| PID_DEBUG_FILE = "/etc/.pid_debug_flag" | ||||
|  | ||||
| PIDERROR = 1 | ||||
| PIDDEBUG = 2 | ||||
|  | ||||
| debuglevel = 0 | ||||
|  | ||||
|  | ||||
| def pid_debug(s): | ||||
|     if PIDDEBUG & debuglevel: | ||||
|         syslog.openlog("FANCONTROL-PID", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_DEBUG, s) | ||||
|  | ||||
|  | ||||
| def pid_error(s): | ||||
|     if PIDERROR & debuglevel: | ||||
|         syslog.openlog("FANCONTROL-PID", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_ERR, s) | ||||
|  | ||||
|  | ||||
| class pid(object): | ||||
|     __config = None | ||||
|     __pid_config = None | ||||
|  | ||||
|     def __init__(self): | ||||
|         self.__config = baseutil.get_monitor_config() | ||||
|         self.__pid_config = copy.deepcopy(self.__config["pid"]) | ||||
|  | ||||
|     def debug_init(self): | ||||
|         global debuglevel | ||||
|         if os.path.exists(PID_DEBUG_FILE): | ||||
|             debuglevel = debuglevel | PIDDEBUG | PIDERROR | ||||
|         else: | ||||
|             debuglevel = debuglevel & ~(PIDDEBUG | PIDERROR) | ||||
|  | ||||
|     def get_para(self, name): | ||||
|         para = self.__pid_config.get(name) | ||||
|         return para | ||||
|  | ||||
|     def get_temp_update(self, pid_para, current_temp): | ||||
|         temp = pid_para["value"] | ||||
|         if temp is None: | ||||
|             return None | ||||
|         temp.append(current_temp) | ||||
|         del temp[0] | ||||
|         return temp | ||||
|  | ||||
|     def cacl(self, last_pwm, name, current_temp): | ||||
|         delta_pwm = 0 | ||||
|         self.debug_init() | ||||
|         pid_debug("last_pwm = %d" % last_pwm) | ||||
|  | ||||
|         pid_para = self.get_para(name) | ||||
|         if pid_para is None: | ||||
|             pid_debug("get %s pid para failed" % name) | ||||
|             return None | ||||
|  | ||||
|         temp = self.get_temp_update(pid_para, current_temp) | ||||
|         if temp is None: | ||||
|             pid_debug("get %s update failed" % name) | ||||
|             return None | ||||
|  | ||||
|         type = pid_para["type"] | ||||
|         Kp = pid_para["Kp"] | ||||
|         Ki = pid_para["Ki"] | ||||
|         Kd = pid_para["Kd"] | ||||
|         target = pid_para["target"] | ||||
|         pwm_min = pid_para["pwm_min"] | ||||
|         pwm_max = pid_para["pwm_max"] | ||||
|         flag = pid_para["flag"] | ||||
|  | ||||
|         if flag != 1: | ||||
|             pid_debug("%s pid flag == 0" % name) | ||||
|             return None | ||||
|  | ||||
|         if type == "duty": | ||||
|             current_pwm = round(last_pwm * 100 / 255) | ||||
|         else: | ||||
|             current_pwm = last_pwm | ||||
|  | ||||
|         if (temp[2] is None): | ||||
|             tmp_pwm = current_pwm | ||||
|         elif ((temp[0] is None) or (temp[1] is None)): | ||||
|             delta_pwm = Ki * (temp[2] - target) | ||||
|             tmp_pwm = current_pwm + delta_pwm | ||||
|         else: | ||||
|             delta_pwm = Kp * (temp[2] - temp[1]) + Ki * (temp[2] - target) + Kd * (temp[2] - 2 * temp[1] + temp[0]) | ||||
|             tmp_pwm = current_pwm + delta_pwm | ||||
|  | ||||
|         pid_debug("delta_pwm = %d" % delta_pwm) | ||||
|         if type == "duty": | ||||
|             pwm = round(tmp_pwm * 255 / 100) | ||||
|         else: | ||||
|             pwm = int(tmp_pwm) | ||||
|  | ||||
|         pwm = min(pwm, pwm_max) | ||||
|         pwm = max(pwm, pwm_min) | ||||
|         pid_debug("last_pwm = 0x%x, pwm = 0x%x" % (last_pwm, pwm)) | ||||
|         return pwm | ||||
							
								
								
									
										953
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/eepromutil/fru.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										953
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/eepromutil/fru.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,953 @@ | ||||
| #!/usr/bin/python3 | ||||
| import collections | ||||
| from bitarray import bitarray | ||||
| from datetime import datetime, timedelta | ||||
|  | ||||
|  | ||||
| __DEBUG__ = "N" | ||||
|  | ||||
|  | ||||
| class FruException(Exception): | ||||
|     def __init__(self, message='fruerror', code=-100): | ||||
|         err = 'errcode: {0} message:{1}'.format(code, message) | ||||
|         Exception.__init__(self, err) | ||||
|         self.code = code | ||||
|         self.message = message | ||||
|  | ||||
|  | ||||
| def e_print(err): | ||||
|     print("ERROR: " + err) | ||||
|  | ||||
|  | ||||
| def d_print(debug_info): | ||||
|     if(__DEBUG__ == "Y"): | ||||
|         print(debug_info) | ||||
|  | ||||
|  | ||||
| class FruUtil(): | ||||
|     @staticmethod | ||||
|     def decodeLength(value): | ||||
|         a = bitarray(8) | ||||
|         a.setall(True) | ||||
|         a[0:1] = 0 | ||||
|         a[1:2] = 0 | ||||
|         x = ord(a.tobytes()) | ||||
|         return x & ord(value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def minToData(): | ||||
|         starttime = datetime(1996, 1, 1, 0, 0, 0) | ||||
|         endtime = datetime.now() | ||||
|         seconds = (endtime - starttime).total_seconds() | ||||
|         mins = seconds // 60 | ||||
|         m = int(round(mins)) | ||||
|         return m | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTimeFormat(): | ||||
|         return datetime.now().strftime('%Y-%m-%d') | ||||
|  | ||||
|     @staticmethod | ||||
|     def getTypeLength(value): | ||||
|         if value is None or len(value) == 0: | ||||
|             return 0 | ||||
|         a = bitarray(8) | ||||
|         a.setall(False) | ||||
|         a[0:1] = 1 | ||||
|         a[1:2] = 1 | ||||
|         x = ord(a.tobytes()) | ||||
|         return x | len(value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def checksum(b): | ||||
|         result = 0 | ||||
|         for i in range(len(b)): | ||||
|             result += ord(b[i]) | ||||
|         return (0x100 - (result & 0xff)) & 0xff | ||||
|  | ||||
|  | ||||
| class BaseArea(object): | ||||
|     SUGGESTED_SIZE_COMMON_HEADER = 8 | ||||
|     SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 | ||||
|     SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 | ||||
|     SUGGESTED_SIZE_BOARD_INFO_AREA = 80 | ||||
|     SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 | ||||
|  | ||||
|     INITVALUE = b'\x00' | ||||
|     resultvalue = INITVALUE * 256 | ||||
|     COMMON_HEAD_VERSION = b'\x01' | ||||
|     __childList = None | ||||
|  | ||||
|     def __init__(self, name="", size=0, offset=0): | ||||
|         self.__childList = [] | ||||
|         self._offset = offset | ||||
|         self.name = name | ||||
|         self._size = size | ||||
|         self._isPresent = False | ||||
|         self._data = b'\x00' * size | ||||
|         self.__dataoffset = 0 | ||||
|  | ||||
|     @property | ||||
|     def childList(self): | ||||
|         return self.__childList | ||||
|  | ||||
|     @childList.setter | ||||
|     def childList(self, value): | ||||
|         self.__childList = value | ||||
|  | ||||
|     @property | ||||
|     def offset(self): | ||||
|         return self._offset | ||||
|  | ||||
|     @offset.setter | ||||
|     def offset(self, value): | ||||
|         self._offset = value | ||||
|  | ||||
|     @property | ||||
|     def size(self): | ||||
|         return self._size | ||||
|  | ||||
|     @size.setter | ||||
|     def size(self, value): | ||||
|         self._size = value | ||||
|  | ||||
|     @property | ||||
|     def data(self): | ||||
|         return self._data | ||||
|  | ||||
|     @data.setter | ||||
|     def data(self, value): | ||||
|         self._data = value | ||||
|  | ||||
|     @property | ||||
|     def isPresent(self): | ||||
|         return self._isPresent | ||||
|  | ||||
|     @isPresent.setter | ||||
|     def isPresent(self, value): | ||||
|         self._isPresent = value | ||||
|  | ||||
|  | ||||
| class InternalUseArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class ChassisInfoArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class BoardInfoArea(BaseArea): | ||||
|     _boardTime = None | ||||
|     _fields = None | ||||
|     _mfg_date = None | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "version             : %x\n" \ | ||||
|                     "length              : %d \n" \ | ||||
|                     "language            : %x \n" \ | ||||
|                     "mfg_date            : %s \n" \ | ||||
|                     "boardManufacturer   : %s \n" \ | ||||
|                     "boardProductName    : %s \n" \ | ||||
|                     "boardSerialNumber   : %s \n" \ | ||||
|                     "boardPartNumber     : %s \n" \ | ||||
|                     "fruFileId           : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (ord(self.boardversion), self.size, | ||||
|                               self.language, self.getMfgRealData(), | ||||
|                               self.boardManufacturer, self.boardProductName, | ||||
|                               self.boardSerialNumber, self.boardPartNumber, | ||||
|                               self.fruFileId) | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 tmpstr += "boardextra%d         : %s \n" % (i, valtmpval) | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         return tmpstr | ||||
|  | ||||
|     def todict(self): | ||||
|         dic = collections.OrderedDict() | ||||
|         dic["boardversion"] = ord(self.boardversion) | ||||
|         dic["boardlength"] = self.size | ||||
|         dic["boardlanguage"] = self.language | ||||
|         dic["boardmfg_date"] = self.getMfgRealData() | ||||
|         dic["boardManufacturer"] = self.boardManufacturer | ||||
|         dic["boardProductName"] = self.boardProductName | ||||
|         dic["boardSerialNumber"] = self.boardSerialNumber | ||||
|         dic["boardPartNumber"] = self.boardPartNumber | ||||
|         dic["boardfruFileId"] = self.fruFileId | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 dic[valtmp] = valtmpval | ||||
|             else: | ||||
|                 break | ||||
|         return dic | ||||
|  | ||||
|     def decodedata(self): | ||||
|         index = 0 | ||||
|         self.areaversion = self.data[index] | ||||
|         index += 1 | ||||
|         d_print("decode length :%d class size:%d" % | ||||
|                 ((ord(self.data[index]) * 8), self.size)) | ||||
|         index += 2 | ||||
|  | ||||
|         timetmp = self.data[index: index + 3] | ||||
|         self.mfg_date = ord(timetmp[0]) | ( | ||||
|             ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) | ||||
|         d_print("decode getMfgRealData :%s" % self.getMfgRealData()) | ||||
|         index += 3 | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardManufacturer = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardManufacturer:%s" % self.boardManufacturer) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardProductName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardProductName:%s" % self.boardProductName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardSerialNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.boardPartNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode boardPartNumber:%s" % self.boardPartNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.fruFileId = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode fruFileId:%s" % self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if self.data[index] != chr(0xc1): | ||||
|                 templen = FruUtil.decodeLength(self.data[index]) | ||||
|                 tmpval = self.data[index + 1: index + templen + 1] | ||||
|                 setattr(self, valtmp, tmpval) | ||||
|                 index += templen + 1 | ||||
|                 d_print("decode boardextra%d:%s" % (i, tmpval)) | ||||
|             else: | ||||
|                 break | ||||
|         return | ||||
|  | ||||
|     def recalcute(self): | ||||
|         d_print("boardInfoArea version:%x" % ord(self.boardversion)) | ||||
|         d_print("boardInfoArea length:%d" % self.size) | ||||
|         d_print("boardInfoArea language:%x" % self.language) | ||||
|         self.mfg_date = FruUtil.minToData() | ||||
|         d_print("boardInfoArea mfg_date:%x" % self.mfg_date) | ||||
|  | ||||
|         self.data = chr(ord(self.boardversion)) + \ | ||||
|             chr(self.size // 8) + chr(self.language) | ||||
|  | ||||
|         self.data += chr(self.mfg_date & 0xFF) | ||||
|         self.data += chr((self.mfg_date >> 8) & 0xFF) | ||||
|         self.data += chr((self.mfg_date >> 16) & 0xFF) | ||||
|  | ||||
|         d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) | ||||
|         typelength = FruUtil.getTypeLength(self.boardManufacturer) | ||||
|         self.data += chr(typelength) | ||||
|         self.data += self.boardManufacturer | ||||
|  | ||||
|         d_print("boardInfoArea boardProductName:%s" % self.boardProductName) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardProductName)) | ||||
|         self.data += self.boardProductName | ||||
|  | ||||
|         d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) | ||||
|         self.data += self.boardSerialNumber | ||||
|  | ||||
|         d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) | ||||
|         self.data += self.boardPartNumber | ||||
|  | ||||
|         d_print("boardInfoArea fruFileId:%s" % self.fruFileId) | ||||
|         self.data += chr(FruUtil.getTypeLength(self.fruFileId)) | ||||
|         self.data += self.fruFileId | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "boardextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) | ||||
|                 self.data += chr(FruUtil.getTypeLength(valtmpval)) | ||||
|                 if valtmpval is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     self.data += valtmpval | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         self.data += chr(0xc1) | ||||
|  | ||||
|         if len(self.data) > (self.size - 1): | ||||
|             incr = (len(self.data) - self.size) // 8 + 1 | ||||
|             self.size += incr * 8 | ||||
|  | ||||
|         self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] | ||||
|         d_print("self data:%d" % len(self.data)) | ||||
|         d_print("self size:%d" % self.size) | ||||
|         d_print("adjust size:%d" % (self.size - len(self.data) - 1)) | ||||
|         self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) | ||||
|  | ||||
|         # checksum | ||||
|         checksum = FruUtil.checksum(self.data) | ||||
|         d_print("board info checksum:%x" % checksum) | ||||
|         self.data += chr(checksum) | ||||
|  | ||||
|     def getMfgRealData(self): | ||||
|         starttime = datetime(1996, 1, 1, 0, 0, 0) | ||||
|         mactime = starttime + timedelta(minutes=self.mfg_date) | ||||
|         return mactime | ||||
|  | ||||
|     @property | ||||
|     def language(self): | ||||
|         self._language = 25 | ||||
|         return self._language | ||||
|  | ||||
|     @property | ||||
|     def mfg_date(self): | ||||
|         return self._mfg_date | ||||
|  | ||||
|     @mfg_date.setter | ||||
|     def mfg_date(self, val): | ||||
|         self._mfg_date = val | ||||
|  | ||||
|     @property | ||||
|     def boardversion(self): | ||||
|         self._boardversion = self.COMMON_HEAD_VERSION | ||||
|         return self._boardversion | ||||
|  | ||||
|     @property | ||||
|     def fruFileId(self): | ||||
|         return self._FRUFileID | ||||
|  | ||||
|     @fruFileId.setter | ||||
|     def fruFileId(self, val): | ||||
|         self._FRUFileID = val | ||||
|  | ||||
|     @property | ||||
|     def boardPartNumber(self): | ||||
|         return self._boardPartNumber | ||||
|  | ||||
|     @boardPartNumber.setter | ||||
|     def boardPartNumber(self, val): | ||||
|         self._boardPartNumber = val | ||||
|  | ||||
|     @property | ||||
|     def boardSerialNumber(self): | ||||
|         return self._boardSerialNumber | ||||
|  | ||||
|     @boardSerialNumber.setter | ||||
|     def boardSerialNumber(self, val): | ||||
|         self._boardSerialNumber = val | ||||
|  | ||||
|     @property | ||||
|     def boardProductName(self): | ||||
|         return self._boradProductName | ||||
|  | ||||
|     @boardProductName.setter | ||||
|     def boardProductName(self, val): | ||||
|         self._boradProductName = val | ||||
|  | ||||
|     @property | ||||
|     def boardManufacturer(self): | ||||
|         return self._boardManufacturer | ||||
|  | ||||
|     @boardManufacturer.setter | ||||
|     def boardManufacturer(self, val): | ||||
|         self._boardManufacturer = val | ||||
|  | ||||
|     @property | ||||
|     def boardTime(self): | ||||
|         return self._boardTime | ||||
|  | ||||
|     @boardTime.setter | ||||
|     def boardTime(self, val): | ||||
|         self._boardTime = val | ||||
|  | ||||
|     @property | ||||
|     def fields(self): | ||||
|         return self._fields | ||||
|  | ||||
|     @fields.setter | ||||
|     def fields(self, val): | ||||
|         self._fields = val | ||||
|  | ||||
|  | ||||
| class ProductInfoArea(BaseArea): | ||||
|     _productManufacturer = None | ||||
|     _productAssetTag = None | ||||
|     _FRUFileID = None | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "version             : %x\n" \ | ||||
|                     "length              : %d \n" \ | ||||
|                     "language            : %x \n" \ | ||||
|                     "productManufacturer : %s \n" \ | ||||
|                     "productName         : %s \n" \ | ||||
|                     "productPartModelName: %s \n" \ | ||||
|                     "productVersion      : %s \n" \ | ||||
|                     "productSerialNumber : %s \n" \ | ||||
|                     "productAssetTag     : %s \n" \ | ||||
|                     "fruFileId           : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (ord(self.areaversion), self.size, | ||||
|                               self.language, self.productManufacturer, | ||||
|                               self.productName, self.productPartModelName, | ||||
|                               self.productVersion, self.productSerialNumber, | ||||
|                               self.productAssetTag, self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 tmpstr += "productextra%d       : %s \n" % (i, valtmpval) | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         return tmpstr | ||||
|  | ||||
|     def todict(self): | ||||
|         dic = collections.OrderedDict() | ||||
|         dic["productversion"] = ord(self.areaversion) | ||||
|         dic["productlength"] = self.size | ||||
|         dic["productlanguage"] = self.language | ||||
|         dic["productManufacturer"] = self.productManufacturer | ||||
|         dic["productName"] = self.productName | ||||
|         dic["productPartModelName"] = self.productPartModelName | ||||
|         dic["productVersion"] = int(self.productVersion, 16) | ||||
|         dic["productSerialNumber"] = self.productSerialNumber | ||||
|         dic["productAssetTag"] = self.productAssetTag | ||||
|         dic["productfruFileId"] = self.fruFileId | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 dic[valtmp] = valtmpval | ||||
|             else: | ||||
|                 break | ||||
|         return dic | ||||
|  | ||||
|     def decodedata(self): | ||||
|         index = 0 | ||||
|         self.areaversion = self.data[index]  # 0 | ||||
|         index += 1 | ||||
|         d_print("decode length %d" % (ord(self.data[index]) * 8)) | ||||
|         d_print("class size %d" % self.size) | ||||
|         index += 2 | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productManufacturer = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productManufacturer:%s" % self.productManufacturer) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productName:%s" % self.productName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productPartModelName = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productPartModelName:%s" % self.productPartModelName) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productVersion = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productVersion:%s" % self.productVersion) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productSerialNumber = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productSerialNumber:%s" % self.productSerialNumber) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.productAssetTag = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode productAssetTag:%s" % self.productAssetTag) | ||||
|  | ||||
|         templen = FruUtil.decodeLength(self.data[index]) | ||||
|         self.fruFileId = self.data[index + 1: index + templen + 1] | ||||
|         index += templen + 1 | ||||
|         d_print("decode fruFileId:%s" % self.fruFileId) | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if self.data[index] != chr(0xc1) and index < self.size - 1: | ||||
|                 templen = FruUtil.decodeLength(self.data[index]) | ||||
|                 if templen == 0: | ||||
|                     break | ||||
|                 tmpval = self.data[index + 1: index + templen + 1] | ||||
|                 d_print("decode boardextra%d:%s" % (i, tmpval)) | ||||
|                 setattr(self, valtmp, tmpval) | ||||
|                 index += templen + 1 | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|     @property | ||||
|     def productVersion(self): | ||||
|         return self._productVersion | ||||
|  | ||||
|     @productVersion.setter | ||||
|     def productVersion(self, name): | ||||
|         self._productVersion = name | ||||
|  | ||||
|     @property | ||||
|     def areaversion(self): | ||||
|         self._areaversion = self.COMMON_HEAD_VERSION | ||||
|         return self._areaversion | ||||
|  | ||||
|     @areaversion.setter | ||||
|     def areaversion(self, name): | ||||
|         self._areaversion = name | ||||
|  | ||||
|     @property | ||||
|     def language(self): | ||||
|         self._language = 25 | ||||
|         return self._language | ||||
|  | ||||
|     @property | ||||
|     def productManufacturer(self): | ||||
|         return self._productManufacturer | ||||
|  | ||||
|     @productManufacturer.setter | ||||
|     def productManufacturer(self, name): | ||||
|         self._productManufacturer = name | ||||
|  | ||||
|     @property | ||||
|     def productName(self): | ||||
|         return self._productName | ||||
|  | ||||
|     @productName.setter | ||||
|     def productName(self, name): | ||||
|         self._productName = name | ||||
|  | ||||
|     @property | ||||
|     def productPartModelName(self): | ||||
|         return self._productPartModelName | ||||
|  | ||||
|     @productPartModelName.setter | ||||
|     def productPartModelName(self, name): | ||||
|         self._productPartModelName = name | ||||
|  | ||||
|     @property | ||||
|     def productSerialNumber(self): | ||||
|         return self._productSerialNumber | ||||
|  | ||||
|     @productSerialNumber.setter | ||||
|     def productSerialNumber(self, name): | ||||
|         self._productSerialNumber = name | ||||
|  | ||||
|     @property | ||||
|     def productAssetTag(self): | ||||
|         return self._productAssetTag | ||||
|  | ||||
|     @productAssetTag.setter | ||||
|     def productAssetTag(self, name): | ||||
|         self._productAssetTag = name | ||||
|  | ||||
|     @property | ||||
|     def fruFileId(self): | ||||
|         return self._FRUFileID | ||||
|  | ||||
|     @fruFileId.setter | ||||
|     def fruFileId(self, name): | ||||
|         self._FRUFileID = name | ||||
|  | ||||
|     def recalcute(self): | ||||
|         d_print("product version:%x" % ord(self.areaversion)) | ||||
|         d_print("product length:%d" % self.size) | ||||
|         d_print("product language:%x" % self.language) | ||||
|         self.data = chr(ord(self.areaversion)) + \ | ||||
|             chr(self.size // 8) + chr(self.language) | ||||
|  | ||||
|         typelength = FruUtil.getTypeLength(self.productManufacturer) | ||||
|         self.data += chr(typelength) | ||||
|         self.data += self.productManufacturer | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productName)) | ||||
|         self.data += self.productName | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) | ||||
|         self.data += self.productPartModelName | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productVersion)) | ||||
|         self.data += self.productVersion | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) | ||||
|         self.data += self.productSerialNumber | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) | ||||
|         if self.productAssetTag is not None: | ||||
|             self.data += self.productAssetTag | ||||
|  | ||||
|         self.data += chr(FruUtil.getTypeLength(self.fruFileId)) | ||||
|         self.data += self.fruFileId | ||||
|  | ||||
|         for i in range(1, 11): | ||||
|             valtmp = "productextra%d" % i | ||||
|             if hasattr(self, valtmp): | ||||
|                 valtmpval = getattr(self, valtmp) | ||||
|                 d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) | ||||
|                 self.data += chr(FruUtil.getTypeLength(valtmpval)) | ||||
|                 if valtmpval is None: | ||||
|                     pass | ||||
|                 else: | ||||
|                     self.data += valtmpval | ||||
|             else: | ||||
|                 break | ||||
|  | ||||
|         self.data += chr(0xc1) | ||||
|         if len(self.data) > (self.size - 1): | ||||
|             incr = (len(self.data) - self.size) // 8 + 1 | ||||
|             self.size += incr * 8 | ||||
|         d_print("self.data:%d" % len(self.data)) | ||||
|         d_print("self.size:%d" % self.size) | ||||
|  | ||||
|         self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] | ||||
|         self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) | ||||
|         checksum = FruUtil.checksum(self.data) | ||||
|         d_print("board info checksum:%x" % checksum) | ||||
|         self.data += chr(checksum) | ||||
|  | ||||
|  | ||||
| class MultiRecordArea(BaseArea): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class Field(object): | ||||
|  | ||||
|     def __init__(self, fieldType="ASCII", fieldData=""): | ||||
|         self.fieldData = fieldData | ||||
|         self.fieldType = fieldType | ||||
|  | ||||
|     @property | ||||
|     def data(self): | ||||
|         return self._data | ||||
|  | ||||
|     @property | ||||
|     def fieldType(self): | ||||
|         return self._fieldType | ||||
|  | ||||
|     @property | ||||
|     def fieldData(self): | ||||
|         return self._fieldData | ||||
|  | ||||
|  | ||||
| class ipmifru(BaseArea): | ||||
|     _BoardInfoArea = None | ||||
|     _ProductInfoArea = None | ||||
|     _InternalUseArea = None | ||||
|     _ChassisInfoArea = None | ||||
|     _multiRecordArea = None | ||||
|     _productinfoAreaOffset = BaseArea.INITVALUE | ||||
|     _boardInfoAreaOffset = BaseArea.INITVALUE | ||||
|     _internalUserAreaOffset = BaseArea.INITVALUE | ||||
|     _chassicInfoAreaOffset = BaseArea.INITVALUE | ||||
|     _multiRecordAreaOffset = BaseArea.INITVALUE | ||||
|     _bindata = None | ||||
|     _bodybin = None | ||||
|     _version = BaseArea.COMMON_HEAD_VERSION | ||||
|     _zeroCheckSum = None | ||||
|     _frusize = 256 | ||||
|  | ||||
|     def __str__(self): | ||||
|         tmpstr = "" | ||||
|         if self.boardInfoArea.isPresent: | ||||
|             tmpstr += "\nboardinfoarea: \n" | ||||
|             tmpstr += self.boardInfoArea.__str__() | ||||
|         if self.productInfoArea.isPresent: | ||||
|             tmpstr += "\nproductinfoarea: \n" | ||||
|             tmpstr += self.productInfoArea.__str__() | ||||
|         return tmpstr | ||||
|  | ||||
|     def decodeBin(self, eeprom): | ||||
|         commonHead = eeprom[0:8] | ||||
|         d_print("decode version %x" % ord(commonHead[0])) | ||||
|         if ord(self.COMMON_HEAD_VERSION) != ord(commonHead[0]): | ||||
|             raise FruException("HEAD VERSION error,not Fru format!", -10) | ||||
|         if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): | ||||
|             strtemp = "check header checksum error [cal:%02x data:%02x]" % ( | ||||
|                 FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) | ||||
|             raise FruException(strtemp, -3) | ||||
|         if ord(commonHead[1]) != ord(self.INITVALUE): | ||||
|             d_print("Internal Use Area is present") | ||||
|             self.internalUseArea = InternalUseArea( | ||||
|                 name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) | ||||
|             self.internalUseArea.isPresent = True | ||||
|             self.internalUserAreaOffset = ord(commonHead[1]) | ||||
|             self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( | ||||
|                 self.internalUserAreaOffset * 8 + self.internalUseArea.size)] | ||||
|         if ord(commonHead[2]) != ord(self.INITVALUE): | ||||
|             d_print("Chassis Info Area is present") | ||||
|             self.chassisInfoArea = ChassisInfoArea( | ||||
|                 name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) | ||||
|             self.chassisInfoArea.isPresent = True | ||||
|             self.chassicInfoAreaOffset = ord(commonHead[2]) | ||||
|             self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( | ||||
|                 self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] | ||||
|         if ord(commonHead[3]) != ord(self.INITVALUE): | ||||
|             self.boardInfoArea = BoardInfoArea( | ||||
|                 name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) | ||||
|             self.boardInfoArea.isPresent = True | ||||
|             self.boardInfoAreaOffset = ord(commonHead[3]) | ||||
|             self.boardInfoArea.size = ord( | ||||
|                 eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 | ||||
|             d_print("Board Info Area is present size:%d" % | ||||
|                     (self.boardInfoArea.size)) | ||||
|             self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( | ||||
|                 self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] | ||||
|             if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): | ||||
|                 strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" %  \ | ||||
|                     (FruUtil.checksum( | ||||
|                         self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:])) | ||||
|                 raise FruException(strtmp, -3) | ||||
|             self.boardInfoArea.decodedata() | ||||
|         if ord(commonHead[4]) != ord(self.INITVALUE): | ||||
|             d_print("Product Info Area is present") | ||||
|             self.productInfoArea = ProductInfoArea( | ||||
|                 name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) | ||||
|             self.productInfoArea.isPresent = True | ||||
|             self.productinfoAreaOffset = ord(commonHead[4]) | ||||
|             d_print("length offset value: %02x" % | ||||
|                     ord(eeprom[self.productinfoAreaOffset * 8 + 1])) | ||||
|             self.productInfoArea.size = ord( | ||||
|                 eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 | ||||
|             d_print("Product Info Area is present size:%d" % | ||||
|                     (self.productInfoArea.size)) | ||||
|  | ||||
|             self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( | ||||
|                 self.productinfoAreaOffset * 8 + self.productInfoArea.size)] | ||||
|             if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): | ||||
|                 strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( | ||||
|                     FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) | ||||
|                 raise FruException(strtmp, -3) | ||||
|             self.productInfoArea.decodedata() | ||||
|         if ord(commonHead[5]) != ord(self.INITVALUE): | ||||
|             self.multiRecordArea = MultiRecordArea( | ||||
|                 name="MultiRecord record Area ") | ||||
|             d_print("MultiRecord record present") | ||||
|             self.multiRecordArea.isPresent = True | ||||
|             self.multiRecordAreaOffset = ord(commonHead[5]) | ||||
|             self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( | ||||
|                 self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] | ||||
|  | ||||
|     def initDefault(self): | ||||
|         self.version = self.COMMON_HEAD_VERSION | ||||
|         self.internalUserAreaOffset = self.INITVALUE | ||||
|         self.chassicInfoAreaOffset = self.INITVALUE | ||||
|         self.boardInfoAreaOffset = self.INITVALUE | ||||
|         self.productinfoAreaOffset = self.INITVALUE | ||||
|         self.multiRecordAreaOffset = self.INITVALUE | ||||
|         self.PAD = self.INITVALUE | ||||
|         self.zeroCheckSum = self.INITVALUE | ||||
|         self.offset = self.SUGGESTED_SIZE_COMMON_HEADER | ||||
|         self.productInfoArea = None | ||||
|         self.internalUseArea = None | ||||
|         self.boardInfoArea = None | ||||
|         self.chassisInfoArea = None | ||||
|         self.multiRecordArea = None | ||||
|         # self.recalcute() | ||||
|  | ||||
|     @property | ||||
|     def version(self): | ||||
|         return self._version | ||||
|  | ||||
|     @version.setter | ||||
|     def version(self, name): | ||||
|         self._version = name | ||||
|  | ||||
|     @property | ||||
|     def internalUserAreaOffset(self): | ||||
|         return self._internalUserAreaOffset | ||||
|  | ||||
|     @internalUserAreaOffset.setter | ||||
|     def internalUserAreaOffset(self, obj): | ||||
|         self._internalUserAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def chassicInfoAreaOffset(self): | ||||
|         return self._chassicInfoAreaOffset | ||||
|  | ||||
|     @chassicInfoAreaOffset.setter | ||||
|     def chassicInfoAreaOffset(self, obj): | ||||
|         self._chassicInfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def productinfoAreaOffset(self): | ||||
|         return self._productinfoAreaOffset | ||||
|  | ||||
|     @productinfoAreaOffset.setter | ||||
|     def productinfoAreaOffset(self, obj): | ||||
|         self._productinfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def boardInfoAreaOffset(self): | ||||
|         return self._boardInfoAreaOffset | ||||
|  | ||||
|     @boardInfoAreaOffset.setter | ||||
|     def boardInfoAreaOffset(self, obj): | ||||
|         self._boardInfoAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def multiRecordAreaOffset(self): | ||||
|         return self._multiRecordAreaOffset | ||||
|  | ||||
|     @multiRecordAreaOffset.setter | ||||
|     def multiRecordAreaOffset(self, obj): | ||||
|         self._multiRecordAreaOffset = obj | ||||
|  | ||||
|     @property | ||||
|     def zeroCheckSum(self): | ||||
|         return self._zeroCheckSum | ||||
|  | ||||
|     @zeroCheckSum.setter | ||||
|     def zeroCheckSum(self, obj): | ||||
|         self._zeroCheckSum = obj | ||||
|  | ||||
|     @property | ||||
|     def productInfoArea(self): | ||||
|         return self._ProductInfoArea | ||||
|  | ||||
|     @productInfoArea.setter | ||||
|     def productInfoArea(self, obj): | ||||
|         self._ProductInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def internalUseArea(self): | ||||
|         return self._InternalUseArea | ||||
|  | ||||
|     @internalUseArea.setter | ||||
|     def internalUseArea(self, obj): | ||||
|         self.internalUseArea = obj | ||||
|  | ||||
|     @property | ||||
|     def boardInfoArea(self): | ||||
|         return self._BoardInfoArea | ||||
|  | ||||
|     @boardInfoArea.setter | ||||
|     def boardInfoArea(self, obj): | ||||
|         self._BoardInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def chassisInfoArea(self): | ||||
|         return self._ChassisInfoArea | ||||
|  | ||||
|     @chassisInfoArea.setter | ||||
|     def chassisInfoArea(self, obj): | ||||
|         self._ChassisInfoArea = obj | ||||
|  | ||||
|     @property | ||||
|     def multiRecordArea(self): | ||||
|         return self._multiRecordArea | ||||
|  | ||||
|     @multiRecordArea.setter | ||||
|     def multiRecordArea(self, obj): | ||||
|         self._multiRecordArea = obj | ||||
|  | ||||
|     @property | ||||
|     def bindata(self): | ||||
|         return self._bindata | ||||
|  | ||||
|     @bindata.setter | ||||
|     def bindata(self, obj): | ||||
|         self._bindata = obj | ||||
|  | ||||
|     @property | ||||
|     def bodybin(self): | ||||
|         return self._bodybin | ||||
|  | ||||
|     @bodybin.setter | ||||
|     def bodybin(self, obj): | ||||
|         self._bodybin = obj | ||||
|  | ||||
|     def recalcuteCommonHead(self): | ||||
|         self.bindata = "" | ||||
|         self.offset = self.SUGGESTED_SIZE_COMMON_HEADER | ||||
|         d_print("common Header %d" % self.offset) | ||||
|         d_print("fru eeprom size  %d" % self._frusize) | ||||
|         if self.internalUseArea is not None and self.internalUseArea.isPresent: | ||||
|             self.internalUserAreaOffset = self.offset // 8 | ||||
|             self.offset += self.internalUseArea.size | ||||
|             d_print("internalUseArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: | ||||
|             self.chassicInfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.chassisInfoArea.size | ||||
|             d_print("chassisInfoArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.boardInfoArea is not None and self.boardInfoArea.isPresent: | ||||
|             self.boardInfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.boardInfoArea.size | ||||
|             d_print("boardInfoArea is present offset:%d" % self.offset) | ||||
|             d_print("boardInfoArea is present size:%d" % | ||||
|                     self.boardInfoArea.size) | ||||
|  | ||||
|         if self.productInfoArea is not None and self.productInfoArea.isPresent: | ||||
|             self.productinfoAreaOffset = self.offset // 8 | ||||
|             self.offset += self.productInfoArea.size | ||||
|             d_print("productInfoArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.multiRecordArea is not None and self.multiRecordArea.isPresent: | ||||
|             self.multiRecordAreaOffset = self.offset // 8 | ||||
|             d_print("multiRecordArea is present offset:%d" % self.offset) | ||||
|  | ||||
|         if self.internalUserAreaOffset == self.INITVALUE: | ||||
|             self.internalUserAreaOffset = 0 | ||||
|         if self.productinfoAreaOffset == self.INITVALUE: | ||||
|             self.productinfoAreaOffset = 0 | ||||
|         if self.chassicInfoAreaOffset == self.INITVALUE: | ||||
|             self.chassicInfoAreaOffset = 0 | ||||
|         if self.boardInfoAreaOffset == self.INITVALUE: | ||||
|             self.boardInfoAreaOffset = 0 | ||||
|         if self.multiRecordAreaOffset == self.INITVALUE: | ||||
|             self.multiRecordAreaOffset = 0 | ||||
|  | ||||
|         self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset | ||||
|                              - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff | ||||
|         d_print("zerochecksum:%x" % self.zeroCheckSum) | ||||
|         self.data = "" | ||||
|         self.data += chr(self.version[0]) + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( | ||||
|             self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + chr(self.INITVALUE[0]) + chr(self.zeroCheckSum) | ||||
|  | ||||
|         self.bindata = self.data + self.bodybin | ||||
|         totallen = len(self.bindata) | ||||
|         d_print("totallen %d" % totallen) | ||||
|         if (totallen < self._frusize): | ||||
|             self.bindata = self.bindata.ljust(self._frusize, chr(self.INITVALUE[0])) | ||||
|         else: | ||||
|             raise FruException('bin data more than %d' % self._frusize, -2) | ||||
|  | ||||
|     def recalcutebin(self): | ||||
|         self.bodybin = "" | ||||
|         if self.internalUseArea is not None and self.internalUseArea.isPresent: | ||||
|             d_print("internalUseArea present") | ||||
|             self.bodybin += self.internalUseArea.data | ||||
|         if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: | ||||
|             d_print("chassisInfoArea present") | ||||
|             self.bodybin += self.chassisInfoArea.data | ||||
|         if self.boardInfoArea is not None and self.boardInfoArea.isPresent: | ||||
|             d_print("boardInfoArea present") | ||||
|             self.boardInfoArea.recalcute() | ||||
|             self.bodybin += self.boardInfoArea.data | ||||
|         if self.productInfoArea is not None and self.productInfoArea.isPresent: | ||||
|             d_print("productInfoAreapresent") | ||||
|             self.productInfoArea.recalcute() | ||||
|             self.bodybin += self.productInfoArea.data | ||||
|         if self.multiRecordArea is not None and self.multiRecordArea.isPresent: | ||||
|             d_print("multiRecordArea present") | ||||
|             self.bodybin += self.productInfoArea.data | ||||
|  | ||||
|     def recalcute(self, fru_eeprom_size=256): | ||||
|         self._frusize = fru_eeprom_size | ||||
|         self.recalcutebin() | ||||
|         self.recalcuteCommonHead() | ||||
| @@ -0,0 +1,449 @@ | ||||
| #!/usr/bin/python3 | ||||
| import binascii | ||||
|  | ||||
|  | ||||
| class OnietlvException(Exception): | ||||
|     def __init__(self, message='onietlverror', code=-100): | ||||
|         err = 'errcode: {0} message:{1}'.format(code, message) | ||||
|         Exception.__init__(self, err) | ||||
|         self.code = code | ||||
|         self.message = message | ||||
|  | ||||
|  | ||||
| class onie_tlv(object): | ||||
|     TLV_INFO_ID_STRING = "TlvInfo\x00" | ||||
|     TLV_INFO_INIA_ID = "\x00\x00\x13\x11" | ||||
|     TLV_INFO_VERSION = 0x01 | ||||
|     TLV_INFO_LENGTH = 0x00 | ||||
|     TLV_INFO_LENGTH_VALUE = 0xba | ||||
|  | ||||
|     TLV_CODE_PRODUCT_NAME = 0x21 | ||||
|     TLV_CODE_PART_NUMBER = 0x22 | ||||
|     TLV_CODE_SERIAL_NUMBER = 0x23 | ||||
|     TLV_CODE_MAC_BASE = 0x24 | ||||
|     TLV_CODE_MANUF_DATE = 0x25 | ||||
|     TLV_CODE_DEVICE_VERSION = 0x26 | ||||
|     TLV_CODE_LABEL_REVISION = 0x27 | ||||
|     TLV_CODE_PLATFORM_NAME = 0x28 | ||||
|     TLV_CODE_ONIE_VERSION = 0x29 | ||||
|     TLV_CODE_MAC_SIZE = 0x2A | ||||
|     TLV_CODE_MANUF_NAME = 0x2B | ||||
|     TLV_CODE_MANUF_COUNTRY = 0x2C | ||||
|     TLV_CODE_VENDOR_NAME = 0x2D | ||||
|     TLV_CODE_DIAG_VERSION = 0x2E | ||||
|     TLV_CODE_SERVICE_TAG = 0x2F | ||||
|     TLV_CODE_VENDOR_EXT = 0xFD | ||||
|     TLV_CODE_CRC_32 = 0xFE | ||||
|     _TLV_DISPLAY_VENDOR_EXT = 1 | ||||
|     TLV_CODE_RJ_CARID = 0x01 | ||||
|     _TLV_INFO_HDR_LEN = 11 | ||||
|     TLV_CODE_PRODUCT_ID = 0x40 | ||||
|     TLV_CODE_HW_VERSION = 0x41 | ||||
|     TLV_CODE_MAIN_FILENAME = 0x42 | ||||
|     TLV_CODE_DTS_FINENAME = 0x43 | ||||
|     TLV_CODE_SY_SERIAL0 = 0x44 | ||||
|     TLV_CODE_SY_SERIAL1 = 0x45 | ||||
|     TLV_CODE_SY_SERIAL2 = 0x46 | ||||
|     TLV_CODE_SY_SERIAL3 = 0x47 | ||||
|     TLV_CODE_PROJECT_ID = 0x48 | ||||
|     TLV_CODE_SETMAC_VERSION = 0x49 | ||||
|     TLV_CODE_EEPROM_TYPE = 0x4A | ||||
|  | ||||
|     @property | ||||
|     def dstatus(self): | ||||
|         return self._dstatus | ||||
|  | ||||
|     @property | ||||
|     def cardid(self): | ||||
|         return self._cardid | ||||
|  | ||||
|     @property | ||||
|     def productname(self): | ||||
|         return self._productname | ||||
|  | ||||
|     @property | ||||
|     def partnum(self): | ||||
|         return self._partnum | ||||
|  | ||||
|     @property | ||||
|     def serialnum(self): | ||||
|         return self._serialnum | ||||
|  | ||||
|     @property | ||||
|     def macbase(self): | ||||
|         return self._macbase | ||||
|  | ||||
|     @property | ||||
|     def manufdate(self): | ||||
|         return self._manufdate | ||||
|  | ||||
|     @property | ||||
|     def deviceversion(self): | ||||
|         return self._deviceversion | ||||
|  | ||||
|     @property | ||||
|     def labelrevision(self): | ||||
|         return self._labelrevision | ||||
|  | ||||
|     @property | ||||
|     def platformname(self): | ||||
|         return self._platformname | ||||
|  | ||||
|     @property | ||||
|     def onieversion(self): | ||||
|         return self._onieversion | ||||
|  | ||||
|     @property | ||||
|     def macsize(self): | ||||
|         return self._macsize | ||||
|  | ||||
|     @property | ||||
|     def manufname(self): | ||||
|         return self._manufname | ||||
|  | ||||
|     @property | ||||
|     def manufcountry(self): | ||||
|         return self._manufcountry | ||||
|  | ||||
|     @property | ||||
|     def vendorname(self): | ||||
|         return self._vendorname | ||||
|  | ||||
|     @property | ||||
|     def diagname(self): | ||||
|         return self._diagname | ||||
|  | ||||
|     @property | ||||
|     def servicetag(self): | ||||
|         return self._servicetag | ||||
|  | ||||
|     @property | ||||
|     def vendorext(self): | ||||
|         return self._vendorext | ||||
|  | ||||
|     @property | ||||
|     def fanbus(self): | ||||
|         return self._fanbus | ||||
|  | ||||
|     @property | ||||
|     def fanloc(self): | ||||
|         return self._fanloc | ||||
|  | ||||
|     def __init__(self): | ||||
|         self._cardid = "" | ||||
|         self._productname = "" | ||||
|         self._partnum = "" | ||||
|         self._serialnum = "" | ||||
|         self._macbase = "" | ||||
|         self._manufdate = "" | ||||
|         self._deviceversion = "" | ||||
|         self._labelrevision = "" | ||||
|         self._platformname = "" | ||||
|         self._onieversion = "" | ||||
|         self._macsize = "" | ||||
|         self._manufname = "" | ||||
|         self._manufcountry = "" | ||||
|         self._vendorname = "" | ||||
|         self._diagname = "" | ||||
|         self._servicetag = "" | ||||
|         self._vendorext = "" | ||||
|         self._productid = "" | ||||
|         self._hwversion = "" | ||||
|         self._mainfilename = "" | ||||
|         self._dtsfilename = "" | ||||
|         self._syserial0 = "" | ||||
|         self._syserial1 = "" | ||||
|         self._syserial2 = "" | ||||
|         self._syserial3 = "" | ||||
|         self._projectid = "" | ||||
|         self._setmacversion = "" | ||||
|         self._eepromtype = "" | ||||
|         self._crc32 = "" | ||||
|         self._dstatus = 0 | ||||
|  | ||||
|     def oniecrc32(self, v): | ||||
|         data_array = bytearray() | ||||
|         for x in v: | ||||
|             data_array.append(ord(x)) | ||||
|         return '0x%08x' % (binascii.crc32(bytes(data_array)) & 0xffffffff) | ||||
|  | ||||
|     def getTLV_BODY(self, type, value): | ||||
|         x = [] | ||||
|         temp_t = "" | ||||
|         if type == self.TLV_CODE_MAC_BASE: | ||||
|             arr = value.split(':') | ||||
|             for tt in arr: | ||||
|                 temp_t += chr(int(tt, 16)) | ||||
|         elif type == self.TLV_CODE_DEVICE_VERSION: | ||||
|             temp_t = chr(value) | ||||
|         elif type == self.TLV_CODE_MAC_SIZE: | ||||
|             temp_t = chr(value >> 8) + chr(value & 0x00ff) | ||||
|         else: | ||||
|             temp_t = value | ||||
|         x.append(chr(type)) | ||||
|         x.append(chr(len(temp_t))) | ||||
|         for i in temp_t: | ||||
|             x.append(i) | ||||
|         return x | ||||
|  | ||||
|     def generate_ext(self, cardid): | ||||
|         s = "%08x" % cardid | ||||
|         ret = "" | ||||
|         for t in range(0, 4): | ||||
|             ret += chr(int(s[2 * t:2 * t + 2], 16)) | ||||
|         ret = chr(0x01) + chr(len(ret)) + ret | ||||
|         return ret | ||||
|  | ||||
|     def generate_value(self, _t): | ||||
|         ret = [] | ||||
|         for i in self.TLV_INFO_ID_STRING: | ||||
|             ret.append(i) | ||||
|         ret.append(chr(self.TLV_INFO_VERSION)) | ||||
|         ret.append(chr(self.TLV_INFO_LENGTH)) | ||||
|         ret.append(chr(self.TLV_INFO_LENGTH_VALUE)) | ||||
|  | ||||
|         total_len = 0 | ||||
|         for key in _t: | ||||
|             x = self.getTLV_BODY(key, _t[key]) | ||||
|             ret += x | ||||
|             total_len += len(x) | ||||
|         ret[10] = chr(total_len + 6) | ||||
|  | ||||
|         ret.append(chr(0xFE)) | ||||
|         ret.append(chr(0x04)) | ||||
|         s = self.oniecrc32(''.join(ret)) | ||||
|         for t in range(0, 4): | ||||
|             ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) | ||||
|         totallen = len(ret) | ||||
|         if (totallen < 256): | ||||
|             for left_t in range(0, 256 - totallen): | ||||
|                 ret.append(chr(0x00)) | ||||
|         return (ret, True) | ||||
|  | ||||
|     def decode_tlv(self, e): | ||||
|         tlv_index = 0 | ||||
|         tlv_end = len(e) | ||||
|         ret = [] | ||||
|         while tlv_index < tlv_end and (tlv_index + 2 + ord(e[tlv_index + 1])) <= len(e): | ||||
|             rt = self.decoder(e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) | ||||
|             ret.append(rt) | ||||
|             if ord(e[tlv_index]) == self.TLV_CODE_CRC_32: | ||||
|                 break | ||||
|             tlv_index += ord(e[tlv_index + 1]) + 2 | ||||
|         return ret | ||||
|  | ||||
|     def decode(self, e): | ||||
|         if e[0:8] != self.TLV_INFO_ID_STRING: | ||||
|             raise OnietlvException("ONIE tlv head info error,not onie tlv type", -1) | ||||
|         total_len = (ord(e[9]) << 8) | ord(e[10]) | ||||
|         tlv_index = self._TLV_INFO_HDR_LEN | ||||
|         tlv_end = self._TLV_INFO_HDR_LEN + total_len | ||||
|         if tlv_end > len(e): | ||||
|             raise OnietlvException("ONIE tlv length error", -2) | ||||
|         ret = [] | ||||
|         ret = self.decode_tlv(e[tlv_index:tlv_end]) | ||||
|         for item in ret: | ||||
|             if item['code'] == self.TLV_CODE_VENDOR_EXT: | ||||
|                 if item["value"][0:4] == self.TLV_INFO_INIA_ID: | ||||
|                     rt = self.decode_tlv(item["value"][4:]) | ||||
|                 else: | ||||
|                     rt = self.decode_tlv(item["value"][0:]) | ||||
|                 ret.extend(rt) | ||||
|         return ret | ||||
|  | ||||
|     def decoder(self, t): | ||||
|         if ord(t[0]) == self.TLV_CODE_PRODUCT_NAME: | ||||
|             name = "Product Name" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._productname = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_PART_NUMBER: | ||||
|             name = "Part Number" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._partnum = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SERIAL_NUMBER: | ||||
|             name = "Serial Number" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._serialnum = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_MAC_BASE: | ||||
|             name = "Base MAC Address" | ||||
|             _len = ord(t[1]) | ||||
|             value = ":".join(['%02X' % ord(T) for T in t[2:8]]).upper() | ||||
|             self._macbase = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_MANUF_DATE: | ||||
|             name = "Manufacture Date" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._manufdate = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_DEVICE_VERSION: | ||||
|             name = "Device Version" | ||||
|             _len = ord(t[1]) | ||||
|             value = ord(t[2]) | ||||
|             self._deviceversion = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_LABEL_REVISION: | ||||
|             name = "Label Revision" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._labelrevision = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_PLATFORM_NAME: | ||||
|             name = "Platform Name" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._platformname = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_ONIE_VERSION: | ||||
|             name = "ONIE Version" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._onieversion = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_MAC_SIZE: | ||||
|             name = "MAC Addresses" | ||||
|             _len = ord(t[1]) | ||||
|             value = str((ord(t[2]) << 8) | ord(t[3])) | ||||
|             self._macsize = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_MANUF_NAME: | ||||
|             name = "Manufacturer" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._manufname = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_MANUF_COUNTRY: | ||||
|             name = "Manufacture Country" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._manufcountry = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_VENDOR_NAME: | ||||
|             name = "Vendor Name" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._vendorname = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_DIAG_VERSION: | ||||
|             name = "Diag Version" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._diagname = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SERVICE_TAG: | ||||
|             name = "Service Tag" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._servicetag = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_VENDOR_EXT: | ||||
|             name = "Vendor Extension" | ||||
|             _len = ord(t[1]) | ||||
|             value = "" | ||||
|             if self._TLV_DISPLAY_VENDOR_EXT: | ||||
|                 value = t[2:2 + ord(t[1])] | ||||
|             self._vendorext = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_CRC_32 and len(t) == 6: | ||||
|             name = "CRC-32" | ||||
|             _len = ord(t[1]) | ||||
|             value = "0x%08X" % (((ord(t[2]) << 24) | ( | ||||
|                 ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) | ||||
|             self._crc32 = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_RJ_CARID: | ||||
|             name = "Card id" | ||||
|             _len = ord(t[1]) | ||||
|             value = "" | ||||
|             for c in t[2:2 + ord(t[1])]: | ||||
|                 value += "%02X" % (ord(c),) | ||||
|             self._cardid = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_PRODUCT_ID: | ||||
|             name = "Product id" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._productid = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_HW_VERSION: | ||||
|             name = "Hardware Version" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._hwversion = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_MAIN_FILENAME: | ||||
|             name = "Main File Name" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._mainfilename = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_DTS_FINENAME: | ||||
|             name = "DTS File Name" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._dtsfilename = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SY_SERIAL0: | ||||
|             name = "SY Serial 0" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._syserial0 = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SY_SERIAL1: | ||||
|             name = "SY Serial 1" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._syserial1 = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SY_SERIAL2: | ||||
|             name = "SY Serial 2" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._syserial2 = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SY_SERIAL3: | ||||
|             name = "SY Serial 3" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._syserial3 = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_PROJECT_ID: | ||||
|             name = "Project id" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._projectid = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_SETMAC_VERSION: | ||||
|             name = "Setmac Version" | ||||
|             _len = ord(t[1]) | ||||
|             value = t[2:2 + ord(t[1])] | ||||
|             self._setmacversion = value | ||||
|         elif ord(t[0]) == self.TLV_CODE_EEPROM_TYPE: | ||||
|             name = "EEPROM Type" | ||||
|             _len = ord(t[1]) | ||||
|             value = "" | ||||
|             for c in t[2:2 + ord(t[1])]: | ||||
|                 value += "%02X" % (ord(c),) | ||||
|             self._eepromtype = value | ||||
|         else: | ||||
|             name = "Unknown" | ||||
|             _len = ord(t[1]) | ||||
|             value = "" | ||||
|             for c in t[2:2 + ord(t[1])]: | ||||
|                 value += "0x%02X " % (ord(c),) | ||||
|         return {"name": name, "code": ord(t[0]), "value": value, "lens": _len} | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr = "Card id              : %s      \n" \ | ||||
|                     "Product Name         : %s      \n" \ | ||||
|                     "Part Number          : %s      \n" \ | ||||
|                     "Serial Number        : %s      \n" \ | ||||
|                     "Base MAC Address     : %s      \n" \ | ||||
|                     "Manufacture Date     : %s      \n" \ | ||||
|                     "Device Version       : %s      \n" \ | ||||
|                     "Label Revision       : %s      \n" \ | ||||
|                     "Platform Name        : %s      \n" \ | ||||
|                     "ONIE Version         : %s      \n" \ | ||||
|                     "MAC Addresses        : %s      \n" \ | ||||
|                     "Manufacturer         : %s      \n" \ | ||||
|                     "Manufacture Country  : %s      \n" \ | ||||
|                     "Vendor Name          : %s      \n" \ | ||||
|                     "Diag Version         : %s      \n" \ | ||||
|                     "Service Tag          : %s      \n" \ | ||||
|                     "CRC-32               : %s      \n" | ||||
|         return formatstr % (self._cardid, | ||||
|                             self._productname, | ||||
|                             self._partnum, | ||||
|                             self._serialnum, | ||||
|                             self._macbase, | ||||
|                             self._manufdate, | ||||
|                             self._deviceversion, | ||||
|                             self._labelrevision, | ||||
|                             self._platformname, | ||||
|                             self._onieversion, | ||||
|                             self._macsize, | ||||
|                             self._manufname, | ||||
|                             self._manufcountry, | ||||
|                             self._vendorname, | ||||
|                             self._diagname, | ||||
|                             self._servicetag, | ||||
|                             self._crc32) | ||||
							
								
								
									
										141
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/baseutil.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										141
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/baseutil.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # baseutil.py | ||||
| # Python implementation of the Class baseutil | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| import importlib.machinery | ||||
| import os | ||||
| import syslog | ||||
| from plat_hal.osutil import osutil | ||||
|  | ||||
| SYSLOG_IDENTIFIER = "HAL" | ||||
|  | ||||
| CONFIG_DB_PATH = "/etc/sonic/config_db.json" | ||||
| BOARD_ID_PATH = "/sys/module/ruijie_common/parameters/dfd_my_type" | ||||
|  | ||||
|  | ||||
| def getonieplatform(path): | ||||
|     if not os.path.isfile(path): | ||||
|         return "" | ||||
|     machine_vars = {} | ||||
|     with open(path) as machine_file: | ||||
|         for line in machine_file: | ||||
|             tokens = line.split('=') | ||||
|             if len(tokens) < 2: | ||||
|                 continue | ||||
|             machine_vars[tokens[0]] = tokens[1].strip() | ||||
|     return machine_vars.get("onie_platform") | ||||
|  | ||||
|  | ||||
| def getboardid(): | ||||
|     if not os.path.exists(BOARD_ID_PATH): | ||||
|         return "NA" | ||||
|     with open(BOARD_ID_PATH) as fd: | ||||
|         id_str = fd.read().strip() | ||||
|     return "0x%x" % (int(id_str, 10)) | ||||
|  | ||||
|  | ||||
| def getplatform_config_db(): | ||||
|     if not os.path.isfile(CONFIG_DB_PATH): | ||||
|         return "" | ||||
|     val = os.popen("sonic-cfggen -j %s -v DEVICE_METADATA.localhost.platform" % CONFIG_DB_PATH).read().strip() | ||||
|     if len(val) <= 0: | ||||
|         return "" | ||||
|     else: | ||||
|         return val | ||||
|  | ||||
|  | ||||
| def getplatform_name(): | ||||
|     if os.path.isfile('/host/machine.conf'): | ||||
|         return getonieplatform('/host/machine.conf') | ||||
|     elif os.path.isfile('/usr/share/sonic/hwsku/machine.conf'): | ||||
|         return getonieplatform('/usr/share/sonic/hwsku/machine.conf') | ||||
|     else: | ||||
|         return getplatform_config_db() | ||||
|  | ||||
|  | ||||
| CONFIG_FILE_LIST = ["/usr/local/bin/", "/usr/lib/python3/dist-packages/", "/usr/local/lib/python3.7/dist-packages/hal-config/", "/usr/local/lib/python3.9/dist-packages/hal-config/"] | ||||
|  | ||||
| platform = (getplatform_name()).replace("-", "_") | ||||
| boardid = getboardid() | ||||
|  | ||||
| boardid_devicefile = (platform + "_"+ boardid + "_device.py") | ||||
| boardid_monitorfile = (platform + "_"+ boardid + "_monitor.py") | ||||
|  | ||||
| devicefile = (platform + "_device.py") | ||||
| monitorfile = (platform + "_monitor.py") | ||||
|  | ||||
|  | ||||
| class baseutil: | ||||
|  | ||||
|     CONFIG_NAME = 'devices' | ||||
|     MONITOR_CONFIG_NAME = 'monitor' | ||||
|     UBOOT_ENV_URL = '/etc/device/uboot_env' | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_config(): | ||||
|         real_path = None | ||||
|         for configfile_path in CONFIG_FILE_LIST: | ||||
|             boardid_config_file_path = (configfile_path + boardid_devicefile) | ||||
|             config_file_path = (configfile_path + devicefile) | ||||
|             if os.path.exists(boardid_config_file_path): | ||||
|                 real_path = boardid_config_file_path | ||||
|                 break | ||||
|             elif os.path.exists(config_file_path): | ||||
|                 real_path = config_file_path | ||||
|                 break | ||||
|         if real_path is None: | ||||
|             raise Exception("get hal device config error") | ||||
|         devices = importlib.machinery.SourceFileLoader(baseutil.CONFIG_NAME, real_path).load_module() | ||||
|         return devices.devices | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_monitor_config(): | ||||
|         real_path = None | ||||
|         for configfile_path in CONFIG_FILE_LIST: | ||||
|             boardid_config_file_path = (configfile_path + boardid_monitorfile) | ||||
|             config_file_path = (configfile_path + monitorfile) | ||||
|             if os.path.exists(boardid_config_file_path): | ||||
|                 real_path = boardid_config_file_path | ||||
|                 break | ||||
|             elif os.path.exists(config_file_path): | ||||
|                 real_path = config_file_path | ||||
|                 break | ||||
|         if real_path is None: | ||||
|             raise Exception("get hal monitor config error") | ||||
|         monitor = importlib.machinery.SourceFileLoader(baseutil.MONITOR_CONFIG_NAME, real_path).load_module() | ||||
|         return monitor.monitor | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_productname(): | ||||
|         ret, val = osutil.command("cat %s |grep productname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL) | ||||
|         tmp = val.lower().replace('-', '_') | ||||
|         if ret != 0 or len(val) <= 0: | ||||
|             raise Exception("get productname error") | ||||
|         else: | ||||
|             return tmp | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_platform(): | ||||
|         ret, val = osutil.command("cat %s |grep conffitname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL) | ||||
|         if ret != 0 or len(val) <= 0: | ||||
|             raise Exception("get platform error") | ||||
|         else: | ||||
|             return val | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_product_fullname(): | ||||
|         ret, val = osutil.command("cat %s |grep productname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL) | ||||
|         if ret != 0 or len(val) <= 0: | ||||
|             raise Exception("get productname error") | ||||
|         else: | ||||
|             return val | ||||
|  | ||||
|     @staticmethod | ||||
|     def logger_debug(msg): | ||||
|         syslog.openlog(SYSLOG_IDENTIFIER) | ||||
|         syslog.syslog(syslog.LOG_DEBUG, msg) | ||||
|         syslog.closelog() | ||||
| @@ -0,0 +1,322 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # chassisbase.py | ||||
| # Python implementation of the Class chassisbase | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.dcdc import dcdc | ||||
| from plat_hal.onie_e2 import onie_e2 | ||||
| from plat_hal.psu import psu | ||||
| from plat_hal.led import led | ||||
| from plat_hal.temp import temp | ||||
| from plat_hal.fan import fan | ||||
| from plat_hal.cpld import cpld | ||||
| from plat_hal.component import component | ||||
| from plat_hal.cpu import cpu | ||||
| from plat_hal.baseutil import baseutil | ||||
|  | ||||
|  | ||||
| class chassisbase(object): | ||||
|     __onie_e2_list = [] | ||||
|     __psu_list = [] | ||||
|     __led_list = [] | ||||
|     __temp_list = [] | ||||
|     __fan_list = [] | ||||
|     __card_list = [] | ||||
|     __sensor_list = [] | ||||
|     __dcdc_list = [] | ||||
|     __cpld_list = [] | ||||
|     __comp_list = [] | ||||
|     __bios_list = [] | ||||
|     __bmc_list = [] | ||||
|     __cpu = None | ||||
|  | ||||
|     def __init__(self, conftype=0, conf=None): | ||||
|         # type: (object, object, object) -> object | ||||
|         """ | ||||
|         init chassisbase as order | ||||
|  | ||||
|         type  = 0  use default conf, maybe auto find by platform | ||||
|         type  = 1  use given conf,  conf is not None | ||||
|  | ||||
|         BITMAP | ||||
|               bit 16 | ||||
|                       bit 0    PSU | ||||
|                       bit 1    LED | ||||
|                       bit 2    TEMP | ||||
|                       bit 3    fan | ||||
|                       bit 4    card | ||||
|                       bit 5    sensor | ||||
|         """ | ||||
|         __confTemp = None | ||||
|  | ||||
|         if conftype == 0: | ||||
|             # user | ||||
|             __confTemp = baseutil.get_config() | ||||
|         elif conftype == 1: | ||||
|             __confTemp = conf | ||||
|  | ||||
|         # onie_e2 | ||||
|         onie_e2temp = [] | ||||
|         onie_e2config = __confTemp.get('onie_e2', []) | ||||
|         for i in range(len((onie_e2config))): | ||||
|             onie_e2_1 = onie_e2(onie_e2config[i]) | ||||
|             onie_e2temp.append(onie_e2_1) | ||||
|         self.onie_e2_list = onie_e2temp | ||||
|  | ||||
|         # psu | ||||
|         psutemp = [] | ||||
|         psuconfig = __confTemp.get('psus', []) | ||||
|         for i in range(len((psuconfig))): | ||||
|             psu1 = psu(psuconfig[i]) | ||||
|             psutemp.append(psu1) | ||||
|         self.psu_list = psutemp | ||||
|  | ||||
|         # led | ||||
|         ledtemp = [] | ||||
|         ledconfig = __confTemp.get('leds', []) | ||||
|         for i in range(len((ledconfig))): | ||||
|             led1 = led(ledconfig[i]) | ||||
|             ledtemp.append(led1) | ||||
|         self.led_list = ledtemp | ||||
|  | ||||
|         # temp | ||||
|         temptemp = [] | ||||
|         tempconfig = __confTemp.get('temps', []) | ||||
|         for i in range(len((tempconfig))): | ||||
|             temp1 = temp(tempconfig[i]) | ||||
|             temptemp.append(temp1) | ||||
|         self.temp_list = temptemp | ||||
|  | ||||
|         # fan | ||||
|         fantemp = [] | ||||
|         fanconfig = __confTemp.get('fans', []) | ||||
|         for i in range(len((fanconfig))): | ||||
|             fan1 = fan(fanconfig[i]) | ||||
|             fantemp.append(fan1) | ||||
|         self.fan_list = fantemp | ||||
|  | ||||
|         # dcdc | ||||
|         dcdctemp = [] | ||||
|         dcdcconfig = __confTemp.get('dcdc', []) | ||||
|         for i in dcdcconfig: | ||||
|             dcdc1 = dcdc(i) | ||||
|             dcdctemp.append(dcdc1) | ||||
|         self.dcdc_list = dcdctemp | ||||
|  | ||||
|         # cpld | ||||
|         cpldtemp = [] | ||||
|         cpldconfig = __confTemp.get('cplds', []) | ||||
|         for i in range(len((cpldconfig))): | ||||
|             cpld1 = cpld(cpldconfig[i]) | ||||
|             cpldtemp.append(cpld1) | ||||
|         self.cpld_list = cpldtemp | ||||
|  | ||||
|         # compoment: cpld/fpga/bios | ||||
|         comptemp = [] | ||||
|         compconfig = __confTemp.get('comp_cpld', []) | ||||
|         for i in range(len((compconfig))): | ||||
|             comp1 = component(compconfig[i]) | ||||
|             comptemp.append(comp1) | ||||
|         self.comp_list = comptemp | ||||
|  | ||||
|         compconfig = __confTemp.get('comp_fpga', []) | ||||
|         for i in range(len((compconfig))): | ||||
|             comp1 = component(compconfig[i]) | ||||
|             self.comp_list.append(comp1) | ||||
|  | ||||
|         compconfig = __confTemp.get('comp_bios', []) | ||||
|         for i in range(len((compconfig))): | ||||
|             comp1 = component(compconfig[i]) | ||||
|             self.comp_list.append(comp1) | ||||
|  | ||||
|         # cpu | ||||
|         cpuconfig = __confTemp.get('cpu', []) | ||||
|         if len(cpuconfig): | ||||
|             self.cpu = cpu(cpuconfig[0]) | ||||
|  | ||||
|     # dcdc | ||||
|     @property | ||||
|     def dcdc_list(self): | ||||
|         return self.__dcdc_list | ||||
|  | ||||
|     @dcdc_list.setter | ||||
|     def dcdc_list(self, val): | ||||
|         self.__dcdc_list = val | ||||
|  | ||||
|     # sensor | ||||
|     @property | ||||
|     def sensor_list(self): | ||||
|         return self.__sensor_list | ||||
|  | ||||
|     @sensor_list.setter | ||||
|     def sensor_list(self, val): | ||||
|         self.__sensor_list = val | ||||
|  | ||||
|     def get_sensor_byname(self, name): | ||||
|         tmp = self.sensor_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # onie_e2 | ||||
|     @property | ||||
|     def onie_e2_list(self): | ||||
|         return self.__onie_e2_list | ||||
|  | ||||
|     @onie_e2_list.setter | ||||
|     def onie_e2_list(self, val): | ||||
|         self.__onie_e2_list = val | ||||
|  | ||||
|     def get_onie_e2_byname(self, name): | ||||
|         tmp = self.onie_e2_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # psu | ||||
|     @property | ||||
|     def psu_list(self): | ||||
|         return self.__psu_list | ||||
|  | ||||
|     @psu_list.setter | ||||
|     def psu_list(self, val): | ||||
|         self.__psu_list = val | ||||
|  | ||||
|     def get_psu_byname(self, name): | ||||
|         tmp = self.psu_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # fan | ||||
|     @property | ||||
|     def fan_list(self): | ||||
|         return self.__fan_list | ||||
|  | ||||
|     @fan_list.setter | ||||
|     def fan_list(self, val): | ||||
|         self.__fan_list = val | ||||
|  | ||||
|     def get_fan_byname(self, name): | ||||
|         tmp = self.fan_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # led | ||||
|  | ||||
|     @property | ||||
|     def led_list(self): | ||||
|         return self.__led_list | ||||
|  | ||||
|     @led_list.setter | ||||
|     def led_list(self, val): | ||||
|         self.__led_list = val | ||||
|  | ||||
|     def get_ledlist_config(self): | ||||
|         pass | ||||
|  | ||||
|     def get_led_byname(self, name): | ||||
|         tmp = self.led_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # temp | ||||
|     @property | ||||
|     def temp_list(self): | ||||
|         return self.__temp_list | ||||
|  | ||||
|     @temp_list.setter | ||||
|     def temp_list(self, val): | ||||
|         self.__temp_list = val | ||||
|  | ||||
|     def get_temp_byname(self, name): | ||||
|         tmp = self.temp_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # cpld | ||||
|     @property | ||||
|     def cpld_list(self): | ||||
|         return self.__cpld_list | ||||
|  | ||||
|     @cpld_list.setter | ||||
|     def cpld_list(self, val): | ||||
|         self.__cpld_list = val | ||||
|  | ||||
|     def get_cpld_byname(self, name): | ||||
|         tmp = self.cpld_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     @property | ||||
|     def comp_list(self): | ||||
|         return self.__comp_list | ||||
|  | ||||
|     @comp_list.setter | ||||
|     def comp_list(self, val): | ||||
|         self.__comp_list = val | ||||
|  | ||||
|     def get_comp_byname(self, name): | ||||
|         tmp = self.comp_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # bios | ||||
|     @property | ||||
|     def bios_list(self): | ||||
|         return self.__bios_list | ||||
|  | ||||
|     @bios_list.setter | ||||
|     def bios_list(self, val): | ||||
|         self.__bios_list = val | ||||
|  | ||||
|     def get_bios_byname(self, name): | ||||
|         tmp = self.bios_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # bmc | ||||
|     @property | ||||
|     def bmc_list(self): | ||||
|         return self.__bmc_list | ||||
|  | ||||
|     @bmc_list.setter | ||||
|     def bmc_list(self, val): | ||||
|         self.__bmc_list = val | ||||
|  | ||||
|     def get_bmc_byname(self, name): | ||||
|         tmp = self.bmc_list | ||||
|         for i in range(len(tmp)): | ||||
|             if name == tmp[i].name: | ||||
|                 return tmp[i] | ||||
|         return None | ||||
|  | ||||
|     # cpu | ||||
|     @property | ||||
|     def cpu(self): | ||||
|         return self.__cpu | ||||
|  | ||||
|     @cpu.setter | ||||
|     def cpu(self, val): | ||||
|         self.__cpu = val | ||||
|  | ||||
|     def get_cpu_byname(self, name): | ||||
|         return self.cpu | ||||
| @@ -0,0 +1,33 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # component.py | ||||
| # Python implementation of the Class fan | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
| from plat_hal.osutil import osutil | ||||
|  | ||||
| class component(devicebase): | ||||
|     __user_reg = None | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.version_file = conf.get('VersionFile', None) | ||||
|             self.comp_id = conf.get("comp_id", None) | ||||
|             self.desc = conf.get("desc", None) | ||||
|             self.slot = conf.get("slot", None) | ||||
|  | ||||
|     def get_version(self): | ||||
|         version = "NA" | ||||
|         try: | ||||
|             ret, version = self.get_value(self.version_file) | ||||
|             if (ret == False): | ||||
|                 return version | ||||
|             pattern = self.version_file.get('pattern', None) | ||||
|             version = osutil.std_match(version, pattern) | ||||
|         except Exception as e: | ||||
|             return version | ||||
|         return version | ||||
							
								
								
									
										63
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/cpld.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										63
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/cpld.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # fan.py | ||||
| # Python implementation of the Class fan | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
|  | ||||
|  | ||||
| class cpld(devicebase): | ||||
|     __user_reg = None | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.user_reg = conf.get('UserReg', None) | ||||
|             self.console_reg = conf.get('ConsoleReg', None) | ||||
|             self.console_reg_attrs = conf.get('ConsoleRegAttrs', None) | ||||
|             self.version_file = conf.get('VersionFile', None) | ||||
|             self.cpld_id = conf.get("cpld_id", None) | ||||
|             self.desc = conf.get("desc", None) | ||||
|             self.slot = conf.get("slot", None) | ||||
|             self.format = conf.get("format", "big_endian") | ||||
|  | ||||
|     def get_user_reg(self): | ||||
|         if (self.user_reg is None): | ||||
|             return False | ||||
|         ret, val = self.get_value(self.user_reg) | ||||
|         return val | ||||
|  | ||||
|     def set_user_reg(self, value): | ||||
|         if (self.user_reg is None): | ||||
|             return False | ||||
|         byte = value & 0xFF | ||||
|         ret, val = self.set_value(self.user_reg, byte) | ||||
|         return ret | ||||
|  | ||||
|     def set_console_owner(self, owner): | ||||
|         ret = False | ||||
|  | ||||
|         if (self.console_reg is None): | ||||
|             return False | ||||
|         tmpattr = self.console_reg_attrs.get(owner, None) | ||||
|         if tmpattr is not None: | ||||
|             ret, val = self.set_value(self.console_reg, tmpattr) | ||||
|         return ret | ||||
|  | ||||
|     def get_version(self): | ||||
|         ret, val = self.get_value(self.version_file) | ||||
|         if (ret == False): | ||||
|             val = "N/A" | ||||
|             return val | ||||
|         val = val.strip('\n').split(" ") | ||||
|         if len(val) < 4: | ||||
|             val = "N/A" | ||||
|             return val | ||||
|         if self.format == "little_endian": | ||||
|             cpld_version = "%s%s%s%s" % (val[3], val[2], val[1], val[0]) | ||||
|         else: | ||||
|             cpld_version = "%s%s%s%s" % (val[0], val[1], val[2], val[3]) | ||||
|         return cpld_version | ||||
							
								
								
									
										36
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/cpu.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										36
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/cpu.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ############################################################################### | ||||
| # | ||||
| # Hardware Abstraction Layer APIs -- CPU APIs. | ||||
| # | ||||
| # Copyright (C) Ruijie, INC. | ||||
| # | ||||
| ############################################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
|  | ||||
|  | ||||
| class cpu(devicebase): | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.cpu_reset_cnt_reg = conf.get('CpuResetCntReg', None) | ||||
|  | ||||
|     def get_cpu_reset_num(self): | ||||
|         """ | ||||
|         get cpu reset num. | ||||
|         @return cpu reset number, -1 for failure | ||||
|         """ | ||||
|         ret = -1 | ||||
|         if self.cpu_reset_cnt_reg is None: | ||||
|             self.logger_debug("ERR: no support get cpu reset num") | ||||
|             return ret | ||||
|         ret, reset_num = self.get_value(self.cpu_reset_cnt_reg) | ||||
|         if ret is False or reset_num is None: | ||||
|             self.logger_debug("ERR: i2c read cpu_reset_cnt_reg,result:%s" % reset_num) | ||||
|         else: | ||||
|             if isinstance(reset_num, str): | ||||
|                 ret = int(reset_num, 16) | ||||
|             else: | ||||
|                 ret = reset_num | ||||
|         return ret | ||||
							
								
								
									
										11
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/dcdc.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/dcdc.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #!/usr/bin/env python3 | ||||
| from plat_hal.devicebase import devicebase | ||||
| from plat_hal.sensor import sensor | ||||
|  | ||||
|  | ||||
| class dcdc(devicebase): | ||||
|     def __init__(self, conf=None): | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.dcdc_id = conf.get("dcdc_id", None) | ||||
|             self.sensor = sensor(conf) | ||||
| @@ -0,0 +1,223 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # devicebase.py | ||||
| # Python implementation of the Class devicebase | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.osutil import osutil | ||||
| from plat_hal.baseutil import baseutil | ||||
| import subprocess | ||||
|  | ||||
|  | ||||
| class devicebase(object): | ||||
|     _name = None | ||||
|     __error_ret = -99999 | ||||
|  | ||||
|     @property | ||||
|     def name(self): | ||||
|         return self._name | ||||
|  | ||||
|     @name.setter | ||||
|     def name(self, val): | ||||
|         self._name = val | ||||
|  | ||||
|     def dumpValueByI2c(self, bus, loc): | ||||
|         str = "" | ||||
|         for i in range(256): | ||||
|             ret, val = self.get_i2c(bus, loc, i) | ||||
|             str += chr(val) | ||||
|         return str | ||||
|  | ||||
|     def byteTostr(self, val): | ||||
|         strtmp = '' | ||||
|         for i in range(len(val)): | ||||
|             strtmp += chr(val[i]) | ||||
|         return strtmp | ||||
|  | ||||
|     def get_eeprom_info(self, conf): | ||||
|         if conf.get('way') == 'sysfs' or conf.get('way') == 'devfile': | ||||
|             ret, eeprom = self.get_value(conf) | ||||
|             if ret is False: | ||||
|                 return None | ||||
|         else: | ||||
|             eeprom = self.dumpValueByI2c(conf.get('bus'), conf.get('addr')) | ||||
|         return eeprom | ||||
|  | ||||
|     def exec_os_cmd(self, cmd): | ||||
|         proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) | ||||
|         stdout = proc.communicate()[0] | ||||
|         proc.wait() | ||||
|         return proc.returncode, stdout | ||||
|  | ||||
|     def get_value(self, config): | ||||
|         ''' | ||||
|             get value by config way | ||||
|             way  i2c/sysfs/lpc | ||||
|         ''' | ||||
|         way = config.get("way") | ||||
|         if way == 'sysfs': | ||||
|             return self.get_sysfs(config.get("loc"), config.get("flock_path")) | ||||
|         elif way == "i2c": | ||||
|             bus = config.get("bus") | ||||
|             addr = config.get("addr") | ||||
|             offset = config.get("offset") | ||||
|             return self.get_i2c(bus, addr, offset) | ||||
|         elif way == "io": | ||||
|             io_addr = config.get('io_addr') | ||||
|             read_len = config.get('read_len', 1) | ||||
|             return self.get_io(io_addr, read_len) | ||||
|         elif way == "i2cword": | ||||
|             bus = config.get("bus") | ||||
|             addr = config.get("addr") | ||||
|             offset = config.get("offset") | ||||
|             return self.get_i2cword(bus, addr, offset) | ||||
|         elif way == "devmem": | ||||
|             addr = config.get("addr") | ||||
|             digit = config.get("digit") | ||||
|             mask = config.get("mask", None) | ||||
|             return self.get_devmem(addr, digit, mask) | ||||
|         elif way == "sdk": | ||||
|             type = config.get("type") | ||||
|             if type == "bcm_temp": | ||||
|                 return self.getbcmtemp() | ||||
|             elif type == "bcm_reg": | ||||
|                 reg = config.get("reg") | ||||
|                 return self.getbcmreg(reg) | ||||
|             else: | ||||
|                 raise Exception("cannot found sdk type deal") | ||||
|         elif way == "devfile": | ||||
|             loc = config.get("loc") | ||||
|             offset = config.get("offset") | ||||
|             len = config.get("len") | ||||
|             return self.devfile_read(loc, offset, len) | ||||
|         elif way == "devfile_ascii": | ||||
|             loc = config.get("loc") | ||||
|             offset = config.get("offset") | ||||
|             len = config.get("len") | ||||
|             return self.devfile_read_ascii(loc, offset, len) | ||||
|         elif way == 'cmd': | ||||
|             cmd = config.get("cmd") | ||||
|             ret, log = self.exec_os_cmd(cmd) | ||||
|             if ret: | ||||
|                 return False, ("cmd write exec %s failed, log: %s" % (cmd, log)) | ||||
|             else: | ||||
|                 return True, log | ||||
|         else: | ||||
|             raise Exception("cannot found way deal") | ||||
|  | ||||
|     def devfile_read(self, loc, offset, len): | ||||
|         return osutil.readdevfile(loc, offset, len) | ||||
|  | ||||
|     def devfile_read_ascii(self, loc, offset, len): | ||||
|         return osutil.readdevfile_ascii(loc, offset, len) | ||||
|  | ||||
|     def get_sysfs(self, loc, flock_path=None): | ||||
|         return self.getsysfs(loc, flock_path) | ||||
|  | ||||
|     def getsysfs(self, loc, flock_path=None): | ||||
|         ret, val = osutil.readsysfs(loc, flock_path) | ||||
|         return ret, val | ||||
|  | ||||
|     def get_devmem(self, addr, digit, mask): | ||||
|         return osutil.getdevmem(addr, digit, mask) | ||||
|  | ||||
|     def get_i2cword(self, bus, addr, offset): | ||||
|         return self.geti2cword(bus, addr, offset) | ||||
|  | ||||
|     def geti2cword(self, bus, addr, offset): | ||||
|         ret, val = osutil.geti2cword(bus, addr, offset) | ||||
|         return ret, val | ||||
|  | ||||
|     def get_io(self, reg_addr, read_len): | ||||
|         return self.getio(reg_addr, read_len) | ||||
|  | ||||
|     def getio(self, reg_addr, read_len): | ||||
|         ret, val = osutil.io_rd(reg_addr, read_len) | ||||
|         return ret, val | ||||
|  | ||||
|     def get_i2c(self, bus, addr, offset): | ||||
|         return self.geti2c(bus, addr, offset) | ||||
|  | ||||
|     def geti2c(self, bus, addr, offset): | ||||
|         ret, val = osutil.rji2cget(bus, addr, offset) | ||||
|         return ret, val | ||||
|  | ||||
|     def set_value(self, config, val): | ||||
|         ''' | ||||
|             get value by config way | ||||
|             way  i2c/sysfs/lpc | ||||
|         ''' | ||||
|         way = config.get("way") | ||||
|         if way == 'sysfs': | ||||
|             return self.set_sysfs(config.get("loc"), "0x%02x" % val) | ||||
|         elif way == "i2c": | ||||
|             bus = config.get("bus") | ||||
|             addr = config.get("addr") | ||||
|             offset = config.get("offset") | ||||
|             return self.set_i2c(bus, addr, offset, val) | ||||
|         elif way == "i2cpec": | ||||
|             bus = config.get("bus") | ||||
|             addr = config.get("addr") | ||||
|             offset = config.get("offset") | ||||
|             return self.seti2c_byte_pec(bus, addr, offset, val) | ||||
|         elif way == 'i2cword': | ||||
|             bus = config.get("bus") | ||||
|             addr = config.get("addr") | ||||
|             offset = config.get("offset") | ||||
|             return self.set_i2cword(bus, addr, offset, val) | ||||
|         elif way == "i2cwordpec": | ||||
|             bus = config.get("bus") | ||||
|             addr = config.get("addr") | ||||
|             offset = config.get("offset") | ||||
|             return self.set_i2cwordpec(bus, addr, offset, val) | ||||
|         return False, "unsupport ways: %s" % way | ||||
|  | ||||
|     def set_sysfs(self, loc, value): | ||||
|         return self.setsysfs(loc, value) | ||||
|  | ||||
|     def setsysfs(self, loc, value): | ||||
|         return osutil.writesysfs(loc, value) | ||||
|  | ||||
|     def set_i2cword(self, bus, addr, offset, byte): | ||||
|         return self.seti2cword(bus, addr, offset, byte) | ||||
|  | ||||
|     def seti2cword(self, bus, addr, offset, byte): | ||||
|         return osutil.seti2cword(bus, addr, offset, byte) | ||||
|  | ||||
|     def set_i2cwordpec(self, bus, addr, offset, val): | ||||
|         return osutil.seti2cwordpec(bus, addr, offset, val) | ||||
|  | ||||
|     def seti2c_byte_pec(self, bus, addr, offset, val): | ||||
|         return osutil.seti2c_byte_pec(bus, addr, offset, val) | ||||
|  | ||||
|     def set_i2c(self, bus, addr, offset, byte): | ||||
|         return self.seti2c(bus, addr, offset, byte) | ||||
|  | ||||
|     def seti2c(self, bus, addr, offset, byte): | ||||
|         ret, val = osutil.rji2cset(bus, addr, offset, byte) | ||||
|         return ret, val | ||||
|  | ||||
|     def getbcmtemp(self): | ||||
|         try: | ||||
|             sta, ret = osutil.getmactemp() | ||||
|             if sta == True: | ||||
|                 mac_aver = float(ret.get("average", self.__error_ret)) | ||||
|                 mac_aver = mac_aver * 1000 | ||||
|             else: | ||||
|                 return False, ret | ||||
|         except AttributeError as e: | ||||
|             return False, str(e) | ||||
|         return True, mac_aver | ||||
|  | ||||
|     def getbcmreg(self, reg): | ||||
|         ret, val = osutil.getsdkreg(reg) | ||||
|         return ret, val | ||||
|  | ||||
|     def logger_debug(self, msg): | ||||
|         baseutil.logger_debug(msg) | ||||
|  | ||||
|     def command(self, cmd): | ||||
|         ret, output = osutil.command(cmd) | ||||
|         return ret, output | ||||
							
								
								
									
										381
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/fan.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										381
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/fan.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,381 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # fan.py | ||||
| # Python implementation of the Class fan | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
| from eepromutil.fru import ipmifru | ||||
| from plat_hal.rotor import rotor | ||||
|  | ||||
|  | ||||
| class fan(devicebase): | ||||
|     __rotor_list = [] | ||||
|     __pn = None | ||||
|     __raweeprom = None | ||||
|     __sn = None | ||||
|     __hw_version = None | ||||
|     __present = None | ||||
|     __e2loc = None | ||||
|     __rotors = None | ||||
|     __AirFlow = None | ||||
|     __SpeedMin = None | ||||
|     __SpeedMax = None | ||||
|     __productName = None | ||||
|     __productSerialNumber = None | ||||
|     __WatchdogStatus = None | ||||
|     __led_attrs_config = None | ||||
|     __led_config = None | ||||
|     __WatchdogStatus_config = None | ||||
|     __AirFlowconifg = None | ||||
|     __EnableWatchdogConf = None | ||||
|     __Rotor_config = None | ||||
|     __fan_display_name = None  # 'N/A' | ||||
|     __fan_display_name_conifg = None | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.sn = conf.get('sn', None) | ||||
|             self.present = conf.get('present', None) | ||||
|             self.e2loc = conf.get('e2loc', None) | ||||
|             self.SpeedMin = conf.get('SpeedMin', None) | ||||
|             self.SpeedMax = conf.get('SpeedMax', None) | ||||
|             self.AirFlowconifg = conf.get("airflow", None) | ||||
|             self.WatchdogStatus_config = conf.get('WatchdogStatus', None) | ||||
|             self.EnableWatchdogConf = conf.get('EnableWatchdogConf', None) | ||||
|             self.led_attrs_config = conf.get('led_attrs', None) | ||||
|             self.led_config = conf.get('led', None) | ||||
|             self.Rotor_config = conf.get('Rotor', None) | ||||
|             self.fan_display_name_conifg = conf.get("fan_display_name", None) | ||||
|             rotor_tmp = [] | ||||
|             for key, value in (self.Rotor_config).items(): | ||||
|                 rotor_tmp.append(rotor(value)) | ||||
|             rotor_tmp.sort(key=lambda x: x.name, reverse=False) | ||||
|             self.rotor_list = rotor_tmp | ||||
|             self.rotors = len(self.rotor_list) | ||||
|  | ||||
|     @property | ||||
|     def EnableWatchdogConf(self): | ||||
|         return self.__EnableWatchdogConf | ||||
|  | ||||
|     @EnableWatchdogConf.setter | ||||
|     def EnableWatchdogConf(self, val): | ||||
|         self.__EnableWatchdogConf = val | ||||
|  | ||||
|     @property | ||||
|     def rotor_list(self): | ||||
|         return self.__rotor_list | ||||
|  | ||||
|     @rotor_list.setter | ||||
|     def rotor_list(self, val): | ||||
|         self.__rotor_list = val | ||||
|  | ||||
|     @property | ||||
|     def Rotor_config(self): | ||||
|         return self.__Rotor_config | ||||
|  | ||||
|     @Rotor_config.setter | ||||
|     def Rotor_config(self, val): | ||||
|         self.__Rotor_config = val | ||||
|  | ||||
|     @property | ||||
|     def productName(self): | ||||
|         return self.__productName | ||||
|  | ||||
|     @productName.setter | ||||
|     def productName(self, val): | ||||
|         self.__productName = val | ||||
|  | ||||
|     @property | ||||
|     def productSerialNumber(self): | ||||
|         return self.__productSerialNumber | ||||
|  | ||||
|     @productSerialNumber.setter | ||||
|     def productSerialNumber(self, val): | ||||
|         self.__productSerialNumber = val | ||||
|  | ||||
|     @property | ||||
|     def hw_version(self): | ||||
|         return self.__hw_version | ||||
|  | ||||
|     @hw_version.setter | ||||
|     def hw_version(self, val): | ||||
|         self.__hw_version = val | ||||
|  | ||||
|     @property | ||||
|     def sn(self): | ||||
|         return self.__sn | ||||
|  | ||||
|     @sn.setter | ||||
|     def sn(self, val): | ||||
|         self.__sn = val | ||||
|  | ||||
|     @property | ||||
|     def pn(self): | ||||
|         return self.__pn | ||||
|  | ||||
|     @pn.setter | ||||
|     def pn(self, val): | ||||
|         self.__pn = val | ||||
|  | ||||
|     @property | ||||
|     def raweeprom(self): | ||||
|         return self.__raweeprom | ||||
|  | ||||
|     @raweeprom.setter | ||||
|     def raweeprom(self, val): | ||||
|         self.__raweeprom = val | ||||
|  | ||||
|     @property | ||||
|     def SpeedMax(self): | ||||
|         return self.__SpeedMax | ||||
|  | ||||
|     @SpeedMax.setter | ||||
|     def SpeedMax(self, val): | ||||
|         self.__SpeedMax = val | ||||
|  | ||||
|     @property | ||||
|     def SpeedMin(self): | ||||
|         return self.__SpeedMin | ||||
|  | ||||
|     @SpeedMin.setter | ||||
|     def SpeedMin(self, val): | ||||
|         self.__SpeedMin = val | ||||
|  | ||||
|     @property | ||||
|     def rotors(self): | ||||
|         return self.__rotors | ||||
|  | ||||
|     @property | ||||
|     def AirFlow(self): | ||||
|         return self.__AirFlow | ||||
|  | ||||
|     @AirFlow.setter | ||||
|     def AirFlow(self, val): | ||||
|         self.__AirFlow = val | ||||
|  | ||||
|     @rotors.setter | ||||
|     def rotors(self, val): | ||||
|         self.__rotors = val | ||||
|  | ||||
|     @property | ||||
|     def fan_display_name_conifg(self): | ||||
|         return self.__fan_display_name_conifg | ||||
|  | ||||
|     @fan_display_name_conifg.setter | ||||
|     def fan_display_name_conifg(self, val): | ||||
|         self.__fan_display_name_conifg = val | ||||
|  | ||||
|     @property | ||||
|     def fan_display_name(self): | ||||
|         return self.__fan_display_name | ||||
|  | ||||
|     @fan_display_name.setter | ||||
|     def fan_display_name(self, val): | ||||
|         self.__fan_display_name = val | ||||
|  | ||||
|     def getspeed(self, conf): | ||||
|         tmp = None | ||||
|         if conf is None: | ||||
|             return -1 | ||||
|         ret, val = self.get_value(conf) | ||||
|         if ret == True: | ||||
|             tmp = int(str(val), 10) | ||||
|         else: | ||||
|             val = None | ||||
|         if val is not None: | ||||
|             return int(15000000 / tmp) | ||||
|         return -1 | ||||
|  | ||||
|     def get_speed(self, rotor_index): | ||||
|         rotor = self.get_rotor_index(rotor_index) | ||||
|         if rotor is None: | ||||
|             return None | ||||
|         speed = rotor.rotor_Speed.Value | ||||
|         if speed is None: | ||||
|             return None | ||||
|         return int(speed) | ||||
|  | ||||
|     def set_led(self, color): | ||||
|         status = self.led_attrs_config.get(color, None) | ||||
|         if status is None: | ||||
|             return False | ||||
|  | ||||
|         mask = self.led_attrs_config.get('mask', 0xff) | ||||
|         ret, value = self.get_value(self.led_config) | ||||
|         if ret is False or value is None: | ||||
|             return False | ||||
|         setval = (int(value) & ~mask) | (status) | ||||
|         ret, val = self.set_value(self.led_config, setval) | ||||
|         return ret | ||||
|  | ||||
|     def get_led(self): | ||||
|         mask = self.led_attrs_config.get('mask', 0xff) | ||||
|         ret, value = self.get_value(self.led_config) | ||||
|         if ret is False or value is None: | ||||
|             return False, 'N/A' | ||||
|         ledval = (int(value) & mask) | ||||
|         for key, val in self.led_attrs_config.items(): | ||||
|             if (ledval == val) and (key != "mask"): | ||||
|                 return True, key | ||||
|         return False, 'N/A' | ||||
|  | ||||
|     def set_speed(self, rotor_index, level): | ||||
|         if level > 255 or level < 0: | ||||
|             return False | ||||
|         rotor = self.get_rotor_index(rotor_index) | ||||
|         if rotor is None: | ||||
|             return False | ||||
|         ret, val = self.set_value(rotor.Speedconfig, int(level)) | ||||
|         return ret | ||||
|  | ||||
|     def get_rotor_index(self, rotor_index): | ||||
|         if rotor_index > len(self.rotor_list): | ||||
|             return None | ||||
|         rotor = self.rotor_list[rotor_index - 1] | ||||
|         return rotor | ||||
|  | ||||
|     def get_rotor_byname(self, rotor_index): | ||||
|         for rotor in self.rotor_list: | ||||
|             if rotor.name == rotor_index: | ||||
|                 return rotor | ||||
|         return None | ||||
|  | ||||
|     def get_presence(self): | ||||
|         ret, val = self.get_value(self.present) | ||||
|         if ret is False or val is None: | ||||
|             return -1 | ||||
|         if isinstance(val, str): | ||||
|             value = int(val, 16) | ||||
|         else: | ||||
|             value = val | ||||
|         mask = self.present.get("mask") | ||||
|         flag = value & mask | ||||
|         okval = self.present.get("okval", 0) | ||||
|         if flag == okval: | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     def get_speed_pwm(self, rotor_index): | ||||
|         rotor = self.get_rotor_index(rotor_index) | ||||
|         if rotor is None: | ||||
|             return False | ||||
|         if rotor.i2c_speed is None: | ||||
|             return False | ||||
|         val = round(rotor.i2c_speed * 100 / 255) | ||||
|         return val | ||||
|  | ||||
|     def feed_watchdog(self, pwm): | ||||
|         ret = False | ||||
|         for rotor in self.rotor_list: | ||||
|             ret, val = rotor.feed_watchdog() | ||||
|             if ret is False: | ||||
|                 return ret | ||||
|         return ret | ||||
|  | ||||
|     def get_fru_info(self): | ||||
|         try: | ||||
|             if self.get_presence() is False: | ||||
|                 raise Exception("%s: not present" % self.name) | ||||
|             eeprom = self.get_eeprom_info(self.e2loc) | ||||
|             if eeprom is None: | ||||
|                 raise Exception("%s: value is none" % self.name) | ||||
|             fru = ipmifru() | ||||
|             if isinstance(eeprom, bytes): | ||||
|                 eeprom = self.byteTostr(eeprom) | ||||
|             fru.decodeBin(eeprom) | ||||
|             self.productName = fru.productInfoArea.productName.strip()  # PN | ||||
|             self.productSerialNumber = fru.productInfoArea.productSerialNumber.strip()  # SN | ||||
|             self.hw_version = fru.productInfoArea.productVersion.strip()  # HW | ||||
|         except Exception as e: | ||||
|             self.productName = None | ||||
|             self.productSerialNumber = None | ||||
|             self.hw_version = None | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     def decode_eeprom_info(self): | ||||
|         '''get fan name, hw version, sn''' | ||||
|         return self.get_fru_info() | ||||
|  | ||||
|     def get_AirFlow(self): | ||||
|         if self.productName is None: | ||||
|             ret = self.decode_eeprom_info() | ||||
|             if ret is False: | ||||
|                 self.AirFlow = None | ||||
|                 return False | ||||
|         if self.AirFlowconifg is None: | ||||
|             self.AirFlow = None | ||||
|             return False | ||||
|         else: | ||||
|             for i in self.AirFlowconifg: | ||||
|                 if self.productName in self.AirFlowconifg[i]: | ||||
|                     self.AirFlow = i | ||||
|                     return True | ||||
|         self.AirFlow = None | ||||
|         return False | ||||
|  | ||||
|     def enable_watchdog(self, enable, timeout_sec): | ||||
|         ret = False | ||||
|         if enable == True: | ||||
|             byte = self.EnableWatchdogConf.get("enable_byte", None) | ||||
|             ret, val = self.set_value(self.EnableWatchdogConf, byte) | ||||
|         elif enable == False: | ||||
|             byte = self.EnableWatchdogConf.get("disable_byte", None) | ||||
|             ret, val = self.set_value(self.EnableWatchdogConf, byte) | ||||
|         return ret | ||||
|  | ||||
|     def get_watchdog_status(self): | ||||
|         dic = {"support": None, "open": None, "work_full": None, "work_allow_set": None} | ||||
|         if self.WatchdogStatus_config is None: | ||||
|             return None | ||||
|         ret, val = self.get_value(self.WatchdogStatus_config) | ||||
|         if ret is False or val is None: | ||||
|             return None | ||||
|         support_watchdog_off = self.WatchdogStatus_config.get("support_watchdog_off", None) | ||||
|         is_open_off = self.WatchdogStatus_config.get("is_open_off", None) | ||||
|         full_running_off = self.WatchdogStatus_config.get("full_running_off", None) | ||||
|         running_setting_off = self.WatchdogStatus_config.get("running_setting_off", None) | ||||
|         if support_watchdog_off is not None: | ||||
|             if support_watchdog_off & val == self.WatchdogStatus_config.get("support_watchdog_mask", None): | ||||
|                 dic["support"] = True | ||||
|             else: | ||||
|                 dic["support"] = False | ||||
|                 return dic | ||||
|         if is_open_off is not None: | ||||
|             if is_open_off & val == self.WatchdogStatus_config.get("is_open_mask", None): | ||||
|                 dic["open"] = True | ||||
|             else: | ||||
|                 dic["open"] = False | ||||
|         if full_running_off is not None: | ||||
|             if full_running_off & val == self.WatchdogStatus_config.get("full_running_mask", None): | ||||
|                 dic["work_full"] = True | ||||
|             else: | ||||
|                 dic["work_full"] = False | ||||
|         if running_setting_off is not None: | ||||
|             if running_setting_off & val == self.WatchdogStatus_config.get("running_setting_mask", None): | ||||
|                 dic["work_allow_set"] = True | ||||
|             else: | ||||
|                 dic["work_allow_set"] = False | ||||
|         return dic | ||||
|  | ||||
|     def get_fan_display_name(self): | ||||
|         if self.productName is None: | ||||
|             ret = self.get_fru_info() | ||||
|             if ret is False: | ||||
|                 self.fan_display_name = None | ||||
|                 return False | ||||
|         if self.fan_display_name_conifg is None: | ||||
|             self.fan_display_name = self.productName | ||||
|             return False | ||||
|         else: | ||||
|             for i in self.fan_display_name_conifg: | ||||
|                 if self.productName in self.fan_display_name_conifg[i]: | ||||
|                     self.fan_display_name = i | ||||
|                     return True | ||||
|         self.fan_display_name = self.productName | ||||
|         return False | ||||
							
								
								
									
										1331
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/interface.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1331
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/interface.py
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										54
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/led.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										54
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/led.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # led.py | ||||
| # Python implementation of the Class led | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
|  | ||||
|  | ||||
| class led(devicebase): | ||||
|     def __init__(self, conf=None): | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.led_type = conf.get('led_type', None) | ||||
|             self.led_attrs_config = conf.get('led_attrs', None) | ||||
|             self.led_config = conf.get('led', None) | ||||
|  | ||||
|     def set_color(self, color): | ||||
|         status = self.led_attrs_config.get(color, None) | ||||
|         if status is None: | ||||
|             return False | ||||
|  | ||||
|         mask = self.led_attrs_config.get('mask', 0xff) | ||||
|  | ||||
|         if isinstance(self.led_config, list): | ||||
|             for led_config_index in self.led_config: | ||||
|                 ret, value = self.get_value(led_config_index) | ||||
|                 if (ret is False) or (value is None): | ||||
|                     return False | ||||
|                 setval = (int(value) & ~mask) | (status) | ||||
|                 ret, val = self.set_value(led_config_index, setval) | ||||
|                 if ret is False: | ||||
|                     return ret | ||||
|         else: | ||||
|             ret, value = self.get_value(self.led_config) | ||||
|             if (ret is False) or (value is None): | ||||
|                 return False | ||||
|             setval = (int(value) & ~mask) | (status) | ||||
|             ret, val = self.set_value(self.led_config, setval) | ||||
|         return ret | ||||
|  | ||||
|     def get_color(self): | ||||
|         mask = self.led_attrs_config.get('mask', 0xff) | ||||
|         ret, value = self.get_value(self.led_config) | ||||
|         if ret is False or value is None: | ||||
|             return False, 'N/A' | ||||
|         ledval = (int(value) & mask) | ||||
|         for key, val in self.led_attrs_config.items(): | ||||
|             if (ledval == val) and (key != "mask"): | ||||
|                 return True, key | ||||
|         return False, 'N/A' | ||||
|  | ||||
							
								
								
									
										127
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/onie_e2.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										127
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/onie_e2.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # onie_e2.py | ||||
| # Python implementation of the Class onie_e2 | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
| from eepromutil.onietlv import onie_tlv | ||||
|  | ||||
|  | ||||
| class onie_e2(devicebase): | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         self._cardid = "" | ||||
|         self._productname = "" | ||||
|         self._partnum = "" | ||||
|         self._serialnum = "" | ||||
|         self._macbase = "" | ||||
|         self._manufdate = "" | ||||
|         self._deviceversion = "" | ||||
|         self._labelrevision = "" | ||||
|         self._platformname = "" | ||||
|         self._onieversion = "" | ||||
|         self._macsize = "" | ||||
|         self._manufname = "" | ||||
|         self._manufcountry = "" | ||||
|         self._vendorname = "" | ||||
|         self._diagname = "" | ||||
|         self._servicetag = "" | ||||
|  | ||||
|         if conf is not None: | ||||
|             self.name = conf.get('name', None) | ||||
|             self.e2loc = conf.get('e2loc', None) | ||||
|             self.e2_path = self.e2loc.get('loc', None) | ||||
|  | ||||
|     @property | ||||
|     def cardid(self): | ||||
|         return self._cardid | ||||
|  | ||||
|     @property | ||||
|     def productname(self): | ||||
|         return self._productname | ||||
|  | ||||
|     @property | ||||
|     def partnum(self): | ||||
|         return self._partnum | ||||
|  | ||||
|     @property | ||||
|     def serialnum(self): | ||||
|         return self._serialnum | ||||
|  | ||||
|     @property | ||||
|     def macbase(self): | ||||
|         return self._macbase | ||||
|  | ||||
|     @property | ||||
|     def manufdate(self): | ||||
|         return self._manufdate | ||||
|  | ||||
|     @property | ||||
|     def deviceversion(self): | ||||
|         return self._deviceversion | ||||
|  | ||||
|     @property | ||||
|     def labelrevision(self): | ||||
|         return self._labelrevision | ||||
|  | ||||
|     @property | ||||
|     def platformname(self): | ||||
|         return self._platformname | ||||
|  | ||||
|     @property | ||||
|     def onieversion(self): | ||||
|         return self._onieversion | ||||
|  | ||||
|     @property | ||||
|     def macsize(self): | ||||
|         return self._macsize | ||||
|  | ||||
|     @property | ||||
|     def manufname(self): | ||||
|         return self._manufname | ||||
|  | ||||
|     @property | ||||
|     def manufcountry(self): | ||||
|         return self._manufcountry | ||||
|  | ||||
|     @property | ||||
|     def vendorname(self): | ||||
|         return self._vendorname | ||||
|  | ||||
|     @property | ||||
|     def diagname(self): | ||||
|         return self._diagname | ||||
|  | ||||
|     @property | ||||
|     def servicetag(self): | ||||
|         return self._servicetag | ||||
|  | ||||
|     def get_onie_e2_info(self): | ||||
|         try: | ||||
|             eeprom = self.get_eeprom_info(self.e2loc) | ||||
|             if eeprom is None: | ||||
|                 raise Exception("%s: value is none" % self.name) | ||||
|             onietlv = onie_tlv() | ||||
|             onietlv.decode(eeprom) | ||||
|             self._cardid = onietlv.cardid | ||||
|             self._productname = onietlv.productname | ||||
|             self._partnum = onietlv.partnum | ||||
|             self._serialnum = onietlv.serialnum | ||||
|             self._macbase = onietlv.macbase | ||||
|             self._manufdate = onietlv.manufdate | ||||
|             self._deviceversion = onietlv.deviceversion | ||||
|             self._labelrevision = onietlv.labelrevision | ||||
|             self._platformname = onietlv.platformname | ||||
|             self._onieversion = onietlv.onieversion | ||||
|             self._macsize = onietlv.macsize | ||||
|             self._manufname = onietlv.manufname | ||||
|             self._manufcountry = onietlv.manufcountry | ||||
|             self._vendorname = onietlv.vendorname | ||||
|             self._diagname = onietlv.diagname | ||||
|             self._servicetag = onietlv.servicetag | ||||
|         except Exception as e: | ||||
|             return False | ||||
|         return True | ||||
							
								
								
									
										401
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/osutil.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										401
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/osutil.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,401 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # osutil.py | ||||
| # Python implementation of the Class osutil | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
|  | ||||
| import os | ||||
| import time | ||||
| import glob | ||||
| import re | ||||
| from rjutil.smbus import SMBus | ||||
| import time | ||||
| import subprocess | ||||
| from functools import wraps | ||||
| import fcntl | ||||
| import syslog | ||||
|  | ||||
|  | ||||
| PLATFORM_HAL_DEBUG_FILE = "/etc/.platform_hal_debug_flag" | ||||
|  | ||||
|  | ||||
| def platform_hal_debug(s): | ||||
|     if os.path.exists(PLATFORM_HAL_DEBUG_FILE): | ||||
|         syslog.openlog("PLATFORM_HAL", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_DEBUG, s) | ||||
|  | ||||
|  | ||||
| def retry(maxretry=6, delay=0.01): | ||||
|     ''' | ||||
|         maxretry:  max retry times | ||||
|         delay   :  interval after last retry | ||||
|     ''' | ||||
|     def decorator(f): | ||||
|         @wraps(f) | ||||
|         def wrapper(*args, **kwargs): | ||||
|             time_retry = maxretry | ||||
|             time_delay = delay | ||||
|             result_msg = "" | ||||
|             while time_retry: | ||||
|                 try: | ||||
|                     val, result_msg = f(*args, **kwargs) | ||||
|                     if val is False: | ||||
|                         time_retry -= 1 | ||||
|                         time.sleep(time_delay) | ||||
|                         continue | ||||
|                     else: | ||||
|                         return val, result_msg | ||||
|                 except Exception as e: | ||||
|                     time_retry -= 1 | ||||
|                     result_msg = str(e) | ||||
|                     time.sleep(time_delay) | ||||
|             return False, "max time retry last errmsg is {}".format(result_msg) | ||||
|         return wrapper | ||||
|     return decorator | ||||
|  | ||||
|  | ||||
| pidfile = -1 | ||||
|  | ||||
|  | ||||
| def file_rw_lock(file_path): | ||||
|     global pidfile | ||||
|     pidfile = open(file_path, "r") | ||||
|     try: | ||||
|         fcntl.flock(pidfile, fcntl.LOCK_EX | fcntl.LOCK_NB) | ||||
|         platform_hal_debug("file_rw_lock success") | ||||
|         return True | ||||
|     except Exception as e: | ||||
|         pidfile.close() | ||||
|         pidfile = -1 | ||||
|         return False | ||||
|  | ||||
|  | ||||
| def file_rw_unlock(): | ||||
|     try: | ||||
|         global pidfile | ||||
|  | ||||
|         if pidfile != -1: | ||||
|             fcntl.flock(pidfile, fcntl.LOCK_UN) | ||||
|             pidfile.close() | ||||
|             pidfile = -1 | ||||
|             platform_hal_debug("file_rw_unlock success") | ||||
|         else: | ||||
|             platform_hal_debug("pidfile is invalid, do nothing") | ||||
|         return True | ||||
|     except Exception as e: | ||||
|         platform_hal_debug("file_rw_unlock err, msg: %s" % (str(e))) | ||||
|         return False | ||||
|  | ||||
|  | ||||
| def take_file_rw_lock(file_path): | ||||
|     loop = 1000 | ||||
|     ret = False | ||||
|     for i in range(0, loop): | ||||
|         ret = file_rw_lock(file_path) | ||||
|         if ret is True: | ||||
|             break | ||||
|         time.sleep(0.001) | ||||
|     return ret | ||||
|  | ||||
|  | ||||
| class osutil(object): | ||||
|     """ | ||||
|        osutil | ||||
|     """ | ||||
|  | ||||
|     @staticmethod | ||||
|     @retry(maxretry=6) | ||||
|     def rji2cget_python(bus, addr, reg): | ||||
|         with SMBus(bus) as y: | ||||
|             val, ind = y.read_byte_data(addr, reg, True) | ||||
|         return val, ind | ||||
|  | ||||
|     @staticmethod | ||||
|     @retry(maxretry=6) | ||||
|     def rji2cset_python(bus, addr, reg, value): | ||||
|         with SMBus(bus) as y: | ||||
|             val, ind = y.write_byte_data(addr, reg, value, True) | ||||
|         return val, ind | ||||
|  | ||||
|     @staticmethod | ||||
|     @retry(maxretry=6) | ||||
|     def rji2cgetword_python(bus, addr, reg): | ||||
|         with SMBus(bus) as y: | ||||
|             val, ind = y.read_word_data(addr, reg, True) | ||||
|         return val, ind | ||||
|  | ||||
|     @staticmethod | ||||
|     @retry(maxretry=6) | ||||
|     def rji2csetword_python(bus, addr, reg, value): | ||||
|         with SMBus(bus) as y: | ||||
|             val, ind = y.write_word_data(addr, reg, value, True) | ||||
|         return val, ind | ||||
|  | ||||
|     @staticmethod | ||||
|     @retry(maxretry=6) | ||||
|     def rji2csetwordpec_python(bus, addr, reg, value): | ||||
|         with SMBus(bus) as y: | ||||
|             val, ind = y.write_word_data_pec(addr, reg, value, True) | ||||
|         return val, ind | ||||
|  | ||||
|     @staticmethod | ||||
|     @retry(maxretry=6) | ||||
|     def rji2cset_byte_pec_python(bus, addr, reg, value): | ||||
|         with SMBus(bus) as y: | ||||
|             val, ind = y.write_byte_data_pec(addr, reg, value, True) | ||||
|         return val, ind | ||||
|  | ||||
|     @staticmethod | ||||
|     def command(cmdstr): | ||||
|         retcode, output = subprocess.getstatusoutput(cmdstr) | ||||
|         return retcode, output | ||||
|  | ||||
|     @staticmethod | ||||
|     def geti2cword_i2ctool(bus, addr, offset): | ||||
|         command_line = "i2cget -f -y %d 0x%02x 0x%02x  wp" % (bus, addr, offset) | ||||
|         retrytime = 6 | ||||
|         ret_t = "" | ||||
|         for i in range(retrytime): | ||||
|             ret, ret_t = osutil.command(command_line) | ||||
|             if ret == 0: | ||||
|                 return True, int(ret_t, 16) | ||||
|             time.sleep(0.1) | ||||
|         return False, ret_t | ||||
|  | ||||
|     @staticmethod | ||||
|     def seti2cword_i2ctool(bus, addr, offset, val): | ||||
|         command_line = "i2cset -f -y %d 0x%02x 0x%0x 0x%04x wp" % (bus, addr, offset, val) | ||||
|         retrytime = 6 | ||||
|         ret_t = "" | ||||
|         for i in range(retrytime): | ||||
|             ret, ret_t = osutil.command(command_line) | ||||
|             if ret == 0: | ||||
|                 return True, ret_t | ||||
|             time.sleep(0.1) | ||||
|         return False, ret_t | ||||
|  | ||||
|     @staticmethod | ||||
|     def rji2cget_i2ctool(bus, devno, address): | ||||
|         command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) | ||||
|         retrytime = 6 | ||||
|         ret_t = "" | ||||
|         for i in range(retrytime): | ||||
|             ret, ret_t = osutil.command(command_line) | ||||
|             if ret == 0: | ||||
|                 return True, int(ret_t, 16) | ||||
|             time.sleep(0.1) | ||||
|         return False, ret_t | ||||
|  | ||||
|     @staticmethod | ||||
|     def rji2cset_i2ctool(bus, devno, address, byte): | ||||
|         command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( | ||||
|             bus, devno, address, byte) | ||||
|         retrytime = 6 | ||||
|         ret_t = "" | ||||
|         for i in range(retrytime): | ||||
|             ret, ret_t = osutil.command(command_line) | ||||
|             if ret == 0: | ||||
|                 return True, ret_t | ||||
|         return False, ret_t | ||||
|  | ||||
|     @staticmethod | ||||
|     def geti2cword(bus, addr, offset): | ||||
|         return osutil.rji2cgetword_python(bus, addr, offset) | ||||
|  | ||||
|     @staticmethod | ||||
|     def seti2cword(bus, addr, offset, val): | ||||
|         return osutil.rji2csetword_python(bus, addr, offset, val) | ||||
|  | ||||
|     @staticmethod | ||||
|     def seti2cwordpec(bus, addr, offset, val): | ||||
|         return osutil.rji2csetwordpec_python(bus, addr, offset, val) | ||||
|  | ||||
|     @staticmethod | ||||
|     def seti2c_byte_pec(bus, addr, offset, val): | ||||
|         return osutil.rji2cset_byte_pec_python(bus, addr, offset, val) | ||||
|  | ||||
|     @staticmethod | ||||
|     def rji2cget(bus, devno, address): | ||||
|         return osutil.rji2cget_python(bus, devno, address) | ||||
|  | ||||
|     @staticmethod | ||||
|     def rji2cset(bus, devno, address, byte): | ||||
|         return osutil.rji2cset_python(bus, devno, address, byte) | ||||
|  | ||||
|     @staticmethod | ||||
|     def byteTostr(val): | ||||
|         strtmp = '' | ||||
|         for i in range(len(val)): | ||||
|             strtmp += chr(val[i]) | ||||
|         return strtmp | ||||
|  | ||||
|     @staticmethod | ||||
|     def io_rd(reg_addr, read_len=1): | ||||
|         try: | ||||
|             regaddr = 0 | ||||
|             if isinstance(reg_addr, int): | ||||
|                 regaddr = reg_addr | ||||
|             else: | ||||
|                 regaddr = int(reg_addr, 16) | ||||
|             devfile = "/dev/port" | ||||
|             fd = os.open(devfile, os.O_RDWR | os.O_CREAT) | ||||
|             os.lseek(fd, regaddr, os.SEEK_SET) | ||||
|             str = os.read(fd, read_len) | ||||
|             return True, "".join(["%02x" % item for item in str]) | ||||
|         except ValueError as e: | ||||
|             return False, str(e) | ||||
|         except Exception as e: | ||||
|             return False, str(e) | ||||
|         finally: | ||||
|             os.close(fd) | ||||
|  | ||||
|     @staticmethod | ||||
|     def readsysfs(location, flock_path=None): | ||||
|         flock_path_tmp = None | ||||
|         platform_hal_debug("readsysfs, location:%s, flock_path:%s" % (location, flock_path)) | ||||
|         try: | ||||
|             if flock_path is not None: | ||||
|                 flock_paths = glob.glob(flock_path) | ||||
|                 if len(flock_paths) != 0: | ||||
|                     flock_path_tmp = flock_paths[0] | ||||
|                     platform_hal_debug("try to get file lock, path:%s" % flock_path_tmp) | ||||
|                     ret = take_file_rw_lock(flock_path_tmp) | ||||
|                     if ret is False: | ||||
|                         platform_hal_debug("take file lock timeout, path:%s" % flock_path_tmp) | ||||
|                         return False, ("take file rw lock timeout, path:%s" % flock_path_tmp) | ||||
|                 else: | ||||
|                     platform_hal_debug("config error, can't find flock_path:%s" % flock_path) | ||||
|  | ||||
|             locations = glob.glob(location) | ||||
|             with open(locations[0], 'rb') as fd1: | ||||
|                 retval = fd1.read() | ||||
|             retval = osutil.byteTostr(retval) | ||||
|             if flock_path_tmp is not None: | ||||
|                 file_rw_unlock() | ||||
|  | ||||
|             retval = retval.rstrip('\r\n') | ||||
|             retval = retval.lstrip(" ") | ||||
|         except Exception as e: | ||||
|             if flock_path_tmp is not None: | ||||
|                 file_rw_unlock() | ||||
|             platform_hal_debug("readsysfs error, msg:%s" % str(e)) | ||||
|             return False, (str(e) + " location[%s]" % location) | ||||
|         return True, retval | ||||
|  | ||||
|     @staticmethod | ||||
|     def writesysfs(location, value): | ||||
|         try: | ||||
|             if not os.path.isfile(location): | ||||
|                 print(location, 'not found !') | ||||
|                 return False, ("location[%s] not found !" % location) | ||||
|             with open(location, 'w') as fd1: | ||||
|                 fd1.write(value) | ||||
|         except Exception as e: | ||||
|             return False, (str(e) + " location[%s]" % location) | ||||
|         return True, ("set location[%s] %s success !" % (location, value)) | ||||
|  | ||||
|     @staticmethod | ||||
|     def getdevmem(addr, digit, mask): | ||||
|         command_line = "devmem 0x%02x %d" % (addr, digit) | ||||
|         retrytime = 6 | ||||
|         ret_t = "" | ||||
|         for i in range(retrytime): | ||||
|             ret, ret_t = osutil.command(command_line) | ||||
|             if ret == 0: | ||||
|                 if mask is not None: | ||||
|                     ret_t = str(int(ret_t, 16) & mask) | ||||
|             return True, ret_t | ||||
|         return False, ret_t | ||||
|  | ||||
|     @staticmethod | ||||
|     def readdevfile_ascii(path, offset, len): | ||||
|         msg = "" | ||||
|         ret = "" | ||||
|         joinstr = '' | ||||
|         fd = -1 | ||||
|  | ||||
|         if not os.path.exists(path): | ||||
|             msg = path + " not found !" | ||||
|             return False, msg | ||||
|  | ||||
|         try: | ||||
|             fd = os.open(path, os.O_RDONLY) | ||||
|             os.lseek(fd, offset, os.SEEK_SET) | ||||
|             ret = os.read(fd, len) | ||||
|             for item in ret: | ||||
|                 joinstr += '%02x ' % item  # like sysfs, display in hex | ||||
|         except Exception as e: | ||||
|             msg = str(e) | ||||
|             return False, msg | ||||
|         finally: | ||||
|             if fd > 0: | ||||
|                 os.close(fd) | ||||
|         return True, joinstr | ||||
|  | ||||
|     @staticmethod | ||||
|     def readdevfile(path, offset, len): | ||||
|         msg = "" | ||||
|         ret = "" | ||||
|         fd = -1 | ||||
|  | ||||
|         if not os.path.exists(path): | ||||
|             msg = path + " not found !" | ||||
|             return False, msg | ||||
|  | ||||
|         try: | ||||
|             fd = os.open(path, os.O_RDONLY) | ||||
|             os.lseek(fd, offset, os.SEEK_SET) | ||||
|             ret = os.read(fd, len) | ||||
|         except Exception as e: | ||||
|             msg = str(e) | ||||
|             return False, msg | ||||
|         finally: | ||||
|             if fd > 0: | ||||
|                 os.close(fd) | ||||
|         return True, ret | ||||
|  | ||||
|     @staticmethod | ||||
|     def rj_os_system(cmd): | ||||
|         status, output = subprocess.getstatusoutput(cmd) | ||||
|         return status, output | ||||
|  | ||||
|     @staticmethod | ||||
|     def getsdkreg(reg): | ||||
|         try: | ||||
|             cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg | ||||
|             ret, result = osutil.rj_os_system(cmd) | ||||
|             result_t = result.strip().replace("\r", "").replace("\n", "") | ||||
|             if ret != 0 or "Error:" in result_t: | ||||
|                 return False, result | ||||
|             patt = r"%s.(.*):(.*)>drivshell" % reg | ||||
|             rt = re.findall(patt, result_t, re.S) | ||||
|             test = re.findall("=(.*)", rt[0][0])[0] | ||||
|         except Exception as e: | ||||
|             return False, 'get sdk register error' | ||||
|         return True, test | ||||
|  | ||||
|     @staticmethod | ||||
|     def getmactemp(): | ||||
|         try: | ||||
|             result = {} | ||||
|             # waitForDocker() | ||||
|             # need to exec twice | ||||
|             osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") | ||||
|             ret, log = osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") | ||||
|             if ret: | ||||
|                 return False, result | ||||
|             else: | ||||
|                 logs = log.splitlines() | ||||
|                 for line in logs: | ||||
|                     if "average" in line: | ||||
|                         b = re.findall(r'\d+.\d+', line) | ||||
|                         result["average"] = b[0] | ||||
|                     elif "maximum" in line: | ||||
|                         b = re.findall(r'\d+.\d+', line) | ||||
|                         result["maximum"] = b[0] | ||||
|         except Exception as e: | ||||
|             return False, str(e) | ||||
|         return True, result | ||||
							
								
								
									
										620
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/psu.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										620
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/psu.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,620 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # psu.py | ||||
| # Python implementation of the Class psu | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
| from eepromutil.fru import ipmifru | ||||
| from plat_hal.sensor import sensor | ||||
|  | ||||
|  | ||||
| class psu(devicebase): | ||||
|     __pmbus = None | ||||
|     __e2loc = None | ||||
|     __present = None | ||||
|     __productManufacturer = None  # : ARTESYN | ||||
|     __productName = None  # : CRPS550W | ||||
|     __productPartModelName = None  # : CSU550AP-3-300 | ||||
|     __productVersion = None  # : AB | ||||
|     __productSerialNumber = None  # : M623UZ00JYABL | ||||
|     __AirFlow = None  # 'N/A' | ||||
|     __AirFlowconifg = None | ||||
|     __psu_display_name = None  # 'N/A' | ||||
|     __psu_display_name_conifg = None | ||||
|     __psu_not_present_pwm = None | ||||
|     __InputStatus_config = None | ||||
|     __OutputStatus_config = None | ||||
|     __FanSpeed_config = None | ||||
|     __Temperature_config = None | ||||
|     __InputStatus = None | ||||
|     __OutputStatus = None | ||||
|     __FanSpeed = None | ||||
|     __Temperature = None | ||||
|     __FanSpeedMin = None | ||||
|     __FanSpeedMax = None | ||||
|     __FanSpeedTolerance = None | ||||
|     __InputsVoltage_config = None | ||||
|     __InputsCurrent_config = None | ||||
|     __InputsPower_config = None | ||||
|     __OutputsVoltage_config = None | ||||
|     __OutputsCurrent_config = None | ||||
|     __OutputsPower_config = None | ||||
|     __InputsVoltage = {} | ||||
|     __InputsCurrent = None | ||||
|     __InputsPower = None | ||||
|     __OutputsVoltage = None | ||||
|     __OutputsCurrent = None | ||||
|     __OutputsPower = None | ||||
|     __InputsType_config = None | ||||
|     __InputsType = None | ||||
|     __psu_sn_config = None | ||||
|     __psu_hw_config = None | ||||
|     __psu_pn_config = None | ||||
|     __psu_vendor_config = None | ||||
|     __TempStatus_config = None | ||||
|     __FanStatus_config = None | ||||
|     __TempStatus = None | ||||
|     __FanStatus = None | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         self.pmbus = conf.get("pmbusloc", None) | ||||
|         self.e2loc = conf.get("e2loc", None) | ||||
|         self.__presentconfig = conf.get("present", None) | ||||
|         self.name = conf.get("name", None) | ||||
|         self.AirFlowconifg = conf.get("airflow", None) | ||||
|         self.psu_display_name_conifg = conf.get("psu_display_name", None) | ||||
|         self.psu_not_present_pwm = conf.get("psu_not_present_pwm", 100) | ||||
|         self.Temperature_config = conf.get("Temperature", None) | ||||
|         self.Temperature = sensor(self.Temperature_config) | ||||
|  | ||||
|         self.FanSpeedTolerance = conf.get('psu_fan_tolerance', 30) | ||||
|         self.FanSpeed_config = conf.get("FanSpeed", None) | ||||
|         self.FanSpeed = sensor(self.FanSpeed_config) | ||||
|  | ||||
|         self.__InputsVoltage_config = conf.get("InputsVoltage", None) | ||||
|         self.generate_psu_input_vol(self.__InputsVoltage_config) | ||||
|         self.__InputsCurrent_config = conf.get("InputsCurrent", None) | ||||
|         self.InputsCurrent = sensor(self.__InputsCurrent_config) | ||||
|         self.__InputsPower_config = conf.get("InputsPower", None) | ||||
|         self.InputsPower = sensor(self.__InputsPower_config) | ||||
|         self.__OutputsVoltage_config = conf.get("OutputsVoltage", None) | ||||
|         self.OutputsVoltage = sensor(self.__OutputsVoltage_config) | ||||
|         self.__OutputsCurrent_config = conf.get("OutputsCurrent", None) | ||||
|         self.OutputsCurrent = sensor(self.__OutputsCurrent_config) | ||||
|         self.__OutputsPower_config = conf.get("OutputsPower", None) | ||||
|         self.OutputsPower = sensor(self.__OutputsPower_config) | ||||
|  | ||||
|         self.__InputStatus_config = conf.get("InputsStatus", None) | ||||
|         self.__OutputStatus_config = conf.get("OutputsStatus", None) | ||||
|         self.__InputsType_config = conf.get('InputsType', None) | ||||
|         self.__psu_sn_config = conf.get('psu_sn', None) | ||||
|         self.__psu_hw_config = conf.get('psu_hw', None) | ||||
|         self.__psu_pn_config = conf.get('psu_pn', None) | ||||
|         self.__psu_vendor_config = conf.get('psu_vendor', None) | ||||
|         self.__TempStatus_config = conf.get("TempStatus", None) | ||||
|         self.__FanStatus_config = conf.get("FanStatus", None) | ||||
|  | ||||
|     def generate_psu_input_vol(self, config): | ||||
|         tmp = {} | ||||
|         for (key, item) in config.items(): | ||||
|             tmp.setdefault(key, sensor(item)) | ||||
|         self.__InputsVoltage = tmp | ||||
|  | ||||
|     def get_psu_sensor_by_name(self, psutype): | ||||
|         return self.__InputsVoltage.get(psutype) or self.__InputsVoltage.get('other') | ||||
|  | ||||
|     @property | ||||
|     def InputsVoltage(self): | ||||
|         psutype = self.InputsType | ||||
|         input_sensor = self.get_psu_sensor_by_name(psutype) | ||||
|         if input_sensor is None: | ||||
|             return None | ||||
|         else: | ||||
|             return input_sensor | ||||
|  | ||||
|     @InputsVoltage.setter | ||||
|     def InputsVoltage(self, val): | ||||
|         self.__InputsVoltage = val | ||||
|  | ||||
|     @property | ||||
|     def InputsCurrent(self): | ||||
|         return self.__InputsCurrent | ||||
|  | ||||
|     @InputsCurrent.setter | ||||
|     def InputsCurrent(self, val): | ||||
|         self.__InputsCurrent = val | ||||
|  | ||||
|     @property | ||||
|     def InputsPower(self): | ||||
|         return self.__InputsPower | ||||
|  | ||||
|     @InputsPower.setter | ||||
|     def InputsPower(self, val): | ||||
|         self.__InputsPower = val | ||||
|  | ||||
|     @property | ||||
|     def OutputsVoltage(self): | ||||
|         return self.__OutputsVoltage | ||||
|  | ||||
|     @OutputsVoltage.setter | ||||
|     def OutputsVoltage(self, val): | ||||
|         self.__OutputsVoltage = val | ||||
|  | ||||
|     @property | ||||
|     def OutputsCurrent(self): | ||||
|         return self.__OutputsCurrent | ||||
|  | ||||
|     @OutputsCurrent.setter | ||||
|     def OutputsCurrent(self, val): | ||||
|         self.__OutputsCurrent = val | ||||
|  | ||||
|     @property | ||||
|     def OutputsPower(self): | ||||
|         return self.__OutputsPower | ||||
|  | ||||
|     @OutputsPower.setter | ||||
|     def OutputsPower(self, val): | ||||
|         self.__OutputsPower = val | ||||
|  | ||||
|     @property | ||||
|     def InputStatus(self): | ||||
|         if self.present == False: | ||||
|             self.__InputStatus = False | ||||
|         else: | ||||
|             ret, val = self.get_value(self.__InputStatus_config) | ||||
|             mask = self.__InputStatus_config.get("mask") | ||||
|             if ret == True: | ||||
|                 ttt = val & mask | ||||
|                 if ttt == 0: | ||||
|                     self.__InputStatus = True | ||||
|                 else: | ||||
|                     self.__InputStatus = False | ||||
|             else: | ||||
|                 self.__InputStatus = False | ||||
|         return self.__InputStatus | ||||
|  | ||||
|     @InputStatus.setter | ||||
|     def InputStatus(self, val): | ||||
|         self.__InputStatus = val | ||||
|  | ||||
|     @property | ||||
|     def TempStatus(self): | ||||
|         if self.__TempStatus_config is None: | ||||
|             return None | ||||
|         if self.present == False: | ||||
|             self.__TempStatus = False | ||||
|         else: | ||||
|             ret, val = self.get_value(self.__TempStatus_config) | ||||
|             mask = self.__TempStatus_config.get("mask") | ||||
|             if ret == True: | ||||
|                 ttt = val & mask | ||||
|                 if ttt == 0: | ||||
|                     self.__TempStatus = True | ||||
|                 else: | ||||
|                     self.__TempStatus = False | ||||
|             else: | ||||
|                 self.__TempStatus = False | ||||
|         return self.__TempStatus | ||||
|  | ||||
|     @TempStatus.setter | ||||
|     def TempStatus(self, val): | ||||
|         self.__TempStatus = val | ||||
|  | ||||
|     @property | ||||
|     def FanStatus(self): | ||||
|         if self.__FanStatus_config is None: | ||||
|             return None | ||||
|         if self.present == False: | ||||
|             self.__FanStatus = False | ||||
|         else: | ||||
|             ret, val = self.get_value(self.__FanStatus_config) | ||||
|             mask = self.__FanStatus_config.get("mask") | ||||
|             if ret == True: | ||||
|                 ttt = val & mask | ||||
|                 if ttt == 0: | ||||
|                     self.__FanStatus = True | ||||
|                 else: | ||||
|                     self.__FanStatus = False | ||||
|             else: | ||||
|                 self.__FanStatus = False | ||||
|         return self.__FanStatus | ||||
|  | ||||
|     @FanStatus.setter | ||||
|     def FanStatus(self, val): | ||||
|         self.__FanStatus = val | ||||
|  | ||||
|     @property | ||||
|     def InputsType(self): | ||||
|         psutypedecode = self.__InputsType_config.get('psutypedecode', None) | ||||
|         if self.present == False: | ||||
|             self.__InputsType = psutypedecode.get(0x00) | ||||
|         else: | ||||
|             ret, val = self.get_value(self.__InputsType_config) | ||||
|             self.__InputsType = self.__InputsType_config.get(val, None) | ||||
|             if self.__InputsType is not None: | ||||
|                 return self.__InputsType | ||||
|             if ret == True and val in psutypedecode: | ||||
|                 self.__InputsType = psutypedecode.get(val) | ||||
|             else: | ||||
|                 self.__InputsType = psutypedecode.get(0x00) | ||||
|         return self.__InputsType | ||||
|  | ||||
|     @InputsType.setter | ||||
|     def InputsType(self, val): | ||||
|         self.__InputsType = val | ||||
|  | ||||
|     @property | ||||
|     def FanSpeedMin(self): | ||||
|         return self.__FanSpeedMin | ||||
|  | ||||
|     @FanSpeedMin.setter | ||||
|     def FanSpeedMin(self, val): | ||||
|         self.__FanSpeedMin = val | ||||
|  | ||||
|     @property | ||||
|     def FanSpeedMax(self): | ||||
|         return self.__FanSpeedMax | ||||
|  | ||||
|     @FanSpeedMax.setter | ||||
|     def FanSpeedMax(self, val): | ||||
|         self.__FanSpeedMax = val | ||||
|  | ||||
|     @property | ||||
|     def FanSpeedTolerance(self): | ||||
|         return self.__FanSpeedTolerance | ||||
|  | ||||
|     @FanSpeedTolerance.setter | ||||
|     def FanSpeedTolerance(self, val): | ||||
|         self.__FanSpeedTolerance = val | ||||
|  | ||||
|     @property | ||||
|     def OutputStatus(self): | ||||
|         if self.present == False: | ||||
|             self.__OutputStatus = False | ||||
|         else: | ||||
|             ret, val = self.get_value(self.__OutputStatus_config) | ||||
|             mask = self.__OutputStatus_config.get("mask") | ||||
|             if ret == True: | ||||
|                 ttt = val & mask | ||||
|                 if ttt == 0: | ||||
|                     self.__OutputStatus = True | ||||
|                 else: | ||||
|                     self.__OutputStatus = False | ||||
|             else: | ||||
|                 self.__OutputStatus = False | ||||
|         return self.__OutputStatus | ||||
|  | ||||
|     @OutputStatus.setter | ||||
|     def OutputStatus(self, val): | ||||
|         self.__OutputStatus = val | ||||
|  | ||||
|     @property | ||||
|     def FanSpeed(self): | ||||
|         return self.__FanSpeed | ||||
|  | ||||
|     @FanSpeed.setter | ||||
|     def FanSpeed(self, val): | ||||
|         self.__FanSpeed = val | ||||
|  | ||||
|     @property | ||||
|     def Temperature(self): | ||||
|         return self.__Temperature | ||||
|  | ||||
|     @Temperature.setter | ||||
|     def Temperature(self, val): | ||||
|         self.__Temperature = val | ||||
|  | ||||
|     @property | ||||
|     def Temperature_config(self): | ||||
|         return self.__Temperature_config | ||||
|  | ||||
|     @Temperature_config.setter | ||||
|     def Temperature_config(self, val): | ||||
|         self.__Temperature_config = val | ||||
|  | ||||
|     @property | ||||
|     def AirFlowconifg(self): | ||||
|         return self.__AirFlowconifg | ||||
|  | ||||
|     @AirFlowconifg.setter | ||||
|     def AirFlowconifg(self, val): | ||||
|         self.__AirFlowconifg = val | ||||
|  | ||||
|     @property | ||||
|     def psu_display_name_conifg(self): | ||||
|         return self.__psu_display_name_conifg | ||||
|  | ||||
|     @psu_display_name_conifg.setter | ||||
|     def psu_display_name_conifg(self, val): | ||||
|         self.__psu_display_name_conifg = val | ||||
|  | ||||
|     @property | ||||
|     def pmbus(self): | ||||
|         return self.__pmbus | ||||
|  | ||||
|     @pmbus.setter | ||||
|     def pmbus(self, val): | ||||
|         self.__pmbus = val | ||||
|  | ||||
|     @property | ||||
|     def e2loc(self): | ||||
|         return self.__e2loc | ||||
|  | ||||
|     @e2loc.setter | ||||
|     def e2loc(self, val): | ||||
|         self.__e2loc = val | ||||
|  | ||||
|     @property | ||||
|     def AirFlow(self): | ||||
|         return self.__AirFlow | ||||
|  | ||||
|     @AirFlow.setter | ||||
|     def AirFlow(self, val): | ||||
|         self.__AirFlow = val | ||||
|  | ||||
|     @property | ||||
|     def psu_display_name(self): | ||||
|         return self.__psu_display_name | ||||
|  | ||||
|     @psu_display_name.setter | ||||
|     def psu_display_name(self, val): | ||||
|         self.__psu_display_name = val | ||||
|  | ||||
|     @property | ||||
|     def psu_not_present_pwm(self): | ||||
|         return self.__psu_not_present_pwm | ||||
|  | ||||
|     @psu_not_present_pwm.setter | ||||
|     def psu_not_present_pwm(self, val): | ||||
|         self.__psu_not_present_pwm = val | ||||
|  | ||||
|     @property | ||||
|     def present(self): | ||||
|         ret, val = self.get_value(self.__presentconfig) | ||||
|         if ret is False or val is None: | ||||
|             return False | ||||
|         mask = self.__presentconfig.get("mask") | ||||
|         if isinstance(val, str): | ||||
|             value = int(val, 16) | ||||
|         else: | ||||
|             value = val | ||||
|         ttt = value & mask | ||||
|         okval = self.__presentconfig.get("okval", 0) | ||||
|         if ttt == okval: | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     @present.setter | ||||
|     def present(self, val): | ||||
|         self.__present = val | ||||
|  | ||||
|     @property | ||||
|     def productManufacturer(self): | ||||
|         return self.__productManufacturer | ||||
|  | ||||
|     @productManufacturer.setter | ||||
|     def productManufacturer(self, val): | ||||
|         self.__productManufacturer = val | ||||
|  | ||||
|     @property | ||||
|     def productName(self): | ||||
|         return self.__productName | ||||
|  | ||||
|     @productName.setter | ||||
|     def productName(self, val): | ||||
|         self.__productName = val | ||||
|  | ||||
|     @property | ||||
|     def productPartModelName(self): | ||||
|         return self.__productPartModelName | ||||
|  | ||||
|     @productPartModelName.setter | ||||
|     def productPartModelName(self, val): | ||||
|         self.__productPartModelName = val | ||||
|  | ||||
|     @property | ||||
|     def productVersion(self): | ||||
|         return self.__productVersion | ||||
|  | ||||
|     @productVersion.setter | ||||
|     def productVersion(self, val): | ||||
|         self.__productVersion = val | ||||
|  | ||||
|     @property | ||||
|     def productSerialNumber(self): | ||||
|         return self.__productSerialNumber | ||||
|  | ||||
|     @productSerialNumber.setter | ||||
|     def productSerialNumber(self, val): | ||||
|         self.__productSerialNumber = val | ||||
|  | ||||
|     @property | ||||
|     def psu_sn_sysfs(self): | ||||
|         if self.__psu_sn_config is None: | ||||
|             return None | ||||
|         ret, val = self.get_value(self.__psu_sn_config) | ||||
|         if ret is False or val is None: | ||||
|             return None | ||||
|         return val | ||||
|  | ||||
|     @property | ||||
|     def psu_hw_sysfs(self): | ||||
|         if self.__psu_hw_config is None: | ||||
|             return None | ||||
|         ret, val = self.get_value(self.__psu_hw_config) | ||||
|         if ret is False or val is None: | ||||
|             return None | ||||
|         return val | ||||
|  | ||||
|     @property | ||||
|     def psu_pn_sysfs(self): | ||||
|         if self.__psu_pn_config is None: | ||||
|             return None | ||||
|         ret, val = self.get_value(self.__psu_pn_config) | ||||
|         if ret is False or val is None: | ||||
|             return None | ||||
|         return val | ||||
|  | ||||
|     @property | ||||
|     def psu_vendor_sysfs(self): | ||||
|         if self.__psu_vendor_config is None: | ||||
|             return None | ||||
|         ret, val = self.get_value(self.__psu_vendor_config) | ||||
|         if ret is False or val is None: | ||||
|             return None | ||||
|         return val | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr =  \ | ||||
|             "name                : %s \n" \ | ||||
|             "productManufacturer : %s \n" \ | ||||
|             "productName         : %s \n" \ | ||||
|             "productPartModelName: %s \n" \ | ||||
|             "productVersion      : %s \n" \ | ||||
|             "productSerialNumber : %s \n" \ | ||||
|             "AirFlow             : %s \n" \ | ||||
|  | ||||
|         tmpstr = formatstr % (self.name, self.productManufacturer, | ||||
|                               self.productName, self.productPartModelName, | ||||
|                               self.productVersion, self.productSerialNumber, self.AirFlow) | ||||
|         return tmpstr | ||||
|  | ||||
|     def get_fan_speed_pwm(self): | ||||
|         if self.present == False: | ||||
|             return self.psu_not_present_pwm | ||||
|         selfconfig = {} | ||||
|         selfconfig['bus'] = self.pmbus['bus'] | ||||
|         selfconfig['addr'] = self.pmbus['addr'] | ||||
|         selfconfig['way'] = 'i2cword' | ||||
|         selfconfig['offset'] = 0x3b | ||||
|         ret, val = self.get_value(selfconfig) | ||||
|         if ret == True: | ||||
|             return val | ||||
|         else: | ||||
|             return None | ||||
|  | ||||
|     def set_fan_speed_pwm(self, pwm): | ||||
|         ''' | ||||
|             pmbus | ||||
|                 if duty: | ||||
|                  i2cset -f -y 0x3b 0x0064  wp | ||||
|         ''' | ||||
|         if self.present == False: | ||||
|             return None | ||||
|         if 0 <= pwm <= 100: | ||||
|             '''enable duty first ''' | ||||
|             selfconfig = {} | ||||
|  | ||||
|             selfconfig['bus'] = self.pmbus['bus'] | ||||
|             selfconfig['addr'] = self.pmbus['addr'] | ||||
|             selfconfig['way'] = 'i2cpec' | ||||
|             selfconfig['offset'] = 0x3a | ||||
|             self.set_value(selfconfig, 0x80) | ||||
|  | ||||
|             selfconfig['way'] = 'i2cwordpec' | ||||
|             selfconfig['offset'] = 0x3b | ||||
|             bytetmp = pwm | ||||
|             ret, val = self.set_value(selfconfig, int(bytetmp)) | ||||
|             if ret == True: | ||||
|                 return True | ||||
|             else: | ||||
|                 return None | ||||
|         else: | ||||
|             raise Exception("pwm not in range [0,100]") | ||||
|  | ||||
|     def get_fru_info_by_sysfs(self): | ||||
|         try: | ||||
|             psu_sn = self.psu_sn_sysfs | ||||
|             psu_hw = self.psu_hw_sysfs | ||||
|             psu_pn = self.psu_pn_sysfs | ||||
|             psu_vendor = self.psu_vendor_sysfs | ||||
|             if psu_sn is None or psu_hw is None or psu_pn is None or psu_vendor is None: | ||||
|                 return False | ||||
|             self.productSerialNumber = psu_sn.strip().replace(chr(0), "") | ||||
|             self.productVersion = psu_hw.strip() | ||||
|             self.productPartModelName = psu_pn.strip() | ||||
|             self.productManufacturer = psu_vendor.strip().replace(chr(0), "") | ||||
|         except Exception as e: | ||||
|             self.productSerialNumber = None | ||||
|             self.productVersion = None | ||||
|             self.productPartModelName = None | ||||
|             self.productManufacturer = None | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     def get_fru_info_by_decode(self): | ||||
|         try: | ||||
|             eeprom = self.get_eeprom_info(self.e2loc) | ||||
|             if eeprom is None: | ||||
|                 raise Exception("%s:value is none" % self.name) | ||||
|             fru = ipmifru() | ||||
|             if isinstance(eeprom, bytes): | ||||
|                 eeprom = self.byteTostr(eeprom) | ||||
|             fru.decodeBin(eeprom) | ||||
|             if fru.productInfoArea is not None: | ||||
|                 self.productManufacturer = fru.productInfoArea.productManufacturer.strip() | ||||
|                 self.productName = fru.productInfoArea.productName.strip() | ||||
|                 self.productPartModelName = fru.productInfoArea.productPartModelName.strip() | ||||
|                 self.productVersion = fru.productInfoArea.productVersion.strip() | ||||
|                 self.productSerialNumber = fru.productInfoArea.productSerialNumber.strip().replace(chr(0), "") | ||||
|         except Exception as e: | ||||
|             self.productManufacturer = None | ||||
|             self.productName = None | ||||
|             self.productPartModelName = None | ||||
|             self.productVersion = None | ||||
|             self.productSerialNumber = None | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     def get_fru_info(self): | ||||
|         try: | ||||
|             if self.present is not True: | ||||
|                 raise Exception("%s: not present" % self.name) | ||||
|             if self.get_fru_info_by_sysfs() is True: | ||||
|                 return True | ||||
|             return self.get_fru_info_by_decode() | ||||
|         except Exception as e: | ||||
|             self.productManufacturer = None | ||||
|             self.productName = None | ||||
|             self.productPartModelName = None | ||||
|             self.productVersion = None | ||||
|             self.productSerialNumber = None | ||||
|             return False | ||||
|  | ||||
|     def get_AirFlow(self): | ||||
|         if self.productPartModelName is None: | ||||
|             ret = self.get_fru_info() | ||||
|             if ret is False: | ||||
|                 self.AirFlow = None | ||||
|                 return False | ||||
|         if self.AirFlowconifg is None: | ||||
|             self.AirFlow = None | ||||
|             return False | ||||
|         else: | ||||
|             for i in self.AirFlowconifg: | ||||
|                 if self.productPartModelName in self.AirFlowconifg[i]: | ||||
|                     self.AirFlow = i | ||||
|                     return True | ||||
|         self.AirFlow = None | ||||
|         return False | ||||
|  | ||||
|     def get_psu_display_name(self): | ||||
|         if self.productPartModelName is None: | ||||
|             ret = self.get_fru_info() | ||||
|             if ret is False: | ||||
|                 self.psu_display_name = None | ||||
|                 return False | ||||
|         if self.psu_display_name_conifg is None: | ||||
|             self.psu_display_name = self.productPartModelName | ||||
|             return False | ||||
|         else: | ||||
|             for i in self.psu_display_name_conifg: | ||||
|                 if self.productPartModelName in self.psu_display_name_conifg[i]: | ||||
|                     self.psu_display_name = i | ||||
|                     return True | ||||
|         self.psu_display_name = self.productPartModelName | ||||
|         return False | ||||
							
								
								
									
										156
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/rotor.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										156
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/rotor.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # rotor.py | ||||
| # Python implementation of the Class rotor | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.devicebase import devicebase | ||||
| from plat_hal.sensor import sensor | ||||
|  | ||||
|  | ||||
| class rotor(devicebase): | ||||
|     __rotor_Running = None | ||||
|     __rotor_HwAlarm_conf = None | ||||
|     __rotor_Speed = None | ||||
|     __rotor_run_conf = None | ||||
|     __Speedconfig = None | ||||
|     __i2c_speed = None | ||||
|     __SpeedMin = None | ||||
|     __SpeedMax = None | ||||
|     __SpeedTolerance = None | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         self.name = conf.get('name', None) | ||||
|         self.rotor_HwAlarm_conf = conf.get('HwAlarm', None) | ||||
|         self.rotor_run_conf = conf.get('Running', None) | ||||
|         self.SpeedMin = conf.get('SpeedMin', None) | ||||
|         self.SpeedMax = conf.get('SpeedMax', None) | ||||
|         self.Tolerance = conf.get('tolerance', 30) | ||||
|         self.rotor_Speed = sensor(conf.get('Speed', None)) | ||||
|         self.Speedconfig = conf.get('Set_speed', None) | ||||
|  | ||||
|     def getRunning(self): | ||||
|         ret, val = self.get_value(self.rotor_run_conf) | ||||
|         if ret is False or val is None: | ||||
|             return False | ||||
|         if isinstance(val, str): | ||||
|             value = int(val, 16) | ||||
|         else: | ||||
|             value = val | ||||
|         mask = self.rotor_run_conf.get("mask") | ||||
|         is_runing_value = self.rotor_run_conf.get("is_runing") | ||||
|         flag = value & mask | ||||
|         if flag == is_runing_value: | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     @property | ||||
|     def SpeedMin(self): | ||||
|         return self.__SpeedMin | ||||
|  | ||||
|     @SpeedMin.setter | ||||
|     def SpeedMin(self, val): | ||||
|         self.__SpeedMin = val | ||||
|  | ||||
|     @property | ||||
|     def SpeedMax(self): | ||||
|         return self.__SpeedMax | ||||
|  | ||||
|     @SpeedMax.setter | ||||
|     def SpeedMax(self, val): | ||||
|         self.__SpeedMax = val | ||||
|  | ||||
|     @property | ||||
|     def Tolerance(self): | ||||
|         return self.__SpeedTolerance | ||||
|  | ||||
|     @Tolerance.setter | ||||
|     def Tolerance(self, val): | ||||
|         self.__SpeedTolerance = val | ||||
|  | ||||
|     @property | ||||
|     def i2c_speed(self): | ||||
|         ret, val = self.get_value(self.Speedconfig) | ||||
|         if ret == False: | ||||
|             return None | ||||
|         if val is not None: | ||||
|             self.__i2c_speed = val | ||||
|         return self.__i2c_speed | ||||
|  | ||||
|     def feed_watchdog(self): | ||||
|         ret, val = self.get_value(self.Speedconfig) | ||||
|         if ret == False: | ||||
|             return False, None | ||||
|         if val is not None: | ||||
|             ret, val = self.set_value(self.Speedconfig, val) | ||||
|             return ret, val | ||||
|         return False, None | ||||
|  | ||||
|     @i2c_speed.setter | ||||
|     def i2c_speed(self, val): | ||||
|         self.__i2c_speed = val | ||||
|  | ||||
|     @property | ||||
|     def Speedconfig(self): | ||||
|         return self.__Speedconfig | ||||
|  | ||||
|     @Speedconfig.setter | ||||
|     def Speedconfig(self, val): | ||||
|         self.__Speedconfig = val | ||||
|  | ||||
|     @property | ||||
|     def rotor_run_conf(self): | ||||
|         return self.__rotor_run_conf | ||||
|  | ||||
|     @rotor_run_conf.setter | ||||
|     def rotor_run_conf(self, val): | ||||
|         self.__rotor_run_conf = val | ||||
|  | ||||
|     @property | ||||
|     def rotor_Speed(self): | ||||
|         return self.__rotor_Speed | ||||
|  | ||||
|     @rotor_Speed.setter | ||||
|     def rotor_Speed(self, val): | ||||
|         self.__rotor_Speed = val | ||||
|  | ||||
|     @property | ||||
|     def rotor_HwAlarm(self): | ||||
|         ret, val = self.get_value(self.rotor_HwAlarm_conf) | ||||
|         mask = self.rotor_HwAlarm_conf.get("mask") | ||||
|         no_alarm_value = self.rotor_HwAlarm_conf.get("no_alarm") | ||||
|         if ret is False or val is None: | ||||
|             return False | ||||
|         if isinstance(val, str): | ||||
|             value = int(val, 16) | ||||
|         else: | ||||
|             value = val | ||||
|         flag = value & mask | ||||
|         if flag == no_alarm_value: | ||||
|             return False | ||||
|         else: | ||||
|             return True | ||||
|  | ||||
|     @rotor_HwAlarm.setter | ||||
|     def rotor_HwAlarm(self, val): | ||||
|         self.__rotor_HwAlarm = val | ||||
|  | ||||
|     @property | ||||
|     def rotor_HwAlarm_conf(self): | ||||
|         return self.__rotor_HwAlarm_conf | ||||
|  | ||||
|     @rotor_HwAlarm_conf.setter | ||||
|     def rotor_HwAlarm_conf(self, val): | ||||
|         self.__rotor_HwAlarm_conf = val | ||||
|  | ||||
|     @property | ||||
|     def rotor_Running(self): | ||||
|         self.__rotor_Running = self.getRunning() | ||||
|         return self.__rotor_Running | ||||
|  | ||||
|     @rotor_Running.setter | ||||
|     def rotor_Running(self, val): | ||||
|         self.__rotor_Running = val | ||||
							
								
								
									
										220
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/sensor.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										220
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/sensor.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,220 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # sensor.py | ||||
| # Python implementation of the Class sensor | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| import time | ||||
| from plat_hal.devicebase import devicebase | ||||
|  | ||||
|  | ||||
| class sensor(devicebase): | ||||
|  | ||||
|     __Value = None | ||||
|     __Min = None | ||||
|     __Max = None | ||||
|     __Low = None | ||||
|     __High = None | ||||
|     __ValueConfig = None | ||||
|     __Flag = None | ||||
|     __Unit = None | ||||
|     __format = None | ||||
|     __read_times = None | ||||
|  | ||||
|     __Min_config = None | ||||
|     __Max_config = None | ||||
|     __Low_config = None | ||||
|     __High_config = None | ||||
|  | ||||
|     @property | ||||
|     def Min_config(self): | ||||
|         return self.__Min_config | ||||
|  | ||||
|     @Min_config.setter | ||||
|     def Min_config(self, val): | ||||
|         self.__Min_config = val | ||||
|  | ||||
|     @property | ||||
|     def Max_config(self): | ||||
|         return self.__Max_config | ||||
|  | ||||
|     @Max_config.setter | ||||
|     def Max_config(self, val): | ||||
|         self.__Max_config = val | ||||
|  | ||||
|     @property | ||||
|     def Low_config(self): | ||||
|         return self.__Low_config | ||||
|  | ||||
|     @Low_config.setter | ||||
|     def Low_config(self, val): | ||||
|         self.__Low_config = val | ||||
|  | ||||
|     @property | ||||
|     def High_config(self): | ||||
|         return self.__High_config | ||||
|  | ||||
|     @High_config.setter | ||||
|     def High_config(self, val): | ||||
|         self.__High_config = val | ||||
|  | ||||
|     @property | ||||
|     def Unit(self): | ||||
|         return self.__Unit | ||||
|  | ||||
|     @Unit.setter | ||||
|     def Unit(self, val): | ||||
|         self.__Unit = val | ||||
|  | ||||
|     @property | ||||
|     def format(self): | ||||
|         return self.__format | ||||
|  | ||||
|     @format.setter | ||||
|     def format(self, val): | ||||
|         self.__format = val | ||||
|  | ||||
|     @property | ||||
|     def read_times(self): | ||||
|         return self.__read_times | ||||
|  | ||||
|     @read_times.setter | ||||
|     def read_times(self, val): | ||||
|         self.__read_times = val | ||||
|  | ||||
|     @property | ||||
|     def ValueConfig(self): | ||||
|         return self.__ValueConfig | ||||
|  | ||||
|     @ValueConfig.setter | ||||
|     def ValueConfig(self, val): | ||||
|         self.__ValueConfig = val | ||||
|  | ||||
|     @property | ||||
|     def Flag(self): | ||||
|         return self.__Flag | ||||
|  | ||||
|     @Flag.setter | ||||
|     def Flag(self, val): | ||||
|         self.__Flag = val | ||||
|  | ||||
|     def get_median(self, value_config, read_times): | ||||
|         val_list = [] | ||||
|         for i in range(0, read_times): | ||||
|             ret, real_value = self.get_value(value_config) | ||||
|             if i != (read_times - 1): | ||||
|                 time.sleep(0.01) | ||||
|             if ret is False or real_value is None: | ||||
|                 continue | ||||
|             val_list.append(real_value) | ||||
|         val_list.sort() | ||||
|         if val_list: | ||||
|             return True, val_list[int((len(val_list) - 1) / 2)] | ||||
|         return False, None | ||||
|  | ||||
|     @property | ||||
|     def Value(self): | ||||
|         try: | ||||
|             ret, val = self.get_median(self.ValueConfig, self.read_times) | ||||
|             if ret is False or val is None: | ||||
|                 return None | ||||
|             if self.format is None: | ||||
|                 self.__Value = int(val) | ||||
|             else: | ||||
|                 self.__Value = eval(self.format % val) | ||||
|             self.__Value = round(float(self.__Value), 3) | ||||
|         except Exception as e: | ||||
|             return None | ||||
|         return self.__Value | ||||
|  | ||||
|     @Value.setter | ||||
|     def Value(self, val): | ||||
|         self.__Value = val | ||||
|  | ||||
|     @property | ||||
|     def Min(self): | ||||
|         try: | ||||
|             if self.format is None: | ||||
|                 self.__Min = self.Min_config | ||||
|             else: | ||||
|                 self.__Min = eval(self.format % self.Min_config) | ||||
|             self.__Min = round(float(self.__Min), 3) | ||||
|         except Exception as e: | ||||
|             return None | ||||
|         return self.__Min | ||||
|  | ||||
|     @Min.setter | ||||
|     def Min(self, val): | ||||
|         self.__Min = val | ||||
|  | ||||
|     @property | ||||
|     def Max(self): | ||||
|         try: | ||||
|             if self.format is None: | ||||
|                 self.__Max = self.Max_config | ||||
|             else: | ||||
|                 self.__Max = eval(self.format % self.Max_config) | ||||
|             self.__Max = round(float(self.__Max), 3) | ||||
|         except Exception as e: | ||||
|             return None | ||||
|         return self.__Max | ||||
|  | ||||
|     @Max.setter | ||||
|     def Max(self, val): | ||||
|         self.__Max = val | ||||
|  | ||||
|     @property | ||||
|     def Low(self): | ||||
|         try: | ||||
|             if self.format is None: | ||||
|                 self.__Low = self.Low_config | ||||
|             else: | ||||
|                 self.__Low = eval(self.format % self.Low_config) | ||||
|         except Exception as e: | ||||
|             return None | ||||
|         return self.__Low | ||||
|  | ||||
|     @Low.setter | ||||
|     def Low(self, val): | ||||
|         self.__Low = val | ||||
|  | ||||
|     @property | ||||
|     def High(self): | ||||
|         try: | ||||
|             if self.format is None: | ||||
|                 self.__High = self.High_config | ||||
|             else: | ||||
|                 self.__High = eval(self.format % self.High_config) | ||||
|         except Exception as e: | ||||
|             return None | ||||
|         return self.__High | ||||
|  | ||||
|     @High.setter | ||||
|     def High(self, val): | ||||
|         self.__High = val | ||||
|  | ||||
|     def __init__(self, conf=None): | ||||
|         self.ValueConfig = conf.get("value", None) | ||||
|         self.Flag = conf.get("flag", None) | ||||
|         self.Min_config = conf.get("Min", None) | ||||
|         self.Max_config = conf.get("Max", None) | ||||
|         self.Low_config = conf.get("Low", None) | ||||
|         self.High_config = conf.get("High", None) | ||||
|         self.Unit = conf.get('Unit', None) | ||||
|         self.format = conf.get('format', None) | ||||
|         self.read_times = conf.get('read_times', 1) | ||||
|  | ||||
|     def __str__(self): | ||||
|         formatstr =  \ | ||||
|             "ValueConfig:                : %s \n" \ | ||||
|             "Min :          %s \n" \ | ||||
|             "Max : %s \n" \ | ||||
|             "Unit  : %s \n" \ | ||||
|             "format:       : %s \n" | ||||
|  | ||||
|         tmpstr = formatstr % (self.ValueConfig, self.Min, | ||||
|                               self.Max, self.Unit, | ||||
|                               self.format) | ||||
|         return tmpstr | ||||
							
								
								
									
										138
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/temp.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										138
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/plat_hal/temp.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| #!/usr/bin/env python3 | ||||
| ####################################################### | ||||
| # | ||||
| # temp.py | ||||
| # Python implementation of the Class temp | ||||
| # Original author: rd@ruijie.com.cn | ||||
| # | ||||
| ####################################################### | ||||
| from plat_hal.sensor import sensor | ||||
| import os | ||||
| import syslog | ||||
|  | ||||
|  | ||||
| PLATFORM_HAL_TEMP_DEBUG_FILE = "/etc/.platform_hal_temp_debug_flag" | ||||
|  | ||||
| def platform_hal_temp_debug(s): | ||||
|     if os.path.exists(PLATFORM_HAL_TEMP_DEBUG_FILE): | ||||
|         syslog.openlog("PLATFORM_HAL_TEPM", syslog.LOG_PID) | ||||
|         syslog.syslog(syslog.LOG_DEBUG, s) | ||||
|  | ||||
| class temp(sensor): | ||||
|     def __init__(self, conf=None): | ||||
|         super(temp, self).__init__(conf.get('Temperature', None)) | ||||
|         self.name = conf.get("name", None) | ||||
|         self.temp_id = conf.get("temp_id", None) | ||||
|         self.api_name = conf.get("api_name", self.name) | ||||
|         self.fix_value =  conf.get("fix_value", None) | ||||
|         self.temp_invalid =  conf.get("invalid", None) | ||||
|         self.temp_error =  conf.get("error", None) | ||||
|  | ||||
|     def __str__(self): | ||||
|         super(temp, self).__str__() | ||||
|  | ||||
|     def temp_cali_by_fan_pwm(self, param, origin_value): | ||||
|         fan_pwm_conf = param.get("fan_pwm") | ||||
|         temp_fix_list = param.get("temp_fix_list") | ||||
|  | ||||
|  | ||||
|         ret, val = self.get_value(fan_pwm_conf) | ||||
|         if ret is False or val is None: | ||||
|             platform_hal_temp_debug("temp calibration get fan pwm failed, msg: %s, return None" % (val)) | ||||
|             return None | ||||
|  | ||||
|         fan_pwm = int(val) | ||||
|         for item in temp_fix_list: | ||||
|             if fan_pwm >= item["min"] and fan_pwm <= item["max"]: | ||||
|                 fix_value = origin_value + item["fix"] | ||||
|                 platform_hal_temp_debug("temp calibration by fan pwm, origin_value: %s, pwm: %s, fix_value: %s" % | ||||
|                     (origin_value, fan_pwm, fix_value)) | ||||
|                 return fix_value | ||||
|         platform_hal_temp_debug("temp calibration by fan pwm, origin_value: %s, pwm: %s, not match return None" % | ||||
|                     (origin_value, fan_pwm)) | ||||
|         return None | ||||
|  | ||||
|     def fix_temp_value(self, origin_value): | ||||
|         try: | ||||
|             fix_type = self.fix_value.get("fix_type") | ||||
|  | ||||
|             if fix_type == "func": | ||||
|                 func_name = self.fix_value.get("func_name") | ||||
|                 func_param = self.fix_value.get("func_param") | ||||
|                 value = eval(func_name)(func_param, origin_value) | ||||
|                 return value | ||||
|  | ||||
|             if fix_type == "config": | ||||
|                 coefficient = self.fix_value.get("coefficient", 1) | ||||
|                 addend = self.fix_value.get("addend", 0) | ||||
|                 value = (origin_value + addend) * coefficient | ||||
|                 platform_hal_temp_debug("temp calibration by config, coefficient: %s, addend: %s, origin_value: %s, fix_value: %s" % | ||||
|                     (coefficient, addend, origin_value, value)) | ||||
|                 return value | ||||
|  | ||||
|             platform_hal_temp_debug("unsupport fix type: %s, return origin value: %s" % (fix_type, origin_value)) | ||||
|             return origin_value | ||||
|         except Exception as e: | ||||
|             platform_hal_temp_debug("fix_temp_value raise exception, msg: %s" % (str(e))) | ||||
|             return None | ||||
|  | ||||
|     def get_max_value(self, conf): | ||||
|         try: | ||||
|             ret, val = self.get_value(conf) | ||||
|             if ret is False or val is None: | ||||
|                 return None | ||||
|             return val | ||||
|         except Exception as e: | ||||
|             return None | ||||
|  | ||||
|     def check_flag(self): | ||||
|         try: | ||||
|             okbit = self.Flag.get('okbit') | ||||
|             okval = self.Flag.get('okval') | ||||
|             ret, val = self.get_value(self.Flag) | ||||
|             if (ret == False) or (val is None): | ||||
|                 return False | ||||
|             val_t = (int(val) & (1 << okbit)) >> okbit | ||||
|             if val_t != okval: | ||||
|                 return False | ||||
|         except Exception as e: | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     @property | ||||
|     def Value(self): | ||||
|         try: | ||||
|             if self.Flag is not None: | ||||
|                 if self.check_flag() == False: | ||||
|                     return None | ||||
|             if isinstance(self.ValueConfig, list): | ||||
|                 max = None | ||||
|                 for i in self.ValueConfig: | ||||
|                     tmp = self.get_max_value(i) | ||||
|                     if tmp is None: | ||||
|                         continue | ||||
|                     if max is None or max < tmp: | ||||
|                         max = tmp | ||||
|                 if max is None: | ||||
|                     return None | ||||
|                 if self.format is None: | ||||
|                     self.__Value = int(max) | ||||
|                 else: | ||||
|                     self.__Value = eval(self.format % max) | ||||
|             else: | ||||
|                 ret, val = self.get_value(self.ValueConfig) | ||||
|                 if ret is False or val is None: | ||||
|                     return None | ||||
|                 if self.format is None: | ||||
|                     self.__Value = int(val) | ||||
|                 else: | ||||
|                     self.__Value = eval(self.format % val) | ||||
|         except Exception as e: | ||||
|             return None | ||||
|         if self.fix_value is not None and self.__Value != self.temp_invalid and self.__Value != self.temp_error: | ||||
|             self.__Value = self.fix_temp_value(self.__Value) | ||||
|         return self.__Value | ||||
|  | ||||
|     @Value.setter | ||||
|     def Value(self, val): | ||||
|         self.__Value = val | ||||
| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import os | ||||
|  | ||||
|  | ||||
| def get_machine_info(): | ||||
|     if not os.path.isfile('/host/machine.conf'): | ||||
|         return None | ||||
|     machine_vars = {} | ||||
|     with open('/host/machine.conf') as machine_file: | ||||
|         for line in machine_file: | ||||
|             tokens = line.split('=') | ||||
|             if len(tokens) < 2: | ||||
|                 continue | ||||
|             machine_vars[tokens[0]] = tokens[1].strip() | ||||
|     return machine_vars | ||||
|  | ||||
|  | ||||
| def get_platform_info(machine_info): | ||||
|     if machine_info is not None: | ||||
|         if 'onie_platform' in machine_info: | ||||
|             return machine_info['onie_platform'] | ||||
|         elif 'aboot_platform' in machine_info: | ||||
|             return machine_info['aboot_platform'] | ||||
|     return None | ||||
|  | ||||
|  | ||||
| def get_board_id(machine_info): | ||||
|     if machine_info is not None: | ||||
|         if 'onie_board_id' in machine_info: | ||||
|             return machine_info['onie_board_id'].lower() | ||||
|     return "NA" | ||||
|  | ||||
|  | ||||
| def get_onie_machine(machine_info): | ||||
|     if machine_info is not None: | ||||
|         if 'onie_machine' in machine_info: | ||||
|             return machine_info['onie_machine'] | ||||
|     return None | ||||
|  | ||||
							
								
								
									
										777
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/rjutil/smbus.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										777
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/lib/rjutil/smbus.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,777 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # smbus2 - A drop-in replacement for smbus-cffi/smbus-python | ||||
| # The MIT License (MIT) | ||||
| # Copyright (c) 2017 Karl-Petter Lindegaard | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in all | ||||
| # copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | ||||
|  | ||||
| import os | ||||
| import sys | ||||
| from fcntl import ioctl | ||||
| from ctypes import c_uint32, c_uint8, c_uint16, c_char, POINTER, Structure, Array, Union, create_string_buffer, string_at | ||||
|  | ||||
|  | ||||
| # Commands from uapi/linux/i2c-dev.h | ||||
| I2C_SLAVE = 0x0703  # Use this slave address | ||||
| I2C_SLAVE_FORCE = 0x0706  # Use this slave address, even if it is already in use by a driver! | ||||
| I2C_FUNCS = 0x0705  # Get the adapter functionality mask | ||||
| I2C_RDWR = 0x0707  # Combined R/W transfer (one STOP only) | ||||
| I2C_SMBUS = 0x0720  # SMBus transfer. Takes pointer to i2c_smbus_ioctl_data | ||||
| I2C_PEC = 0x0708 | ||||
|  | ||||
| # SMBus transfer read or write markers from uapi/linux/i2c.h | ||||
| I2C_SMBUS_WRITE = 0 | ||||
| I2C_SMBUS_READ = 1 | ||||
|  | ||||
| # Size identifiers uapi/linux/i2c.h | ||||
| I2C_SMBUS_QUICK = 0 | ||||
| I2C_SMBUS_BYTE = 1 | ||||
| I2C_SMBUS_BYTE_DATA = 2 | ||||
| I2C_SMBUS_WORD_DATA = 3 | ||||
| I2C_SMBUS_PROC_CALL = 4 | ||||
| # This isn't supported by Pure-I2C drivers with SMBUS emulation, like those in RaspberryPi, OrangePi, etc :( | ||||
| I2C_SMBUS_BLOCK_DATA = 5 | ||||
| I2C_SMBUS_BLOCK_PROC_CALL = 7  # Like I2C_SMBUS_BLOCK_DATA, it isn't supported by Pure-I2C drivers either. | ||||
| I2C_SMBUS_I2C_BLOCK_DATA = 8 | ||||
| I2C_SMBUS_BLOCK_MAX = 32 | ||||
|  | ||||
| # To determine what functionality is present (uapi/linux/i2c.h) | ||||
| try: | ||||
|     from enum import IntFlag | ||||
| except Exception as e: | ||||
|     IntFlag = int | ||||
|  | ||||
|  | ||||
| class I2cFunc(IntFlag): | ||||
|     """ | ||||
|     These flags identify the operations supported by an I2C/SMBus device. | ||||
|  | ||||
|     You can test these flags on your `smbus.funcs` | ||||
|  | ||||
|     On newer python versions, I2cFunc is an IntFlag enum, but it | ||||
|     falls back to class with a bunch of int constants on older releases. | ||||
|     """ | ||||
|     I2C = 0x00000001 | ||||
|     ADDR_10BIT = 0x00000002 | ||||
|     PROTOCOL_MANGLING = 0x00000004  # I2C_M_IGNORE_NAK etc. | ||||
|     SMBUS_PEC = 0x00000008 | ||||
|     NOSTART = 0x00000010  # I2C_M_NOSTART | ||||
|     SLAVE = 0x00000020 | ||||
|     SMBUS_BLOCK_PROC_CALL = 0x00008000  # SMBus 2.0 | ||||
|     SMBUS_QUICK = 0x00010000 | ||||
|     SMBUS_READ_BYTE = 0x00020000 | ||||
|     SMBUS_WRITE_BYTE = 0x00040000 | ||||
|     SMBUS_READ_BYTE_DATA = 0x00080000 | ||||
|     SMBUS_WRITE_BYTE_DATA = 0x00100000 | ||||
|     SMBUS_READ_WORD_DATA = 0x00200000 | ||||
|     SMBUS_WRITE_WORD_DATA = 0x00400000 | ||||
|     SMBUS_PROC_CALL = 0x00800000 | ||||
|     SMBUS_READ_BLOCK_DATA = 0x01000000 | ||||
|     SMBUS_WRITE_BLOCK_DATA = 0x02000000 | ||||
|     SMBUS_READ_I2C_BLOCK = 0x04000000  # I2C-like block xfer | ||||
|     SMBUS_WRITE_I2C_BLOCK = 0x08000000  # w/ 1-byte reg. addr. | ||||
|     SMBUS_HOST_NOTIFY = 0x10000000 | ||||
|  | ||||
|     SMBUS_BYTE = 0x00060000 | ||||
|     SMBUS_BYTE_DATA = 0x00180000 | ||||
|     SMBUS_WORD_DATA = 0x00600000 | ||||
|     SMBUS_BLOCK_DATA = 0x03000000 | ||||
|     SMBUS_I2C_BLOCK = 0x0c000000 | ||||
|     SMBUS_EMUL = 0x0eff0008 | ||||
|  | ||||
|  | ||||
| # i2c_msg flags from uapi/linux/i2c.h | ||||
| I2C_M_RD = 0x0001 | ||||
|  | ||||
| # Pointer definitions | ||||
| LP_c_uint8 = POINTER(c_uint8) | ||||
| LP_c_uint16 = POINTER(c_uint16) | ||||
| LP_c_uint32 = POINTER(c_uint32) | ||||
|  | ||||
|  | ||||
| ############################################################# | ||||
| # Type definitions as in i2c.h | ||||
|  | ||||
|  | ||||
| class i2c_smbus_data(Array): | ||||
|     """ | ||||
|     Adaptation of the i2c_smbus_data union in ``i2c.h``. | ||||
|  | ||||
|     Data for SMBus messages. | ||||
|     """ | ||||
|     _length_ = I2C_SMBUS_BLOCK_MAX + 2 | ||||
|     _type_ = c_uint8 | ||||
|  | ||||
|  | ||||
| class union_i2c_smbus_data(Union): | ||||
|     _fields_ = [ | ||||
|         ("byte", c_uint8), | ||||
|         ("word", c_uint16), | ||||
|         ("block", i2c_smbus_data) | ||||
|     ] | ||||
|  | ||||
|  | ||||
| union_pointer_type = POINTER(union_i2c_smbus_data) | ||||
|  | ||||
|  | ||||
| class i2c_smbus_ioctl_data(Structure): | ||||
|     """ | ||||
|     As defined in ``i2c-dev.h``. | ||||
|     """ | ||||
|     _fields_ = [ | ||||
|         ('read_write', c_uint8), | ||||
|         ('command', c_uint8), | ||||
|         ('size', c_uint32), | ||||
|         ('data', union_pointer_type)] | ||||
|     __slots__ = [name for name, type in _fields_] | ||||
|  | ||||
|     @staticmethod | ||||
|     def create(read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE_DATA): | ||||
|         u = union_i2c_smbus_data() | ||||
|         return i2c_smbus_ioctl_data( | ||||
|             read_write=read_write, command=command, size=size, | ||||
|             data=union_pointer_type(u)) | ||||
|  | ||||
|  | ||||
| ############################################################# | ||||
| # Type definitions for i2c_rdwr combined transactions | ||||
|  | ||||
|  | ||||
| class i2c_msg(Structure): | ||||
|     """ | ||||
|     As defined in ``i2c.h``. | ||||
|     """ | ||||
|     _fields_ = [ | ||||
|         ('addr', c_uint16), | ||||
|         ('flags', c_uint16), | ||||
|         ('len', c_uint16), | ||||
|         ('buf', POINTER(c_char))] | ||||
|  | ||||
|     def __iter__(self): | ||||
|         """ Iterator / Generator | ||||
|  | ||||
|         :return: iterates over :py:attr:`buf` | ||||
|         :rtype: :py:class:`generator` which returns int values | ||||
|         """ | ||||
|         idx = 0 | ||||
|         while idx < self.len: | ||||
|             yield ord(self.buf[idx]) | ||||
|             idx += 1 | ||||
|  | ||||
|     def __len__(self): | ||||
|         return self.len | ||||
|  | ||||
|     def __bytes__(self): | ||||
|         return string_at(self.buf, self.len) | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return 'i2c_msg(%d,%d,%r)' % (self.addr, self.flags, self.__bytes__()) | ||||
|  | ||||
|     def __str__(self): | ||||
|         s = self.__bytes__() | ||||
|         if sys.version_info.major >= 3: | ||||
|             s = ''.join(map(chr, s)) | ||||
|         return s | ||||
|  | ||||
|     @staticmethod | ||||
|     def read(address, length): | ||||
|         """ | ||||
|         Prepares an i2c read transaction. | ||||
|  | ||||
|         :param address: Slave address. | ||||
|         :type: address: int | ||||
|         :param length: Number of bytes to read. | ||||
|         :type: length: int | ||||
|         :return: New :py:class:`i2c_msg` instance for read operation. | ||||
|         :rtype: :py:class:`i2c_msg` | ||||
|         """ | ||||
|         arr = create_string_buffer(length) | ||||
|         return i2c_msg( | ||||
|             addr=address, flags=I2C_M_RD, len=length, | ||||
|             buf=arr) | ||||
|  | ||||
|     @staticmethod | ||||
|     def write(address, buf): | ||||
|         """ | ||||
|         Prepares an i2c write transaction. | ||||
|  | ||||
|         :param address: Slave address. | ||||
|         :type address: int | ||||
|         :param buf: Bytes to write. Either list of values or str. | ||||
|         :type buf: list | ||||
|         :return: New :py:class:`i2c_msg` instance for write operation. | ||||
|         :rtype: :py:class:`i2c_msg` | ||||
|         """ | ||||
|         if sys.version_info.major >= 3: | ||||
|             if isinstance(buf, str): | ||||
|                 buf = bytes(map(ord, buf)) | ||||
|             else: | ||||
|                 buf = bytes(buf) | ||||
|         else: | ||||
|             if not isinstance(buf, str): | ||||
|                 buf = ''.join([chr(x) for x in buf]) | ||||
|         arr = create_string_buffer(buf, len(buf)) | ||||
|         return i2c_msg( | ||||
|             addr=address, flags=0, len=len(arr), | ||||
|             buf=arr) | ||||
|  | ||||
|  | ||||
| class i2c_rdwr_ioctl_data(Structure): | ||||
|     """ | ||||
|     As defined in ``i2c-dev.h``. | ||||
|     """ | ||||
|     _fields_ = [ | ||||
|         ('msgs', POINTER(i2c_msg)), | ||||
|         ('nmsgs', c_uint32) | ||||
|     ] | ||||
|     __slots__ = [name for name, type in _fields_] | ||||
|  | ||||
|     @staticmethod | ||||
|     def create(*i2c_msg_instances): | ||||
|         """ | ||||
|         Factory method for creating a i2c_rdwr_ioctl_data struct that can | ||||
|         be called with ``ioctl(fd, I2C_RDWR, data)``. | ||||
|  | ||||
|         :param i2c_msg_instances: Up to 42 i2c_msg instances | ||||
|         :rtype: i2c_rdwr_ioctl_data | ||||
|         """ | ||||
|         n_msg = len(i2c_msg_instances) | ||||
|         msg_array = (i2c_msg * n_msg)(*i2c_msg_instances) | ||||
|         return i2c_rdwr_ioctl_data( | ||||
|             msgs=msg_array, | ||||
|             nmsgs=n_msg | ||||
|         ) | ||||
|  | ||||
|  | ||||
| ############################################################# | ||||
|  | ||||
|  | ||||
| class SMBus(object): | ||||
|  | ||||
|     def __init__(self, bus=None, force=False): | ||||
|         """ | ||||
|         Initialize and (optionally) open an i2c bus connection. | ||||
|  | ||||
|         :param bus: i2c bus number (e.g. 0 or 1) | ||||
|             or an absolute file path (e.g. `/dev/i2c-42`). | ||||
|             If not given, a subsequent  call to ``open()`` is required. | ||||
|         :type bus: int or str | ||||
|         :param force: force using the slave address even when driver is | ||||
|             already using it. | ||||
|         :type force: boolean | ||||
|         """ | ||||
|         self.fd = None | ||||
|         self.funcs = I2cFunc(0) | ||||
|         if bus is not None: | ||||
|             self.open(bus) | ||||
|         self.address = None | ||||
|         self.force = force | ||||
|         self._force_last = None | ||||
|  | ||||
|     def __enter__(self): | ||||
|         """Enter handler.""" | ||||
|         return self | ||||
|  | ||||
|     def __exit__(self, exc_type, exc_val, exc_tb): | ||||
|         """Exit handler.""" | ||||
|         self.close() | ||||
|  | ||||
|     def open(self, bus): | ||||
|         """ | ||||
|         Open a given i2c bus. | ||||
|  | ||||
|         :param bus: i2c bus number (e.g. 0 or 1) | ||||
|             or an absolute file path (e.g. '/dev/i2c-42'). | ||||
|         :type bus: int or str | ||||
|         :raise TypeError: if type(bus) is not in (int, str) | ||||
|         """ | ||||
|         if isinstance(bus, int): | ||||
|             filepath = "/dev/i2c-{}".format(bus) | ||||
|         elif isinstance(bus, str): | ||||
|             filepath = bus | ||||
|         else: | ||||
|             raise TypeError("Unexpected type(bus)={}".format(type(bus))) | ||||
|  | ||||
|         self.fd = os.open(filepath, os.O_RDWR) | ||||
|         self.funcs = self._get_funcs() | ||||
|  | ||||
|     def close(self): | ||||
|         """ | ||||
|         Close the i2c connection. | ||||
|         """ | ||||
|         if self.fd: | ||||
|             os.close(self.fd) | ||||
|             self.fd = None | ||||
|  | ||||
|     def _set_address(self, address, force=None): | ||||
|         """ | ||||
|         Set i2c slave address to use for subsequent calls. | ||||
|  | ||||
|         :param address: | ||||
|         :type address: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         """ | ||||
|         force = force if force is not None else self.force | ||||
|         if self.address != address or self._force_last != force: | ||||
|             if force is True: | ||||
|                 ioctl(self.fd, I2C_SLAVE_FORCE, address) | ||||
|             else: | ||||
|                 ioctl(self.fd, I2C_SLAVE, address) | ||||
|             self.address = address | ||||
|             self._force_last = force | ||||
|  | ||||
|     def _get_funcs(self): | ||||
|         """ | ||||
|         Returns a 32-bit value stating supported I2C functions. | ||||
|  | ||||
|         :rtype: int | ||||
|         """ | ||||
|         f = c_uint32() | ||||
|         ioctl(self.fd, I2C_FUNCS, f) | ||||
|         return f.value | ||||
|  | ||||
|     def write_quick(self, i2c_addr, force=None): | ||||
|         """ | ||||
|         Perform quick transaction. Throws IOError if unsuccessful. | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         """ | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_WRITE, command=0, size=I2C_SMBUS_QUICK) | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|  | ||||
|     def read_byte(self, i2c_addr, force=None): | ||||
|         """ | ||||
|         Read a single byte from a device. | ||||
|  | ||||
|         :rtype: int | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :return: Read byte value | ||||
|         """ | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE | ||||
|         ) | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         return msg.data.contents.byte | ||||
|  | ||||
|     def write_byte(self, i2c_addr, value, force=None): | ||||
|         """ | ||||
|         Write a single byte to a device. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param value: value to write | ||||
|         :type value: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         """ | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_WRITE, command=value, size=I2C_SMBUS_BYTE | ||||
|         ) | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|  | ||||
|     def read_byte_data(self, i2c_addr, register, force=None): | ||||
|         """ | ||||
|         Read a single byte from a designated register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to read | ||||
|         :type register: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :return: Read byte value | ||||
|         :rtype: int | ||||
|         """ | ||||
|         val_t = -1 | ||||
|         returnmsg = "" | ||||
|         try: | ||||
|             self._set_address(i2c_addr, force=force) | ||||
|             msg = i2c_smbus_ioctl_data.create( | ||||
|                 read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BYTE_DATA | ||||
|             ) | ||||
|             val_t = ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         except Exception as e: | ||||
|             self.close() | ||||
|             returnmsg = str(e) | ||||
|         if val_t < 0: | ||||
|             return False, returnmsg | ||||
|         else: | ||||
|             return True, msg.data.contents.byte | ||||
|  | ||||
|     def write_byte_data(self, i2c_addr, register, value, force=None): | ||||
|         """ | ||||
|         Write a byte to a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to write to | ||||
|         :type register: int | ||||
|         :param value: Byte value to transmit | ||||
|         :type value: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: None | ||||
|         """ | ||||
|         val_t = -1 | ||||
|         returnmsg = "" | ||||
|         try: | ||||
|             self._set_address(i2c_addr, force=force) | ||||
|             msg = i2c_smbus_ioctl_data.create( | ||||
|                 read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA | ||||
|             ) | ||||
|             msg.data.contents.byte = value | ||||
|             val_t = ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         except Exception as e: | ||||
|             returnmsg = str(e) | ||||
|             self.close() | ||||
|         if val_t < 0: | ||||
|             return False, returnmsg or "" | ||||
|         else: | ||||
|             return True, "" | ||||
|  | ||||
|     def write_byte_data_pec(self, i2c_addr, register, value, force=None): | ||||
|         """ | ||||
|         Write a byte to a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to write to | ||||
|         :type register: int | ||||
|         :param value: Byte value to transmit | ||||
|         :type value: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: None | ||||
|         """ | ||||
|         val_t = -1 | ||||
|         returnmsg = "" | ||||
|         try: | ||||
|             val_t = ioctl(self.fd, I2C_PEC, 1) | ||||
|             if val_t < 0: | ||||
|                 raise Exception("set pec mod error") | ||||
|             self._set_address(i2c_addr, force=force) | ||||
|             msg = i2c_smbus_ioctl_data.create( | ||||
|                 read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA | ||||
|             ) | ||||
|             msg.data.contents.byte = value | ||||
|             val_t = ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         except Exception as e: | ||||
|             returnmsg = str(e) | ||||
|             self.close() | ||||
|         if val_t < 0: | ||||
|             return False, returnmsg or "" | ||||
|         else: | ||||
|             return True, "" | ||||
|  | ||||
|     def read_word_data(self, i2c_addr, register, force=None): | ||||
|         """ | ||||
|         Read a single word (2 bytes) from a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to read | ||||
|         :type register: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :return: 2-byte word | ||||
|         :rtype: int | ||||
|         """ | ||||
|         val_t = -1 | ||||
|         returnmsg = "" | ||||
|         try: | ||||
|             self._set_address(i2c_addr, force=force) | ||||
|             msg = i2c_smbus_ioctl_data.create( | ||||
|                 read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_WORD_DATA | ||||
|             ) | ||||
|             val_t = ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         except Exception as e: | ||||
|             returnmsg = str(e) | ||||
|             self.close() | ||||
|         if val_t < 0: | ||||
|             return False, returnmsg or "" | ||||
|         else: | ||||
|             return True, msg.data.contents.word | ||||
|  | ||||
|     def write_word_data_pec(self, i2c_addr, register, value, force=None): | ||||
|         """ | ||||
|         Write a byte to a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to write to | ||||
|         :type register: int | ||||
|         :param value: Word value to transmit | ||||
|         :type value: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: None | ||||
|         """ | ||||
|         val_t = -1 | ||||
|         returnmsg = "" | ||||
|         try: | ||||
|             val_t = ioctl(self.fd, I2C_PEC, 1) | ||||
|             if val_t < 0: | ||||
|                 raise Exception("set pec mod error") | ||||
|             self._set_address(i2c_addr, force=force) | ||||
|             msg = i2c_smbus_ioctl_data.create( | ||||
|                 read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA | ||||
|             ) | ||||
|             msg.data.contents.word = value | ||||
|             val_t = ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         except Exception as e: | ||||
|             returnmsg = str(e) | ||||
|             self.close() | ||||
|         if val_t < 0: | ||||
|             return False, returnmsg or "" | ||||
|         else: | ||||
|             return True, "" | ||||
|  | ||||
|     def write_word_data(self, i2c_addr, register, value, force=None): | ||||
|         """ | ||||
|         Write a byte to a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to write to | ||||
|         :type register: int | ||||
|         :param value: Word value to transmit | ||||
|         :type value: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: None | ||||
|         """ | ||||
|         val_t = -1 | ||||
|         returnmsg = "" | ||||
|         try: | ||||
|             self._set_address(i2c_addr, force=force) | ||||
|             msg = i2c_smbus_ioctl_data.create( | ||||
|                 read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA | ||||
|             ) | ||||
|             msg.data.contents.word = value | ||||
|             val_t = ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         except Exception as e: | ||||
|             returnmsg = str(e) | ||||
|             self.close() | ||||
|         if val_t < 0: | ||||
|             return False, returnmsg or "" | ||||
|         else: | ||||
|             return True, "" | ||||
|  | ||||
|     def process_call(self, i2c_addr, register, value, force=None): | ||||
|         """ | ||||
|         Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to read/write to | ||||
|         :type register: int | ||||
|         :param value: Word value to transmit | ||||
|         :type value: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: int | ||||
|         """ | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_PROC_CALL | ||||
|         ) | ||||
|         msg.data.contents.word = value | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         return msg.data.contents.word | ||||
|  | ||||
|     def read_block_data(self, i2c_addr, register, force=None): | ||||
|         """ | ||||
|         Read a block of up to 32-bytes from a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Start register | ||||
|         :type register: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :return: List of bytes | ||||
|         :rtype: list | ||||
|         """ | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BLOCK_DATA | ||||
|         ) | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         length = msg.data.contents.block[0] | ||||
|         return msg.data.contents.block[1:length + 1] | ||||
|  | ||||
|     def write_block_data(self, i2c_addr, register, data, force=None): | ||||
|         """ | ||||
|         Write a block of byte data to a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Start register | ||||
|         :type register: int | ||||
|         :param data: List of bytes | ||||
|         :type data: list | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: None | ||||
|         """ | ||||
|         length = len(data) | ||||
|         if length > I2C_SMBUS_BLOCK_MAX: | ||||
|             raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_DATA | ||||
|         ) | ||||
|         msg.data.contents.block[0] = length | ||||
|         msg.data.contents.block[1:length + 1] = data | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|  | ||||
|     def block_process_call(self, i2c_addr, register, data, force=None): | ||||
|         """ | ||||
|         Executes a SMBus Block Process Call, sending a variable-size data | ||||
|         block and receiving another variable-size response | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Register to read/write to | ||||
|         :type register: int | ||||
|         :param data: List of bytes | ||||
|         :type data: list | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :return: List of bytes | ||||
|         :rtype: list | ||||
|         """ | ||||
|         length = len(data) | ||||
|         if length > I2C_SMBUS_BLOCK_MAX: | ||||
|             raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_PROC_CALL | ||||
|         ) | ||||
|         msg.data.contents.block[0] = length | ||||
|         msg.data.contents.block[1:length + 1] = data | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         length = msg.data.contents.block[0] | ||||
|         return msg.data.contents.block[1:length + 1] | ||||
|  | ||||
|     def read_i2c_block_data(self, i2c_addr, register, length, force=None): | ||||
|         """ | ||||
|         Read a block of byte data from a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Start register | ||||
|         :type register: int | ||||
|         :param length: Desired block length | ||||
|         :type length: int | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :return: List of bytes | ||||
|         :rtype: list | ||||
|         """ | ||||
|         if length > I2C_SMBUS_BLOCK_MAX: | ||||
|             raise ValueError("Desired block length over %d bytes" % I2C_SMBUS_BLOCK_MAX) | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA | ||||
|         ) | ||||
|         msg.data.contents.byte = length | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|         return msg.data.contents.block[1:length + 1] | ||||
|  | ||||
|     def write_i2c_block_data(self, i2c_addr, register, data, force=None): | ||||
|         """ | ||||
|         Write a block of byte data to a given register. | ||||
|  | ||||
|         :param i2c_addr: i2c address | ||||
|         :type i2c_addr: int | ||||
|         :param register: Start register | ||||
|         :type register: int | ||||
|         :param data: List of bytes | ||||
|         :type data: list | ||||
|         :param force: | ||||
|         :type force: Boolean | ||||
|         :rtype: None | ||||
|         """ | ||||
|         length = len(data) | ||||
|         if length > I2C_SMBUS_BLOCK_MAX: | ||||
|             raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) | ||||
|         self._set_address(i2c_addr, force=force) | ||||
|         msg = i2c_smbus_ioctl_data.create( | ||||
|             read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA | ||||
|         ) | ||||
|         msg.data.contents.block[0] = length | ||||
|         msg.data.contents.block[1:length + 1] = data | ||||
|         ioctl(self.fd, I2C_SMBUS, msg) | ||||
|  | ||||
|     def i2c_rdwr(self, *i2c_msgs): | ||||
|         """ | ||||
|         Combine a series of i2c read and write operations in a single | ||||
|         transaction (with repeated start bits but no stop bits in between). | ||||
|  | ||||
|         This method takes i2c_msg instances as input, which must be created | ||||
|         first with :py:meth:`i2c_msg.read` or :py:meth:`i2c_msg.write`. | ||||
|  | ||||
|         :param i2c_msgs: One or more i2c_msg class instances. | ||||
|         :type i2c_msgs: i2c_msg | ||||
|         :rtype: None | ||||
|         """ | ||||
|         ioctl_data = i2c_rdwr_ioctl_data.create(*i2c_msgs) | ||||
|         ioctl(self.fd, I2C_RDWR, ioctl_data) | ||||
|  | ||||
|  | ||||
| class SMBusWrapper: | ||||
|     """ | ||||
|     Wrapper class around the SMBus. | ||||
|     Deprecated as of version 0.3.0. Please replace with :py:class:`SMBus`. | ||||
|  | ||||
|     Enables the user to wrap access to the :py:class:`SMBus` class in a | ||||
|     "with" statement. If auto_cleanup is True (default), the | ||||
|     :py:class:`SMBus` handle will be automatically closed | ||||
|     upon exit of the ``with`` block. | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, bus_number=0, auto_cleanup=True, force=False): | ||||
|         """ | ||||
|         :param auto_cleanup: Close bus when leaving scope. | ||||
|         :type auto_cleanup: Boolean | ||||
|         :param force: Force using the slave address even when driver is already using it. | ||||
|         :type force: Boolean | ||||
|         """ | ||||
|         self.bus_number = bus_number | ||||
|         self.auto_cleanup = auto_cleanup | ||||
|         self.force = force | ||||
|  | ||||
|     def __enter__(self): | ||||
|         self.bus = SMBus(bus=self.bus_number, force=self.force) | ||||
|         return self.bus | ||||
|  | ||||
|     def __exit__(self, exc_type, exc_val, exc_tb): | ||||
|         if self.auto_cleanup: | ||||
|             self.bus.close() | ||||
| @@ -0,0 +1,2 @@ | ||||
| blacklist rg_fpga_pcie | ||||
| blacklist rg_spi_gpio | ||||
							
								
								
									
										50
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/modules/Makefile
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										50
									
								
								platform/broadcom/sonic-platform-modules-tencent/common/modules/Makefile
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| PWD		= $(shell pwd) | ||||
| EXTRA_CFLAGS:= -I$(M)/include | ||||
| EXTRA_CFLAGS+= -Wall | ||||
| KVERSION   ?= $(shell uname -r) | ||||
| KERNEL_SRC ?=  /lib/modules/$(KVERSION) | ||||
|  | ||||
| module_out_put_dir := $(PWD)/build | ||||
| export module_out_put_dir | ||||
|  | ||||
| RG_PLAT_SYSFS_DIR = $(PWD)/rg_plat_sysfs | ||||
|  | ||||
| export RG_PLAT_SYSFS_DIR | ||||
|  | ||||
| ruijie_common-objs := ruijie_common_module.o dfd_tlveeprom.o | ||||
| obj-m += rg_pmbus_core.o | ||||
| obj-m += rg_csu550.o | ||||
| obj-m += ruijie_common.o | ||||
| obj-m += rg_ina3221.o | ||||
| obj-m += rg_mac_bsc.o | ||||
| obj-m += rg_tps53622.o | ||||
| obj-m += rg_fpga_pcie.o | ||||
| obj-m += rg_pcie_dev.o | ||||
| obj-m += rg_fpga_i2c_bus_drv.o | ||||
| obj-m += rg_fpga_pca954x_drv.o | ||||
| obj-m += rg_lpc_drv.o | ||||
| obj-m += rg_i2c_dev.o | ||||
| obj-m += rg_io_dev.o | ||||
| obj-m += rg_eeprom_93xx46.o | ||||
| obj-m += rg_ucd9000.o | ||||
| obj-m += rg_spi_93xx46.o | ||||
| obj-m += rg_gpio_d1500.o | ||||
| obj-m += rg_gpio_device.o | ||||
| obj-m += rg_wdt.o | ||||
| obj-m += rg_optoe.o | ||||
| obj-m += rg_spi_gpio.o | ||||
| obj-m += rg_spi_gpio_device.o | ||||
| obj-m += rg_xdpe132g5c.o | ||||
| obj-m += rg_i2c_gpio_device.o | ||||
|  | ||||
| all : | ||||
| 	$(MAKE) -C $(RG_PLAT_SYSFS_DIR) | ||||
| 	$(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules | ||||
| 	@if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi | ||||
| 	cp -p  $(PWD)/*.ko $(module_out_put_dir) | ||||
|  | ||||
| clean : | ||||
| 	rm  -rf $(module_out_put_dir) | ||||
| 	rm -f ${PWD}/*.o ${PWD}/*.ko ${PWD}/*.mod.c ${PWD}/.*.cmd ${PWD}/.*.o.d ${PWD}/*.mod | ||||
| 	rm -f ${PWD}/Module.markers ${PWD}/Module.symvers ${PWD}/modules.order | ||||
| 	rm -rf ${PWD}/.tmp_versions | ||||
| @@ -0,0 +1,516 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2014 FreeIPMI Core Team | ||||
|  * | ||||
|  * 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 3 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. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| /*****************************************************************************\ | ||||
|  *  Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC. | ||||
|  *  Copyright (C) 2007 The Regents of the University of California. | ||||
|  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). | ||||
|  *  Written by Albert Chu <chu11@llnl.gov> | ||||
|  *  UCRL-CODE-232183 | ||||
|  * | ||||
|  *  This file is part of Ipmi-fru, a tool used for retrieving | ||||
|  *  motherboard field replaceable unit (FRU) information. For details, | ||||
|  *  see http://www.llnl.gov/linux/. | ||||
|  * | ||||
|  *  Ipmi-fru 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 3 of the License, or (at your | ||||
|  *  option) any later version. | ||||
|  * | ||||
|  *  Ipmi-fru is distributed in the hope that it will be useful, but | ||||
|  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||||
|  *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | ||||
|  *  for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License along | ||||
|  *  with Ipmi-fru.  If not, see <http://www.gnu.org/licenses/>. | ||||
| \*****************************************************************************/ | ||||
| #include <linux/module.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/jiffies.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/hwmon.h> | ||||
| #include <linux/hwmon-sysfs.h> | ||||
| #include <linux/err.h> | ||||
| #include <linux/mutex.h> | ||||
| #include "ruijie.h" | ||||
| #include "dfd_tlveeprom.h" | ||||
|  | ||||
| /* using in is_valid_tlvinfo_header */ | ||||
| static u_int32_t eeprom_size; | ||||
|  | ||||
| /* | ||||
|  *  List of TLV codes and names. | ||||
|  */ | ||||
| static const struct tlv_code_desc tlv_code_list[] = { | ||||
|     { TLV_CODE_PRODUCT_NAME      , "Product Name"}, | ||||
|     { TLV_CODE_PART_NUMBER       , "Part Number"}, | ||||
|     { TLV_CODE_SERIAL_NUMBER     , "Serial Number"}, | ||||
|     { TLV_CODE_MAC_BASE          , "Base MAC Address"}, | ||||
|     { TLV_CODE_MANUF_DATE        , "Manufacture Date"}, | ||||
|     { TLV_CODE_DEVICE_VERSION    , "Device Version"}, | ||||
|     { TLV_CODE_LABEL_REVISION    , "Label Revision"}, | ||||
|     { TLV_CODE_PLATFORM_NAME     , "Platform Name"}, | ||||
|     { TLV_CODE_ONIE_VERSION      , "ONIE Version"}, | ||||
|     { TLV_CODE_MAC_SIZE          , "MAC Addresses"}, | ||||
|     { TLV_CODE_MANUF_NAME        , "Manufacturer"}, | ||||
|     { TLV_CODE_MANUF_COUNTRY     , "Country Code"}, | ||||
|     { TLV_CODE_VENDOR_NAME       , "Vendor Name"}, | ||||
|     { TLV_CODE_DIAG_VERSION      , "Diag Version"}, | ||||
|     { TLV_CODE_SERVICE_TAG       , "Service Tag"}, | ||||
|     { TLV_CODE_VENDOR_EXT        , "Vendor Extension"}, | ||||
|     { TLV_CODE_CRC_32            , "CRC-32"}, | ||||
| }; | ||||
|  | ||||
| #if 0 | ||||
| #define OPENBMC_VPD_KEY_INVAIL_VAL 0 | ||||
|  | ||||
| static const tlv_code_map_t tlv_code_map[] = { | ||||
|     { TLV_CODE_PRODUCT_NAME   , OPENBMC_VPD_KEY_PRODUCT_NAME}, | ||||
|     { TLV_CODE_PART_NUMBER    , OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM}, | ||||
|     { TLV_CODE_SERIAL_NUMBER  , OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM}, | ||||
|     { TLV_CODE_MAC_BASE       , OPENBMC_VPD_KEY_INVAIL_VAL}, | ||||
|     { TLV_CODE_MANUF_DATE     , OPENBMC_VPD_KEY_BOARD_MFG_DATE}, | ||||
|     { TLV_CODE_DEVICE_VERSION , OPENBMC_VPD_KEY_PRODUCT_VER}, | ||||
|     { TLV_CODE_LABEL_REVISION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM7}, | ||||
|     { TLV_CODE_PLATFORM_NAME  , OPENBMC_VPD_KEY_PRODUCT_CUSTOM1}, | ||||
|     { TLV_CODE_ONIE_VERSION   , OPENBMC_VPD_KEY_PRODUCT_CUSTOM2}, | ||||
|     { TLV_CODE_MAC_SIZE       , OPENBMC_VPD_KEY_INVAIL_VAL}, | ||||
|     { TLV_CODE_MANUF_NAME     , OPENBMC_VPD_KEY_PRODUCT_MFR}, | ||||
|     { TLV_CODE_MANUF_COUNTRY  , OPENBMC_VPD_KEY_PRODUCT_CUSTOM3}, | ||||
|     { TLV_CODE_VENDOR_NAME    , OPENBMC_VPD_KEY_PRODUCT_CUSTOM4}, | ||||
|     { TLV_CODE_DIAG_VERSION   , OPENBMC_VPD_KEY_PRODUCT_CUSTOM8}, | ||||
|     { TLV_CODE_SERVICE_TAG    , OPENBMC_VPD_KEY_PRODUCT_CUSTOM5}, | ||||
|     { TLV_CODE_VENDOR_EXT     , OPENBMC_VPD_KEY_PRODUCT_CUSTOM6}, | ||||
|     { TLV_CODE_CRC_32         , OPENBMC_VPD_KEY_INVAIL_VAL}, | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #define TLV_CODE_NUM (sizeof(tlv_code_list) / sizeof(tlv_code_list[0])) | ||||
|  | ||||
| #if 0 | ||||
| #define TLV_CODE_MAP_NUM (sizeof(tlv_code_map) / sizeof(tlv_code_map[0])) | ||||
| #endif | ||||
|  | ||||
| const unsigned long crc_table[] = { | ||||
|     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | ||||
|     0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | ||||
|     0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | ||||
|     0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | ||||
|     0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | ||||
|     0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | ||||
|     0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | ||||
|     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | ||||
|     0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | ||||
|     0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | ||||
|     0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | ||||
|     0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | ||||
|     0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | ||||
|     0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | ||||
|     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | ||||
|     0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | ||||
|     0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | ||||
|     0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | ||||
|     0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | ||||
|     0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | ||||
|     0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | ||||
|     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | ||||
|     0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | ||||
|     0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | ||||
|     0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | ||||
|     0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | ||||
|     0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | ||||
|     0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | ||||
|     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | ||||
|     0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | ||||
|     0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | ||||
|     0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, | ||||
| }; | ||||
|  | ||||
| static unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len) | ||||
| { | ||||
|     unsigned i; | ||||
|     if (len < 1) | ||||
|         return 0xffffffff; | ||||
|  | ||||
|     for (i = 0; i != len; ++i) | ||||
|     { | ||||
|         crc = crc_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); | ||||
|     } | ||||
|  | ||||
|     crc = crc ^ 0xffffffff; | ||||
|  | ||||
|     return crc; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  is_valid_tlv | ||||
|  * | ||||
|  *  Perform basic sanity checks on a TLV field. The TLV is pointed to | ||||
|  *  by the parameter provided. | ||||
|  *      1. The type code is not reserved (0x00 or 0xFF) | ||||
|  */ | ||||
| static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) | ||||
| { | ||||
|     return ((tlv->type != 0x00) && (tlv->type != 0xFF)); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  is_valid_tlvinfo_header | ||||
|  * | ||||
|  *  Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM | ||||
|  *  data pointed to by the parameter: | ||||
|  *      1. First 8 bytes contain null-terminated ASCII string "TlvInfo" | ||||
|  *      2. Version byte is 1 | ||||
|  *      3. Total length bytes contain value which is less than or equal | ||||
|  *         to the allowed maximum (2048-11) | ||||
|  * | ||||
|  */ | ||||
| static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) | ||||
| { | ||||
|     int max_size = eeprom_size; | ||||
|     return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && | ||||
|        (hdr->version == TLV_INFO_VERSION) && | ||||
|        (be16_to_cpu(hdr->totallen) <= max_size) ); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  decode_tlv_value | ||||
|  * | ||||
|  *  Decode a single TLV value into a string. | ||||
|  | ||||
|  *  The validity of EEPROM contents and the TLV field have been verified | ||||
|  *  prior to calling this function. | ||||
|  */ | ||||
| static void decode_tlv_value(tlvinfo_tlv_t *tlv, tlv_decode_value_t *decode_value) | ||||
| { | ||||
|     int i; | ||||
|     char *value; | ||||
|     u_int32_t length; | ||||
|  | ||||
|     value = (char *)decode_value->value; | ||||
|  | ||||
|     switch (tlv->type) { | ||||
|     case TLV_CODE_PRODUCT_NAME: | ||||
|     case TLV_CODE_PART_NUMBER: | ||||
|     case TLV_CODE_SERIAL_NUMBER: | ||||
|     case TLV_CODE_MANUF_DATE: | ||||
|     case TLV_CODE_LABEL_REVISION: | ||||
|     case TLV_CODE_PLATFORM_NAME: | ||||
|     case TLV_CODE_ONIE_VERSION: | ||||
|     case TLV_CODE_MANUF_NAME: | ||||
|     case TLV_CODE_MANUF_COUNTRY: | ||||
|     case TLV_CODE_VENDOR_NAME: | ||||
|     case TLV_CODE_DIAG_VERSION: | ||||
|     case TLV_CODE_SERVICE_TAG: | ||||
|     case TLV_CODE_VENDOR_EXT: | ||||
|         memcpy(value, tlv->value, tlv->length); | ||||
|         value[tlv->length] = 0; | ||||
|         length = tlv->length; | ||||
|         break; | ||||
|     case TLV_CODE_MAC_BASE: | ||||
|         length = sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X", | ||||
|                 tlv->value[0], tlv->value[1], tlv->value[2], | ||||
|                 tlv->value[3], tlv->value[4], tlv->value[5]); | ||||
|         break; | ||||
|     case TLV_CODE_DEVICE_VERSION: | ||||
|         length = sprintf(value, "%u", tlv->value[0]); | ||||
|         break; | ||||
|     case TLV_CODE_MAC_SIZE: | ||||
|         length = sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]); | ||||
|         break; | ||||
|     #if 0 | ||||
|     case TLV_CODE_VENDOR_EXT: | ||||
|         value[0] = 0; | ||||
|         length = 0; | ||||
|         for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) { | ||||
|             length += sprintf(value, "%s 0x%02X", value, tlv->value[i]); | ||||
|         } | ||||
|         break; | ||||
|     #endif | ||||
|     case TLV_CODE_CRC_32: | ||||
|         length = sprintf(value, "0x%02X%02X%02X%02X", tlv->value[0], | ||||
|                 tlv->value[1], tlv->value[2], tlv->value[3]); | ||||
|         break; | ||||
|     default: | ||||
|         value[0] = 0; | ||||
|         length = 0; | ||||
|         for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) { | ||||
|             length += sprintf(value, "%s 0x%02X", value, tlv->value[i]); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     decode_value->length = length; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  is_checksum_valid | ||||
|  * | ||||
|  *  Validate the checksum in the provided TlvInfo EEPROM data. First, | ||||
|  *  verify that the TlvInfo header is valid, then make sure the last | ||||
|  *  TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data | ||||
|  *  and compare it to the value stored in the EEPROM CRC-32 TLV. | ||||
|  */ | ||||
| static bool is_checksum_valid(u_int8_t *eeprom) | ||||
| { | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     tlvinfo_tlv_t *eeprom_crc; | ||||
|     unsigned int calc_crc; | ||||
|     unsigned int stored_crc; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|  | ||||
|     // Is the eeprom header valid? | ||||
|     if (!is_valid_tlvinfo_header(eeprom_hdr)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Is the last TLV a CRC? | ||||
|     eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + | ||||
|         be16_to_cpu(eeprom_hdr->totallen) - (sizeof(tlvinfo_tlv_t) + 4)]; | ||||
|     if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Calculate the checksum | ||||
|     calc_crc = crc32(0xffffffffL, (const unsigned char *)eeprom, sizeof(tlvinfo_header_t) + | ||||
|              be16_to_cpu(eeprom_hdr->totallen) - 4); | ||||
|     stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | | ||||
|           (eeprom_crc->value[2] <<  8) | eeprom_crc->value[3]); | ||||
|  | ||||
|     return (calc_crc == stored_crc); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  tlvinfo_find_tlv | ||||
|  * | ||||
|  *  This function finds the TLV with the supplied code in the EERPOM. | ||||
|  *  An offset from the beginning of the EEPROM is returned in the | ||||
|  *  eeprom_index parameter if the TLV is found. | ||||
|  */ | ||||
| static bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index) | ||||
| { | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     tlvinfo_tlv_t    *eeprom_tlv; | ||||
|     int eeprom_end; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|  | ||||
|     // Search through the TLVs, looking for the first one which matches the | ||||
|     // supplied type code. | ||||
|     *eeprom_index = sizeof(tlvinfo_header_t); | ||||
|     eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); | ||||
|     while (*eeprom_index < eeprom_end) { | ||||
|         eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; | ||||
|         if (!is_valid_tlv(eeprom_tlv)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (eeprom_tlv->type == tcode) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  tlvinfo_decode_tlv | ||||
|  * | ||||
|  *  This function finds the TLV with the supplied code in the EERPOM | ||||
|  *  and decodes the value into the buffer provided. | ||||
|  */ | ||||
| static bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, tlv_decode_value_t *decode_value) | ||||
| { | ||||
|     int eeprom_index; | ||||
|     tlvinfo_tlv_t *eeprom_tlv; | ||||
|  | ||||
|     // Find the TLV and then decode it | ||||
|     if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { | ||||
|         eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; | ||||
|         decode_tlv_value(eeprom_tlv, decode_value); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  parse_tlv_eeprom | ||||
|  * | ||||
|  *  parse the EEPROM into memory, if it hasn't already been read. | ||||
|  */ | ||||
| int parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size) | ||||
| { | ||||
|     unsigned int i; | ||||
|     bool ret; | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     //tlv_info_vec_t tlv_info; | ||||
|     tlv_decode_value_t decode_value; | ||||
|     int j; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|     eeprom_size = size; /* eeprom real size */ | ||||
|  | ||||
|     if (!is_valid_tlvinfo_header(eeprom_hdr)) { | ||||
|         DBG_ERROR("Failed to check tlv header.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (!is_checksum_valid(eeprom)) { | ||||
|         DBG_ERROR("Failed to check tlv crc.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < TLV_CODE_NUM; i++) { | ||||
|         memset((void *)&decode_value, 0, sizeof(tlv_decode_value_t)); | ||||
|         ret = tlvinfo_decode_tlv(eeprom, tlv_code_list[i].m_code, &decode_value); | ||||
|         if (!ret) { | ||||
|             DBG_ERROR("No found type: %s\n", tlv_code_list[i].m_name); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         DBG_DEBUG("i: %d,Found type: %s tlv[%d]:%s\n", i, tlv_code_list[i].m_name, tlv_code_list[i].m_code, | ||||
|             decode_value.value); | ||||
|         for (j = 0; j < decode_value.length; j++) { | ||||
|             if ((j % 16) == 0) { | ||||
|                 DBG_DEBUG("\n"); | ||||
|             } | ||||
|             DBG_DEBUG("%02x ", decode_value.value[j]); | ||||
|         } | ||||
|         DBG_DEBUG("\n\n"); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| static int dfd_parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size, u_int8_t main_type, tlv_decode_value_t *decode_value) | ||||
| { | ||||
|     bool ret; | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     //tlv_info_vec_t tlv_info; | ||||
|     int j; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|     eeprom_size = size; /* eeprom real size */ | ||||
|  | ||||
|     if (!is_valid_tlvinfo_header(eeprom_hdr)) { | ||||
|         DBG_ERROR("Failed to check tlv header.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (!is_checksum_valid(eeprom)) { | ||||
|         DBG_ERROR("Failed to check tlv crc.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     ret = tlvinfo_decode_tlv(eeprom, main_type, decode_value); | ||||
|     if (!ret) { | ||||
|         DBG_ERROR("No found type: %d\n", main_type); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG("Found type: %d, value: %s\n", main_type,decode_value->value); | ||||
|     for (j = 0; j < decode_value->length; j++) { | ||||
|         if ((j % 16) == 0) { | ||||
|             DBG_DEBUG("\n"); | ||||
|         } | ||||
|         DBG_DEBUG("%02x ", decode_value->value[j]); | ||||
|     } | ||||
|     DBG_DEBUG("\n\n"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int tlvinfo_find_rg_ext_tlv(tlv_decode_value_t *ext_tlv_value, u_int8_t ext_type, | ||||
|     u_int8_t *buf, u_int8_t *buf_len) | ||||
| { | ||||
|     tlvinfo_tlv_t    *eeprom_tlv; | ||||
|     int eeprom_end, eeprom_index; | ||||
|  | ||||
|     // Search through the TLVs, looking for the first one which matches the | ||||
|     // supplied type code. | ||||
|     DBG_DEBUG("ext_tlv_value->length: %d.\n", ext_tlv_value->length); | ||||
|     for (eeprom_index = 0; eeprom_index < ext_tlv_value->length; eeprom_index++) { | ||||
|         if ((eeprom_index % 16) == 0) { | ||||
|             DBG_DEBUG("\n"); | ||||
|         } | ||||
|         DBG_DEBUG("%02x ", ext_tlv_value->value[eeprom_index]); | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG("\n"); | ||||
|  | ||||
|     eeprom_index = 0; | ||||
|     eeprom_end = ext_tlv_value->length; | ||||
|     while (eeprom_index < eeprom_end) { | ||||
|         eeprom_tlv = (tlvinfo_tlv_t *) &(ext_tlv_value->value[eeprom_index]); | ||||
|         if (!is_valid_tlv(eeprom_tlv)) { | ||||
|             DBG_ERROR("tlv is not valid, eeprom_tlv->type 0x%x.\n", eeprom_tlv->type); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length); | ||||
|         if (eeprom_tlv->type == ext_type) { | ||||
|             if (*buf_len >= eeprom_tlv->length) { | ||||
|                 memcpy(buf, eeprom_tlv->value, eeprom_tlv->length); | ||||
|                 DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length); | ||||
|                 *buf_len = eeprom_tlv->length; | ||||
|                 return 0; | ||||
|             } | ||||
|             DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, eeprom_tlv->length); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; | ||||
|     } | ||||
|  | ||||
|     DBG_ERROR("ext_type %d: tlv is not found.\n", ext_type); | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len) | ||||
| { | ||||
|     tlv_decode_value_t decode_value; | ||||
|     int ret; | ||||
|  | ||||
|     if (eeprom == NULL || tlv_type == NULL || buf == NULL) { | ||||
|         DBG_ERROR("Input para invalid.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     memset((void *)&decode_value, 0, sizeof(tlv_decode_value_t)); | ||||
|     ret = dfd_parse_tlv_eeprom(eeprom, size, tlv_type->main_type, &decode_value); | ||||
|     if (ret) { | ||||
|         DBG_ERROR("dfd_parse_tlv_eeprom failed ret %d.\n", ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if (tlv_type->main_type != TLV_CODE_VENDOR_EXT) { | ||||
|         if (*buf_len >= decode_value.length) { | ||||
|             memcpy(buf, decode_value.value, decode_value.length); | ||||
|             *buf_len = decode_value.length; | ||||
|             return 0; | ||||
|         } | ||||
|         DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, decode_value.length); | ||||
|         return -1; | ||||
|     } | ||||
|     DBG_DEBUG("info_len %d.\n", decode_value.length); | ||||
|  | ||||
|     return tlvinfo_find_rg_ext_tlv(&decode_value, tlv_type->ext_type, buf, buf_len); | ||||
| } | ||||
| @@ -0,0 +1,121 @@ | ||||
| #ifndef DFD_OPENBMC_TLVEEPROM_H | ||||
| #define DFD_OPENBMC_TLVEEPROM_H | ||||
|  | ||||
| #ifndef u_int8_t | ||||
| #define u_int8_t unsigned char | ||||
| #endif | ||||
|  | ||||
| #ifndef u_int16_t | ||||
| #define u_int16_t unsigned short | ||||
| #endif | ||||
|  | ||||
| #ifndef u_int32_t | ||||
| #define u_int32_t unsigned int | ||||
| #endif | ||||
|  | ||||
| #ifndef be16_to_cpu | ||||
| #define be16_to_cpu(x)   ntohs(x) | ||||
| #endif | ||||
|  | ||||
| #ifndef cpu_to_be16 | ||||
| #define cpu_to_be16(x)   htons(x) | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  *  The TLV Types. | ||||
|  * | ||||
|  *  Keep these in sync with tlv_code_list in cmd_sys_eeprom.c | ||||
|  */ | ||||
| #define TLV_CODE_PRODUCT_NAME   0x21 | ||||
| #define TLV_CODE_PART_NUMBER    0x22 | ||||
| #define TLV_CODE_SERIAL_NUMBER  0x23 | ||||
| #define TLV_CODE_MAC_BASE       0x24 | ||||
| #define TLV_CODE_MANUF_DATE     0x25 | ||||
| #define TLV_CODE_DEVICE_VERSION 0x26 | ||||
| #define TLV_CODE_LABEL_REVISION 0x27 | ||||
| #define TLV_CODE_PLATFORM_NAME  0x28 | ||||
| #define TLV_CODE_ONIE_VERSION   0x29 | ||||
| #define TLV_CODE_MAC_SIZE       0x2A | ||||
| #define TLV_CODE_MANUF_NAME     0x2B | ||||
| #define TLV_CODE_MANUF_COUNTRY  0x2C | ||||
| #define TLV_CODE_VENDOR_NAME    0x2D | ||||
| #define TLV_CODE_DIAG_VERSION   0x2E | ||||
| #define TLV_CODE_SERVICE_TAG    0x2F | ||||
| #define TLV_CODE_VENDOR_EXT     0xFD | ||||
| #define TLV_CODE_CRC_32         0xFE | ||||
|  | ||||
| #define TLV_CODE_NAME_LEN 64 | ||||
| /* | ||||
|  *  Struct for displaying the TLV codes and names. | ||||
|  */ | ||||
| struct tlv_code_desc { | ||||
|     u_int8_t m_code; | ||||
|     char m_name[TLV_CODE_NAME_LEN]; | ||||
| }; | ||||
|  | ||||
| typedef struct dfd_tlv_type_s { | ||||
|     u_int8_t main_type; | ||||
|     u_int8_t ext_type; | ||||
| } dfd_tlv_type_t; | ||||
|  | ||||
| // Header Field Constants | ||||
| #define TLV_INFO_ID_STRING      "TlvInfo" | ||||
| #define TLV_INFO_VERSION        0x01 | ||||
| /*#define TLV_TOTAL_LEN_MAX       (XXXXXXXX - sizeof(tlvinfo_header_t))*/ | ||||
|  | ||||
| struct __attribute__ ((__packed__)) tlvinfo_header_s { | ||||
|     char    signature[8];   /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */ | ||||
|     u_int8_t      version;  /* 0x08        Structure version */ | ||||
|     u_int16_t     totallen; /* 0x09 - 0x0A Length of all data which follows */ | ||||
| }; | ||||
| typedef struct tlvinfo_header_s tlvinfo_header_t; | ||||
|  | ||||
| /* | ||||
|  * TlvInfo TLV: Layout of a TLV field | ||||
|  */ | ||||
| struct __attribute__ ((__packed__)) tlvinfo_tlv_s { | ||||
|     u_int8_t  type; | ||||
|     u_int8_t  length; | ||||
|     u_int8_t  value[0]; | ||||
| }; | ||||
| typedef struct tlvinfo_tlv_s tlvinfo_tlv_t; | ||||
|  | ||||
| #define TLV_VALUE_MAX_LEN        255 | ||||
| /* | ||||
|  * The max decode value is currently for the 'raw' type or the 'vendor | ||||
|  * extension' type, both of which have the same decode format.  The | ||||
|  * max decode string size is computed as follows: | ||||
|  * | ||||
|  *   strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1 | ||||
|  * | ||||
|  */ | ||||
| #define TLV_DECODE_VALUE_MAX_LEN    ((5 * TLV_VALUE_MAX_LEN) + 1) | ||||
|  | ||||
| typedef struct tlv_decode_value_s { | ||||
|     u_int8_t value[TLV_DECODE_VALUE_MAX_LEN]; | ||||
|     u_int32_t length; | ||||
| } tlv_decode_value_t; | ||||
|  | ||||
| typedef enum dfd_tlvinfo_ext_tlv_type_e { | ||||
|     DFD_TLVINFO_EXT_TLV_TYPE_DEV_TYPE   = 1, | ||||
| } dfd_tlvinfo_ext_tlv_type_t; | ||||
|  | ||||
| #if 0 | ||||
| #define TLV_TIME_LEN 64 | ||||
|  | ||||
| int ipmi_tlv_validate_fru_area(const uint8_t fruid, const char *fru_file_name, | ||||
|                            sd_bus *bus_type, const bool bmc_fru); | ||||
|  | ||||
| extern const char *get_vpd_key_names(int key_id); | ||||
| extern std::string getService(sdbusplus::bus::bus& bus, | ||||
|                          const std::string& intf, | ||||
|                          const std::string& path); | ||||
| extern std::string getFRUValue(const std::string& section, | ||||
|                         const std::string& key, | ||||
|                         const std::string& delimiter, | ||||
|                         IPMIFruInfo& fruData); | ||||
| #endif | ||||
|  | ||||
| int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len); | ||||
|  | ||||
| #endif /* endif DFD_OPENBMC_TLVEEPROM_H */ | ||||
| @@ -0,0 +1,129 @@ | ||||
| #ifndef _FPGA_I2C_H | ||||
| #define _FPGA_I2C_H | ||||
|  | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/kallsyms.h> | ||||
| #if 0 | ||||
|  | ||||
| #define FPGA_I2C_EXT_9548_ADDR        (0x00) | ||||
| #define FPGA_I2C_EXT_9548_CHAN        (0x04) | ||||
| #define FPGA_I2C_DEV_SLAVE_ADDR       (0x08) | ||||
| #define FPGA_I2C_DEV_REG_ADDR         (0x0C) | ||||
| #define FPGA_I2C_DEV_RDWR_LEN         (0x10) | ||||
| #define FPGA_I2C_CTRL_REG             (0x14) | ||||
| #define FPGA_I2C_STATUS_REG           (0x18) | ||||
| #define FPGA_I2C_SCALE_REG            (0x1C) | ||||
| #define FPGA_I2C_FILTER_REG           (0x20) | ||||
| #define FPGA_I2C_STRETCH_REG          (0x24) | ||||
| #define FPGA_I2C_EXT_9548_EXITS_FLAG  (0x28) | ||||
| #define FPGA_I2C_INTERNAL_9548_CHAN   (0x2C) | ||||
| #define FPGA_I2C_RDWR_DATA_BUF        (0x80) | ||||
| #endif | ||||
| #define FPGA_I2C_RDWR_MAX_LEN_DEFAULT (128) | ||||
| #define I2C_REG_MAX_WIDTH             (16) | ||||
|  | ||||
| #define DEV_NAME_MAX_LEN              (64) | ||||
|  | ||||
| #define FPGA_I2C_MAX_TIMES            (10) | ||||
| #define FPGA_I2C_XFER_TIME_OUT        (100000) | ||||
| #define FPGA_I2C_SLEEP_TIME           (40) | ||||
|  | ||||
| typedef struct fpga_i2c_reg_s { | ||||
|     uint32_t i2c_scale; | ||||
|     uint32_t i2c_filter; | ||||
|     uint32_t i2c_stretch; | ||||
|     uint32_t i2c_ext_9548_exits_flag; | ||||
|     uint32_t i2c_ext_9548_addr; | ||||
|     uint32_t i2c_ext_9548_chan; | ||||
|     uint32_t i2c_in_9548_chan; | ||||
|     uint32_t i2c_slave; | ||||
|     uint32_t i2c_reg; | ||||
|     uint32_t i2c_reg_len; | ||||
|     uint32_t i2c_data_len; | ||||
|     uint32_t i2c_ctrl; | ||||
|     uint32_t i2c_status; | ||||
|     uint32_t i2c_err_vec; | ||||
|     uint32_t i2c_data_buf; | ||||
|     uint32_t i2c_data_buf_len; | ||||
| } fpga_i2c_reg_t; | ||||
|  | ||||
| typedef struct fpga_i2c_reset_cfg_s { | ||||
|     uint32_t i2c_adap_reset_flag; | ||||
|     uint32_t reset_addr; | ||||
|     uint32_t reset_on; | ||||
|     uint32_t reset_off; | ||||
|     uint32_t reset_delay_b; | ||||
|     uint32_t reset_delay; | ||||
|     uint32_t reset_delay_a; | ||||
| } fpga_i2c_reset_cfg_t; | ||||
|  | ||||
| typedef struct fpga_i2c_reg_addr_s { | ||||
|     uint8_t reg_addr_len; | ||||
|     uint8_t read_reg_addr[I2C_REG_MAX_WIDTH]; | ||||
| } fpga_i2c_reg_addr_t; | ||||
|  | ||||
| typedef struct fpga_i2c_dev_s { | ||||
|     fpga_i2c_reg_t reg; | ||||
|     fpga_i2c_reset_cfg_t reset_cfg; | ||||
|     fpga_i2c_reg_addr_t i2c_addr_desc; | ||||
|     const char *dev_name; | ||||
|     uint32_t i2c_scale_value; | ||||
|     uint32_t i2c_filter_value; | ||||
|     uint32_t i2c_stretch_value; | ||||
|     uint32_t i2c_timeout; | ||||
|     uint32_t i2c_func_mode; | ||||
|     wait_queue_head_t queue; | ||||
|     struct i2c_adapter adap; | ||||
|     int adap_nr; | ||||
|     struct device *dev; | ||||
|     bool i2c_params_check; | ||||
| } fpga_i2c_dev_t; | ||||
|  | ||||
| typedef struct fpga_i2c_bus_device_s { | ||||
|     int i2c_timeout; | ||||
|     int i2c_scale; | ||||
|     int i2c_filter; | ||||
|     int i2c_stretch; | ||||
|     int i2c_ext_9548_exits_flag; | ||||
|     int i2c_ext_9548_addr; | ||||
|     int i2c_ext_9548_chan; | ||||
|     int i2c_in_9548_chan; | ||||
|     int i2c_slave; | ||||
|     int i2c_reg; | ||||
|     int i2c_reg_len; | ||||
|     int i2c_data_len; | ||||
|     int i2c_ctrl; | ||||
|     int i2c_status; | ||||
|     int i2c_err_vec; | ||||
|     int i2c_data_buf; | ||||
|     int i2c_data_buf_len; | ||||
|     char dev_name[DEV_NAME_MAX_LEN]; | ||||
|     int adap_nr; | ||||
|     int i2c_scale_value; | ||||
|     int i2c_filter_value; | ||||
|     int i2c_stretch_value; | ||||
|     int i2c_func_mode; | ||||
|     int i2c_adap_reset_flag; | ||||
|     int i2c_reset_addr; | ||||
|     int i2c_reset_on; | ||||
|     int i2c_reset_off; | ||||
|     int i2c_rst_delay_b;        /* delay time before reset(us) */ | ||||
|     int i2c_rst_delay;          /* reset time(us) */ | ||||
|     int i2c_rst_delay_a;        /* delay time after reset(us) */ | ||||
|     int device_flag; | ||||
|     bool i2c_params_check; | ||||
|     int i2c_data_buf_len_reg; | ||||
|     int i2c_offset_reg; | ||||
| } fpga_i2c_bus_device_t; | ||||
|  | ||||
| typedef struct fpga_pca954x_device_s { | ||||
|     struct i2c_client *client; | ||||
|     uint32_t i2c_bus; | ||||
|     uint32_t i2c_addr; | ||||
|     uint32_t fpga_9548_flag; | ||||
|     uint32_t fpga_9548_reset_flag; | ||||
|     uint32_t pca9548_base_nr; | ||||
| } fpga_pca954x_device_t; | ||||
|  | ||||
| #endif /* _FPGA_I2C_H */ | ||||
| @@ -0,0 +1,203 @@ | ||||
| /* | ||||
|  * csu550.c - PMBUS for csu550 | ||||
|  * | ||||
|  * Copyright (c) 2018 sonic_rd <sonic_rd@ruijie.com.cn> | ||||
|  * | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/jiffies.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/hwmon.h> | ||||
| #include <linux/hwmon-sysfs.h> | ||||
| #include <linux/version.h> | ||||
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,152) | ||||
| #include <linux/i2c/pmbus.h> | ||||
| #else | ||||
| #include <linux/pmbus.h> | ||||
| #endif | ||||
| #include <linux/err.h> | ||||
| #include <linux/mutex.h> | ||||
| #include "rg_pmbus.h" | ||||
|  | ||||
| /* | ||||
|  * Find sensor groups and status registers on each page. | ||||
|  */ | ||||
| static void pmbus_find_sensor_groups(struct i2c_client *client, | ||||
| 				     struct pmbus_driver_info *info) | ||||
| { | ||||
| 	int page; | ||||
|  | ||||
| 	/* Sensors detected on page 0 only */ | ||||
| 	if (rg_pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) | ||||
| 		info->func[0] |= PMBUS_HAVE_VIN; | ||||
| 	if (rg_pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) | ||||
| 		info->func[0] |= PMBUS_HAVE_IIN; | ||||
| 	if (rg_pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) | ||||
| 		info->func[0] |= PMBUS_HAVE_PIN; | ||||
| 	if (info->func[0] | ||||
| 	    && rg_pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) | ||||
| 		info->func[0] |= PMBUS_HAVE_STATUS_INPUT; | ||||
| 	if (rg_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && | ||||
| 	    rg_pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { | ||||
| 		info->func[0] |= PMBUS_HAVE_FAN12; | ||||
| 		if (rg_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) | ||||
| 			info->func[0] |= PMBUS_HAVE_STATUS_FAN12; | ||||
| 	} | ||||
| 	if (rg_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) | ||||
| 		info->func[0] |= PMBUS_HAVE_TEMP; | ||||
| 	if (rg_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) | ||||
| 		info->func[0] |= PMBUS_HAVE_TEMP2; | ||||
| 	if (rg_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) | ||||
| 		info->func[0] |= PMBUS_HAVE_TEMP3; | ||||
| 	if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | ||||
| 			     | PMBUS_HAVE_TEMP3) | ||||
| 	    && rg_pmbus_check_byte_register(client, 0, | ||||
| 					 PMBUS_STATUS_TEMPERATURE)) | ||||
| 			info->func[0] |= PMBUS_HAVE_STATUS_TEMP; | ||||
|  | ||||
| 	/* Sensors detected on all pages */ | ||||
| 	for (page = 0; page < info->pages; page++) { | ||||
| 		if (rg_pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { | ||||
| 			info->func[page] |= PMBUS_HAVE_VOUT; | ||||
| 			if (rg_pmbus_check_byte_register(client, page, | ||||
| 						      PMBUS_STATUS_VOUT)) | ||||
| 				info->func[page] |= PMBUS_HAVE_STATUS_VOUT; | ||||
| 		} | ||||
| 		if (rg_pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { | ||||
| 			info->func[page] |= PMBUS_HAVE_IOUT; | ||||
| 			if (rg_pmbus_check_byte_register(client, 0, | ||||
| 						      PMBUS_STATUS_IOUT)) | ||||
| 				info->func[page] |= PMBUS_HAVE_STATUS_IOUT; | ||||
| 		} | ||||
| 		if (rg_pmbus_check_word_register(client, page, PMBUS_READ_POUT)) | ||||
| 			info->func[page] |= PMBUS_HAVE_POUT; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Identify chip parameters. | ||||
|  */ | ||||
| static int pmbus_identify(struct i2c_client *client, | ||||
| 			  struct pmbus_driver_info *info) | ||||
| { | ||||
| 	int ret = 0; | ||||
|  | ||||
| 	if (!info->pages) { | ||||
| 		/* | ||||
| 		 * Check if the PAGE command is supported. If it is, | ||||
| 		 * keep setting the page number until it fails or until the | ||||
| 		 * maximum number of pages has been reached. Assume that | ||||
| 		 * this is the number of pages supported by the chip. | ||||
| 		 */ | ||||
| 		if (rg_pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { | ||||
| 			int page; | ||||
|  | ||||
| 			for (page = 1; page < PMBUS_PAGES; page++) { | ||||
| 				if (rg_pmbus_set_page(client, page) < 0) | ||||
| 					break; | ||||
| 			} | ||||
| 			(void)rg_pmbus_set_page(client, 0); | ||||
| 			info->pages = page; | ||||
| 		} else { | ||||
| 			info->pages = 1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (rg_pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { | ||||
| 		int vout_mode; | ||||
|  | ||||
| 		vout_mode = rg_pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); | ||||
| 		if (vout_mode >= 0 && vout_mode != 0xff) { | ||||
| 			switch (vout_mode >> 5) { | ||||
| 			case 0: | ||||
| 				break; | ||||
| 			case 1: | ||||
| 				info->format[PSC_VOLTAGE_OUT] = vid; | ||||
| 				break; | ||||
| 			case 2: | ||||
| 				info->format[PSC_VOLTAGE_OUT] = direct; | ||||
| 				break; | ||||
| 			default: | ||||
| 				ret = -ENODEV; | ||||
| 				goto abort; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * We should check if the COEFFICIENTS register is supported. | ||||
| 	 * If it is, and the chip is configured for direct mode, we can read | ||||
| 	 * the coefficients from the chip, one set per group of sensor | ||||
| 	 * registers. | ||||
| 	 * | ||||
| 	 * To do this, we will need access to a chip which actually supports the | ||||
| 	 * COEFFICIENTS command, since the command is too complex to implement | ||||
| 	 * without testing it. Until then, abort if a chip configured for direct | ||||
| 	 * mode was detected. | ||||
| 	 */ | ||||
| 	if (info->format[PSC_VOLTAGE_OUT] == direct) { | ||||
| 		ret = -ENODEV; | ||||
| 		goto abort; | ||||
| 	} | ||||
|  | ||||
| 	/* Try to find sensor groups  */ | ||||
| 	pmbus_find_sensor_groups(client, info); | ||||
| abort: | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int pmbus_probe(struct i2c_client *client, | ||||
| 		       const struct i2c_device_id *id) | ||||
| { | ||||
| 	struct pmbus_driver_info *info; | ||||
| 	struct pmbus_platform_data *pdata = NULL; | ||||
| 	struct device *dev = &client->dev; | ||||
|  | ||||
| 	info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), | ||||
| 			    GFP_KERNEL); | ||||
| 	if (!info) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
|     if (!strncmp(id->name, "dps460", sizeof("dps460")) || | ||||
| 		!strncmp(id->name, "rg_fsp1200", sizeof("rg_fsp1200")) || !strncmp(id->name, "rg_dps550", sizeof("rg_dps550"))) { | ||||
|         pdata = kzalloc(sizeof(struct pmbus_platform_data), GFP_KERNEL); | ||||
|         if (!pdata) { | ||||
|                 kfree(info); | ||||
|                 return -ENOMEM; | ||||
|         } | ||||
|             pdata->flags = PMBUS_SKIP_STATUS_CHECK; | ||||
|     } | ||||
|  | ||||
| 	info->pages = id->driver_data; | ||||
| 	info->identify = pmbus_identify; | ||||
| 	dev->platform_data = pdata; | ||||
|  | ||||
| 	return rg_pmbus_do_probe(client, id, info); | ||||
| } | ||||
|  | ||||
| static const struct i2c_device_id pmbus_id[] = { | ||||
|    {"rg_csu550", 0}, | ||||
|    {"rg_csu800", 1}, | ||||
|    {"rg_fsp1200", 1}, | ||||
|    {"rg_dps550", 1}, | ||||
|    {} | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(i2c, pmbus_id); | ||||
|  | ||||
| /* This is the driver that will be inserted */ | ||||
| static struct i2c_driver pmbus_driver = { | ||||
| 	.driver = { | ||||
| 		   .name = "rg_pmbus", | ||||
| 		   }, | ||||
| 	.probe = pmbus_probe, | ||||
| 	.remove = rg_pmbus_do_remove, | ||||
| 	.id_table = pmbus_id, | ||||
| }; | ||||
|  | ||||
| module_i2c_driver(pmbus_driver); | ||||
|  | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| MODULE_DESCRIPTION("ruijie psupmbus driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| @@ -0,0 +1,555 @@ | ||||
| /* | ||||
|  * Driver for 93xx46 EEPROMs | ||||
|  * | ||||
|  * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  */ | ||||
|  | ||||
| #include <linux/delay.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/gpio/consumer.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/of_device.h> | ||||
| #include <linux/of_gpio.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/spi/spi.h> | ||||
| #include <linux/nvmem-provider.h> | ||||
| #include <linux/eeprom_93xx46.h> | ||||
|  | ||||
| #define OP_START	0x4 | ||||
| #define OP_WRITE	(OP_START | 0x1) | ||||
| #define OP_READ		(OP_START | 0x2) | ||||
| #define ADDR_EWDS	0x00 | ||||
| #define ADDR_ERAL	0x20 | ||||
| #define ADDR_EWEN	0x30 | ||||
|  | ||||
| static int g_rg_eeprom_93xx46_debug = 0; | ||||
|  | ||||
| module_param(g_rg_eeprom_93xx46_debug, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define SPI_93xx46_DEBUG_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_rg_eeprom_93xx46_debug) { \ | ||||
|         printk(KERN_INFO "[EEPROM-93xx46][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| struct eeprom_93xx46_devtype_data { | ||||
| 	unsigned int quirks; | ||||
| }; | ||||
|  | ||||
| static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { | ||||
| 	.quirks = EEPROM_93XX46_QUIRK_SINGLE_WORD_READ | | ||||
| 		  EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, | ||||
| }; | ||||
|  | ||||
| struct eeprom_93xx46_dev { | ||||
| 	struct spi_device *spi; | ||||
| 	struct eeprom_93xx46_platform_data *pdata; | ||||
| 	struct mutex lock; | ||||
| 	struct nvmem_config nvmem_config; | ||||
| 	struct nvmem_device *nvmem; | ||||
| 	int addrlen; | ||||
| 	int size; | ||||
| }; | ||||
|  | ||||
| static inline bool has_quirk_single_word_read(struct eeprom_93xx46_dev *edev) | ||||
| { | ||||
| 	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_SINGLE_WORD_READ; | ||||
| } | ||||
|  | ||||
| static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev) | ||||
| { | ||||
| 	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH; | ||||
| } | ||||
|  | ||||
| static int eeprom_93xx46_read(void *priv, unsigned int off, | ||||
| 			      void *val, size_t count) | ||||
| { | ||||
| 	struct eeprom_93xx46_dev *edev = priv; | ||||
| 	char *buf = val; | ||||
| 	int err = 0; | ||||
|  | ||||
| 	if (unlikely(off >= edev->size)) | ||||
| 		return 0; | ||||
| 	if ((off + count) > edev->size) | ||||
| 		count = edev->size - off; | ||||
| 	if (unlikely(!count)) | ||||
| 		return count; | ||||
|  | ||||
| 	mutex_lock(&edev->lock); | ||||
|  | ||||
| 	if (edev->pdata->prepare) | ||||
| 		edev->pdata->prepare(edev); | ||||
|  | ||||
| 	while (count) { | ||||
| 		struct spi_message m; | ||||
| 		struct spi_transfer t[2] = { { 0 } }; | ||||
| 		u16 cmd_addr = OP_READ << edev->addrlen; | ||||
| 		size_t nbytes = count; | ||||
| 		int bits; | ||||
|         int data_bit; | ||||
|  | ||||
| 		if (edev->addrlen == 7) { | ||||
| 			cmd_addr |= off & 0x7f; | ||||
| 			bits = 10; | ||||
|             data_bit = 8; | ||||
| 			if (has_quirk_single_word_read(edev)) | ||||
| 				nbytes = 1; | ||||
| 		} else { | ||||
| 			cmd_addr |= (off >> 1) & 0x3f; | ||||
| 			bits = 9; | ||||
|             data_bit = 16; | ||||
| 			if (has_quirk_single_word_read(edev)) | ||||
| 				nbytes = 2; | ||||
| 		} | ||||
|  | ||||
| 		dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", | ||||
| 			cmd_addr, edev->spi->max_speed_hz); | ||||
|  | ||||
| 		spi_message_init(&m); | ||||
|  | ||||
| 		t[0].tx_buf = (char *)&cmd_addr; | ||||
| 		t[0].len = 2; | ||||
| 		t[0].bits_per_word = bits; | ||||
| 		spi_message_add_tail(&t[0], &m); | ||||
|  | ||||
| 		t[1].rx_buf = buf; | ||||
| 		t[1].len = nbytes; | ||||
| 		t[1].bits_per_word = data_bit; | ||||
| 		spi_message_add_tail(&t[1], &m); | ||||
|  | ||||
| 		err = spi_sync(edev->spi, &m); | ||||
| 		/* have to wait at least Tcsl ns */ | ||||
| 		ndelay(250); | ||||
|  | ||||
| 		if (err) { | ||||
| 			dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n", | ||||
| 				nbytes, (int)off, err); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		buf += nbytes; | ||||
| 		off += nbytes; | ||||
| 		count -= nbytes; | ||||
| 	} | ||||
|  | ||||
| 	if (edev->pdata->finish) | ||||
| 		edev->pdata->finish(edev); | ||||
|  | ||||
| 	mutex_unlock(&edev->lock); | ||||
|  | ||||
| 	return err; | ||||
| } | ||||
|  | ||||
| static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) | ||||
| { | ||||
| 	struct spi_message m; | ||||
| 	struct spi_transfer t; | ||||
| 	int bits, ret; | ||||
| 	u16 cmd_addr; | ||||
|  | ||||
| 	cmd_addr = OP_START << edev->addrlen; | ||||
| 	if (edev->addrlen == 7) { | ||||
| 		cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1; | ||||
| 		bits = 10; | ||||
| 	} else { | ||||
| 		cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS); | ||||
| 		bits = 9; | ||||
| 	} | ||||
|  | ||||
| 	if (has_quirk_instruction_length(edev)) { | ||||
| 		cmd_addr <<= 2; | ||||
| 		bits += 2; | ||||
| 	} | ||||
|  | ||||
| 	dev_dbg(&edev->spi->dev, "ew%s cmd 0x%04x, %d bits\n", | ||||
| 			is_on ? "en" : "ds", cmd_addr, bits); | ||||
|  | ||||
| 	spi_message_init(&m); | ||||
| 	memset(&t, 0, sizeof(t)); | ||||
|  | ||||
| 	t.tx_buf = &cmd_addr; | ||||
| 	t.len = 2; | ||||
| 	t.bits_per_word = bits; | ||||
| 	spi_message_add_tail(&t, &m); | ||||
|  | ||||
| 	mutex_lock(&edev->lock); | ||||
|  | ||||
| 	if (edev->pdata->prepare) | ||||
| 		edev->pdata->prepare(edev); | ||||
|  | ||||
| 	ret = spi_sync(edev->spi, &m); | ||||
| 	/* have to wait at least Tcsl ns */ | ||||
| 	ndelay(250); | ||||
| 	if (ret) | ||||
| 		dev_err(&edev->spi->dev, "erase/write %sable error %d\n", | ||||
| 			is_on ? "en" : "dis", ret); | ||||
|  | ||||
| 	if (edev->pdata->finish) | ||||
| 		edev->pdata->finish(edev); | ||||
|  | ||||
| 	mutex_unlock(&edev->lock); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t | ||||
| eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, | ||||
| 			 char *buf, unsigned off) | ||||
| { | ||||
| 	struct spi_message m; | ||||
| 	struct spi_transfer t[2]; | ||||
| 	int bits, data_len, ret; | ||||
| 	u16 cmd_addr; | ||||
|     int data_bit; | ||||
|  | ||||
| 	cmd_addr = OP_WRITE << edev->addrlen; | ||||
|  | ||||
| 	if (edev->addrlen == 7) { | ||||
| 		cmd_addr |= off & 0x7f; | ||||
| 		bits = 10; | ||||
| 		data_len = 1; | ||||
|         data_bit = 8; | ||||
| 	} else { | ||||
| 		cmd_addr |= (off >> 1) & 0x3f; | ||||
| 		bits = 9; | ||||
| 		data_len = 2; | ||||
|         data_bit = 16; | ||||
| 	} | ||||
|  | ||||
| 	dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr); | ||||
|  | ||||
| 	spi_message_init(&m); | ||||
| 	memset(t, 0, sizeof(t)); | ||||
|  | ||||
| 	t[0].tx_buf = (char *)&cmd_addr; | ||||
| 	t[0].len = 2; | ||||
| 	t[0].bits_per_word = bits; | ||||
| 	spi_message_add_tail(&t[0], &m); | ||||
|  | ||||
| 	t[1].tx_buf = buf; | ||||
| 	t[1].len = data_len; | ||||
| 	t[1].bits_per_word = data_bit; | ||||
| 	spi_message_add_tail(&t[1], &m); | ||||
|  | ||||
| 	ret = spi_sync(edev->spi, &m); | ||||
| 	/* have to wait program cycle time Twc ms */ | ||||
| 	mdelay(6); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int eeprom_93xx46_write(void *priv, unsigned int off, | ||||
| 				   void *val, size_t count) | ||||
| { | ||||
| 	struct eeprom_93xx46_dev *edev = priv; | ||||
| 	char *buf = val; | ||||
| 	int i, ret, step = 1; | ||||
|  | ||||
| 	if (unlikely(off >= edev->size)) | ||||
| 		return -EFBIG; | ||||
| 	if ((off + count) > edev->size) | ||||
| 		count = edev->size - off; | ||||
| 	if (unlikely(!count)) | ||||
| 		return count; | ||||
|  | ||||
| 	/* only write even number of bytes on 16-bit devices */ | ||||
| 	if (edev->addrlen == 6) { | ||||
| 		step = 2; | ||||
| 		count &= ~1; | ||||
| 	} | ||||
|  | ||||
| 	/* erase/write enable */ | ||||
| 	ret = eeprom_93xx46_ew(edev, 1); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	mutex_lock(&edev->lock); | ||||
|  | ||||
| 	if (edev->pdata->prepare) | ||||
| 		edev->pdata->prepare(edev); | ||||
|  | ||||
| 	for (i = 0; i < count; i += step) { | ||||
| 		ret = eeprom_93xx46_write_word(edev, &buf[i], off + i); | ||||
| 		if (ret) { | ||||
| 			dev_err(&edev->spi->dev, "write failed at %d: %d\n", | ||||
| 				(int)off + i, ret); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (edev->pdata->finish) | ||||
| 		edev->pdata->finish(edev); | ||||
|  | ||||
| 	mutex_unlock(&edev->lock); | ||||
|  | ||||
| 	/* erase/write disable */ | ||||
| 	eeprom_93xx46_ew(edev, 0); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) | ||||
| { | ||||
| 	struct eeprom_93xx46_platform_data *pd = edev->pdata; | ||||
| 	struct spi_message m; | ||||
| 	struct spi_transfer t; | ||||
| 	int bits, ret; | ||||
| 	u16 cmd_addr; | ||||
|  | ||||
| 	cmd_addr = OP_START << edev->addrlen; | ||||
| 	if (edev->addrlen == 7) { | ||||
| 		cmd_addr |= ADDR_ERAL << 1; | ||||
| 		bits = 10; | ||||
| 	} else { | ||||
| 		cmd_addr |= ADDR_ERAL; | ||||
| 		bits = 9; | ||||
| 	} | ||||
|  | ||||
| 	if (has_quirk_instruction_length(edev)) { | ||||
| 		cmd_addr <<= 2; | ||||
| 		bits += 2; | ||||
| 	} | ||||
|  | ||||
| 	dev_dbg(&edev->spi->dev, "eral cmd 0x%04x, %d bits\n", cmd_addr, bits); | ||||
|  | ||||
| 	spi_message_init(&m); | ||||
| 	memset(&t, 0, sizeof(t)); | ||||
|  | ||||
| 	t.tx_buf = &cmd_addr; | ||||
| 	t.len = 2; | ||||
| 	t.bits_per_word = bits; | ||||
| 	spi_message_add_tail(&t, &m); | ||||
|  | ||||
| 	mutex_lock(&edev->lock); | ||||
|  | ||||
| 	if (edev->pdata->prepare) | ||||
| 		edev->pdata->prepare(edev); | ||||
|  | ||||
| 	ret = spi_sync(edev->spi, &m); | ||||
| 	if (ret) | ||||
| 		dev_err(&edev->spi->dev, "erase error %d\n", ret); | ||||
| 	/* have to wait erase cycle time Tec ms */ | ||||
| 	mdelay(6); | ||||
|  | ||||
| 	if (pd->finish) | ||||
| 		pd->finish(edev); | ||||
|  | ||||
| 	mutex_unlock(&edev->lock); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t eeprom_93xx46_store_erase(struct device *dev, | ||||
| 					 struct device_attribute *attr, | ||||
| 					 const char *buf, size_t count) | ||||
| { | ||||
| 	struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev); | ||||
| 	int erase = 0, ret; | ||||
|  | ||||
| 	sscanf(buf, "%d", &erase); | ||||
| 	if (erase) { | ||||
| 		ret = eeprom_93xx46_ew(edev, 1); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 		ret = eeprom_93xx46_eral(edev); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 		ret = eeprom_93xx46_ew(edev, 0); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 	} | ||||
| 	return count; | ||||
| } | ||||
| static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); | ||||
|  | ||||
| static void select_assert(void *context) | ||||
| { | ||||
| 	struct eeprom_93xx46_dev *edev = context; | ||||
|  | ||||
| 	gpiod_set_value_cansleep(edev->pdata->select, 1); | ||||
| } | ||||
|  | ||||
| static void select_deassert(void *context) | ||||
| { | ||||
| 	struct eeprom_93xx46_dev *edev = context; | ||||
|  | ||||
| 	gpiod_set_value_cansleep(edev->pdata->select, 0); | ||||
| } | ||||
|  | ||||
| static const struct of_device_id eeprom_93xx46_of_table[] = { | ||||
| 	{ .compatible = "eeprom-93xx46", }, | ||||
| 	{ .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, | ||||
| 	{} | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); | ||||
|  | ||||
| static int eeprom_93xx46_probe_dt(struct spi_device *spi) | ||||
| { | ||||
| 	const struct of_device_id *of_id = | ||||
| 		of_match_device(eeprom_93xx46_of_table, &spi->dev); | ||||
| 	struct device_node *np = spi->dev.of_node; | ||||
| 	struct eeprom_93xx46_platform_data *pd; | ||||
| 	u32 tmp; | ||||
| 	int gpio; | ||||
| 	enum of_gpio_flags of_flags; | ||||
| 	int ret; | ||||
|  | ||||
| 	pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL); | ||||
| 	if (!pd) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	ret = of_property_read_u32(np, "data-size", &tmp); | ||||
| 	if (ret < 0) { | ||||
| 		dev_err(&spi->dev, "data-size property not found\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	if (tmp == 8) { | ||||
| 		pd->flags |= EE_ADDR8; | ||||
| 	} else if (tmp == 16) { | ||||
| 		pd->flags |= EE_ADDR16; | ||||
| 	} else { | ||||
| 		dev_err(&spi->dev, "invalid data-size (%d)\n", tmp); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	if (of_property_read_bool(np, "read-only")) | ||||
| 		pd->flags |= EE_READONLY; | ||||
|  | ||||
| 	gpio = of_get_named_gpio_flags(np, "select-gpios", 0, &of_flags); | ||||
| 	if (gpio_is_valid(gpio)) { | ||||
| 		unsigned long flags = | ||||
| 			of_flags == OF_GPIO_ACTIVE_LOW ? GPIOF_ACTIVE_LOW : 0; | ||||
|  | ||||
| 		ret = devm_gpio_request_one(&spi->dev, gpio, flags, | ||||
| 					    "eeprom_93xx46_select"); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
|  | ||||
| 		pd->select = gpio_to_desc(gpio); | ||||
| 		pd->prepare = select_assert; | ||||
| 		pd->finish = select_deassert; | ||||
|  | ||||
| 		gpiod_direction_output(pd->select, 0); | ||||
| 	} | ||||
|  | ||||
|     if (of_id) { | ||||
|         if (of_id->data) { | ||||
|             const struct eeprom_93xx46_devtype_data *data = of_id->data; | ||||
|  | ||||
|             pd->quirks = data->quirks; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	spi->dev.platform_data = pd; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int eeprom_93xx46_probe(struct spi_device *spi) | ||||
| { | ||||
| 	struct eeprom_93xx46_platform_data *pd; | ||||
| 	struct eeprom_93xx46_dev *edev; | ||||
| 	int err; | ||||
|  | ||||
| 	if (spi->dev.of_node) { | ||||
| 		err = eeprom_93xx46_probe_dt(spi); | ||||
| 		if (err < 0) | ||||
| 			return err; | ||||
| 	} | ||||
|  | ||||
| 	pd = spi->dev.platform_data; | ||||
| 	if (!pd) { | ||||
| 		dev_err(&spi->dev, "missing platform data\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
|  | ||||
| 	edev = kzalloc(sizeof(*edev), GFP_KERNEL); | ||||
| 	if (!edev) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	if (pd->flags & EE_ADDR8) | ||||
| 		edev->addrlen = 7; | ||||
| 	else if (pd->flags & EE_ADDR16) | ||||
| 		edev->addrlen = 6; | ||||
| 	else { | ||||
| 		dev_err(&spi->dev, "unspecified address type\n"); | ||||
| 		err = -EINVAL; | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
| 	mutex_init(&edev->lock); | ||||
|  | ||||
| 	edev->spi = spi; | ||||
| 	edev->pdata = pd; | ||||
|  | ||||
| 	edev->size = 128; | ||||
| 	edev->nvmem_config.name = dev_name(&spi->dev); | ||||
| 	edev->nvmem_config.dev = &spi->dev; | ||||
| 	edev->nvmem_config.read_only = pd->flags & EE_READONLY; | ||||
| 	edev->nvmem_config.root_only = true; | ||||
| 	edev->nvmem_config.owner = THIS_MODULE; | ||||
| 	edev->nvmem_config.compat = true; | ||||
| 	edev->nvmem_config.base_dev = &spi->dev; | ||||
| 	edev->nvmem_config.reg_read = eeprom_93xx46_read; | ||||
| 	edev->nvmem_config.reg_write = eeprom_93xx46_write; | ||||
| 	edev->nvmem_config.priv = edev; | ||||
| 	edev->nvmem_config.stride = 4; | ||||
| 	edev->nvmem_config.word_size = 1; | ||||
| 	edev->nvmem_config.size = edev->size; | ||||
|  | ||||
| 	edev->nvmem = nvmem_register(&edev->nvmem_config); | ||||
| 	if (IS_ERR(edev->nvmem)) { | ||||
| 		err = PTR_ERR(edev->nvmem); | ||||
| 		goto fail; | ||||
| 	} | ||||
|  | ||||
|     if (g_rg_eeprom_93xx46_debug) { | ||||
|         dev_info(&spi->dev, "%d-bit eeprom %s\n", | ||||
|             (pd->flags & EE_ADDR8) ? 8 : 16, | ||||
|             (pd->flags & EE_READONLY) ? "(readonly)" : ""); | ||||
|     } | ||||
|  | ||||
| 	if (!(pd->flags & EE_READONLY)) { | ||||
| 		if (device_create_file(&spi->dev, &dev_attr_erase)) | ||||
| 			dev_err(&spi->dev, "can't create erase interface\n"); | ||||
| 	} | ||||
|  | ||||
| 	spi_set_drvdata(spi, edev); | ||||
| 	return 0; | ||||
| fail: | ||||
| 	kfree(edev); | ||||
| 	return err; | ||||
| } | ||||
|  | ||||
| static int eeprom_93xx46_remove(struct spi_device *spi) | ||||
| { | ||||
| 	struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi); | ||||
|  | ||||
| 	nvmem_unregister(edev->nvmem); | ||||
|  | ||||
| 	if (!(edev->pdata->flags & EE_READONLY)) | ||||
| 		device_remove_file(&spi->dev, &dev_attr_erase); | ||||
|  | ||||
| 	kfree(edev); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct spi_driver rg_eeprom_93xx46_driver = { | ||||
| 	.driver = { | ||||
| 		.name	= "rg_93xx46", | ||||
| 		.of_match_table = of_match_ptr(eeprom_93xx46_of_table), | ||||
| 	}, | ||||
| 	.probe		= eeprom_93xx46_probe, | ||||
| 	.remove		= eeprom_93xx46_remove, | ||||
| }; | ||||
|  | ||||
| module_spi_driver(rg_eeprom_93xx46_driver); | ||||
|  | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs"); | ||||
| MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>"); | ||||
| MODULE_ALIAS("spi:93xx46"); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,531 @@ | ||||
| /* | ||||
|  * Copyright(C) 2016 Ruijie Network. All rights reserved. | ||||
|  * | ||||
|  * fpga_pca954x_drv.c | ||||
|  * Original Author: sonic_rd@ruijie.com.cn 2020-08-10 | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/i2c-mux.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include "fpga_i2c.h" | ||||
|  | ||||
| extern int i2c_device_func_write(const char *path, uint32_t pos, uint8_t *val, size_t size); | ||||
| extern int pcie_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count); | ||||
|  | ||||
| #define PCA954X_MAX_NCHANS           (8) | ||||
| #define FPGA_INTERNAL_PCA9548        (1) | ||||
| #define FPGA_EXTERNAL_PCA9548        (2) | ||||
| #define FPGA_I2C_EXT_9548_EXITS      (0x01 << 0) | ||||
| #define FPGA_I2C_9548_NO_RESET       (0x01 << 1) | ||||
|  | ||||
| #define SYMBOL_I2C_DEV_MODE          (1) | ||||
| #define FILE_MODE                    (2) | ||||
| #define SYMBOL_PCIE_DEV_MODE         (3) | ||||
| #define SYMBOL_IO_DEV_MODE           (4) | ||||
|  | ||||
| int g_fpga_pca954x_debug = 0; | ||||
| int g_fpga_pca954x_error = 0; | ||||
|  | ||||
| module_param(g_fpga_pca954x_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_fpga_pca954x_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define FPGA_PCA954X_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_fpga_pca954x_debug) { \ | ||||
|         printk(KERN_INFO "[FPGA_PCA954X][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define FPGA_PCA954X_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_fpga_pca954x_error) { \ | ||||
|         printk(KERN_ERR "[FPGA_PCA954X][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| enum pca_type { | ||||
|     pca_9540, | ||||
|     pca_9541, | ||||
|     pca_9542, | ||||
|     pca_9543, | ||||
|     pca_9544, | ||||
|     pca_9545, | ||||
|     pca_9546, | ||||
|     pca_9547, | ||||
|     pca_9548, | ||||
| }; | ||||
|  | ||||
| struct pca954x { | ||||
|     enum pca_type type; | ||||
|     struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; | ||||
|     u8 last_chan;                   /* last register value */ | ||||
|     uint32_t fpga_9548_flag; | ||||
|     uint32_t fpga_9548_reset_flag; | ||||
|     uint32_t pca9548_base_nr; | ||||
|     struct i2c_client *client; | ||||
| }; | ||||
|  | ||||
| struct chip_desc { | ||||
|     u8 nchans; | ||||
|     u8 enable;    /* used for muxes only */ | ||||
|     enum muxtype { | ||||
|         pca954x_ismux = 0, | ||||
|         pca954x_isswi | ||||
|     } muxtype; | ||||
| }; | ||||
|  | ||||
| /* Provide specs for the PCA954x types we know about */ | ||||
| static const struct chip_desc chips[] = { | ||||
|     [pca_9540] = { | ||||
|         .nchans = 2, | ||||
|         .enable = 0x4, | ||||
|         .muxtype = pca954x_ismux, | ||||
|     }, | ||||
|     [pca_9541] = { | ||||
|         .nchans = 1, | ||||
|         .muxtype = pca954x_isswi, | ||||
|     }, | ||||
|     [pca_9543] = { | ||||
|         .nchans = 2, | ||||
|         .muxtype = pca954x_isswi, | ||||
|     }, | ||||
|     [pca_9544] = { | ||||
|         .nchans = 4, | ||||
|         .enable = 0x4, | ||||
|         .muxtype = pca954x_ismux, | ||||
|     }, | ||||
|     [pca_9545] = { | ||||
|         .nchans = 4, | ||||
|         .muxtype = pca954x_isswi, | ||||
|     }, | ||||
|     [pca_9547] = { | ||||
|         .nchans = 8, | ||||
|         .enable = 0x8, | ||||
|         .muxtype = pca954x_ismux, | ||||
|     }, | ||||
|     [pca_9548] = { | ||||
|         .nchans = 8, | ||||
|         .muxtype = pca954x_isswi, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static const struct i2c_device_id fpga_pca954x_id[] = { | ||||
|     { "rg_fpga_pca9540", pca_9540 }, | ||||
|     { "rg_fpga_pca9541", pca_9541 }, | ||||
|     { "rg_fpga_pca9542", pca_9543 }, | ||||
|     { "rg_fpga_pca9543", pca_9543 }, | ||||
|     { "rg_fpga_pca9544", pca_9544 }, | ||||
|     { "rg_fpga_pca9545", pca_9545 }, | ||||
|     { "rg_fpga_pca9546", pca_9545 }, | ||||
|     { "rg_fpga_pca9547", pca_9547 }, | ||||
|     { "rg_fpga_pca9548", pca_9548 }, | ||||
|     { } | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(i2c, fpga_pca954x_id); | ||||
|  | ||||
| static int fpga_file_write(const char *path, int pos, unsigned char *val, size_t size) | ||||
| { | ||||
|     int ret; | ||||
|     struct file *filp; | ||||
|     loff_t tmp_pos; | ||||
|  | ||||
|     filp = filp_open(path, O_RDWR, 777); | ||||
|     if (IS_ERR(filp)) { | ||||
|         FPGA_PCA954X_ERROR("write open failed errno = %ld\r\n", -PTR_ERR(filp)); | ||||
|         filp = NULL; | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     tmp_pos = (loff_t)pos; | ||||
|     ret = kernel_write(filp, val, size, &tmp_pos); | ||||
|     if (ret < 0) { | ||||
|         FPGA_PCA954X_ERROR("kernel_write failed, path=%s, addr=%d, size=%ld, ret=%d\r\n", path, pos, size, ret); | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     vfs_fsync(filp, 1); | ||||
|     filp_close(filp, NULL); | ||||
|  | ||||
|     return ret; | ||||
|  | ||||
| exit: | ||||
|     if (filp != NULL) { | ||||
|         filp_close(filp, NULL); | ||||
|     } | ||||
|  | ||||
|     return -1; | ||||
|  | ||||
| } | ||||
| static int fpga_device_write(fpga_i2c_dev_t *fpga_i2c, int pos, unsigned char *val, size_t size) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     switch (fpga_i2c->i2c_func_mode) { | ||||
|     case SYMBOL_I2C_DEV_MODE: | ||||
|         ret = i2c_device_func_write(fpga_i2c->dev_name, pos, val, size); | ||||
|         break; | ||||
|     case FILE_MODE: | ||||
|         ret = fpga_file_write(fpga_i2c->dev_name, pos, val, size); | ||||
|         break; | ||||
|     case SYMBOL_PCIE_DEV_MODE: | ||||
|         ret = pcie_device_func_write(fpga_i2c->dev_name, pos, val, size); | ||||
|         break; | ||||
|     default: | ||||
|         FPGA_PCA954X_ERROR("err func mode, write failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int fpga_reg_write(fpga_i2c_dev_t *fpga_i2c, uint32_t addr, uint8_t val) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     ret = fpga_device_write(fpga_i2c, addr, &val, sizeof(uint8_t)); | ||||
|     if (ret < 0) { | ||||
|         FPGA_PCA954X_ERROR("fpga_device_write failed. name:%s, addr:0x%x, value:0x%x.\n", | ||||
|             fpga_i2c->dev_name, addr, val); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     FPGA_PCA954X_VERBOSE("fpga reg write success, dev name:%s, offset:0x%x, value:0x%x.\n", | ||||
|         fpga_i2c->dev_name, addr, val); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,7) | ||||
| static int pca954x_select_chan(struct i2c_adapter *adap, void *client, u32 chan) | ||||
| { | ||||
|     struct pca954x *data = i2c_get_clientdata(client); | ||||
|     fpga_i2c_dev_t *fpga_i2c; | ||||
|     fpga_i2c_reg_t *reg; | ||||
|     int ret; | ||||
|     u8 regval, i2c_9548_opt; | ||||
|  | ||||
|     while(i2c_parent_is_i2c_adapter(adap)){ | ||||
|         adap = to_i2c_adapter(adap->dev.parent); | ||||
|     } | ||||
|  | ||||
|     FPGA_PCA954X_VERBOSE("root bus:%d, chan:0x%x, 9548 flag:0x%x, 9548 addr:0x%x.\n", | ||||
|         adap->nr, chan, data->fpga_9548_flag, client->addr); | ||||
|     fpga_i2c = i2c_get_adapdata(adap); | ||||
|     reg = &fpga_i2c->reg; | ||||
|  | ||||
|     regval = 1 << chan; | ||||
|     if (data->fpga_9548_flag == FPGA_INTERNAL_PCA9548) { | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_in_9548_chan, regval); | ||||
|     } else { | ||||
|         if (data->fpga_9548_reset_flag == 1) { | ||||
|             i2c_9548_opt = FPGA_I2C_EXT_9548_EXITS & ~(FPGA_I2C_9548_NO_RESET); | ||||
|         } else { | ||||
|             i2c_9548_opt = FPGA_I2C_EXT_9548_EXITS | FPGA_I2C_9548_NO_RESET; | ||||
|         } | ||||
|         FPGA_PCA954X_VERBOSE("fpga pca9548 reset flag:0x%x, opt:0x%x.\n", | ||||
|             data->fpga_9548_reset_flag, i2c_9548_opt); | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_exits_flag, i2c_9548_opt); | ||||
|         ret += fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_addr, client->addr); | ||||
|         ret += fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_chan, regval); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int pca954x_deselect_mux(struct i2c_adapter *adap, void *client, u32 chan) | ||||
| { | ||||
|     struct pca954x *data = i2c_get_clientdata(client); | ||||
|     fpga_i2c_dev_t *fpga_i2c; | ||||
|     fpga_i2c_reg_t *reg; | ||||
|     int ret; | ||||
|  | ||||
|     while(i2c_parent_is_i2c_adapter(adap)){ | ||||
|         adap = to_i2c_adapter(adap->dev.parent); | ||||
|     } | ||||
|  | ||||
|     fpga_i2c = i2c_get_adapdata(adap); | ||||
|     reg = &fpga_i2c->reg; | ||||
|     /* Deselect active channel */ | ||||
|     data->last_chan = 0; | ||||
|     if (data->fpga_9548_flag == FPGA_INTERNAL_PCA9548) { | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_in_9548_chan, 0); | ||||
|     } else { | ||||
|  | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_exits_flag, FPGA_I2C_9548_NO_RESET); | ||||
|         ret += fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_chan, 0); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
| #else | ||||
| static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) | ||||
| { | ||||
|     struct pca954x *data = i2c_mux_priv(muxc); | ||||
|     struct i2c_client *client = data->client; | ||||
|     struct i2c_adapter *adap; | ||||
|     fpga_i2c_dev_t *fpga_i2c; | ||||
|     fpga_i2c_reg_t *reg; | ||||
|     int ret; | ||||
|     u8 regval, i2c_9548_opt; | ||||
|  | ||||
|     adap = muxc->parent; | ||||
|     while(i2c_parent_is_i2c_adapter(adap)){ | ||||
|         adap = to_i2c_adapter(adap->dev.parent); | ||||
|     } | ||||
|  | ||||
|     FPGA_PCA954X_VERBOSE("root bus:%d, chan:0x%x, 9548 flag:0x%x, 9548 addr:0x%x.\n", | ||||
|         adap->nr, chan, data->fpga_9548_flag, client->addr); | ||||
|     fpga_i2c = i2c_get_adapdata(adap); | ||||
|     reg = &fpga_i2c->reg; | ||||
|  | ||||
|     regval = 1 << chan; | ||||
|     if (data->fpga_9548_flag == FPGA_INTERNAL_PCA9548) { | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_in_9548_chan, regval); | ||||
|     } else { | ||||
|         if (data->fpga_9548_reset_flag == 1) { | ||||
|             i2c_9548_opt = FPGA_I2C_EXT_9548_EXITS & ~(FPGA_I2C_9548_NO_RESET); | ||||
|         } else { | ||||
|             i2c_9548_opt = FPGA_I2C_EXT_9548_EXITS | FPGA_I2C_9548_NO_RESET; | ||||
|         } | ||||
|         FPGA_PCA954X_VERBOSE("fpga pca9548 reset flag:0x%x, opt:0x%x.\n", | ||||
|             data->fpga_9548_reset_flag, i2c_9548_opt); | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_exits_flag, i2c_9548_opt); | ||||
|         ret += fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_addr, client->addr); | ||||
|         ret += fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_chan, regval); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) | ||||
| { | ||||
|     struct pca954x *data = i2c_mux_priv(muxc); | ||||
|     struct i2c_adapter *adap; | ||||
|     fpga_i2c_dev_t *fpga_i2c; | ||||
|     fpga_i2c_reg_t *reg; | ||||
|     int ret; | ||||
|  | ||||
|     adap = muxc->parent; | ||||
|     while(i2c_parent_is_i2c_adapter(adap)){ | ||||
|         adap = to_i2c_adapter(adap->dev.parent); | ||||
|     } | ||||
|  | ||||
|     fpga_i2c = i2c_get_adapdata(adap); | ||||
|     reg = &fpga_i2c->reg; | ||||
|     ret = 0; | ||||
|     /* Deselect active channel */ | ||||
|     data->last_chan = 0; | ||||
|  | ||||
|     if (data->fpga_9548_flag == FPGA_INTERNAL_PCA9548) { | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_in_9548_chan, 0); | ||||
|     } else { | ||||
|  | ||||
|         ret = fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_exits_flag, FPGA_I2C_9548_NO_RESET); | ||||
|         ret += fpga_reg_write(fpga_i2c, reg->i2c_ext_9548_chan, 0); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
| #endif | ||||
| /* | ||||
|  * I2C init/probing/exit functions | ||||
|  */ | ||||
| static int fpga_i2c_pca954x_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||||
| { | ||||
|     struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); | ||||
|     int num, force, class; | ||||
|     struct pca954x *data; | ||||
|     int ret = -ENODEV; | ||||
|     struct device *dev; | ||||
|     int dynamic_nr = 1; | ||||
|     fpga_pca954x_device_t *fpga_pca954x_device; | ||||
|  | ||||
| #if LINUX_VERSION_CODE > KERNEL_VERSION(4,6,7) | ||||
|     struct i2c_mux_core *muxc; | ||||
| #endif | ||||
|  | ||||
|     if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) { | ||||
|         dev_err(&client->dev, "i2c adapter:%d, unsupport I2C_FUNC_SMBUS_BYTE.\n", adap->nr); | ||||
|         goto err; | ||||
|     } | ||||
|  | ||||
| #if LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,7) | ||||
|     data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); | ||||
|     if (!data) { | ||||
|         dev_err(&client->dev, "kzalloc failed.\n"); | ||||
|         ret = -ENOMEM; | ||||
|         goto err; | ||||
|     } | ||||
|  | ||||
|     i2c_set_clientdata(client, data); | ||||
| #else | ||||
|     muxc = i2c_mux_alloc(adap, &client->dev, | ||||
|                  PCA954X_MAX_NCHANS, sizeof(*data), 0, | ||||
|                  pca954x_select_chan, pca954x_deselect_mux); | ||||
|     if (!muxc) { | ||||
|         dev_err(&client->dev, "i2c_mux_alloc failed.\n"); | ||||
|         return -ENOMEM; | ||||
|     } | ||||
|     data = i2c_mux_priv(muxc); | ||||
|     i2c_set_clientdata(client, muxc); | ||||
|     data->client = client; | ||||
| #endif | ||||
|  | ||||
|     dev = &client->dev; | ||||
|     if (dev == NULL) { | ||||
|         dev_err(&client->dev, "dev is NULL.\n"); | ||||
|         ret = -ENODEV; | ||||
|         goto exit_free; | ||||
|     } | ||||
|  | ||||
|     if (dev->of_node == NULL) { | ||||
|         if (client->dev.platform_data == NULL) { | ||||
|             dev_err(&client->dev, "Failed to get 954x platform data config.\n"); | ||||
|             ret = -EINVAL; | ||||
|             goto exit_free; | ||||
|         } | ||||
|         fpga_pca954x_device = client->dev.platform_data; | ||||
|         data->fpga_9548_flag = fpga_pca954x_device->fpga_9548_flag; | ||||
|         data->fpga_9548_reset_flag = fpga_pca954x_device->fpga_9548_reset_flag; | ||||
|         data->pca9548_base_nr = fpga_pca954x_device->pca9548_base_nr; | ||||
|         if (data->pca9548_base_nr == 0) { | ||||
|  | ||||
|             dynamic_nr = 1; | ||||
|         } else { | ||||
|             dynamic_nr = 0; | ||||
|             FPGA_PCA954X_VERBOSE("pca9548_base_nr:%u.\n", data->pca9548_base_nr); | ||||
|         } | ||||
|     } else { | ||||
|         data->type = id->driver_data; | ||||
|         /* BUS ID */ | ||||
|         ret = of_property_read_u32(dev->of_node, "fpga_9548_flag", &data->fpga_9548_flag); | ||||
|         ret += of_property_read_u32(dev->of_node, "fpga_9548_reset_flag", &data->fpga_9548_reset_flag); | ||||
|         if (ret != 0) { | ||||
|             dev_err(&client->dev, "Failed to get 954x dts config, ret:%d.\n", ret); | ||||
|             ret = -EINVAL; | ||||
|             goto exit_free; | ||||
|         } | ||||
|         if (of_property_read_u32(dev->of_node, "pca9548_base_nr", &data->pca9548_base_nr)) { | ||||
|  | ||||
|             dynamic_nr = 1; | ||||
|             FPGA_PCA954X_VERBOSE("pca9548_base_nr not found, use dynamic adap number"); | ||||
|         } else { | ||||
|             dynamic_nr = 0; | ||||
|             FPGA_PCA954X_VERBOSE("pca9548_base_nr:%u.\n", data->pca9548_base_nr); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (data->fpga_9548_flag != FPGA_EXTERNAL_PCA9548 && data->fpga_9548_flag != FPGA_INTERNAL_PCA9548) { | ||||
|         dev_err(&client->dev, "Error: fpga 954x flag config error, value:0x%x.\n", data->fpga_9548_flag); | ||||
|         ret = -EINVAL; | ||||
|         goto exit_free; | ||||
|     } | ||||
|  | ||||
|     data->type = id->driver_data; | ||||
|     data->last_chan = 0;   /* force the first selection */ | ||||
|  | ||||
|     /* Now create an adapter for each channel */ | ||||
|     for (num = 0; num < chips[data->type].nchans; num++) { | ||||
|         if (dynamic_nr == 1) { | ||||
|             force = 0;              /* dynamic adap number */ | ||||
|         } else { | ||||
|             force = data->pca9548_base_nr + num; | ||||
|         } | ||||
|         class = 0;              /* no class by default */ | ||||
| #if LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,7) | ||||
|         data->virt_adaps[num] = | ||||
|             i2c_add_mux_adapter(adap, &client->dev, client, | ||||
|                 force, num, class, pca954x_select_chan, pca954x_deselect_mux); | ||||
|  | ||||
|         if (data->virt_adaps[num] == NULL) { | ||||
|             ret = -ENODEV; | ||||
|             dev_err(&client->dev, "Failed to register multiplexed adapter %d as bus %d\n", | ||||
|                 num, force); | ||||
|             goto virt_reg_failed; | ||||
|         } | ||||
| #else | ||||
|         ret = i2c_mux_add_adapter(muxc, force, num, class); | ||||
|         if (ret) { | ||||
|             dev_err(&client->dev, "Failed to register multiplexed adapter %d as bus %d\n", | ||||
|                 num, force); | ||||
|             goto virt_reg_failed; | ||||
|         } | ||||
| #endif | ||||
|     } /* end for num = 0; num < chips[data->type].nchans... */ | ||||
|  | ||||
|     dev_info(&client->dev, "registered %d multiplexed busses for I2C %s %s\n", | ||||
|         num, chips[data->type].muxtype == pca954x_ismux ? "mux" : "switch", client->name); | ||||
|  | ||||
|     return 0; | ||||
|  | ||||
| virt_reg_failed: | ||||
| #if LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,7) | ||||
|     for (num--; num >= 0; num--) | ||||
|         i2c_del_mux_adapter(data->virt_adaps[num]); | ||||
| exit_free: | ||||
|     kfree(data); | ||||
| #else | ||||
| exit_free: | ||||
|     i2c_mux_del_adapters(muxc); | ||||
| #endif | ||||
| err: | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int fpga_i2c_pca954x_remove(struct i2c_client *client) | ||||
| { | ||||
| #if LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,7) | ||||
|     struct pca954x *data = i2c_get_clientdata(client); | ||||
|     const struct chip_desc *chip = &chips[data->type]; | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < chip->nchans; ++i) | ||||
|     if (data->virt_adaps[i]) { | ||||
|         i2c_del_mux_adapter(data->virt_adaps[i]); | ||||
|         data->virt_adaps[i] = NULL; | ||||
|     } | ||||
|  | ||||
|     kfree(data); | ||||
| #else | ||||
|     struct i2c_mux_core *muxc = i2c_get_clientdata(client); | ||||
|  | ||||
|     i2c_mux_del_adapters(muxc); | ||||
| #endif | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static struct i2c_driver fpga_i2c_pca954x_driver = { | ||||
|     .driver        = { | ||||
|         .name = "rg_fpga_pca954x", | ||||
|         .owner = THIS_MODULE, | ||||
|     }, | ||||
|     .probe = fpga_i2c_pca954x_probe, | ||||
|     .remove = fpga_i2c_pca954x_remove, | ||||
|     .id_table = fpga_pca954x_id, | ||||
| }; | ||||
|  | ||||
| static int __init fpga_i2c_pca954x_init(void) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     ret = i2c_add_driver(&fpga_i2c_pca954x_driver); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static void __exit fpga_i2c_pca954x_exit(void) | ||||
| { | ||||
|     i2c_del_driver(&fpga_i2c_pca954x_driver); | ||||
| } | ||||
|  | ||||
| module_init(fpga_i2c_pca954x_init); | ||||
| module_exit(fpga_i2c_pca954x_exit); | ||||
| MODULE_DESCRIPTION("fpga pca954x driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,167 @@ | ||||
| /* | ||||
|  * Copyright(C) 2016 Ruijie Network. All rights reserved. | ||||
|  * | ||||
|  * rg_fpga_pcie.c | ||||
|  * ko to enable fpga pcie | ||||
|  * Original Author: sonic_rd@ruijie.com.cn 2020-08-10 | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/pci.h> | ||||
|  | ||||
| #define FPGA_MSI_IRQ_NUM            (14) | ||||
| #define FPGA_MSI_IRQ_BEGIN          (0) | ||||
| #define XILINX_FPGA_USE_MSI         (0) | ||||
| #define XILINX_FPGA_NUSE_MSI        (1) | ||||
|  | ||||
| int g_fpga_pcie_dev_debug = 0; | ||||
| int g_fpga_pcie_dev_error = 0; | ||||
| module_param(g_fpga_pcie_dev_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_fpga_pcie_dev_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define FPGA_PCIE_DEV_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_fpga_pcie_dev_debug) { \ | ||||
|         printk(KERN_INFO "[FPGA_PCIE][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define FPGA_PCIE_DEV_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_fpga_pcie_dev_error) { \ | ||||
|         printk(KERN_ERR "[FPGA_PCIE][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| typedef struct rg_fpga_pcie_s { | ||||
|     struct pci_dev *pci_dev; | ||||
|     int driver_data; | ||||
| } rg_fpga_pcie_t; | ||||
|  | ||||
| static void fpga_pcie_recover(struct pci_dev *pdev, const struct pci_device_id *id) | ||||
| { | ||||
|     struct resource *mem_base; | ||||
|     u32 bar0_val; | ||||
|     int ret; | ||||
|  | ||||
|     mem_base = &pdev->resource[0]; | ||||
|     ret = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar0_val); | ||||
|     if (ret) { | ||||
|         FPGA_PCIE_DEV_ERROR("pci_read_config_dword failed ret %d.\n", ret); | ||||
|         return; | ||||
|     } | ||||
|     FPGA_PCIE_DEV_VERBOSE("mem_base->start[0x%llx], bar0_val[0x%x], ret %d.\n", | ||||
|         mem_base->start, bar0_val, ret); | ||||
|  | ||||
|     if (bar0_val != mem_base->start) { | ||||
|         ret = pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, mem_base->start); | ||||
|         if (ret) { | ||||
|             FPGA_PCIE_DEV_ERROR("pci_write_config_dword mem_base->start[0x%llx], failed ret %d.\n", mem_base->start, ret); | ||||
|             return; | ||||
|         } | ||||
|         FPGA_PCIE_DEV_VERBOSE("pci_write_config_dword mem_base->start[0x%llx] success.\n", mem_base->start); | ||||
|     } else { | ||||
|         FPGA_PCIE_DEV_VERBOSE("mem_base->start[0x%llx], bar0_val[0x%x], do nothing.\n", | ||||
|             mem_base->start, bar0_val); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int fpga_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||||
| { | ||||
|     int err; | ||||
|     rg_fpga_pcie_t *rg_fpga_pcie; | ||||
|  | ||||
|     FPGA_PCIE_DEV_VERBOSE("Enter vendor 0x%x, subsystem_vendor 0x%x.\n", pdev->vendor, pdev->subsystem_vendor); | ||||
|  | ||||
|     rg_fpga_pcie = devm_kzalloc(&pdev->dev, sizeof(rg_fpga_pcie_t), GFP_KERNEL); | ||||
|     if (!rg_fpga_pcie) { | ||||
|         dev_err(&pdev->dev, "devm_kzalloc failed.\n"); | ||||
|         return -ENOMEM; | ||||
|     } | ||||
|  | ||||
|     fpga_pcie_recover(pdev, id); | ||||
|  | ||||
|     /* enable device: ask low-level code to enable I/O and memory */ | ||||
|     FPGA_PCIE_DEV_VERBOSE("start pci_enable_device!\n"); | ||||
|     err = pci_enable_device(pdev); | ||||
|     if (err) { | ||||
|         dev_err(&pdev->dev, "Failed to enable pci device, ret:%d.\n", err); | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     FPGA_PCIE_DEV_VERBOSE("start pci_set_master!\n"); | ||||
|     pci_set_master(pdev); | ||||
|  | ||||
|     rg_fpga_pcie->driver_data = id->driver_data; | ||||
|     rg_fpga_pcie->pci_dev = pdev; | ||||
|     pci_set_drvdata(pdev, rg_fpga_pcie); | ||||
|  | ||||
|     if (rg_fpga_pcie->driver_data == XILINX_FPGA_USE_MSI) { | ||||
|         FPGA_PCIE_DEV_VERBOSE("start pci_enable_msi_range!\n"); | ||||
| #if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,152) | ||||
|         err = pci_enable_msi_range(pdev, FPGA_MSI_IRQ_BEGIN + 1, FPGA_MSI_IRQ_NUM); | ||||
| #else | ||||
|         err = pci_alloc_irq_vectors_affinity(pdev, FPGA_MSI_IRQ_BEGIN + 1, | ||||
|                 FPGA_MSI_IRQ_NUM, PCI_IRQ_MSI, NULL); | ||||
| #endif | ||||
|         if (err != FPGA_MSI_IRQ_NUM) { | ||||
|             FPGA_PCIE_DEV_ERROR("pci_enable_msi_block err %d FPGA_MSI_IRQ_NUM %d.\n", err, | ||||
|                 FPGA_MSI_IRQ_NUM); | ||||
|             dev_err(&pdev->dev, "Failed to enable pci msi, ret:%d.\n", err); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     dev_info(&pdev->dev, "fpga pci device init success.\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void fpga_pcie_remove(struct pci_dev *pdev) | ||||
| { | ||||
|     rg_fpga_pcie_t *rg_fpga_pcie; | ||||
|  | ||||
|     FPGA_PCIE_DEV_VERBOSE("fpga_pcie_remove.\n"); | ||||
|  | ||||
|     rg_fpga_pcie = pci_get_drvdata(pdev); | ||||
|     if (rg_fpga_pcie->driver_data == XILINX_FPGA_USE_MSI) { | ||||
|         FPGA_PCIE_DEV_VERBOSE("start pci_disable_msi!\n"); | ||||
|         pci_disable_msi(pdev); | ||||
|     } | ||||
|  | ||||
|     pci_disable_device(pdev); | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static const struct pci_device_id fpga_pci_ids[] = { | ||||
|         { PCI_DEVICE(0x10ee, 0x7022), .driver_data = XILINX_FPGA_USE_MSI}, | ||||
|         { PCI_DEVICE(0x10ee, 0x7011), .driver_data = XILINX_FPGA_NUSE_MSI}, | ||||
|         {0} | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(pci, fpga_pci_ids); | ||||
|  | ||||
| static struct pci_driver rg_fpga_pcie_driver = { | ||||
|     .name = "rg_fpga_pcie", | ||||
|     .id_table = fpga_pci_ids,/* only dynamic id's */ | ||||
|     .probe = fpga_pcie_probe, | ||||
|     .remove = fpga_pcie_remove, | ||||
| }; | ||||
|  | ||||
| static int __init rg_fpga_pcie_init(void) | ||||
| { | ||||
|  | ||||
|     FPGA_PCIE_DEV_VERBOSE("rg_fpga_pcie_init enter!\n"); | ||||
|     return pci_register_driver(&rg_fpga_pcie_driver); | ||||
| } | ||||
|  | ||||
| static void __exit rg_fpga_pcie_exit(void) | ||||
| { | ||||
|     FPGA_PCIE_DEV_VERBOSE("rg_fpga_pcie_exit enter!\n"); | ||||
|     pci_unregister_driver(&rg_fpga_pcie_driver); | ||||
|     return; | ||||
| } | ||||
|  | ||||
| module_init(rg_fpga_pcie_init); | ||||
| module_exit(rg_fpga_pcie_exit); | ||||
| MODULE_DESCRIPTION("fpga pcie driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,367 @@ | ||||
| /* | ||||
|  * This file is subject to the terms and conditions of the GNU General Public | ||||
|  * License.  See the file "COPYING" in the main directory of this archive | ||||
|  * for more details. | ||||
|  * | ||||
|  * Copyright (C) 2011, 2012 Cavium Inc. | ||||
|  */ | ||||
| #include <linux/init.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/gpio.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/spinlock.h> | ||||
|  | ||||
| #define GPIO_NAME           "rg_gpio_d1500" | ||||
|  | ||||
| #define GPIO_BASE           (0x500) | ||||
| #define GP_IO_SEL           (GPIO_BASE + 0x4) | ||||
| #define GP_LVL              (GPIO_BASE + 0xC) | ||||
| #define GPI_NMI_EN          (GPIO_BASE + 0x28) | ||||
| #define GPI_NMI_STS         (GPIO_BASE + 0x2a) | ||||
| #define GPI_INV             (GPIO_BASE + 0x2c) | ||||
| #define GPIO_USE_SEL2       (GPIO_BASE + 0x30) | ||||
| #define GP_IO_SEL2          (GPIO_BASE + 0x34) | ||||
| #define GP_LVL2             (GPIO_BASE + 0x38) | ||||
| #define GPI_NMI_EN_2        (GPIO_BASE + 0x3c) | ||||
| #define GPI_NMI_STS_2       (GPIO_BASE + 0x3e) | ||||
| #define GPIO_USE_SEL3       (GPIO_BASE + 0x40) | ||||
| #define GP_IO_SEL3          (GPIO_BASE + 0x44) | ||||
| #define GP_LVL3             (GPIO_BASE + 0x48) | ||||
| #define GPI_NMI_EN_3        (GPIO_BASE + 0x50) | ||||
| #define GPI_NMI_STS_3       (GPIO_BASE + 0x54) | ||||
|  | ||||
| #define GPIO_BASE_ID        (0) | ||||
| #define BANKSIZE            (32) | ||||
| #define D1500_GPIO_PIN_NUM  (96) | ||||
| #define CELL_NUM            (2) | ||||
|  | ||||
| int g_gpio_d1500_debug = 0; | ||||
| int g_gpio_d1500_error = 0; | ||||
| module_param(g_gpio_d1500_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_gpio_d1500_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define GPIO_DEBUG_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_gpio_d1500_debug) { \ | ||||
|         printk(KERN_ERR "[GPIO-D1500][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define GPIO_DEBUG_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_gpio_d1500_error) { \ | ||||
|         printk(KERN_ERR "[GPIO-D1500][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| static DEFINE_SPINLOCK(sio_lock); | ||||
|  | ||||
| struct gpio_d1500_t { | ||||
|     struct gpio_chip chip; | ||||
|     u64 register_base; | ||||
| }; | ||||
|  | ||||
| static int rg_gpio_get(struct gpio_chip *gc, unsigned gpio_num) | ||||
| { | ||||
|     u32 data = 0; | ||||
|     unsigned int bank, offset; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     bank = gpio_num / BANKSIZE; | ||||
|     offset = gpio_num % BANKSIZE; | ||||
|  | ||||
|     spin_lock_irqsave(&sio_lock, flags); | ||||
|     if (bank == 0) { | ||||
|         data = inl(GP_LVL) & (1 << offset); | ||||
|         if (data) { | ||||
|             data = 1; | ||||
|         } | ||||
|     } else if (bank == 1) { | ||||
|         data = inl(GP_LVL2) & (1 << offset); | ||||
|         if (data) { | ||||
|             data = 1; | ||||
|         } | ||||
|     } else if (bank == 2) { | ||||
|         data = inl(GP_LVL3) & (1 << offset); | ||||
|         if (data) { | ||||
|             data = 1; | ||||
|         } | ||||
|     } | ||||
|     spin_unlock_irqrestore(&sio_lock, flags); | ||||
|  | ||||
|     return data; | ||||
| } | ||||
|  | ||||
| static int rg_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) | ||||
| { | ||||
|     u32 data; | ||||
|     unsigned int bank, offset; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     bank = gpio_num / BANKSIZE; | ||||
|     offset = gpio_num % BANKSIZE; | ||||
|  | ||||
|     spin_lock_irqsave(&sio_lock, flags); | ||||
|     if (bank == 0) { | ||||
|         data = inl(GP_IO_SEL); | ||||
|         data = data | (1 << offset); | ||||
|         outl(data, GP_IO_SEL); | ||||
|     } else if (bank == 1) { | ||||
|         data = inl(GP_IO_SEL2); | ||||
|         data = data | (1 << offset); | ||||
|         outl(data, GP_IO_SEL2); | ||||
|     } else if (bank == 2) { | ||||
|         data = inl(GP_IO_SEL3); | ||||
|         data = data | (1 << offset); | ||||
|         outl(data, GP_IO_SEL3); | ||||
|     } | ||||
|     spin_unlock_irqrestore(&sio_lock, flags); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void rg_gpio_set(struct gpio_chip *gc, | ||||
|                 unsigned gpio_num, int val) | ||||
| { | ||||
|     u32 data; | ||||
|     unsigned int bank, offset; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     bank = gpio_num / BANKSIZE; | ||||
|     offset = gpio_num % BANKSIZE; | ||||
|  | ||||
|     spin_lock_irqsave(&sio_lock, flags); | ||||
|     if (bank == 0) { | ||||
|         data = inl(GP_LVL); | ||||
|         if (val) { | ||||
|             data = data | (1 << offset); | ||||
|         } else { | ||||
|             data = data & ~(1 << offset); | ||||
|         } | ||||
|         outl(data, GP_LVL); | ||||
|     } else if (bank == 1) { | ||||
|         data = inl(GP_LVL2); | ||||
|         if (val) { | ||||
|             data = data | (1 << offset); | ||||
|         } else { | ||||
|             data = data & ~(1 << offset); | ||||
|         } | ||||
|         outl(data, GP_LVL2); | ||||
|     } else if (bank == 2) { | ||||
|         data = inl(GP_LVL3); | ||||
|         if (val) { | ||||
|             data = data | (1 << offset); | ||||
|         } else { | ||||
|             data = data & ~(1 << offset); | ||||
|         } | ||||
|         outl(data, GP_LVL3); | ||||
|     } | ||||
|     spin_unlock_irqrestore(&sio_lock, flags); | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static int rg_gpio_direction_out(struct gpio_chip *gc, | ||||
|                     unsigned gpio_num, int val) | ||||
| { | ||||
|     u32 data; | ||||
|     unsigned int bank, offset; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     bank = gpio_num / BANKSIZE; | ||||
|     offset = gpio_num % BANKSIZE; | ||||
|  | ||||
|     spin_lock_irqsave(&sio_lock, flags); | ||||
|     if (bank == 0) { | ||||
|         data = inl(GP_IO_SEL); | ||||
|         data = data & ~(1 << offset); | ||||
|         outl(data, GP_IO_SEL); | ||||
|  | ||||
|         data = inl(GP_LVL); | ||||
|         if (val) { | ||||
|             data = data | (1 << offset); | ||||
|         } else { | ||||
|             data = data & ~(1 << offset); | ||||
|         } | ||||
|         outl(data, GP_LVL); | ||||
|     } else if (bank == 1) { | ||||
|         data = inl(GP_IO_SEL2); | ||||
|         data = data & ~(1 << offset); | ||||
|         outl(data, GP_IO_SEL2); | ||||
|  | ||||
|         data = inl(GP_LVL2); | ||||
|         if (val) { | ||||
|             data = data | (1 << offset); | ||||
|         } else { | ||||
|             data = data & ~(1 << offset); | ||||
|         } | ||||
|         outl(data, GP_LVL2); | ||||
|     } else if (bank == 2) { | ||||
|         data = inl(GP_IO_SEL3); | ||||
|         data = data & ~(1 << offset); | ||||
|         outl(data, GP_IO_SEL3); | ||||
|  | ||||
|         data = inl(GP_LVL3); | ||||
|         if (val) { | ||||
|             data = data | (1 << offset); | ||||
|         } else { | ||||
|             data = data & ~(1 << offset); | ||||
|         } | ||||
|         outl(data, GP_LVL3); | ||||
|     } | ||||
|     spin_unlock_irqrestore(&sio_lock, flags); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #ifdef CONFIG_OF | ||||
| static int rg_gpio_of_xlate(struct gpio_chip *chip, | ||||
|                               const struct of_phandle_args *gpio_desc, | ||||
|                               u32 *flags) | ||||
| { | ||||
|     if (chip->of_gpio_n_cells < 2) { | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (flags) { | ||||
|         *flags = gpio_desc->args[1]; | ||||
|     } | ||||
|  | ||||
|     return gpio_desc->args[0]; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int rg_gpio_request(struct gpio_chip *chip, unsigned int offset) | ||||
| { | ||||
|     u32 data; | ||||
|     unsigned int bank, tmp_offset; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     bank = offset / BANKSIZE; | ||||
|     tmp_offset = offset % BANKSIZE; | ||||
|  | ||||
|     spin_lock_irqsave(&sio_lock, flags); | ||||
|     if (bank == 0) { | ||||
|         data = inl(GPIO_BASE); | ||||
|         data = data | (1 << tmp_offset); | ||||
|         outl(data, GPIO_BASE); | ||||
|     } else if (bank == 1) { | ||||
|         data = inl(GPIO_USE_SEL2); | ||||
|         data = data | (1 << tmp_offset); | ||||
|         outl(data, GPIO_USE_SEL2); | ||||
|     } else if (bank == 2) { | ||||
|         data = inl(GPIO_USE_SEL3); | ||||
|         data = data | (1 << tmp_offset); | ||||
|         outl(data, GPIO_USE_SEL3); | ||||
|     } | ||||
|     spin_unlock_irqrestore(&sio_lock, flags); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static void rg_gpio_free(struct gpio_chip *chip, unsigned int offset) | ||||
| { | ||||
|     u32 data; | ||||
|     unsigned int bank, tmp_offset; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     bank = offset / BANKSIZE; | ||||
|     tmp_offset = offset % BANKSIZE; | ||||
|  | ||||
|     spin_lock_irqsave(&sio_lock, flags); | ||||
|     if (bank == 0) { | ||||
|         data = inl(GPIO_BASE); | ||||
|         data = data & ~(1 << tmp_offset); | ||||
|         outl(data, GPIO_BASE); | ||||
|     } else if (bank == 1) { | ||||
|         data = inl(GPIO_USE_SEL2); | ||||
|         data = data & ~(1 << tmp_offset); | ||||
|         outl(data, GPIO_USE_SEL2); | ||||
|     } else if (bank == 2) { | ||||
|         data = inl(GPIO_USE_SEL3); | ||||
|         data = data & ~(1 << tmp_offset); | ||||
|         outl(data, GPIO_USE_SEL3); | ||||
|     } | ||||
|  | ||||
|     spin_unlock_irqrestore(&sio_lock, flags); | ||||
|  | ||||
|     return; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static struct gpio_chip rg_gpio_chip = { | ||||
|     .label              = GPIO_NAME, | ||||
|     .owner              = THIS_MODULE, | ||||
|     .base               = GPIO_BASE_ID, | ||||
|     .get                = rg_gpio_get, | ||||
|     .direction_input    = rg_gpio_direction_in, | ||||
|     .set                = rg_gpio_set, | ||||
|     .direction_output   = rg_gpio_direction_out, | ||||
| #ifdef CONFIG_OF | ||||
|     .of_xlate           = rg_gpio_of_xlate, | ||||
| #endif | ||||
|     .request            = rg_gpio_request, | ||||
|     .ngpio              = D1500_GPIO_PIN_NUM, | ||||
| #ifdef CONFIG_OF | ||||
|     .of_gpio_n_cells    = CELL_NUM, | ||||
| #endif | ||||
|     .can_sleep          = false, | ||||
| }; | ||||
|  | ||||
| static int rg_gpio_probe(struct platform_device *pdev) | ||||
| { | ||||
|     struct gpio_d1500_t *gpio; | ||||
|     int err; | ||||
|  | ||||
|     gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | ||||
|     if (!gpio) { | ||||
|         dev_err(&pdev->dev, "gpio kzalloc failed\n"); | ||||
|         return -ENOMEM; | ||||
|     } | ||||
|  | ||||
|     rg_gpio_chip.parent = &pdev->dev; | ||||
|     gpio->register_base = GPIO_BASE; | ||||
|     gpio->chip = rg_gpio_chip; | ||||
|     pdev->dev.platform_data = &rg_gpio_chip; | ||||
|     err = devm_gpiochip_add_data(&pdev->dev, &rg_gpio_chip, gpio); | ||||
|     if (err) { | ||||
|         dev_err(&pdev->dev, "gpiochip add failed\n"); | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     dev_info(&pdev->dev, "register %llu gpio success.\n", gpio->register_base); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int rg_gpio_remove(struct platform_device *pdev) | ||||
| { | ||||
|     dev_info(&pdev->dev, "unregister d1500 gpio success\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const struct of_device_id gpio_d1500_match[] = { | ||||
|     { | ||||
|         .compatible = "ruijie,rg_gpio_d1500", | ||||
|     }, | ||||
|     {}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, gpio_d1500_match); | ||||
|  | ||||
| static struct platform_driver rg_gpio_driver = { | ||||
|     .driver = { | ||||
|         .name        = GPIO_NAME, | ||||
|         .of_match_table = gpio_d1500_match, | ||||
|     }, | ||||
|     .probe      = rg_gpio_probe, | ||||
|     .remove     = rg_gpio_remove, | ||||
| }; | ||||
|  | ||||
| module_platform_driver(rg_gpio_driver); | ||||
|  | ||||
| MODULE_DESCRIPTION("d1500 gpio driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,54 @@ | ||||
| #include <linux/module.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/platform_device.h> | ||||
|  | ||||
| static int g_rg_gpio_device_debug = 0; | ||||
| static int g_rg_gpio_device_error = 0; | ||||
|  | ||||
| module_param(g_rg_gpio_device_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_rg_gpio_device_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define RG_GPIO_DEVICE_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_rg_gpio_device_debug) { \ | ||||
|         printk(KERN_INFO "[RG_GPIO_DEVICE][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define RG_GPIO_DEVICE_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_rg_gpio_device_error) { \ | ||||
|         printk(KERN_ERR "[RG_GPIO_DEVICE][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| static void rg_gpio_device_release(struct device *dev) | ||||
| { | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static struct platform_device rg_gpio_d1500_device = { | ||||
|     .name   = "rg_gpio_d1500", | ||||
|     .id = -1, | ||||
|     .dev    = { | ||||
|         .release = rg_gpio_device_release, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static int __init rg_gpio_device_init(void) | ||||
| { | ||||
|     RG_GPIO_DEVICE_VERBOSE("rg_gpio_device_init enter!\n"); | ||||
|     return platform_device_register(&rg_gpio_d1500_device); | ||||
| } | ||||
|  | ||||
| static void __exit rg_gpio_device_exit(void) | ||||
| { | ||||
|     RG_GPIO_DEVICE_VERBOSE("rg_gpio_device_exit enter!\n"); | ||||
|     return platform_device_unregister(&rg_gpio_d1500_device); | ||||
| } | ||||
|  | ||||
| module_init(rg_gpio_device_init); | ||||
| module_exit(rg_gpio_device_exit); | ||||
| MODULE_DESCRIPTION("GPIO Devices"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd@ruijie.com.cn"); | ||||
| @@ -0,0 +1,777 @@ | ||||
| /* | ||||
|  * Copyright(C) 2022 Ruijie Network. All rights reserved. | ||||
|  * | ||||
|  * rg_io_dev.c | ||||
|  * ko to read/write i2c client through /dev/XXX device | ||||
|  * Original Author: sonic_rd@ruijie.com.cn 2022-09-09 | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/miscdevice.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/of_platform.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/export.h> | ||||
| #include <linux/uio.h> | ||||
|  | ||||
| #include "rg_i2c_dev.h" | ||||
|  | ||||
| #define MAX_I2C_DEV_NUM      (256) | ||||
| #define FPGA_MAX_LEN         (256) | ||||
| #define MAX_NAME_SIZE        (20) | ||||
| #define MAX_BUS_WIDTH        (16) | ||||
| #define TRANSFER_WRITE_BUFF  (FPGA_MAX_LEN + MAX_BUS_WIDTH) | ||||
|  | ||||
| #define WIDTH_1Byte          (1) | ||||
| #define WIDTH_2Byte          (2) | ||||
| #define WIDTH_4Byte          (4) | ||||
|  | ||||
| static int g_i2c_dev_debug = 0; | ||||
| static int g_i2c_dev_error = 0; | ||||
|  | ||||
| module_param(g_i2c_dev_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_i2c_dev_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define I2C_DEV_DEBUG_DMESG(fmt, args...) do {                                        \ | ||||
|     if (g_i2c_dev_debug) { \ | ||||
|         printk(KERN_ERR "[I2C_DEV][DEBUG][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define I2C_DEV_DEBUG_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_i2c_dev_error) { \ | ||||
|         printk(KERN_ERR "[I2C_DEV][ERR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| static struct i2c_dev_info* i2c_dev_arry[MAX_I2C_DEV_NUM]; | ||||
|  | ||||
| struct i2c_dev_info { | ||||
|     const char *name; | ||||
|     uint32_t data_bus_width; | ||||
|     uint32_t addr_bus_width; | ||||
|     uint32_t per_rd_len; | ||||
|     uint32_t per_wr_len; | ||||
|     uint32_t i2c_len; | ||||
|     struct miscdevice misc; | ||||
|     struct i2c_client *client; | ||||
| }; | ||||
|  | ||||
| static int transfer_read(struct i2c_client *client, u8 *buf, loff_t regaddr, size_t count) | ||||
| { | ||||
|     struct i2c_adapter *adap; | ||||
|     int i; | ||||
|     u8 offset_buf[MAX_BUS_WIDTH]; | ||||
|     struct i2c_msg msgs[2]; | ||||
|     int msgs_num, ret; | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|  | ||||
|     if (!client) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get read client\n"); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     adap = client->adapter; | ||||
|     if (!adap) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get read adap\n"); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     i2c_dev = i2c_get_clientdata(client); | ||||
|     if (!i2c_dev) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get read i2c_dev\n"); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     i = 0; | ||||
|  | ||||
|     memset(offset_buf, 0, sizeof(offset_buf)); | ||||
|  | ||||
|     switch (i2c_dev->addr_bus_width) { | ||||
|     case WIDTH_4Byte: | ||||
|         offset_buf[i++] = (regaddr >> 24) & 0xFF; | ||||
|         offset_buf[i++] = (regaddr >> 16) & 0xFF; | ||||
|         offset_buf[i++] = (regaddr >> 8) & 0xFF; | ||||
|         offset_buf[i++] = regaddr & 0xFF; | ||||
|         break; | ||||
|     case WIDTH_2Byte: | ||||
|         offset_buf[i++] = (regaddr >> 8) & 0xFF; | ||||
|         offset_buf[i++] = regaddr & 0xFF; | ||||
|         break; | ||||
|     case WIDTH_1Byte: | ||||
|         offset_buf[i++] = regaddr & 0xFF; | ||||
|         break; | ||||
|     default: | ||||
|         I2C_DEV_DEBUG_ERROR("Only support 1,2,4 Byte Address Width,but set width = %u\n", | ||||
|             i2c_dev->addr_bus_width); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (adap->algo->master_xfer) { | ||||
|         memset(msgs, 0, sizeof(msgs)); | ||||
|         msgs[0].addr = client->addr; | ||||
|         msgs[0].flags = 0; | ||||
|         msgs[0].len = i2c_dev->addr_bus_width; | ||||
|         msgs[0].buf = offset_buf; | ||||
|  | ||||
|         msgs[1].addr = client->addr; | ||||
|         msgs[1].flags = I2C_M_RD; | ||||
|         msgs[1].len = count; | ||||
|         msgs[1].buf = buf; | ||||
|  | ||||
|         msgs_num = 2; | ||||
|         ret = i2c_transfer(client->adapter, msgs, msgs_num); | ||||
|         if (ret != msgs_num) { | ||||
|             I2C_DEV_DEBUG_ERROR("i2c_transfer read error\n"); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|     } else { | ||||
|         I2C_DEV_DEBUG_ERROR("don't find read master_xfer\n"); | ||||
|         return -EINVAL; | ||||
|  | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int transfer_write(struct i2c_client *client, u8 *buf, loff_t regaddr, size_t count) | ||||
| { | ||||
|     struct i2c_adapter *adap; | ||||
|     int i; | ||||
|     u8 offset_buf[TRANSFER_WRITE_BUFF]; | ||||
|     struct i2c_msg msgs[1]; | ||||
|     int msgs_num, ret; | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|  | ||||
|     if (!client) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get write client\n"); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     adap = client->adapter; | ||||
|     if (!adap) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get write adap\n"); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     i2c_dev = i2c_get_clientdata(client); | ||||
|     if (!i2c_dev) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get read i2c_dev\n"); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     i = 0; | ||||
|  | ||||
|     memset(offset_buf, 0, sizeof(offset_buf)); | ||||
|  | ||||
|     switch (i2c_dev->addr_bus_width) { | ||||
|     case WIDTH_4Byte: | ||||
|         offset_buf[i++] = (regaddr >> 24) & 0xFF; | ||||
|         offset_buf[i++] = (regaddr >> 16) & 0xFF; | ||||
|         offset_buf[i++] = (regaddr >> 8) & 0xFF; | ||||
|         offset_buf[i++] = regaddr & 0xFF; | ||||
|         break; | ||||
|     case WIDTH_2Byte: | ||||
|         offset_buf[i++] = (regaddr >> 8) & 0xFF; | ||||
|         offset_buf[i++] = regaddr & 0xFF; | ||||
|         break; | ||||
|     case WIDTH_1Byte: | ||||
|         offset_buf[i++] = regaddr & 0xFF; | ||||
|         break; | ||||
|     default: | ||||
|         I2C_DEV_DEBUG_ERROR("Only support 1,2,4 Byte Address Width,but set width = %u\n", | ||||
|             i2c_dev->addr_bus_width); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     memcpy(offset_buf + i2c_dev->addr_bus_width, buf, count); | ||||
|  | ||||
|     if (adap->algo->master_xfer) { | ||||
|         memset(msgs, 0, sizeof(msgs)); | ||||
|  | ||||
|         msgs[0].addr = client->addr; | ||||
|         msgs[0].flags = 0; | ||||
|         msgs[0].len = i2c_dev->addr_bus_width + count; | ||||
|         msgs[0].buf = offset_buf; | ||||
|  | ||||
|         msgs_num = 1; | ||||
|         ret = i2c_transfer(adap, msgs, msgs_num); | ||||
|         if (ret != msgs_num) { | ||||
|             I2C_DEV_DEBUG_ERROR("i2c_transfer write error\n"); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|     } else { | ||||
|         I2C_DEV_DEBUG_ERROR("don't find write master_xfer\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static long i2c_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int i2c_dev_open(struct inode *inode, struct file *file) | ||||
| { | ||||
|     unsigned int minor = iminor(inode); | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|  | ||||
|     i2c_dev = i2c_dev_arry[minor]; | ||||
|     if (i2c_dev == NULL) { | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     file->private_data = i2c_dev; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int i2c_dev_release(struct inode *inode, struct file *file) | ||||
| { | ||||
|     file->private_data = NULL; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int device_read(struct i2c_dev_info *i2c_dev, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     int i, j, ret; | ||||
|     u8 tmp_offset; | ||||
|     u8 val[FPGA_MAX_LEN]; | ||||
|     u32 width, rd_len, per_len, tmp; | ||||
|     u32 max_per_len; | ||||
|  | ||||
|     if (offset > i2c_dev->i2c_len) { | ||||
|         I2C_DEV_DEBUG_DMESG("offset: 0x%x, i2c len: 0x%x, count: %lu, EOF.\n", | ||||
|             offset, i2c_dev->i2c_len, count); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if (count > (i2c_dev->i2c_len - offset)) { | ||||
|         I2C_DEV_DEBUG_DMESG("read count out of range. input len:%lu, read len:%u.\n", | ||||
|             count, i2c_dev->i2c_len - offset); | ||||
|         count = i2c_dev->i2c_len - offset; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         I2C_DEV_DEBUG_DMESG("offset: 0x%x, i2c len: 0x%x, read len: %lu, EOF.\n", | ||||
|             offset, i2c_dev->i2c_len, count); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     width = i2c_dev->data_bus_width; | ||||
|     switch (width) { | ||||
|     case WIDTH_4Byte: | ||||
|         tmp_offset = offset & 0x3; | ||||
|         if (tmp_offset) { | ||||
|             I2C_DEV_DEBUG_ERROR("data bus width:%u, offset:%u, read size %lu invalid.\n", | ||||
|                 width, offset, count); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|         break; | ||||
|     case WIDTH_2Byte: | ||||
|         tmp_offset = offset & 0x1; | ||||
|         if (tmp_offset) { | ||||
|             I2C_DEV_DEBUG_ERROR("data bus width:%u, offset:%u, read size %lu invalid.\n", | ||||
|                 width, offset, count); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|         break; | ||||
|     case WIDTH_1Byte: | ||||
|         break; | ||||
|     default: | ||||
|         I2C_DEV_DEBUG_ERROR("Only support 1,2,4 Byte Data Width,but set width = %u\n", width); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     max_per_len = i2c_dev->per_rd_len; | ||||
|     tmp = (width - 1) & count; | ||||
|     rd_len = (tmp == 0) ? count : count + width - tmp; | ||||
|     per_len = (rd_len > max_per_len) ? (max_per_len) : (rd_len); | ||||
|  | ||||
|     memset(val, 0, sizeof(val)); | ||||
|     for (i = 0; i < rd_len; i += per_len) { | ||||
|         ret = transfer_read(i2c_dev->client, val + i, offset + i, per_len); | ||||
|         if (ret < 0) { | ||||
|             I2C_DEV_DEBUG_ERROR("read error.read offset = %u\n", (offset + i)); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (width == WIDTH_1Byte) { | ||||
|         memcpy(buf, val, count); | ||||
|     } else { | ||||
|         for (i = 0; i < count; i += width) { | ||||
|             for (j = 0; (j < width) && (i + j < count); j++) { | ||||
|                 buf[i + j] = val[i + width - j - 1]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| static int device_write(struct i2c_dev_info *i2c_dev, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     int i, j, ret; | ||||
|     u8 tmp_offset; | ||||
|     u32 width; | ||||
|     u8 val[FPGA_MAX_LEN]; | ||||
|     u32 wr_len, per_len, tmp; | ||||
|     u32 max_per_len; | ||||
|  | ||||
|     if (offset > i2c_dev->i2c_len) { | ||||
|         I2C_DEV_DEBUG_DMESG("offset: 0x%x, i2c len: 0x%x, count: %lu, EOF.\n", | ||||
|             offset, i2c_dev->i2c_len, count); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if (count > (i2c_dev->i2c_len - offset)) { | ||||
|         I2C_DEV_DEBUG_DMESG("read count out of range. input len:%lu, read len:%u.\n", | ||||
|             count, i2c_dev->i2c_len - offset); | ||||
|         count = i2c_dev->i2c_len - offset; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         I2C_DEV_DEBUG_DMESG("offset: 0x%x, i2c len: 0x%x, read len: %lu, EOF.\n", | ||||
|             offset, i2c_dev->i2c_len, count); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     width = i2c_dev->data_bus_width; | ||||
|     switch (width) { | ||||
|     case WIDTH_4Byte: | ||||
|         tmp_offset = offset & 0x3; | ||||
|         if (tmp_offset) { | ||||
|             I2C_DEV_DEBUG_ERROR("data bus width:%u, offset:%u, read size %lu invalid.\n", | ||||
|                 width, offset, count); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|         break; | ||||
|     case WIDTH_2Byte: | ||||
|         tmp_offset = offset & 0x1; | ||||
|         if (tmp_offset) { | ||||
|             I2C_DEV_DEBUG_ERROR("data bus width:%u, offset:%u, read size %lu invalid.\n", | ||||
|                 width, offset, count); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|         break; | ||||
|     case WIDTH_1Byte: | ||||
|         break; | ||||
|     default: | ||||
|         I2C_DEV_DEBUG_ERROR("Only support 1,2,4 Byte Data Width,but set width = %u\n", width); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     memset(val, 0, sizeof(val)); | ||||
|  | ||||
|     if (width == WIDTH_1Byte) { | ||||
|         memcpy(val, buf, count); | ||||
|     } else { | ||||
|         for (i = 0; i < count; i += width) { | ||||
|             for (j = 0; (j < width) && (i + j < count); j++) { | ||||
|                 val[i + width - j - 1] = buf[i + j]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     max_per_len = i2c_dev->per_wr_len; | ||||
|     tmp = (width - 1) & count; | ||||
|     wr_len = (tmp == 0) ? count : count + width - tmp; | ||||
|     per_len = (wr_len > max_per_len) ? (max_per_len) : (wr_len); | ||||
|  | ||||
|     for (i = 0; i < wr_len; i += per_len) { | ||||
|         ret = transfer_write(i2c_dev->client, val + i, offset + i, per_len); | ||||
|         if (ret < 0) { | ||||
|             I2C_DEV_DEBUG_ERROR("write error.offset = %u\n", (offset + i)); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| static ssize_t i2c_dev_read(struct file *file, char __user *buf, size_t count, loff_t *offset) | ||||
| { | ||||
|     u8 val[FPGA_MAX_LEN]; | ||||
|     int ret, read_len; | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|  | ||||
|     i2c_dev = file->private_data; | ||||
|     if (i2c_dev == NULL) { | ||||
|         I2C_DEV_DEBUG_ERROR("can't get read private_data.n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         I2C_DEV_DEBUG_ERROR("Invalid params, read count is 0.n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > sizeof(val)) { | ||||
|         I2C_DEV_DEBUG_DMESG("read conut %lu exceed max %lu.\n", count, sizeof(val)); | ||||
|         count = sizeof(val); | ||||
|     } | ||||
|  | ||||
|     memset(val, 0, sizeof(val)); | ||||
|     read_len = device_read(i2c_dev, (uint32_t)*offset, val, count); | ||||
|     if (read_len < 0) { | ||||
|         I2C_DEV_DEBUG_ERROR("i2c dev read failed, dev name:%s, offset:0x%x, len:%lu.\n", | ||||
|             i2c_dev->name, (uint32_t)*offset, count); | ||||
|         return read_len; | ||||
|     } | ||||
|  | ||||
|     if (access_ok(buf, read_len)) { | ||||
|         I2C_DEV_DEBUG_DMESG("user space read, buf: %p, offset: %lld, read conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         if (copy_to_user(buf, val, read_len)) { | ||||
|             I2C_DEV_DEBUG_ERROR("copy_to_user failed.\n"); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } else { | ||||
|         I2C_DEV_DEBUG_DMESG("kernel space read, buf: %p, offset: %lld, read conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         memcpy(buf, val, read_len); | ||||
|     } | ||||
|  | ||||
|     *offset += read_len; | ||||
|     ret = read_len; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t i2c_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     I2C_DEV_DEBUG_DMESG("i2c_dev_read_iter, file: %p, count: %lu, offset: %lld\n", | ||||
|         iocb->ki_filp, to->count, iocb->ki_pos); | ||||
|     ret = i2c_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t i2c_dev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) | ||||
| { | ||||
|     u8 val[FPGA_MAX_LEN]; | ||||
|     int write_len; | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|  | ||||
|     i2c_dev = file->private_data; | ||||
|     if (i2c_dev == NULL) { | ||||
|         I2C_DEV_DEBUG_ERROR("get write private_data error.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         I2C_DEV_DEBUG_ERROR("Invalid params, write count is 0.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > sizeof(val)) { | ||||
|         I2C_DEV_DEBUG_DMESG("write conut %lu exceed max %lu.\n", count, sizeof(val)); | ||||
|         count = sizeof(val); | ||||
|     } | ||||
|  | ||||
|     memset(val, 0, sizeof(val)); | ||||
|     if (access_ok(buf, count)) { | ||||
|         I2C_DEV_DEBUG_DMESG("user space write, buf: %p, offset: %lld, write conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         if (copy_from_user(val, buf, count)) { | ||||
|             I2C_DEV_DEBUG_ERROR("copy_from_user failed.\n"); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } else { | ||||
|         I2C_DEV_DEBUG_DMESG("kernel space write, buf: %p, offset: %lld, write conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         memcpy(val, buf, count); | ||||
|     } | ||||
|  | ||||
|     write_len = device_write(i2c_dev, (uint32_t)*offset, val, count); | ||||
|     if (write_len < 0) { | ||||
|         I2C_DEV_DEBUG_ERROR("i2c dev write failed, dev name:%s, offset:0x%llx, len:%lu.\n", | ||||
|             i2c_dev->name, *offset, count); | ||||
|         return write_len; | ||||
|     } | ||||
|  | ||||
|     *offset += write_len; | ||||
|     return write_len; | ||||
| } | ||||
|  | ||||
| static ssize_t i2c_dev_write_iter(struct kiocb *iocb, struct iov_iter *from) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     I2C_DEV_DEBUG_DMESG("i2c_dev_write_iter, file: %p, count: %lu, offset: %lld\n", | ||||
|         iocb->ki_filp, from->count, iocb->ki_pos); | ||||
|     ret = i2c_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static loff_t i2c_dev_llseek(struct file *file, loff_t offset, int origin) | ||||
| { | ||||
|     loff_t ret = 0; | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|  | ||||
|     i2c_dev = file->private_data; | ||||
|     if (i2c_dev == NULL) { | ||||
|         I2C_DEV_DEBUG_ERROR("i2c_dev is NULL, llseek failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     switch (origin) { | ||||
|     case SEEK_SET: | ||||
|         if (offset < 0) { | ||||
|             I2C_DEV_DEBUG_ERROR("SEEK_SET, offset:%lld, invalid.\n", offset); | ||||
|             ret = -EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         if (offset > i2c_dev->i2c_len) { | ||||
|             I2C_DEV_DEBUG_ERROR("SEEK_SET out of range, offset:%lld, i2c_len:0x%x.\n", | ||||
|                 offset, i2c_dev->i2c_len); | ||||
|             ret = - EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         file->f_pos = offset; | ||||
|         ret = file->f_pos; | ||||
|         break; | ||||
|     case SEEK_CUR: | ||||
|         if (((file->f_pos + offset) > i2c_dev->i2c_len) || ((file->f_pos + offset) < 0)) { | ||||
|             I2C_DEV_DEBUG_ERROR("SEEK_CUR out of range, f_ops:%lld, offset:%lld, i2c_len:0x%x.\n", | ||||
|                 file->f_pos, offset, i2c_dev->i2c_len); | ||||
|             ret = - EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         file->f_pos += offset; | ||||
|         ret = file->f_pos; | ||||
|         break; | ||||
|     default: | ||||
|         I2C_DEV_DEBUG_ERROR("unsupport llseek type:%d.\n", origin); | ||||
|         ret = -EINVAL; | ||||
|         break; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static const struct file_operations i2c_dev_fops = { | ||||
|     .owner      = THIS_MODULE, | ||||
|     .llseek     = i2c_dev_llseek, | ||||
|     .read_iter     = i2c_dev_read_iter, | ||||
|     .write_iter    = i2c_dev_write_iter, | ||||
|     .unlocked_ioctl = i2c_dev_ioctl, | ||||
|     .open       = i2c_dev_open, | ||||
|     .release    = i2c_dev_release, | ||||
| }; | ||||
|  | ||||
| static struct i2c_dev_info * dev_match(const char *path) | ||||
| { | ||||
|     struct i2c_dev_info * i2c_dev; | ||||
|     char dev_name[MAX_NAME_SIZE]; | ||||
|     int i; | ||||
|     for (i = 0; i < MAX_I2C_DEV_NUM; i++) { | ||||
|         if (i2c_dev_arry[ i ] == NULL) { | ||||
|             continue; | ||||
|         } | ||||
|         i2c_dev = i2c_dev_arry[ i ]; | ||||
|         snprintf(dev_name, MAX_NAME_SIZE,"/dev/%s", i2c_dev->name); | ||||
|         if (!strcmp(path, dev_name)) { | ||||
|             I2C_DEV_DEBUG_DMESG("get dev_name = %s, minor = %d\n", dev_name, i); | ||||
|             return i2c_dev; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int i2c_device_func_read(const char *path, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     struct i2c_dev_info *i2c_dev = NULL; | ||||
|     int ret; | ||||
|  | ||||
|     if(path == NULL){ | ||||
|         I2C_DEV_DEBUG_ERROR("path NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if(buf == NULL){ | ||||
|         I2C_DEV_DEBUG_ERROR("buf NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > FPGA_MAX_LEN) { | ||||
|         I2C_DEV_DEBUG_ERROR("read conut %lu, beyond max:%d.\n", count, FPGA_MAX_LEN); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     i2c_dev = dev_match(path); | ||||
|     if (i2c_dev == NULL) { | ||||
|         I2C_DEV_DEBUG_ERROR("i2c_dev match failed. dev path = %s", path); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     ret = device_read(i2c_dev, offset, buf, count); | ||||
|     if (ret < 0) { | ||||
|         I2C_DEV_DEBUG_ERROR("fpga i2c dev read failed, dev name:%s, offset:0x%x, len:%lu.\n", | ||||
|             i2c_dev->name, offset, count); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
| EXPORT_SYMBOL(i2c_device_func_read); | ||||
|  | ||||
| int i2c_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     struct i2c_dev_info *i2c_dev = NULL; | ||||
|     int ret; | ||||
|  | ||||
|     if(path == NULL){ | ||||
|         I2C_DEV_DEBUG_ERROR("path NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if(buf == NULL){ | ||||
|         I2C_DEV_DEBUG_ERROR("buf NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > FPGA_MAX_LEN) { | ||||
|         I2C_DEV_DEBUG_ERROR("write conut %lu, beyond max:%d.\n", count, FPGA_MAX_LEN); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     i2c_dev = dev_match(path); | ||||
|     if (i2c_dev == NULL) { | ||||
|         I2C_DEV_DEBUG_ERROR("i2c_dev match failed. dev path = %s", path); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     ret = device_write (i2c_dev, offset, buf, count); | ||||
|     if (ret < 0) { | ||||
|         I2C_DEV_DEBUG_ERROR("i2c dev write failed, dev name:%s, offset:0x%x, len:%lu.\n", | ||||
|             i2c_dev->name, offset, count); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
| EXPORT_SYMBOL(i2c_device_func_write); | ||||
|  | ||||
| static int i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||||
| { | ||||
|     int ret = 0; | ||||
|     struct i2c_dev_info *i2c_dev; | ||||
|     struct miscdevice *misc; | ||||
|     i2c_dev_device_t *i2c_dev_device; | ||||
|  | ||||
|     i2c_dev = devm_kzalloc(&client->dev, sizeof(struct i2c_dev_info), GFP_KERNEL); | ||||
|     if (!i2c_dev) { | ||||
|         dev_err(&client->dev, "devm_kzalloc error. \n"); | ||||
|         return -ENOMEM; | ||||
|     } | ||||
|  | ||||
|     i2c_set_clientdata(client, i2c_dev); | ||||
|     i2c_dev->client = client; | ||||
|  | ||||
|     if (client->dev.of_node) { | ||||
|  | ||||
|         ret += of_property_read_string(client->dev.of_node, "i2c_name", &i2c_dev->name); | ||||
|         ret += of_property_read_u32(client->dev.of_node, "data_bus_width", &i2c_dev->data_bus_width); | ||||
|         ret += of_property_read_u32(client->dev.of_node, "addr_bus_width", &i2c_dev->addr_bus_width); | ||||
|         ret += of_property_read_u32(client->dev.of_node, "per_rd_len", &i2c_dev->per_rd_len); | ||||
|         ret += of_property_read_u32(client->dev.of_node, "per_wr_len", &i2c_dev->per_wr_len); | ||||
|         ret += of_property_read_u32(client->dev.of_node, "i2c_len", &i2c_dev->i2c_len); | ||||
|         if (ret != 0) { | ||||
|             dev_err(&client->dev, "dts config error.ret:%d.\n", ret); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|     } else { | ||||
|         if (client->dev.platform_data == NULL) { | ||||
|             dev_err(&client->dev, "Failed to get platform data config.\n"); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|         i2c_dev_device = client->dev.platform_data; | ||||
|         i2c_dev->name = i2c_dev_device->i2c_name; | ||||
|         i2c_dev->data_bus_width = i2c_dev_device->data_bus_width; | ||||
|         i2c_dev->addr_bus_width = i2c_dev_device->addr_bus_width; | ||||
|         i2c_dev->per_rd_len = i2c_dev_device->per_rd_len; | ||||
|         i2c_dev->per_wr_len = i2c_dev_device->per_wr_len; | ||||
|         i2c_dev->i2c_len = i2c_dev_device->i2c_len; | ||||
|     } | ||||
|  | ||||
|     if ((i2c_dev->per_rd_len & (i2c_dev->data_bus_width - 1)) || | ||||
|         (i2c_dev->per_wr_len & (i2c_dev->data_bus_width - 1))) { | ||||
|         dev_err(&client->dev, "Invalid config per_rd_len %d per_wr_len %d data bus_width %d.\n", | ||||
|             i2c_dev->per_rd_len, i2c_dev->per_wr_len, i2c_dev->data_bus_width); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|  | ||||
|     if ((i2c_dev->i2c_len == 0) || (i2c_dev->i2c_len & (i2c_dev->data_bus_width - 1))) { | ||||
|         dev_err(&client->dev, "Invalid config i2c_len %d, data bus_width %d.\n", | ||||
|             i2c_dev->i2c_len, i2c_dev->data_bus_width); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|  | ||||
|     misc = &i2c_dev->misc; | ||||
|     misc->minor = MISC_DYNAMIC_MINOR; | ||||
|     misc->name = i2c_dev->name; | ||||
|     misc->fops = &i2c_dev_fops; | ||||
|     misc->mode = 0666; | ||||
|     if (misc_register(misc) != 0) { | ||||
|         dev_err(&client->dev, "register %s faild.\n", misc->name); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|  | ||||
|     if (misc->minor >= MAX_I2C_DEV_NUM) { | ||||
|         dev_err(&client->dev, "minor number beyond the limit! is %d.\n", misc->minor); | ||||
|         misc_deregister(misc); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|     i2c_dev_arry[misc->minor] = i2c_dev; | ||||
|  | ||||
|     dev_info(&client->dev, "register %u addr_bus_width %u data_bus_width 0x%x i2c_len device %s with %u per_rd_len %u per_wr_len success.\n", | ||||
|         i2c_dev->addr_bus_width, i2c_dev->data_bus_width, i2c_dev->i2c_len, i2c_dev->name, i2c_dev->per_rd_len, i2c_dev->per_wr_len); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int i2c_dev_remove(struct i2c_client *client) | ||||
| { | ||||
|     int i; | ||||
|     for (i = 0; i < MAX_I2C_DEV_NUM; i++) { | ||||
|         if (i2c_dev_arry[i] != NULL) { | ||||
|             misc_deregister(&i2c_dev_arry[i]->misc); | ||||
|             i2c_dev_arry[i] = NULL; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const struct i2c_device_id i2c_dev_id[] = { | ||||
|     { "rg-i2c-dev", 0 }, | ||||
|     { } | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(i2c, i2c_dev_id); | ||||
|  | ||||
| static const struct of_device_id i2c_dev_of_match[] = { | ||||
|     { .compatible = "ruijie,rg-i2c-dev" }, | ||||
|     { }, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, i2c_dev_of_match); | ||||
|  | ||||
| static struct i2c_driver i2c_dev_driver = { | ||||
|     .driver = { | ||||
|         .name = "rg-i2c-dev", | ||||
|         .of_match_table = i2c_dev_of_match, | ||||
|     }, | ||||
|     .probe      = i2c_dev_probe, | ||||
|     .remove     = i2c_dev_remove, | ||||
|     .id_table   = i2c_dev_id, | ||||
| }; | ||||
| module_i2c_driver(i2c_dev_driver); | ||||
|  | ||||
| MODULE_DESCRIPTION("i2c dev driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,18 @@ | ||||
| #ifndef __RG_I2C_DEV_H__ | ||||
| #define __RG_I2C_DEV_H__ | ||||
|  | ||||
| #define I2C_DEV_NAME_MAX_LEN (64) | ||||
|  | ||||
| typedef struct i2c_dev_device_s { | ||||
|     struct i2c_client *client; | ||||
|     uint32_t i2c_bus; | ||||
|     uint32_t i2c_addr; | ||||
|     char i2c_name[I2C_DEV_NAME_MAX_LEN]; | ||||
|     uint32_t data_bus_width; | ||||
|     uint32_t addr_bus_width; | ||||
|     uint32_t per_rd_len; | ||||
|     uint32_t per_wr_len; | ||||
|     uint32_t i2c_len; | ||||
| } i2c_dev_device_t; | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,110 @@ | ||||
| #include <linux/init.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/platform_data/i2c-gpio.h> | ||||
| #include <linux/gpio.h> | ||||
| #include <linux/gpio/machine.h> | ||||
| #include <linux/delay.h> | ||||
| #include <asm/delay.h> | ||||
| #include <linux/miscdevice.h> | ||||
|  | ||||
| static int gpio_sda = 17; | ||||
| module_param(gpio_sda, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| static int gpio_scl = 1; | ||||
| module_param(gpio_scl, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| static int gpio_udelay = 2; | ||||
| module_param(gpio_udelay, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| static int g_rg_i2c_gpio_device_debug = 0; | ||||
| static int g_rg_i2c_gpio_device_error = 0; | ||||
|  | ||||
| module_param(g_rg_i2c_gpio_device_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_rg_i2c_gpio_device_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define RG_I2C_GPIO_DEVICE_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_rg_i2c_gpio_device_debug) { \ | ||||
|         printk(KERN_INFO "[RG_I2C_GPIO_DEVICE][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define RG_I2C_GPIO_DEVICE_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_rg_i2c_gpio_device_error) { \ | ||||
|         printk(KERN_ERR "[RG_I2C_GPIO_DEVICE][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| /****************** i2c adapter with gpio ***********************/ | ||||
| static struct i2c_gpio_platform_data i2c_pdata = { | ||||
|     .udelay = 2, | ||||
|     .scl_is_output_only = 0, | ||||
|     .sda_is_open_drain  = 0, | ||||
|     .scl_is_open_drain = 0, | ||||
| }; | ||||
|  | ||||
| static void i2c_gpio_release(struct device *dev) | ||||
| { | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static struct platform_device rg_i2c_gpio_device = { | ||||
|     .name       = "i2c-gpio", | ||||
|     .id     = -1, | ||||
|     .num_resources  = 0, | ||||
|     .resource   = NULL, | ||||
|     .dev        = { | ||||
|         .platform_data = &i2c_pdata, | ||||
|         .release = i2c_gpio_release, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * i2c | ||||
|  */ | ||||
| static struct gpiod_lookup_table rg_i2c_gpio_table = { | ||||
|     .dev_id = "i2c-gpio", | ||||
|     .table = { | ||||
|         GPIO_LOOKUP_IDX("rg_gpio_d1500", 17, NULL, 0, | ||||
|                 GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), | ||||
|         GPIO_LOOKUP_IDX("rg_gpio_d1500", 1, NULL, 1, | ||||
|                 GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static int __init rg_i2c_gpio_device_init(void) | ||||
| { | ||||
|     int err; | ||||
|  | ||||
|     RG_I2C_GPIO_DEVICE_VERBOSE("rg_i2c_gpio_device_init enter!\n"); | ||||
|     rg_i2c_gpio_table.table[0].chip_hwnum = gpio_sda; | ||||
|     rg_i2c_gpio_table.table[1].chip_hwnum = gpio_scl; | ||||
|     i2c_pdata.udelay = gpio_udelay; | ||||
|     gpiod_add_lookup_table(&rg_i2c_gpio_table); | ||||
|  | ||||
|     err = platform_device_register(&rg_i2c_gpio_device); | ||||
|     if (err < 0) { | ||||
|         printk(KERN_ERR "register i2c gpio device fail(%d). \n", err); | ||||
|         gpiod_remove_lookup_table(&rg_i2c_gpio_table); | ||||
|         return -1; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void __exit rg_i2c_gpio_device_exit(void) | ||||
| { | ||||
|     RG_I2C_GPIO_DEVICE_VERBOSE("rg_i2c_gpio_device_exit enter!\n"); | ||||
|     platform_device_unregister(&rg_i2c_gpio_device); | ||||
|     gpiod_remove_lookup_table(&rg_i2c_gpio_table); | ||||
| } | ||||
|  | ||||
| module_init(rg_i2c_gpio_device_init); | ||||
| module_exit(rg_i2c_gpio_device_exit); | ||||
| MODULE_DESCRIPTION("I2C GPIO Devices"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd@ruijie.com.cn"); | ||||
| @@ -0,0 +1,445 @@ | ||||
| /* | ||||
|  * INA3221 Triple Current/Voltage Monitor | ||||
|  * | ||||
|  * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ | ||||
|  *	Andrew F. Davis <afd@ti.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * 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 <linux/hwmon.h> | ||||
| #include <linux/hwmon-sysfs.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/regmap.h> | ||||
|  | ||||
| #define INA3221_DRIVER_NAME		"rg_ina3221" | ||||
|  | ||||
| #define INA3221_CONFIG			0x00 | ||||
| #define INA3221_SHUNT1			0x01 | ||||
| #define INA3221_BUS1			0x02 | ||||
| #define INA3221_SHUNT2			0x03 | ||||
| #define INA3221_BUS2			0x04 | ||||
| #define INA3221_SHUNT3			0x05 | ||||
| #define INA3221_BUS3			0x06 | ||||
| #define INA3221_CRIT1			0x07 | ||||
| #define INA3221_WARN1			0x08 | ||||
| #define INA3221_CRIT2			0x09 | ||||
| #define INA3221_WARN2			0x0a | ||||
| #define INA3221_CRIT3			0x0b | ||||
| #define INA3221_WARN3			0x0c | ||||
| #define INA3221_MASK_ENABLE		0x0f | ||||
|  | ||||
| #define INA3221_CONFIG_MODE_SHUNT	BIT(1) | ||||
| #define INA3221_CONFIG_MODE_BUS		BIT(2) | ||||
| #define INA3221_CONFIG_MODE_CONTINUOUS	BIT(3) | ||||
|  | ||||
| #define INA3221_RSHUNT_DEFAULT		10000 | ||||
|  | ||||
| enum ina3221_fields { | ||||
| 	/* Configuration */ | ||||
| 	F_RST, | ||||
|  | ||||
| 	/* Alert Flags */ | ||||
| 	F_WF3, F_WF2, F_WF1, | ||||
| 	F_CF3, F_CF2, F_CF1, | ||||
|  | ||||
| 	/* sentinel */ | ||||
| 	F_MAX_FIELDS | ||||
| }; | ||||
|  | ||||
| static const struct reg_field ina3221_reg_fields[] = { | ||||
| 	[F_RST] = REG_FIELD(INA3221_CONFIG, 15, 15), | ||||
|  | ||||
| 	[F_WF3] = REG_FIELD(INA3221_MASK_ENABLE, 3, 3), | ||||
| 	[F_WF2] = REG_FIELD(INA3221_MASK_ENABLE, 4, 4), | ||||
| 	[F_WF1] = REG_FIELD(INA3221_MASK_ENABLE, 5, 5), | ||||
| 	[F_CF3] = REG_FIELD(INA3221_MASK_ENABLE, 7, 7), | ||||
| 	[F_CF2] = REG_FIELD(INA3221_MASK_ENABLE, 8, 8), | ||||
| 	[F_CF1] = REG_FIELD(INA3221_MASK_ENABLE, 9, 9), | ||||
| }; | ||||
|  | ||||
| enum ina3221_channels { | ||||
| 	INA3221_CHANNEL1, | ||||
| 	INA3221_CHANNEL2, | ||||
| 	INA3221_CHANNEL3, | ||||
| 	INA3221_NUM_CHANNELS | ||||
| }; | ||||
|  | ||||
| static const unsigned int register_channel[] = { | ||||
| 	[INA3221_SHUNT1] = INA3221_CHANNEL1, | ||||
| 	[INA3221_SHUNT2] = INA3221_CHANNEL2, | ||||
| 	[INA3221_SHUNT3] = INA3221_CHANNEL3, | ||||
| 	[INA3221_CRIT1] = INA3221_CHANNEL1, | ||||
| 	[INA3221_CRIT2] = INA3221_CHANNEL2, | ||||
| 	[INA3221_CRIT3] = INA3221_CHANNEL3, | ||||
| 	[INA3221_WARN1] = INA3221_CHANNEL1, | ||||
| 	[INA3221_WARN2] = INA3221_CHANNEL2, | ||||
| 	[INA3221_WARN3] = INA3221_CHANNEL3, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * struct ina3221_data - device specific information | ||||
|  * @regmap: Register map of the device | ||||
|  * @fields: Register fields of the device | ||||
|  * @shunt_resistors: Array of resistor values per channel | ||||
|  */ | ||||
| struct ina3221_data { | ||||
| 	struct regmap *regmap; | ||||
| 	struct regmap_field *fields[F_MAX_FIELDS]; | ||||
| 	int shunt_resistors[INA3221_NUM_CHANNELS]; | ||||
| }; | ||||
|  | ||||
| static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, | ||||
| 			      int *val) | ||||
| { | ||||
| 	unsigned int regval; | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = regmap_read(ina->regmap, reg, ®val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	*val = sign_extend32(regval >> 3, 12); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_show_bus_voltage(struct device *dev, | ||||
| 					struct device_attribute *attr, | ||||
| 					char *buf) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int reg = sd_attr->index; | ||||
| 	int val, voltage_mv, ret; | ||||
|  | ||||
| 	ret = ina3221_read_value(ina, reg, &val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	voltage_mv = val * 8; | ||||
|  | ||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", voltage_mv); | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_show_shunt_voltage(struct device *dev, | ||||
| 					  struct device_attribute *attr, | ||||
| 					  char *buf) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int reg = sd_attr->index; | ||||
| 	int val, voltage_uv, ret; | ||||
|  | ||||
| 	ret = ina3221_read_value(ina, reg, &val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 	voltage_uv = val * 40; | ||||
|  | ||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", voltage_uv); | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_show_current(struct device *dev, | ||||
| 				    struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int reg = sd_attr->index; | ||||
| 	unsigned int channel = register_channel[reg]; | ||||
| 	int resistance_uo = ina->shunt_resistors[channel]; | ||||
| 	int val, current_ma, voltage_nv, ret; | ||||
|  | ||||
| 	ret = ina3221_read_value(ina, reg, &val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 	voltage_nv = val * 40000; | ||||
|  | ||||
| 	current_ma = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo); | ||||
|  | ||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", current_ma); | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_set_current(struct device *dev, | ||||
| 				   struct device_attribute *attr, | ||||
| 				   const char *buf, size_t count) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int reg = sd_attr->index; | ||||
| 	unsigned int channel = register_channel[reg]; | ||||
| 	int resistance_uo = ina->shunt_resistors[channel]; | ||||
| 	int val, current_ma, voltage_uv, ret; | ||||
|  | ||||
| 	ret = kstrtoint(buf, 0, ¤t_ma); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	/* clamp current */ | ||||
| 	current_ma = clamp_val(current_ma, | ||||
| 			       INT_MIN / resistance_uo, | ||||
| 			       INT_MAX / resistance_uo); | ||||
|  | ||||
| 	voltage_uv = DIV_ROUND_CLOSEST(current_ma * resistance_uo, 1000); | ||||
|  | ||||
| 	/* clamp voltage */ | ||||
| 	voltage_uv = clamp_val(voltage_uv, -163800, 163800); | ||||
|  | ||||
| 	/* 1 / 40uV(scale) << 3(register shift) = 5 */ | ||||
| 	val = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8; | ||||
|  | ||||
| 	ret = regmap_write(ina->regmap, reg, val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	return count; | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_show_shunt(struct device *dev, | ||||
| 				  struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int channel = sd_attr->index; | ||||
| 	unsigned int resistance_uo; | ||||
|  | ||||
| 	resistance_uo = ina->shunt_resistors[channel]; | ||||
|  | ||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", resistance_uo); | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_set_shunt(struct device *dev, | ||||
| 				 struct device_attribute *attr, | ||||
| 				 const char *buf, size_t count) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int channel = sd_attr->index; | ||||
| 	int val; | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = kstrtoint(buf, 0, &val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	val = clamp_val(val, 1, INT_MAX); | ||||
|  | ||||
| 	ina->shunt_resistors[channel] = val; | ||||
|  | ||||
| 	return count; | ||||
| } | ||||
|  | ||||
| static ssize_t ina3221_show_alert(struct device *dev, | ||||
| 				  struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||||
| 	struct ina3221_data *ina = dev_get_drvdata(dev); | ||||
| 	unsigned int field = sd_attr->index; | ||||
| 	unsigned int regval; | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = regmap_field_read(ina->fields[field], ®val); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", regval); | ||||
| } | ||||
|  | ||||
| /* bus voltage */ | ||||
| static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, | ||||
| 		ina3221_show_bus_voltage, NULL, INA3221_BUS1); | ||||
| static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, | ||||
| 		ina3221_show_bus_voltage, NULL, INA3221_BUS2); | ||||
| static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, | ||||
| 		ina3221_show_bus_voltage, NULL, INA3221_BUS3); | ||||
|  | ||||
| /* calculated current */ | ||||
| static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, | ||||
| 		ina3221_show_current, NULL, INA3221_SHUNT1); | ||||
| static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, | ||||
| 		ina3221_show_current, NULL, INA3221_SHUNT2); | ||||
| static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, | ||||
| 		ina3221_show_current, NULL, INA3221_SHUNT3); | ||||
|  | ||||
| /* shunt resistance */ | ||||
| static SENSOR_DEVICE_ATTR(shunt1_resistor, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL1); | ||||
| static SENSOR_DEVICE_ATTR(shunt2_resistor, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL2); | ||||
| static SENSOR_DEVICE_ATTR(shunt3_resistor, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL3); | ||||
|  | ||||
| /* critical current */ | ||||
| static SENSOR_DEVICE_ATTR(curr1_crit, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_current, ina3221_set_current, INA3221_CRIT1); | ||||
| static SENSOR_DEVICE_ATTR(curr2_crit, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_current, ina3221_set_current, INA3221_CRIT2); | ||||
| static SENSOR_DEVICE_ATTR(curr3_crit, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_current, ina3221_set_current, INA3221_CRIT3); | ||||
|  | ||||
| /* critical current alert */ | ||||
| static SENSOR_DEVICE_ATTR(curr1_crit_alarm, S_IRUGO, | ||||
| 		ina3221_show_alert, NULL, F_CF1); | ||||
| static SENSOR_DEVICE_ATTR(curr2_crit_alarm, S_IRUGO, | ||||
| 		ina3221_show_alert, NULL, F_CF2); | ||||
| static SENSOR_DEVICE_ATTR(curr3_crit_alarm, S_IRUGO, | ||||
| 		ina3221_show_alert, NULL, F_CF3); | ||||
|  | ||||
| /* warning current */ | ||||
| static SENSOR_DEVICE_ATTR(curr1_max, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_current, ina3221_set_current, INA3221_WARN1); | ||||
| static SENSOR_DEVICE_ATTR(curr2_max, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_current, ina3221_set_current, INA3221_WARN2); | ||||
| static SENSOR_DEVICE_ATTR(curr3_max, S_IRUGO | S_IWUSR, | ||||
| 		ina3221_show_current, ina3221_set_current, INA3221_WARN3); | ||||
|  | ||||
| /* warning current alert */ | ||||
| static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, | ||||
| 		ina3221_show_alert, NULL, F_WF1); | ||||
| static SENSOR_DEVICE_ATTR(curr2_max_alarm, S_IRUGO, | ||||
| 		ina3221_show_alert, NULL, F_WF2); | ||||
| static SENSOR_DEVICE_ATTR(curr3_max_alarm, S_IRUGO, | ||||
| 		ina3221_show_alert, NULL, F_WF3); | ||||
|  | ||||
| /* shunt voltage */ | ||||
| static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, | ||||
| 		ina3221_show_shunt_voltage, NULL, INA3221_SHUNT1); | ||||
| static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, | ||||
| 		ina3221_show_shunt_voltage, NULL, INA3221_SHUNT2); | ||||
| static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, | ||||
| 		ina3221_show_shunt_voltage, NULL, INA3221_SHUNT3); | ||||
|  | ||||
| static struct attribute *ina3221_attrs[] = { | ||||
| 	/* channel 1 */ | ||||
| 	&sensor_dev_attr_in1_input.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr1_input.dev_attr.attr, | ||||
| 	&sensor_dev_attr_shunt1_resistor.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr1_crit.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr1_crit_alarm.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr1_max.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr, | ||||
| 	&sensor_dev_attr_in4_input.dev_attr.attr, | ||||
|  | ||||
| 	/* channel 2 */ | ||||
| 	&sensor_dev_attr_in2_input.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr2_input.dev_attr.attr, | ||||
| 	&sensor_dev_attr_shunt2_resistor.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr2_crit.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr2_crit_alarm.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr2_max.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr2_max_alarm.dev_attr.attr, | ||||
| 	&sensor_dev_attr_in5_input.dev_attr.attr, | ||||
|  | ||||
| 	/* channel 3 */ | ||||
| 	&sensor_dev_attr_in3_input.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr3_input.dev_attr.attr, | ||||
| 	&sensor_dev_attr_shunt3_resistor.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr3_crit.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr3_crit_alarm.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr3_max.dev_attr.attr, | ||||
| 	&sensor_dev_attr_curr3_max_alarm.dev_attr.attr, | ||||
| 	&sensor_dev_attr_in6_input.dev_attr.attr, | ||||
|  | ||||
| 	NULL, | ||||
| }; | ||||
| ATTRIBUTE_GROUPS(ina3221); | ||||
|  | ||||
| static const struct regmap_range ina3221_yes_ranges[] = { | ||||
| 	regmap_reg_range(INA3221_SHUNT1, INA3221_BUS3), | ||||
| 	regmap_reg_range(INA3221_MASK_ENABLE, INA3221_MASK_ENABLE), | ||||
| }; | ||||
|  | ||||
| static const struct regmap_access_table ina3221_volatile_table = { | ||||
| 	.yes_ranges = ina3221_yes_ranges, | ||||
| 	.n_yes_ranges = ARRAY_SIZE(ina3221_yes_ranges), | ||||
| }; | ||||
|  | ||||
| static const struct regmap_config ina3221_regmap_config = { | ||||
| 	.reg_bits = 8, | ||||
| 	.val_bits = 16, | ||||
|  | ||||
| 	.cache_type = REGCACHE_RBTREE, | ||||
| 	.volatile_table = &ina3221_volatile_table, | ||||
| }; | ||||
|  | ||||
| static int ina3221_probe(struct i2c_client *client, | ||||
| 			 const struct i2c_device_id *id) | ||||
| { | ||||
| 	struct device *dev = &client->dev; | ||||
| 	struct ina3221_data *ina; | ||||
| 	struct device *hwmon_dev; | ||||
| 	int i, ret; | ||||
|  | ||||
| 	ina = devm_kzalloc(dev, sizeof(*ina), GFP_KERNEL); | ||||
| 	if (!ina) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	ina->regmap = devm_regmap_init_i2c(client, &ina3221_regmap_config); | ||||
| 	if (IS_ERR(ina->regmap)) { | ||||
| 		dev_err(dev, "Unable to allocate register map\n"); | ||||
| 		return PTR_ERR(ina->regmap); | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < F_MAX_FIELDS; i++) { | ||||
| 		ina->fields[i] = devm_regmap_field_alloc(dev, | ||||
| 							 ina->regmap, | ||||
| 							 ina3221_reg_fields[i]); | ||||
| 		if (IS_ERR(ina->fields[i])) { | ||||
| 			dev_err(dev, "Unable to allocate regmap fields\n"); | ||||
| 			return PTR_ERR(ina->fields[i]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < INA3221_NUM_CHANNELS; i++) | ||||
| 		ina->shunt_resistors[i] = INA3221_RSHUNT_DEFAULT; | ||||
|  | ||||
| 	ret = regmap_field_write(ina->fields[F_RST], true); | ||||
| 	if (ret) { | ||||
| 		dev_err(dev, "Unable to reset device\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, | ||||
| 							   client->name, | ||||
| 							   ina, ina3221_groups); | ||||
| 	if (IS_ERR(hwmon_dev)) { | ||||
| 		dev_err(dev, "Unable to register hwmon device\n"); | ||||
| 		return PTR_ERR(hwmon_dev); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static const struct of_device_id ina3221_of_match_table[] = { | ||||
| 	{ .compatible = "ruijie,rg_ina3221", }, | ||||
| 	{ /* sentinel */ } | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, ina3221_of_match_table); | ||||
|  | ||||
| static const struct i2c_device_id ina3221_ids[] = { | ||||
| 	{ "rg_ina3221", 0 }, | ||||
| 	{ /* sentinel */ } | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(i2c, ina3221_ids); | ||||
|  | ||||
| static struct i2c_driver ina3221_i2c_driver = { | ||||
| 	.probe = ina3221_probe, | ||||
| 	.driver = { | ||||
| 		.name = INA3221_DRIVER_NAME, | ||||
| 		.of_match_table = ina3221_of_match_table, | ||||
| 	}, | ||||
| 	.id_table = ina3221_ids, | ||||
| }; | ||||
| module_i2c_driver(ina3221_i2c_driver); | ||||
|  | ||||
| MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); | ||||
| MODULE_DESCRIPTION("Texas Instruments INA3221 HWMon Driver"); | ||||
| MODULE_LICENSE("GPL v2"); | ||||
| @@ -0,0 +1,574 @@ | ||||
| /* | ||||
|  * Copyright(C) 2022 Ruijie Network. All rights reserved. | ||||
|  * | ||||
|  * rg_io_dev.c | ||||
|  * ko to read/write ioports through /dev/XXX device | ||||
|  * Original Author: sonic_rd@ruijie.com.cn 2022-09-09 | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/miscdevice.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/of_platform.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/export.h> | ||||
| #include <linux/uio.h> | ||||
|  | ||||
| #include "rg_io_dev.h" | ||||
|  | ||||
| #define PROXY_NAME "rg-io-dev" | ||||
| #define MAX_IO_DEV_NUM                     (256) | ||||
| #define IO_RDWR_MAX_LEN                    (256) | ||||
| #define MAX_NAME_SIZE                      (20) | ||||
| #define IO_INDIRECT_ADDR_H(addr)           ((addr >> 8) & 0xff) | ||||
| #define IO_INDIRECT_ADDR_L(addr)           ((addr) & 0xff) | ||||
| #define IO_INDIRECT_OP_WRITE               (0x2) | ||||
| #define IO_INDIRECT_OP_READ                (0X3) | ||||
|  | ||||
| static int g_io_dev_debug = 0; | ||||
| static int g_io_dev_error = 0; | ||||
|  | ||||
| module_param(g_io_dev_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_io_dev_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define IO_DEV_DEBUG_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_io_dev_debug) { \ | ||||
|         printk(KERN_INFO "[IO_DEV][VER][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define IO_DEV_DEBUG_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_io_dev_error) { \ | ||||
|         printk(KERN_ERR "[IO_DEV][ERR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| typedef struct rg_io_dev_s { | ||||
|     const char *name; | ||||
|     uint32_t io_base; | ||||
|     uint32_t io_len; | ||||
|     uint32_t indirect_addr; | ||||
|     uint32_t wr_data; | ||||
|     uint32_t addr_low; | ||||
|     uint32_t addr_high; | ||||
|     uint32_t rd_data; | ||||
|     uint32_t opt_ctl; | ||||
|     spinlock_t io_dev_lock; | ||||
|     struct miscdevice misc; | ||||
| } rg_io_dev_t; | ||||
|  | ||||
| static rg_io_dev_t* io_dev_arry[MAX_IO_DEV_NUM]; | ||||
|  | ||||
| static int io_dev_open(struct inode *inode, struct file *file) | ||||
| { | ||||
|     unsigned int minor = iminor(inode); | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|  | ||||
|     if (minor >= MAX_IO_DEV_NUM) { | ||||
|         IO_DEV_DEBUG_ERROR("minor out of range, minor = %d.\n", minor); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     rg_io_dev = io_dev_arry[minor]; | ||||
|     if (rg_io_dev == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("rg_io_dev is NULL, open failed, minor = %d\n", minor); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     file->private_data = rg_io_dev; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int io_dev_release(struct inode *inode, struct file *file) | ||||
| { | ||||
|     file->private_data = NULL; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| uint8_t io_indirect_addressing_read(rg_io_dev_t *rg_io_dev, uint32_t address) | ||||
| { | ||||
|     uint8_t addr_l, addr_h, value; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     addr_h = IO_INDIRECT_ADDR_H(address); | ||||
|     addr_l = IO_INDIRECT_ADDR_L(address); | ||||
|     IO_DEV_DEBUG_VERBOSE("read one count, addr = 0x%x\n", address); | ||||
|  | ||||
|     spin_lock_irqsave(&rg_io_dev->io_dev_lock, flags); | ||||
|  | ||||
|     outb(addr_l, rg_io_dev->io_base + rg_io_dev->addr_low); | ||||
|  | ||||
|     outb(addr_h, rg_io_dev->io_base + rg_io_dev->addr_high); | ||||
|  | ||||
|     outb(IO_INDIRECT_OP_READ, rg_io_dev->io_base + rg_io_dev->opt_ctl); | ||||
|  | ||||
|     value = inb(rg_io_dev->io_base + rg_io_dev->rd_data); | ||||
|  | ||||
|     spin_unlock_irqrestore(&rg_io_dev->io_dev_lock, flags); | ||||
|  | ||||
|     return value; | ||||
| } | ||||
|  | ||||
| static int io_dev_read_tmp(rg_io_dev_t *rg_io_dev, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     int i; | ||||
|  | ||||
|     if (offset > rg_io_dev->io_len) { | ||||
|         IO_DEV_DEBUG_VERBOSE("offset:0x%x, io len:0x%x, EOF.\n", offset, rg_io_dev->io_len); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if (count > rg_io_dev->io_len - offset) { | ||||
|         IO_DEV_DEBUG_VERBOSE("read count out of range. input len:%lu, read len:%u.\n", | ||||
|             count, rg_io_dev->io_len - offset); | ||||
|         count = rg_io_dev->io_len - offset; | ||||
|     } | ||||
|     if (rg_io_dev->indirect_addr) { | ||||
|         for (i = 0; i < count; i++) { | ||||
|             buf[i] = io_indirect_addressing_read(rg_io_dev, offset + i); | ||||
|         } | ||||
|     } else { | ||||
|         for (i = 0; i < count; i++) { | ||||
|             buf[i] = inb(rg_io_dev->io_base + offset + i); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| static ssize_t io_dev_read(struct file *file, char __user *buf, size_t count, loff_t *offset) | ||||
| { | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|     int ret, read_len; | ||||
|     u8 buf_tmp[IO_RDWR_MAX_LEN]; | ||||
|  | ||||
|     rg_io_dev = file->private_data; | ||||
|     if (rg_io_dev == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("rg_io_dev is NULL, read failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         IO_DEV_DEBUG_ERROR("Invalid params, read count is 0.n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > sizeof(buf_tmp)) { | ||||
|         IO_DEV_DEBUG_VERBOSE("read conut %lu exceed max %lu.\n", count, sizeof(buf_tmp)); | ||||
|         count = sizeof(buf_tmp); | ||||
|     } | ||||
|  | ||||
|     memset(buf_tmp, 0, sizeof(buf_tmp)); | ||||
|     read_len = io_dev_read_tmp(rg_io_dev, *offset, buf_tmp, count); | ||||
|     if (read_len < 0) { | ||||
|         IO_DEV_DEBUG_ERROR("io_dev_read_tmp failed, ret:%d.\n", read_len); | ||||
|         return read_len; | ||||
|     } | ||||
|  | ||||
|     if (access_ok(buf, read_len)) { | ||||
|         IO_DEV_DEBUG_VERBOSE("user space read, buf: %p, offset: %lld, read conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         if (copy_to_user(buf, buf_tmp, read_len)) { | ||||
|             IO_DEV_DEBUG_ERROR("copy_to_user failed.\n"); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } else { | ||||
|         IO_DEV_DEBUG_VERBOSE("kernel space read, buf: %p, offset: %lld, read conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         memcpy(buf, buf_tmp, read_len); | ||||
|     } | ||||
|     *offset += read_len; | ||||
|     ret = read_len; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t io_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     IO_DEV_DEBUG_VERBOSE("io_dev_read_iter, file: %p, count: %lu, offset: %lld\n", | ||||
|         iocb->ki_filp, to->count, iocb->ki_pos); | ||||
|     ret = io_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void io_indirect_addressing_write(rg_io_dev_t *rg_io_dev, uint32_t address, uint8_t reg_val) | ||||
| { | ||||
|     uint8_t addr_l, addr_h; | ||||
|     unsigned long flags; | ||||
|  | ||||
|     addr_h = IO_INDIRECT_ADDR_H(address); | ||||
|     addr_l = IO_INDIRECT_ADDR_L(address); | ||||
|     IO_DEV_DEBUG_VERBOSE("write one count, addr = 0x%x\n", address); | ||||
|  | ||||
|     spin_lock_irqsave(&rg_io_dev->io_dev_lock, flags); | ||||
|  | ||||
|     outb(reg_val, rg_io_dev->io_base + rg_io_dev->wr_data); | ||||
|  | ||||
|     outb(addr_l, rg_io_dev->io_base + rg_io_dev->addr_low); | ||||
|  | ||||
|     outb(addr_h, rg_io_dev->io_base + rg_io_dev->addr_high); | ||||
|  | ||||
|     outb(IO_INDIRECT_OP_WRITE, rg_io_dev->io_base + rg_io_dev->opt_ctl); | ||||
|  | ||||
|     spin_unlock_irqrestore(&rg_io_dev->io_dev_lock, flags); | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static int io_dev_write_tmp(rg_io_dev_t *rg_io_dev, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     int i; | ||||
|  | ||||
|     if (offset > rg_io_dev->io_len) { | ||||
|         IO_DEV_DEBUG_VERBOSE("offset:0x%x, io len:0x%x, EOF.\n", offset, rg_io_dev->io_len); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if (count > rg_io_dev->io_len - offset) { | ||||
|         IO_DEV_DEBUG_VERBOSE("write count out of range. input len:%lu, write len:%u.\n", | ||||
|             count, rg_io_dev->io_len - offset); | ||||
|         count = rg_io_dev->io_len - offset; | ||||
|     } | ||||
|     if (rg_io_dev->indirect_addr) { | ||||
|         for (i = 0; i < count; i++) { | ||||
|             io_indirect_addressing_write(rg_io_dev, offset + i, buf[i]); | ||||
|         } | ||||
|     } else { | ||||
|         for (i = 0; i < count; i++) { | ||||
|             outb(buf[i], rg_io_dev->io_base + offset + i); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| static ssize_t io_dev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) | ||||
| { | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|     int write_len; | ||||
|     u8 buf_tmp[IO_RDWR_MAX_LEN]; | ||||
|  | ||||
|     rg_io_dev = file->private_data; | ||||
|     if (rg_io_dev == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("rg_io_dev is NULL, write failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         IO_DEV_DEBUG_ERROR("Invalid params, write count is 0.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > sizeof(buf_tmp)) { | ||||
|         IO_DEV_DEBUG_VERBOSE("write conut %lu exceed max %lu.\n", count, sizeof(buf_tmp)); | ||||
|         count = sizeof(buf_tmp); | ||||
|     } | ||||
|  | ||||
|     memset(buf_tmp, 0, sizeof(buf_tmp)); | ||||
|     if (access_ok(buf, count)) { | ||||
|         IO_DEV_DEBUG_VERBOSE("user space write, buf: %p, offset: %lld, write conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         if (copy_from_user(buf_tmp, buf, count)) { | ||||
|             IO_DEV_DEBUG_ERROR("copy_from_user failed.\n"); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } else { | ||||
|         IO_DEV_DEBUG_VERBOSE("kernel space write, buf: %p, offset: %lld, write conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         memcpy(buf_tmp, buf, count); | ||||
|     } | ||||
|  | ||||
|     write_len = io_dev_write_tmp(rg_io_dev, *offset, buf_tmp, count); | ||||
|     if (write_len < 0) { | ||||
|         IO_DEV_DEBUG_ERROR("io_dev_write_tmp failed, ret:%d.\n", write_len); | ||||
|         return write_len; | ||||
|     } | ||||
|  | ||||
|     *offset += write_len; | ||||
|     return write_len; | ||||
| } | ||||
|  | ||||
| static ssize_t io_dev_write_iter(struct kiocb *iocb, struct iov_iter *from) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     IO_DEV_DEBUG_VERBOSE("io_dev_write_iter, file: %p, count: %lu, offset: %lld\n", | ||||
|         iocb->ki_filp, from->count, iocb->ki_pos); | ||||
|     ret = io_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static loff_t io_dev_llseek(struct file *file, loff_t offset, int origin) | ||||
| { | ||||
|     loff_t ret = 0; | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|  | ||||
|     rg_io_dev = file->private_data; | ||||
|     if (rg_io_dev == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("rg_io_dev is NULL, llseek failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     switch (origin) { | ||||
|     case SEEK_SET: | ||||
|         if (offset < 0) { | ||||
|             IO_DEV_DEBUG_ERROR("SEEK_SET, offset:%lld, invalid.\n", offset); | ||||
|             ret = -EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         if (offset > rg_io_dev->io_len) { | ||||
|             IO_DEV_DEBUG_ERROR("SEEK_SET out of range, offset:%lld, io_len:0x%x.\n", | ||||
|                 offset, rg_io_dev->io_len); | ||||
|             ret = - EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         file->f_pos = offset; | ||||
|         ret = file->f_pos; | ||||
|         break; | ||||
|     case SEEK_CUR: | ||||
|         if (((file->f_pos + offset) > rg_io_dev->io_len) || ((file->f_pos + offset) < 0)) { | ||||
|             IO_DEV_DEBUG_ERROR("SEEK_CUR out of range, f_ops:%lld, offset:%lld, io_len:0x%x.\n", | ||||
|                 file->f_pos, offset, rg_io_dev->io_len); | ||||
|             ret = - EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         file->f_pos += offset; | ||||
|         ret = file->f_pos; | ||||
|         break; | ||||
|     default: | ||||
|         IO_DEV_DEBUG_ERROR("unsupport llseek type:%d.\n", origin); | ||||
|         ret = -EINVAL; | ||||
|         break; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static long io_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const struct file_operations io_dev_fops = { | ||||
|     .owner      = THIS_MODULE, | ||||
|     .llseek     = io_dev_llseek, | ||||
|     .read_iter  = io_dev_read_iter, | ||||
|     .write_iter = io_dev_write_iter, | ||||
|     .unlocked_ioctl = io_dev_ioctl, | ||||
|     .open       = io_dev_open, | ||||
|     .release    = io_dev_release, | ||||
| }; | ||||
|  | ||||
| static rg_io_dev_t *dev_match(const char *path) | ||||
| { | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|     char dev_name[MAX_NAME_SIZE]; | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < MAX_IO_DEV_NUM; i++) { | ||||
|         if (io_dev_arry[i] == NULL) { | ||||
|             continue; | ||||
|         } | ||||
|         rg_io_dev = io_dev_arry[i]; | ||||
|         snprintf(dev_name, MAX_NAME_SIZE,"/dev/%s", rg_io_dev->name); | ||||
|         if (!strcmp(path, dev_name)) { | ||||
|             IO_DEV_DEBUG_VERBOSE("get dev_name = %s, minor = %d\n", dev_name, i); | ||||
|             return rg_io_dev; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int io_device_func_read(const char *path, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|     int read_len; | ||||
|  | ||||
|     if (path == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("path NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("buf NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     rg_io_dev = dev_match(path); | ||||
|     if (rg_io_dev == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("io_dev match failed. dev path = %s", path); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     read_len = io_dev_read_tmp(rg_io_dev, offset, buf, count); | ||||
|     if (read_len < 0) { | ||||
|         IO_DEV_DEBUG_ERROR("io_dev_read_tmp failed, ret:%d.\n", read_len); | ||||
|     } | ||||
|     return read_len; | ||||
| } | ||||
| EXPORT_SYMBOL(io_device_func_read); | ||||
|  | ||||
| int io_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|     int write_len; | ||||
|  | ||||
|     if (path == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("path NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("buf NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     rg_io_dev = dev_match(path); | ||||
|     if (rg_io_dev == NULL) { | ||||
|         IO_DEV_DEBUG_ERROR("i2c_dev match failed. dev path = %s", path); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     write_len = io_dev_write_tmp(rg_io_dev, offset, buf, count); | ||||
|     if (write_len < 0) { | ||||
|         IO_DEV_DEBUG_ERROR("io_dev_write_tmp failed, ret:%d.\n", write_len); | ||||
|     } | ||||
|     return write_len; | ||||
| } | ||||
| EXPORT_SYMBOL(io_device_func_write); | ||||
|  | ||||
| static int io_dev_probe(struct platform_device *pdev) | ||||
| { | ||||
|     int ret; | ||||
|     rg_io_dev_t *rg_io_dev; | ||||
|     struct miscdevice *misc; | ||||
|     io_dev_device_t *io_dev_device; | ||||
|  | ||||
|     rg_io_dev = devm_kzalloc(&pdev->dev, sizeof(rg_io_dev_t), GFP_KERNEL); | ||||
|     if (!rg_io_dev) { | ||||
|         dev_err(&pdev->dev, "devm_kzalloc failed.\n"); | ||||
|         ret = -ENOMEM; | ||||
|         return ret; | ||||
|     } | ||||
|     spin_lock_init(&rg_io_dev->io_dev_lock); | ||||
|  | ||||
|     if (pdev->dev.of_node) { | ||||
|         ret = 0; | ||||
|         ret += of_property_read_string(pdev->dev.of_node, "io_dev_name", &rg_io_dev->name); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "io_base", &rg_io_dev->io_base); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "io_len", &rg_io_dev->io_len); | ||||
|         if (of_property_read_bool(pdev->dev.of_node, "indirect_addr")) { | ||||
|  | ||||
|             rg_io_dev->indirect_addr = 1; | ||||
|             ret += of_property_read_u32(pdev->dev.of_node, "wr_data", &rg_io_dev->wr_data); | ||||
|             ret += of_property_read_u32(pdev->dev.of_node, "addr_low", &rg_io_dev->addr_low); | ||||
|             ret += of_property_read_u32(pdev->dev.of_node, "addr_high", &rg_io_dev->addr_high); | ||||
|             ret += of_property_read_u32(pdev->dev.of_node, "rd_data", &rg_io_dev->rd_data); | ||||
|             ret += of_property_read_u32(pdev->dev.of_node, "opt_ctl", &rg_io_dev->opt_ctl); | ||||
|         } else { | ||||
|  | ||||
|             rg_io_dev->indirect_addr = 0; | ||||
|         } | ||||
|         if (ret != 0) { | ||||
|             dev_err(&pdev->dev, "Failed to get dts config, ret:%d.\n", ret); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|     } else { | ||||
|         if (pdev->dev.platform_data == NULL) { | ||||
|             dev_err(&pdev->dev, "Failed to get platform data config.\n"); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|         io_dev_device = pdev->dev.platform_data; | ||||
|         rg_io_dev->name = io_dev_device->io_dev_name; | ||||
|         rg_io_dev->io_base = io_dev_device->io_base; | ||||
|         rg_io_dev->io_len = io_dev_device->io_len; | ||||
|         rg_io_dev->indirect_addr = io_dev_device->indirect_addr; | ||||
|         if (rg_io_dev->indirect_addr == 1) { | ||||
|             rg_io_dev->wr_data = io_dev_device->wr_data; | ||||
|             rg_io_dev->addr_low = io_dev_device->addr_low; | ||||
|             rg_io_dev->addr_high = io_dev_device->addr_high; | ||||
|             rg_io_dev->rd_data = io_dev_device->rd_data; | ||||
|             rg_io_dev->opt_ctl = io_dev_device->opt_ctl; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     IO_DEV_DEBUG_VERBOSE("name:%s, io base:0x%x, io len:0x%x, addressing type:%s.\n", | ||||
|         rg_io_dev->name, rg_io_dev->io_base, rg_io_dev->io_len, | ||||
|         rg_io_dev->indirect_addr ? "indirect" : "direct"); | ||||
|  | ||||
|     misc = &rg_io_dev->misc; | ||||
|     misc->minor = MISC_DYNAMIC_MINOR; | ||||
|     misc->name = rg_io_dev->name; | ||||
|     misc->fops = &io_dev_fops; | ||||
|     misc->mode = 0666; | ||||
|     if (misc_register(misc) != 0) { | ||||
|         dev_err(&pdev->dev, "Failed to register %s device.\n", misc->name); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|     if (misc->minor >= MAX_IO_DEV_NUM) { | ||||
|         dev_err(&pdev->dev, "Error: device minor[%d] more than max io device num[%d].\n", | ||||
|             misc->minor, MAX_IO_DEV_NUM); | ||||
|         misc_deregister(misc); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|     io_dev_arry[misc->minor] = rg_io_dev; | ||||
|     dev_info(&pdev->dev, "register %s device [0x%x][0x%x] with minor %d using %s addressing success.\n", | ||||
|         misc->name, rg_io_dev->io_base, rg_io_dev->io_len, misc->minor, | ||||
|         rg_io_dev->indirect_addr ? "indirect" : "direct"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int io_dev_remove(struct platform_device *pdev) | ||||
| { | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < MAX_IO_DEV_NUM ; i++) { | ||||
|         if (io_dev_arry[i] != NULL) { | ||||
|             misc_deregister(&io_dev_arry[i]->misc); | ||||
|             io_dev_arry[i] = NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static struct of_device_id io_dev_match[] = { | ||||
|     { | ||||
|         .compatible = "ruijie,rg-io-dev", | ||||
|     }, | ||||
|     {}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, io_dev_match); | ||||
|  | ||||
| static struct platform_driver rg_io_dev_driver = { | ||||
|     .probe      = io_dev_probe, | ||||
|     .remove     = io_dev_remove, | ||||
|     .driver     = { | ||||
|         .owner  = THIS_MODULE, | ||||
|         .name   = PROXY_NAME, | ||||
|         .of_match_table = io_dev_match, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static int __init rg_io_dev_init(void) | ||||
| { | ||||
|     return platform_driver_register(&rg_io_dev_driver); | ||||
| } | ||||
|  | ||||
| static void __exit rg_io_dev_exit(void) | ||||
| { | ||||
|     platform_driver_unregister(&rg_io_dev_driver); | ||||
| } | ||||
|  | ||||
| module_init(rg_io_dev_init); | ||||
| module_exit(rg_io_dev_exit); | ||||
| MODULE_DESCRIPTION("IO device driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,19 @@ | ||||
| #ifndef __RG_IO_DEV_H__ | ||||
| #define __RG_IO_DEV_H__ | ||||
|  | ||||
| #define IO_DEV_NAME_MAX_LEN (64) | ||||
|  | ||||
| typedef struct io_dev_device_s { | ||||
|     char io_dev_name[IO_DEV_NAME_MAX_LEN]; | ||||
|     uint32_t io_base; | ||||
|     uint32_t io_len; | ||||
|     uint32_t indirect_addr; | ||||
|     uint32_t wr_data; | ||||
|     uint32_t addr_low; | ||||
|     uint32_t addr_high; | ||||
|     uint32_t rd_data; | ||||
|     uint32_t opt_ctl; | ||||
|     int device_flag; | ||||
| } io_dev_device_t; | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,169 @@ | ||||
| /* | ||||
|  * Copyright(C) 2016 Ruijie Network. All rights reserved. | ||||
|  * | ||||
|  * rg_lpc_drv.c | ||||
|  * ko to set lpc pcie config io addr and enable lpc | ||||
|  * Original Author: sonic_rd@ruijie.com.cn 2020-08-14 | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/of_platform.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/ioport.h> | ||||
|  | ||||
| #include "rg_lpc_drv.h" | ||||
|  | ||||
| #define LPC_DRIVER_NAME                    "rg-lpc" | ||||
| #define LPC_MAKE_PCI_IO_RANGE(__base)      ((0xfc0001) | ((__base) & (0xFFFC))) | ||||
|  | ||||
| int g_lpc_dev_debug = 0; | ||||
| int g_lpc_dev_error = 0; | ||||
|  | ||||
| module_param(g_lpc_dev_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_lpc_dev_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define LPC_DEV_DEBUG_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_lpc_dev_debug) { \ | ||||
|         printk(KERN_INFO "[LPC_DEV][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define LPC_DEV_DEBUG_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_lpc_dev_error) { \ | ||||
|         printk(KERN_ERR "[LPC_DEV][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| typedef struct rg_lpc_dev_s { | ||||
|     const char *lpc_io_name; | ||||
|     uint32_t domain; | ||||
|     uint32_t bus; | ||||
|     uint32_t slot; | ||||
|     uint32_t fn; | ||||
|     uint32_t lpc_io_base; | ||||
|     uint32_t lpc_io_size; | ||||
|     uint32_t lpc_gen_dec; | ||||
| } rg_lpc_dev_t; | ||||
|  | ||||
| static int rg_lpc_probe(struct platform_device *pdev) | ||||
| { | ||||
|     int ret, devfn; | ||||
|     rg_lpc_dev_t *rg_lpc_dev; | ||||
|     struct pci_dev *pci_dev; | ||||
|     lpc_drv_device_t *lpc_drv_device; | ||||
|  | ||||
|     rg_lpc_dev = devm_kzalloc(&pdev->dev, sizeof(rg_lpc_dev_t), GFP_KERNEL); | ||||
|     if (!rg_lpc_dev) { | ||||
|         dev_err(&pdev->dev, "devm_kzalloc failed.\n"); | ||||
|         ret = -ENOMEM; | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if (pdev->dev.of_node) { | ||||
|         ret = 0; | ||||
|         ret += of_property_read_string(pdev->dev.of_node, "lpc_io_name", &rg_lpc_dev->lpc_io_name); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_domain", &rg_lpc_dev->domain); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_bus", &rg_lpc_dev->bus); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_slot", &rg_lpc_dev->slot); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_fn", &rg_lpc_dev->fn); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "lpc_io_base", &rg_lpc_dev->lpc_io_base); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "lpc_io_size", &rg_lpc_dev->lpc_io_size); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "lpc_gen_dec", &rg_lpc_dev->lpc_gen_dec); | ||||
|         if (ret != 0) { | ||||
|             dev_err(&pdev->dev, "Failed to get dts config, ret:%d.\n", ret); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|     } else { | ||||
|         if (pdev->dev.platform_data == NULL) { | ||||
|             dev_err(&pdev->dev, "Failed to get platform data config.\n"); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|         lpc_drv_device = pdev->dev.platform_data; | ||||
|         rg_lpc_dev->lpc_io_name = lpc_drv_device->lpc_io_name; | ||||
|         rg_lpc_dev->domain = lpc_drv_device->pci_domain; | ||||
|         rg_lpc_dev->bus = lpc_drv_device->pci_bus; | ||||
|         rg_lpc_dev->slot = lpc_drv_device->pci_slot; | ||||
|         rg_lpc_dev->fn = lpc_drv_device->pci_fn; | ||||
|         rg_lpc_dev->lpc_io_base = lpc_drv_device->lpc_io_base; | ||||
|         rg_lpc_dev->lpc_io_size = lpc_drv_device->lpc_io_size; | ||||
|         rg_lpc_dev->lpc_gen_dec = lpc_drv_device->lpc_gen_dec; | ||||
|     } | ||||
|  | ||||
|     LPC_DEV_DEBUG_VERBOSE("domain:0x%04x, bus:0x%02x, slot:0x%02x, fn:%u\n", | ||||
|         rg_lpc_dev->domain,rg_lpc_dev->bus, rg_lpc_dev->slot, rg_lpc_dev->fn); | ||||
|     LPC_DEV_DEBUG_VERBOSE("lpc_io_name:%s, lpc_io_base:0x%x, lpc_io_size:%u, lpc_gen_dec:0x%x.\n", | ||||
|         rg_lpc_dev->lpc_io_name, rg_lpc_dev->lpc_io_base, rg_lpc_dev->lpc_io_size, rg_lpc_dev->lpc_gen_dec); | ||||
|  | ||||
|     devfn = PCI_DEVFN(rg_lpc_dev->slot, rg_lpc_dev->fn); | ||||
|     pci_dev = pci_get_domain_bus_and_slot(rg_lpc_dev->domain, rg_lpc_dev->bus, devfn); | ||||
|     if (pci_dev == NULL) { | ||||
|         dev_err(&pdev->dev, "Failed to find pci_dev, domain:0x%04x, bus:0x%02x, devfn:0x%x\n", | ||||
|             rg_lpc_dev->domain, rg_lpc_dev->bus, devfn); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|  | ||||
|     pci_write_config_dword(pci_dev, rg_lpc_dev->lpc_gen_dec, LPC_MAKE_PCI_IO_RANGE(rg_lpc_dev->lpc_io_base)); | ||||
|     if (!request_region(rg_lpc_dev->lpc_io_base, rg_lpc_dev->lpc_io_size, rg_lpc_dev->lpc_io_name)) { | ||||
|         dev_err(&pdev->dev, "Failed to request_region [0x%x][0x%x].\n", rg_lpc_dev->lpc_io_base, rg_lpc_dev->lpc_io_size); | ||||
|         return -EBUSY; | ||||
|     } | ||||
|  | ||||
|     platform_set_drvdata(pdev, rg_lpc_dev); | ||||
|  | ||||
|     dev_info(&pdev->dev, "lpc request_region [0x%x][0x%x] success.\n", rg_lpc_dev->lpc_io_base, rg_lpc_dev->lpc_io_size); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int rg_lpc_remove(struct platform_device *pdev) | ||||
| { | ||||
|     rg_lpc_dev_t *rg_lpc_dev; | ||||
|  | ||||
|     rg_lpc_dev = platform_get_drvdata(pdev); | ||||
|     if (rg_lpc_dev) { | ||||
|         release_region(rg_lpc_dev->lpc_io_base , rg_lpc_dev->lpc_io_size); | ||||
|         LPC_DEV_DEBUG_VERBOSE("lpc base:0x%x, len:0x%x.\n", rg_lpc_dev->lpc_io_base, rg_lpc_dev->lpc_io_size); | ||||
|     } | ||||
|     LPC_DEV_DEBUG_VERBOSE("lpc remove.\n"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static struct of_device_id lpc_dev_match[] = { | ||||
|     { | ||||
|         .compatible = "ruijie,rg-lpc", | ||||
|     }, | ||||
|     {}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, lpc_dev_match); | ||||
|  | ||||
| static struct platform_driver rg_lpc_driver = { | ||||
|     .probe      = rg_lpc_probe, | ||||
|     .remove     = rg_lpc_remove, | ||||
|     .driver     = { | ||||
|         .owner  = THIS_MODULE, | ||||
|         .name   = LPC_DRIVER_NAME, | ||||
|         .of_match_table = lpc_dev_match, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static int __init rg_lpc_init(void) | ||||
| { | ||||
|     return platform_driver_register(&rg_lpc_driver); | ||||
| } | ||||
|  | ||||
| static void __exit rg_lpc_exit(void) | ||||
| { | ||||
|     platform_driver_unregister(&rg_lpc_driver); | ||||
| } | ||||
|  | ||||
| module_init(rg_lpc_init); | ||||
| module_exit(rg_lpc_exit); | ||||
| MODULE_DESCRIPTION("lpc driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,18 @@ | ||||
| #ifndef __RG_LPC_DRV_H__ | ||||
| #define __RG_LPC_DRV_H__ | ||||
|  | ||||
| #define LPC_IO_NAME_MAX_LEN (64) | ||||
|  | ||||
| typedef struct lpc_drv_device_s { | ||||
|     char lpc_io_name[LPC_IO_NAME_MAX_LEN]; | ||||
|     int pci_domain; | ||||
|     int pci_bus; | ||||
|     int pci_slot; | ||||
|     int pci_fn; | ||||
|     int lpc_io_base; | ||||
|     int lpc_io_size; | ||||
|     int lpc_gen_dec; | ||||
|     int device_flag; | ||||
| } lpc_drv_device_t; | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,658 @@ | ||||
| /* | ||||
|  * rg_mac_th3.c - A driver for control rg_mac_th3 base on rg_mac.c | ||||
|  * | ||||
|  * Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> | ||||
|  * Copyright (c) 2018 ruijie <rd@ruijie.com.cn> | ||||
|  * | ||||
|  * 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. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/jiffies.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/hwmon.h> | ||||
| #include <linux/hwmon-sysfs.h> | ||||
| #include <linux/err.h> | ||||
| #include <linux/mutex.h> | ||||
|  | ||||
| #define MAC_TEMP_INVALID    (99999999) | ||||
|  | ||||
| #define MAC_SIZE		    (256) | ||||
| #define MAC_TEMP_NUM        (16) | ||||
|  | ||||
| #define MAC_ID_REG          (0x02000000) | ||||
|  | ||||
| typedef enum { | ||||
|     DBG_START, | ||||
|     DBG_VERBOSE, | ||||
|     DBG_KEY, | ||||
|     DBG_WARN, | ||||
|     DBG_ERROR, | ||||
|     DBG_END, | ||||
| } dbg_level_t; | ||||
|  | ||||
| typedef enum{ | ||||
|     MAC_TYPE_START, | ||||
|     TD4_X9 = 0xb780, | ||||
|     TD4_X9_8 = 0xb788, | ||||
|     TH3 = 0xb980, | ||||
|     TD3 = 0xb870, | ||||
|     TD4 = 0xb880, | ||||
|     TH4 = 0xb990, | ||||
|     MAC_TYPE_END, | ||||
| } mac_type; | ||||
|  | ||||
| typedef struct sensor_regs_s { | ||||
|     int id; | ||||
|     u32 reg; | ||||
| } sensor_reg_t; | ||||
|  | ||||
| typedef struct mac_temp_regs_s { | ||||
|     int mac_type; | ||||
|     sensor_reg_t sensor_reg[MAC_TEMP_NUM]; | ||||
| } mac_temp_reg_t; | ||||
|  | ||||
| typedef enum { | ||||
|     MAC_TEMP_START, | ||||
|     MAC_TEMP_INDEX1, | ||||
|     MAC_TEMP_INDEX2, | ||||
|     MAC_TEMP_INDEX3, | ||||
|     MAC_TEMP_INDEX4, | ||||
|     MAC_TEMP_INDEX5, | ||||
|     MAC_TEMP_INDEX6, | ||||
|     MAC_TEMP_INDEX7, | ||||
|     MAC_TEMP_INDEX8, | ||||
|     MAC_TEMP_INDEX9, | ||||
|     MAC_TEMP_INDEX10, | ||||
|     MAC_TEMP_INDEX11, | ||||
|     MAC_TEMP_INDEX12, | ||||
|     MAC_TEMP_INDEX13, | ||||
|     MAC_TEMP_INDEX14, | ||||
|     MAC_TEMP_INDEX15, | ||||
|     MAC_TEMP_END, | ||||
| } mac_hwmon_index; | ||||
|  | ||||
| static mac_temp_reg_t mac_temp_reg[] = { | ||||
|     { | ||||
|         /* TD3 */ | ||||
|         .mac_type = TD3, | ||||
|         .sensor_reg = { | ||||
|             {.id = MAC_TEMP_INDEX1,  .reg = 0x02004700}, | ||||
|             {.id = MAC_TEMP_INDEX2,  .reg = 0x02004800}, | ||||
|             {.id = MAC_TEMP_INDEX3,  .reg = 0x02004900}, | ||||
|             {.id = MAC_TEMP_INDEX4,  .reg = 0x02004a00}, | ||||
|             {.id = MAC_TEMP_INDEX5,  .reg = 0x02004b00}, | ||||
|             {.id = MAC_TEMP_INDEX6,  .reg = 0x02004c00}, | ||||
|             {.id = MAC_TEMP_INDEX7,  .reg = 0x02004d00}, | ||||
|             {.id = MAC_TEMP_INDEX8,  .reg = 0x02004e00}, | ||||
|             {.id = MAC_TEMP_INDEX9,  .reg = 0x02005200}, | ||||
|             {.id = MAC_TEMP_INDEX10, .reg = 0x02005100}, | ||||
|             {.id = MAC_TEMP_INDEX11, .reg = 0x02005000}, | ||||
|             {.id = MAC_TEMP_INDEX12, .reg = 0x02004f00}, | ||||
|         }, | ||||
|     }, | ||||
|     { | ||||
|         /* TD4 */ | ||||
|         .mac_type = TD4, | ||||
|         .sensor_reg = { | ||||
|             {.id = MAC_TEMP_INDEX1,  .reg = 0x02004900}, | ||||
|             {.id = MAC_TEMP_INDEX2,  .reg = 0x02004b00}, | ||||
|             {.id = MAC_TEMP_INDEX3,  .reg = 0x02004d00}, | ||||
|             {.id = MAC_TEMP_INDEX4,  .reg = 0x02004f00}, | ||||
|             {.id = MAC_TEMP_INDEX5,  .reg = 0x02005100}, | ||||
|             {.id = MAC_TEMP_INDEX6,  .reg = 0x02005300}, | ||||
|             {.id = MAC_TEMP_INDEX7,  .reg = 0x02005500}, | ||||
|             {.id = MAC_TEMP_INDEX8,  .reg = 0x02005700}, | ||||
|             {.id = MAC_TEMP_INDEX9,  .reg = 0x02005900}, | ||||
|             {.id = MAC_TEMP_INDEX10, .reg = 0x02005b00}, | ||||
|             {.id = MAC_TEMP_INDEX11, .reg = 0x02005d00}, | ||||
|             {.id = MAC_TEMP_INDEX12, .reg = 0x02005f00}, | ||||
|             {.id = MAC_TEMP_INDEX13, .reg = 0x02006100}, | ||||
|             {.id = MAC_TEMP_INDEX14, .reg = 0x02006300}, | ||||
|             {.id = MAC_TEMP_INDEX15, .reg = 0x02006500}, | ||||
|         }, | ||||
|     }, | ||||
|     { | ||||
|         /* TD4_X9 */ | ||||
|         .mac_type = TD4_X9, | ||||
|         .sensor_reg = { | ||||
|             {.id = MAC_TEMP_INDEX1,  .reg = 0x02005a00}, | ||||
|             {.id = MAC_TEMP_INDEX2,  .reg = 0x02005c00}, | ||||
|             {.id = MAC_TEMP_INDEX3,  .reg = 0x02005e00}, | ||||
|             {.id = MAC_TEMP_INDEX4,  .reg = 0x02006000}, | ||||
|             {.id = MAC_TEMP_INDEX5,  .reg = 0x02006200}, | ||||
|             {.id = MAC_TEMP_INDEX6,  .reg = 0x02006400}, | ||||
|             {.id = MAC_TEMP_INDEX7,  .reg = 0x02006600}, | ||||
|             {.id = MAC_TEMP_INDEX8,  .reg = 0x02006800}, | ||||
|             {.id = MAC_TEMP_INDEX9,  .reg = 0x02006a00}, | ||||
|         }, | ||||
|     }, | ||||
|     { | ||||
|         /* TD4_X9_8 */ | ||||
|         .mac_type = TD4_X9_8, | ||||
|         .sensor_reg = { | ||||
|             {.id = MAC_TEMP_INDEX1,  .reg = 0x02005a00}, | ||||
|             {.id = MAC_TEMP_INDEX2,  .reg = 0x02005c00}, | ||||
|             {.id = MAC_TEMP_INDEX3,  .reg = 0x02005e00}, | ||||
|             {.id = MAC_TEMP_INDEX4,  .reg = 0x02006000}, | ||||
|             {.id = MAC_TEMP_INDEX5,  .reg = 0x02006200}, | ||||
|             {.id = MAC_TEMP_INDEX6,  .reg = 0x02006400}, | ||||
|             {.id = MAC_TEMP_INDEX7,  .reg = 0x02006600}, | ||||
|             {.id = MAC_TEMP_INDEX8,  .reg = 0x02006800}, | ||||
|             {.id = MAC_TEMP_INDEX9,  .reg = 0x02006a00}, | ||||
|         }, | ||||
|     }, | ||||
|     { | ||||
|         /* TH3 */ | ||||
|         .mac_type = TH3, | ||||
|         .sensor_reg = { | ||||
|             {.id = MAC_TEMP_INDEX1,  .reg = 0x02004a00}, | ||||
|             {.id = MAC_TEMP_INDEX2,  .reg = 0x02004b00}, | ||||
|             {.id = MAC_TEMP_INDEX3,  .reg = 0x02004c00}, | ||||
|             {.id = MAC_TEMP_INDEX4,  .reg = 0x02004d00}, | ||||
|             {.id = MAC_TEMP_INDEX5,  .reg = 0x02004e00}, | ||||
|             {.id = MAC_TEMP_INDEX6,  .reg = 0x02004f00}, | ||||
|             {.id = MAC_TEMP_INDEX7,  .reg = 0x02005000}, | ||||
|             {.id = MAC_TEMP_INDEX8,  .reg = 0x02005100}, | ||||
|             {.id = MAC_TEMP_INDEX9,  .reg = 0x02005200}, | ||||
|             {.id = MAC_TEMP_INDEX10, .reg = 0x02005300}, | ||||
|             {.id = MAC_TEMP_INDEX11, .reg = 0x02005400}, | ||||
|             {.id = MAC_TEMP_INDEX12, .reg = 0x02005500}, | ||||
|             {.id = MAC_TEMP_INDEX13, .reg = 0x02005600}, | ||||
|             {.id = MAC_TEMP_INDEX14, .reg = 0x02005700}, | ||||
|             {.id = MAC_TEMP_INDEX15, .reg = 0x02005800}, | ||||
|         }, | ||||
|     }, | ||||
|     { | ||||
|         /* TH4 */ | ||||
|         .mac_type = TH4, | ||||
|         .sensor_reg = { | ||||
|             {.id = MAC_TEMP_INDEX1,  .reg = 0x0201d800}, | ||||
|             {.id = MAC_TEMP_INDEX2,  .reg = 0x0201e000}, | ||||
|             {.id = MAC_TEMP_INDEX3,  .reg = 0x0201e800}, | ||||
|             {.id = MAC_TEMP_INDEX4,  .reg = 0x0201f000}, | ||||
|             {.id = MAC_TEMP_INDEX5,  .reg = 0x0201f800}, | ||||
|             {.id = MAC_TEMP_INDEX6,  .reg = 0x02020000}, | ||||
|             {.id = MAC_TEMP_INDEX7,  .reg = 0x02020800}, | ||||
|             {.id = MAC_TEMP_INDEX8,  .reg = 0x02021000}, | ||||
|             {.id = MAC_TEMP_INDEX9,  .reg = 0x02021800}, | ||||
|             {.id = MAC_TEMP_INDEX10, .reg = 0x02022000}, | ||||
|             {.id = MAC_TEMP_INDEX11, .reg = 0x02022800}, | ||||
|             {.id = MAC_TEMP_INDEX12, .reg = 0x02023000}, | ||||
|             {.id = MAC_TEMP_INDEX13, .reg = 0x02023800}, | ||||
|             {.id = MAC_TEMP_INDEX14, .reg = 0x02024000}, | ||||
|             {.id = MAC_TEMP_INDEX15, .reg = 0x02024800}, | ||||
|         }, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static int debuglevel = 0; | ||||
| module_param(debuglevel, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| static int mac_pcie_id = MAC_TYPE_START; | ||||
| module_param(mac_pcie_id, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define DBG_DEBUG(fmt, arg...)  do { \ | ||||
|     if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ | ||||
|           printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ | ||||
|     } else if ( debuglevel >= DBG_ERROR ) {   \ | ||||
|         printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ | ||||
|     } else {    } \ | ||||
| } while (0) | ||||
|  | ||||
| #define DBG_ERROR(fmt, arg...)  do { \ | ||||
|      if ( debuglevel > DBG_START) {  \ | ||||
|         printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ | ||||
|        } \ | ||||
|  } while (0) | ||||
|  | ||||
| struct mac_data { | ||||
|     struct i2c_client   *client; | ||||
|     struct device		*hwmon_dev; | ||||
|     struct mutex        update_lock; | ||||
|     u8                  data[MAC_SIZE]; /* Register value */ | ||||
| }; | ||||
|  | ||||
| static int rg_i2c_read_one_time(struct i2c_client *client, u8 *recv_buf, int size) | ||||
| { | ||||
|     struct i2c_msg msgs[2]; | ||||
|     int ret = 0; | ||||
|  | ||||
|     if ((client == NULL) || (recv_buf == NULL)) { | ||||
|         DBG_DEBUG("i2c_client || recv_buf = NULL\r\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     memset(msgs, 0, sizeof(msgs)); | ||||
|  | ||||
|     msgs[0].buf = recv_buf; | ||||
|     msgs[0].len = size; | ||||
|     msgs[0].addr = client->addr; | ||||
|     msgs[0].flags |= I2C_M_RD; | ||||
|  | ||||
|     ret = i2c_transfer(client->adapter, msgs, 1); | ||||
|     if (ret < 0) { | ||||
|         return ret; | ||||
|     } | ||||
|     DBG_DEBUG("i2c_transfer, dev_addr 0x%x, size %d.\n", client->addr, size); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int rg_i2c_write_one_time(struct i2c_client *client, u8 *write_buf, int size) | ||||
| { | ||||
|     struct i2c_msg msgs[2]; | ||||
|     int ret = 0; | ||||
|  | ||||
|     if ((client == NULL) || (write_buf == NULL)) { | ||||
|         DBG_DEBUG("i2c_client || write_buf = NULL\r\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if ((size <= 0)) { | ||||
|         DBG_DEBUG("size invalid, size %d\n", size); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     memset(msgs, 0, sizeof(msgs)); | ||||
|  | ||||
|     msgs[0].len = size; | ||||
|     msgs[0].buf = write_buf; | ||||
|     msgs[0].addr = client->addr; | ||||
|  | ||||
|     ret = i2c_transfer(client->adapter, msgs, 1); | ||||
|     if (ret < 0) { | ||||
|         return ret; | ||||
|     } | ||||
|     DBG_DEBUG("i2c_transfer, dev_addr 0x%x, size %d\n", client->addr, size); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static u8 step2_buf1[8] = {0x03, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||||
| static u8 step2_buf2[8] = {0x03, 0x21, 0x04, 0x0c, 0x2c, 0x38, 0x02, 0x00}; | ||||
| static u8 step2_buf3[8] = {0x03, 0x21, 0x04, 0x10, 0x02, 0x00, 0x4a, 0x00}; | ||||
| static u8 step2_buf4[8] = {0x03, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01}; | ||||
| static u8 step2_buf5[4] = {0x03, 0x21, 0x04, 0x08}; | ||||
| static u8 step2_buf6[4] = {0x03, 0x21, 0x04, 0x10}; | ||||
|  | ||||
| static int getmac_register(struct i2c_client *client, u32 index, int *reg_value) | ||||
| { | ||||
|     int i; | ||||
|     int ret = 0; | ||||
|     int value = 0; | ||||
|     unsigned char read_buf[8]; | ||||
|  | ||||
|     if (index == 0) { | ||||
|         DBG_ERROR("invalid index\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     step2_buf3[7]  = index & 0xff; | ||||
|     step2_buf3[6]  = (index >> 8) & 0xff; | ||||
|     step2_buf3[5]  = (index >> 16) & 0xff; | ||||
|     step2_buf3[4]  = (index >> 24) & 0xff; | ||||
|  | ||||
|      ret = rg_i2c_write_one_time(client, step2_buf1, 8); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("write step2_buf1 failed, ret = %d\n", ret); | ||||
|      } | ||||
|      ret = rg_i2c_write_one_time(client, step2_buf2, 8); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("write step2_buf2 failed, ret = %d\n", ret); | ||||
|      } | ||||
|      ret = rg_i2c_write_one_time(client, step2_buf3, 8); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("write step2_buf3 failed, ret = %d\n", ret); | ||||
|      } | ||||
|      ret = rg_i2c_write_one_time(client, step2_buf4, 8); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("write step2_buf4 failed, ret = %d\n", ret); | ||||
|      } | ||||
|  | ||||
|      ret = rg_i2c_write_one_time(client, step2_buf5, 4); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("write step2_buf5 failed, ret = %d\n", ret); | ||||
|      } | ||||
|      ret = rg_i2c_read_one_time(client, read_buf, 4); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("read failed, ret = %d\n", ret); | ||||
|      } | ||||
|      for (i = 0; i < 4; i++) { | ||||
|          DBG_DEBUG("read_buf[%d] = 0x%x \n", i, read_buf[i]); | ||||
|      } | ||||
|  | ||||
|      ret = rg_i2c_write_one_time(client, step2_buf6, 4); | ||||
|      if (ret < 0) { | ||||
|          DBG_ERROR("write step2_buf6 failed, ret = %d\n", ret); | ||||
|      } | ||||
|  | ||||
|     ret = rg_i2c_read_one_time(client, read_buf, 4); | ||||
|     if (ret < 0) { | ||||
|         DBG_ERROR("read failed, ret = %d\n", ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     value = (read_buf[0] << 24)| (read_buf[1] << 16) | (read_buf[2] << 8) | read_buf[3]; | ||||
|     *reg_value = value; | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int mac_calcute(u32 reg, int *temp) | ||||
| { | ||||
|     int ret = 0; | ||||
|     u32 tmp = 0; | ||||
|  | ||||
|     switch(mac_pcie_id) { | ||||
|     case TD3: | ||||
|     case TH3: | ||||
|         tmp = reg & 0x3ff; | ||||
|         *temp =  434100 - (tmp * 535); | ||||
|         break; | ||||
|     case TD4: | ||||
|     case TH4: | ||||
|     case TD4_X9: | ||||
|     case TD4_X9_8: | ||||
|         tmp = reg & 0x7ff; | ||||
|         *temp = (356070 - (tmp * 237)); | ||||
|         break; | ||||
|     default: | ||||
|         ret = -1; | ||||
|         DBG_ERROR("read failed, ret = %d\n", ret); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     if ((*temp / 1000 < -70) || (*temp / 1000 > 200)) { | ||||
|         ret = -1; | ||||
|         DBG_ERROR("mac temp invalid, temp = %d\n", *temp ); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int find_reg_type(int type, int *type_index) | ||||
| { | ||||
|     int i; | ||||
|     int size; | ||||
|  | ||||
|     size = ARRAY_SIZE(mac_temp_reg); | ||||
|     for (i = 0; i < size; i++) { | ||||
|         if (mac_temp_reg[i].mac_type == type) { | ||||
|             *type_index = i; | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static sensor_reg_t * find_reg_offset(int type, int index) | ||||
| { | ||||
|     int i; | ||||
|     int type_index; | ||||
|     int ret; | ||||
|  | ||||
|     ret = find_reg_type(type, &type_index); | ||||
|     if (ret < 0) { | ||||
|         DBG_ERROR("find_reg_type failed, ret = %d\n", ret); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < MAC_TEMP_NUM; i++) { | ||||
|         if (mac_temp_reg[type_index].sensor_reg[i].id == index) { | ||||
|             return &(mac_temp_reg[type_index].sensor_reg[i]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| static int get_mactemp(struct i2c_client *client, int index, int *temp) | ||||
| { | ||||
|     int ret; | ||||
|     int reg_value; | ||||
|  | ||||
|     if (index == 0) { | ||||
|         DBG_ERROR("invalid index\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     ret = getmac_register(client, index, ®_value); | ||||
|     if (ret < 0) { | ||||
|         DBG_ERROR("getmac_register failed, ret = %d\n", ret); | ||||
|         return ret; | ||||
|     } | ||||
|     DBG_DEBUG("reg_value = 0x%x \n", reg_value); | ||||
|  | ||||
|     ret = mac_calcute(reg_value, temp); | ||||
|     if (ret < 0) { | ||||
|         DBG_ERROR("mac_calcute failed, ret = %d\n", ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static ssize_t show_mac_temp(struct device *dev, struct device_attribute *da, char *buf) | ||||
| { | ||||
|     struct mac_data *data = dev_get_drvdata(dev); | ||||
|     struct i2c_client *client = data->client; | ||||
|     u32 index_value = to_sensor_dev_attr_2(da)->index; | ||||
|     sensor_reg_t *t; | ||||
|     int result = 0; | ||||
|     int temp = -MAC_TEMP_INVALID; | ||||
|  | ||||
|     mutex_lock(&data->update_lock); | ||||
|     t = find_reg_offset(mac_pcie_id, index_value); | ||||
|     if (t == NULL) { | ||||
|         temp = -MAC_TEMP_INVALID; | ||||
|         DBG_ERROR("find_reg_offset failed, mac_pcie_id = %d, index_value = %d\n", mac_pcie_id, index_value); | ||||
|     } else { | ||||
|         result = get_mactemp(client, t->reg, &temp); | ||||
|         if (result < 0) { | ||||
|             temp = -MAC_TEMP_INVALID; | ||||
|             DBG_ERROR("get_mactemp failed, ret = %d\n", result); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     mutex_unlock(&data->update_lock); | ||||
|     return snprintf(buf, MAC_SIZE, "%d\n", temp); | ||||
| } | ||||
|  | ||||
| static ssize_t show_mac_max_temp(struct device *dev, struct device_attribute *da, char *buf) | ||||
| { | ||||
|     struct mac_data *data = dev_get_drvdata(dev); | ||||
|     struct i2c_client *client = data->client; | ||||
|     int i; | ||||
|     int result; | ||||
|     int temp = -MAC_TEMP_INVALID; | ||||
|     int type_index; | ||||
|     int tmp; | ||||
|  | ||||
|     mutex_lock(&data->update_lock); | ||||
|  | ||||
|     result = find_reg_type(mac_pcie_id, &type_index); | ||||
|     if (result < 0) { | ||||
|         DBG_ERROR("find_reg_type failed, ret = %d\n", result); | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < MAC_TEMP_NUM; i++) { | ||||
|         result = get_mactemp(client, mac_temp_reg[type_index].sensor_reg[i].reg, &tmp); | ||||
|         if (result < 0) { | ||||
|             DBG_ERROR("get_mactemp failed, ret = %d\n", result); | ||||
|             tmp = -MAC_TEMP_INVALID; | ||||
|         } | ||||
|  | ||||
|         temp = (temp > tmp) ? temp : tmp; | ||||
|     } | ||||
|  | ||||
| exit: | ||||
|     mutex_unlock(&data->update_lock); | ||||
|     return snprintf(buf, MAC_SIZE, "%d\n", temp); | ||||
| } | ||||
|  | ||||
| static int mac_bsc_init(struct i2c_client *client) | ||||
| { | ||||
|     int ret; | ||||
|     int reg_value; | ||||
|     int mac_id = 0; | ||||
|  | ||||
|     ret = getmac_register(client, MAC_ID_REG, ®_value); | ||||
|     if (ret < 0) { | ||||
|         DBG_ERROR("getmac_register failed, ret = %d\n", ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG("reg_value = 0x%x \n", reg_value); | ||||
|     mac_id = reg_value & 0xffff; | ||||
|     return mac_id; | ||||
| } | ||||
|  | ||||
| static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX1); | ||||
| static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX2); | ||||
| static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX3); | ||||
| static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX4); | ||||
| static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX5); | ||||
| static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX6); | ||||
| static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX7); | ||||
| static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX8); | ||||
| static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX9); | ||||
| static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX10); | ||||
| static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX11); | ||||
| static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX12); | ||||
| static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX13); | ||||
| static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX14); | ||||
| static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, show_mac_temp, NULL, MAC_TEMP_INDEX15); | ||||
| static SENSOR_DEVICE_ATTR(temp99_input, S_IRUGO, show_mac_max_temp, NULL, 0); | ||||
|  | ||||
| static struct attribute *mac_hwmon_attrs[] = { | ||||
|     &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_temp6_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp7_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp8_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp9_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp10_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp11_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp12_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp13_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp14_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp15_input.dev_attr.attr, | ||||
|     &sensor_dev_attr_temp99_input.dev_attr.attr, | ||||
|     NULL | ||||
| }; | ||||
| ATTRIBUTE_GROUPS(mac_hwmon); | ||||
|  | ||||
| static int init_bcs_command(int mac_type) { | ||||
|     int ret; | ||||
|  | ||||
|     ret = 0; | ||||
|     switch (mac_type) { | ||||
|         case TD3: | ||||
|             step2_buf2[5] = 0x38; | ||||
|             break; | ||||
|         case TH3: | ||||
|         case TH4: | ||||
|         case TD4: | ||||
|         case TD4_X9: | ||||
|         case TD4_X9_8: | ||||
|             step2_buf2[5] = 0x40; | ||||
|             break; | ||||
|         default: | ||||
|             ret = -1; | ||||
|             break; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int mac_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||||
| { | ||||
|     struct mac_data *data; | ||||
|     int mac_type; | ||||
|     int ret; | ||||
|  | ||||
|     mac_type = id->driver_data; | ||||
|     mac_pcie_id = mac_type; | ||||
|     if (init_bcs_command(mac_type) < 0) { | ||||
|         DBG_ERROR("mactype[%x] not support \n", mac_type); | ||||
|         return -1; | ||||
|     }; | ||||
|  | ||||
|     if (mac_type == TD4) { | ||||
|         ret = mac_bsc_init(client); | ||||
|         if (ret < 0) { | ||||
|             DBG_ERROR("mac_bsc_init failed, ret = %d\n", ret); | ||||
|             return -1; | ||||
|         } | ||||
|         mac_type = ret; | ||||
|         mac_pcie_id = mac_type; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG("=========mac_probe(%x)===========\n",client->addr); | ||||
|     DBG_DEBUG("mac_type: %x\n", mac_type); | ||||
|     data = devm_kzalloc(&client->dev, sizeof(struct mac_data), GFP_KERNEL); | ||||
|     if (!data) { | ||||
|         return -ENOMEM; | ||||
|     } | ||||
|  | ||||
|     data->client = client; | ||||
|     i2c_set_clientdata(client, data); | ||||
|     mutex_init(&data->update_lock); | ||||
|  | ||||
|     data->hwmon_dev = hwmon_device_register_with_groups(&client->dev, client->name, data, mac_hwmon_groups); | ||||
| 	if (IS_ERR(data->hwmon_dev)) { | ||||
|         return PTR_ERR(data->hwmon_dev); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int mac_remove(struct i2c_client *client) | ||||
| { | ||||
|     struct mac_data *data = i2c_get_clientdata(client); | ||||
|     hwmon_device_unregister(data->hwmon_dev); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const struct i2c_device_id mac_id[] = { | ||||
|     { "rg_mac_bsc_td3", TD3 }, | ||||
|     { "rg_mac_bsc_td4", TD4 }, | ||||
|     { "rg_mac_bsc_th3", TH3 }, | ||||
|     { "rg_mac_bsc_th4", TH4 }, | ||||
|     {} | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(i2c, mac_id); | ||||
|  | ||||
| static struct i2c_driver rg_mac_bsc_driver = { | ||||
|     .driver = { | ||||
|         .name   = "rg_mac_bsc", | ||||
|     }, | ||||
|     .probe      = mac_probe, | ||||
|     .remove     = mac_remove, | ||||
|     .id_table   = mac_id, | ||||
| }; | ||||
|  | ||||
| module_i2c_driver(rg_mac_bsc_driver); | ||||
|  | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| MODULE_DESCRIPTION("ruijie mac bsc driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,773 @@ | ||||
| /* | ||||
|  * Copyright(C) 2022 Ruijie Network. All rights reserved. | ||||
|  * | ||||
|  * rg_pcie_dev.c | ||||
|  * ko to read/write pcie iomem and ioports through /dev/XXX device | ||||
|  * Original Author: sonic_rd@ruijie.com.cn 2022-09-09 | ||||
|  */ | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/miscdevice.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/of_platform.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/uio.h> | ||||
|  | ||||
| #include "rg_pcie_dev.h" | ||||
|  | ||||
| #define PROXY_NAME "rg-pci-dev" | ||||
| #define MAX_NAME_SIZE            (20) | ||||
| #define MAX_PCIE_NUM             (256) | ||||
| #define PCI_RDWR_MAX_LEN         (256) | ||||
| #define PCIE_BUS_WIDTH_1         (1) | ||||
| #define PCIE_BUS_WIDTH_2         (2) | ||||
| #define PCIE_BUS_WIDTH_4         (4) | ||||
|  | ||||
| static int g_pcie_dev_debug = 0; | ||||
| static int g_pcie_dev_error = 0; | ||||
|  | ||||
| module_param(g_pcie_dev_debug, int, S_IRUGO | S_IWUSR); | ||||
| module_param(g_pcie_dev_error, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| #define PCIE_DEV_DEBUG_VERBOSE(fmt, args...) do {                                        \ | ||||
|     if (g_pcie_dev_debug) { \ | ||||
|         printk(KERN_INFO "[PCIE_DEV][VER][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| #define PCIE_DEV_DEBUG_ERROR(fmt, args...) do {                                        \ | ||||
|     if (g_pcie_dev_error) { \ | ||||
|         printk(KERN_ERR "[PCIE_DEV][ERR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ | ||||
|     } \ | ||||
| } while (0) | ||||
|  | ||||
| typedef struct firmware_upg_s { | ||||
|     int upg_ctrl_base; | ||||
|     int upg_flash_base; | ||||
| } firmware_upg_t; | ||||
|  | ||||
| typedef struct rg_pci_dev_s { | ||||
|     const char *name; | ||||
|     uint32_t domain; | ||||
|     uint32_t bus; | ||||
|     uint32_t slot; | ||||
|     uint32_t fn; | ||||
|     uint32_t bar; | ||||
|     void __iomem *pci_mem_base; | ||||
|     uint32_t pci_io_base; | ||||
|     uint32_t bar_len; | ||||
|     uint32_t bar_flag; | ||||
|     uint32_t bus_width; | ||||
|     struct miscdevice misc; | ||||
|     void (*setreg)(struct rg_pci_dev_s *rg_pci_dev, int reg, u32 value); | ||||
|     u32 (*getreg)(struct rg_pci_dev_s *rg_pci_dev, int reg); | ||||
|     firmware_upg_t firmware_upg; | ||||
| } rg_pci_dev_t; | ||||
|  | ||||
| static rg_pci_dev_t* pcie_dev_arry[MAX_PCIE_NUM]; | ||||
|  | ||||
| static void pci_dev_setreg_8(rg_pci_dev_t *rg_pci_dev, int reg, u32 value) | ||||
| { | ||||
|     u8 w_value; | ||||
|  | ||||
|     w_value = (u8)(value & 0xff); | ||||
|     if (rg_pci_dev->bar_flag == IORESOURCE_MEM) { | ||||
|         writeb(w_value, rg_pci_dev->pci_mem_base + reg); | ||||
|     } else { | ||||
|         outb(w_value, rg_pci_dev->pci_io_base + reg); | ||||
|     } | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static void pci_dev_setreg_16(rg_pci_dev_t *rg_pci_dev, int reg, u32 value) | ||||
| { | ||||
|     u16 w_value; | ||||
|  | ||||
|     w_value = (u16)(value & 0xffff); | ||||
|     if (rg_pci_dev->bar_flag == IORESOURCE_MEM) { | ||||
|         writew(w_value, rg_pci_dev->pci_mem_base + reg); | ||||
|     } else { | ||||
|         outw(w_value, rg_pci_dev->pci_io_base + reg); | ||||
|     } | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static void pci_dev_setreg_32(rg_pci_dev_t *rg_pci_dev, int reg, u32 value) | ||||
| { | ||||
|  | ||||
|     if (rg_pci_dev->bar_flag == IORESOURCE_MEM) { | ||||
|         writel(value, rg_pci_dev->pci_mem_base + reg); | ||||
|     } else { | ||||
|         outl(value, rg_pci_dev->pci_io_base + reg); | ||||
|     } | ||||
|     return; | ||||
| } | ||||
|  | ||||
| static inline u32 pci_dev_getreg_8(rg_pci_dev_t *rg_pci_dev, int reg) | ||||
| { | ||||
|     u32 value; | ||||
|  | ||||
|     if (rg_pci_dev->bar_flag == IORESOURCE_MEM) { | ||||
|         value = readb(rg_pci_dev->pci_mem_base + reg); | ||||
|     } else { | ||||
|         value = inb(rg_pci_dev->pci_io_base + reg); | ||||
|     } | ||||
|  | ||||
|     return value; | ||||
| } | ||||
|  | ||||
| static inline u32 pci_dev_getreg_16(rg_pci_dev_t *rg_pci_dev, int reg) | ||||
| { | ||||
|     u32 value; | ||||
|  | ||||
|     if (rg_pci_dev->bar_flag == IORESOURCE_MEM) { | ||||
|         value = readw(rg_pci_dev->pci_mem_base + reg); | ||||
|     } else { | ||||
|         value = inw(rg_pci_dev->pci_io_base + reg); | ||||
|     } | ||||
|  | ||||
|     return value; | ||||
| } | ||||
|  | ||||
| static inline u32 pci_dev_getreg_32(rg_pci_dev_t *rg_pci_dev, int reg) | ||||
| { | ||||
|     u32 value; | ||||
|  | ||||
|     if (rg_pci_dev->bar_flag == IORESOURCE_MEM) { | ||||
|         value = readl(rg_pci_dev->pci_mem_base + reg); | ||||
|     } else { | ||||
|         value = inl(rg_pci_dev->pci_io_base + reg); | ||||
|     } | ||||
|  | ||||
|     return value; | ||||
| } | ||||
|  | ||||
| static inline void pci_dev_setreg(rg_pci_dev_t *rg_pci_dev, int reg, u32 value) | ||||
| { | ||||
|     rg_pci_dev->setreg(rg_pci_dev, reg, value); | ||||
| } | ||||
|  | ||||
| static inline u32 pci_dev_getreg(rg_pci_dev_t *rg_pci_dev, int reg) | ||||
| { | ||||
|     return rg_pci_dev->getreg(rg_pci_dev, reg); | ||||
| } | ||||
|  | ||||
| static int pci_dev_open(struct inode *inode, struct file *file) | ||||
| { | ||||
|     unsigned int minor = iminor(inode); | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|  | ||||
|     PCIE_DEV_DEBUG_VERBOSE("inode: %p, file: %p, minor: %u", inode, file, minor); | ||||
|  | ||||
|     if (minor >= MAX_PCIE_NUM) { | ||||
|         PCIE_DEV_DEBUG_ERROR("minor out of range, minor = %d.\n", minor); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     rg_pci_dev = pcie_dev_arry[minor]; | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("rg_pci_dev is NULL, open failed, minor = %d\n", minor); | ||||
|         return -ENODEV; | ||||
|     } | ||||
|  | ||||
|     file->private_data = rg_pci_dev; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int pci_dev_release(struct inode *inode, struct file *file) | ||||
| { | ||||
|     file->private_data = NULL; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int pci_dev_read_tmp(rg_pci_dev_t *rg_pci_dev, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     int width, i, j; | ||||
|     u32 val; | ||||
|  | ||||
|     if (offset > rg_pci_dev->bar_len) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("offset:0x%x, bar len:0x%x, EOF.\n", offset, rg_pci_dev->bar_len); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     width = rg_pci_dev->bus_width; | ||||
|  | ||||
|     if (offset % width) { | ||||
|         PCIE_DEV_DEBUG_ERROR("pci bus width:%d, offset:0x%x, read size %lu invalid.\n", | ||||
|             width, offset, count); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > rg_pci_dev->bar_len - offset) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("read count out of range. input len:%lu, read len:%u.\n", | ||||
|             count, rg_pci_dev->bar_len - offset); | ||||
|         count = rg_pci_dev->bar_len - offset; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < count; i += width) { | ||||
|         val = pci_dev_getreg(rg_pci_dev, offset + i); | ||||
|         for (j = 0; (j < width) && (i + j < count); j++) { | ||||
|             buf[i + j] = (val >> (8 * j)) & 0xff; | ||||
|         } | ||||
|     } | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| static ssize_t pci_dev_read(struct file *file, char __user *buf, size_t count, loff_t *offset) | ||||
| { | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     int ret, read_len; | ||||
|     u8 buf_tmp[PCI_RDWR_MAX_LEN]; | ||||
|  | ||||
|     rg_pci_dev = file->private_data; | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("rg_pci_dev is NULL, read failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("Invalid params, read count is 0.n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > sizeof(buf_tmp)) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("read conut %lu exceed max %lu.\n", count, sizeof(buf_tmp)); | ||||
|         count = sizeof(buf_tmp); | ||||
|     } | ||||
|  | ||||
|     memset(buf_tmp, 0, sizeof(buf_tmp)); | ||||
|     read_len = pci_dev_read_tmp(rg_pci_dev, *offset, buf_tmp, count); | ||||
|     if (read_len < 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("pci_dev_read_tmp failed, ret:%d.\n", read_len); | ||||
|         return read_len; | ||||
|     } | ||||
|     if (access_ok(buf, read_len)) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("user space read, buf: %p, offset: %lld, read conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         if (copy_to_user(buf, buf_tmp, read_len)) { | ||||
|             PCIE_DEV_DEBUG_ERROR("copy_to_user failed.\n"); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } else { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("kernel space read, buf: %p, offset: %lld, read conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         memcpy(buf, buf_tmp, read_len); | ||||
|     } | ||||
|     *offset += read_len; | ||||
|     ret = read_len; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static ssize_t pci_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     PCIE_DEV_DEBUG_VERBOSE("pci_dev_read_iter, file: %p, count: %lu, offset: %lld\n", | ||||
|         iocb->ki_filp, to->count, iocb->ki_pos); | ||||
|     ret = pci_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int pci_dev_write_tmp(rg_pci_dev_t *rg_pci_dev, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     int width, i, j; | ||||
|     u32 val; | ||||
|  | ||||
|     if (offset > rg_pci_dev->bar_len) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("offset:0x%x, bar len:0x%x, EOF.\n", offset, rg_pci_dev->bar_len); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     width = rg_pci_dev->bus_width; | ||||
|  | ||||
|     if (offset % width) { | ||||
|         PCIE_DEV_DEBUG_ERROR("pci bus width:%d, offset:0x%x, read size %lu invalid.\n", | ||||
|             width, offset, count); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > rg_pci_dev->bar_len - offset) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("write count out of range. input len:%lu, write len:%u.\n", | ||||
|             count, rg_pci_dev->bar_len - offset); | ||||
|         count = rg_pci_dev->bar_len - offset; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < count; i += width) { | ||||
|         val = 0; | ||||
|         for (j = 0; (j < width) && (i + j < count); j++) { | ||||
|             val |= buf[i + j] << (8 * j); | ||||
|         } | ||||
|         pci_dev_setreg(rg_pci_dev, i + offset, val); | ||||
|     } | ||||
|  | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| static ssize_t pci_dev_write(struct file *file, const char __user *buf, size_t count, | ||||
|                    loff_t *offset) | ||||
| { | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     u8 buf_tmp[PCI_RDWR_MAX_LEN]; | ||||
|     int write_len; | ||||
|  | ||||
|     rg_pci_dev = file->private_data; | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("rg_pci_dev is NULL, write failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count == 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("Invalid params, write count is 0.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (count > sizeof(buf_tmp)) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("write conut %lu exceed max %lu.\n", count, sizeof(buf_tmp)); | ||||
|         count = sizeof(buf_tmp); | ||||
|     } | ||||
|  | ||||
|     memset(buf_tmp, 0, sizeof(buf_tmp)); | ||||
|     if (access_ok(buf, count)) { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("user space write, buf: %p, offset: %lld, write conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         if (copy_from_user(buf_tmp, buf, count)) { | ||||
|             PCIE_DEV_DEBUG_ERROR("copy_from_user failed.\n"); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|     } else { | ||||
|         PCIE_DEV_DEBUG_VERBOSE("kernel space write, buf: %p, offset: %lld, write conut %lu.\n", | ||||
|             buf, *offset, count); | ||||
|         memcpy(buf_tmp, buf, count); | ||||
|     } | ||||
|  | ||||
|     write_len = pci_dev_write_tmp(rg_pci_dev, *offset, buf_tmp, count); | ||||
|     if (write_len < 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("pci_dev_write_tmp failed, ret:%d.\n", write_len); | ||||
|         return write_len; | ||||
|     } | ||||
|  | ||||
|     *offset += write_len; | ||||
|     return write_len; | ||||
| } | ||||
|  | ||||
| static ssize_t pci_dev_write_iter(struct kiocb *iocb, struct iov_iter *from) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     PCIE_DEV_DEBUG_VERBOSE("pci_dev_write_iter, file: %p, count: %lu, offset: %lld\n", | ||||
|         iocb->ki_filp, from->count, iocb->ki_pos); | ||||
|     ret = pci_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static loff_t pci_dev_llseek(struct file *file, loff_t offset, int origin) | ||||
| { | ||||
|     loff_t ret = 0; | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|  | ||||
|     rg_pci_dev = file->private_data; | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("rg_pci_dev is NULL, llseek failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     switch (origin) { | ||||
|     case SEEK_SET: | ||||
|         if (offset < 0) { | ||||
|             PCIE_DEV_DEBUG_ERROR("SEEK_SET, offset:%lld, invalid.\n", offset); | ||||
|             ret = -EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         if (offset > rg_pci_dev->bar_len) { | ||||
|             PCIE_DEV_DEBUG_ERROR("SEEK_SET out of range, offset:%lld, bar len:0x%x.\n", | ||||
|                 offset, rg_pci_dev->bar_len); | ||||
|             ret = - EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         file->f_pos = offset; | ||||
|         ret = file->f_pos; | ||||
|         break; | ||||
|     case SEEK_CUR: | ||||
|         if (((file->f_pos + offset) > rg_pci_dev->bar_len) || ((file->f_pos + offset) < 0)) { | ||||
|             PCIE_DEV_DEBUG_ERROR("SEEK_CUR out of range, f_ops:%lld, offset:%lld, bar len:0x%x.\n", | ||||
|                 file->f_pos, offset, rg_pci_dev->bar_len); | ||||
|             ret = - EINVAL; | ||||
|             break; | ||||
|         } | ||||
|         file->f_pos += offset; | ||||
|         ret = file->f_pos; | ||||
|         break; | ||||
|     default: | ||||
|         PCIE_DEV_DEBUG_ERROR("unsupport llseek type:%d.\n", origin); | ||||
|         ret = -EINVAL; | ||||
|         break; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static long pci_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||||
| { | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     void __user *argp; | ||||
|     firmware_upg_t *firmware_upg; | ||||
|     int upg_ctrl_base; | ||||
|     int upg_flash_base; | ||||
|  | ||||
|     PCIE_DEV_DEBUG_VERBOSE("ioctl, cmd=0x%02x, arg=0x%02lx\n",cmd, arg); | ||||
|  | ||||
|     rg_pci_dev = file->private_data; | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("rg_pci_dev is NULL, ioctl failed.\n"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     firmware_upg = &rg_pci_dev->firmware_upg; | ||||
|  | ||||
|     argp = (void __user *)arg; | ||||
|  | ||||
|     switch (cmd) { | ||||
|     case GET_FPGA_UPG_CTL_BASE: | ||||
|         if (firmware_upg->upg_ctrl_base < 0) { | ||||
|             PCIE_DEV_DEBUG_ERROR("dts not adaptive upg_ctrl_base\n"); | ||||
|             return -EFAULT; | ||||
|         } else { | ||||
|             upg_ctrl_base = firmware_upg->upg_ctrl_base; | ||||
|             if (copy_to_user(argp, &upg_ctrl_base, sizeof(upg_ctrl_base))) { | ||||
|                 PCIE_DEV_DEBUG_ERROR("upg_ctrl_base copy_from_user failed\n"); | ||||
|                 return -EFAULT; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     case GET_FPGA_UPG_FLASH_BASE: | ||||
|         if (firmware_upg->upg_flash_base < 0) { | ||||
|             PCIE_DEV_DEBUG_ERROR("dts not adaptive upg_flash_base\n"); | ||||
|             return -EFAULT; | ||||
|         } else { | ||||
|             upg_flash_base = firmware_upg->upg_flash_base; | ||||
|             if (copy_to_user(argp, &upg_flash_base, sizeof(upg_flash_base))) { | ||||
|                 PCIE_DEV_DEBUG_ERROR("upg_flash_base copy_from_user failed\n"); | ||||
|                 return -EFAULT; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     default: | ||||
|         PCIE_DEV_DEBUG_ERROR("command unsupported \n"); | ||||
|         return -ENOTTY; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const struct file_operations pcie_dev_fops = { | ||||
|     .owner      = THIS_MODULE, | ||||
|     .llseek     = pci_dev_llseek, | ||||
|     .read_iter  = pci_dev_read_iter, | ||||
|     .write_iter = pci_dev_write_iter, | ||||
|     .unlocked_ioctl = pci_dev_ioctl, | ||||
|     .open       = pci_dev_open, | ||||
|     .release    = pci_dev_release, | ||||
| }; | ||||
|  | ||||
| static rg_pci_dev_t *dev_match(const char *path) | ||||
| { | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     char dev_name[MAX_NAME_SIZE]; | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < MAX_PCIE_NUM; i++) { | ||||
|         if (pcie_dev_arry[i] == NULL) { | ||||
|             continue; | ||||
|         } | ||||
|         rg_pci_dev = pcie_dev_arry[i]; | ||||
|         snprintf(dev_name, MAX_NAME_SIZE,"/dev/%s", rg_pci_dev->name); | ||||
|         if (!strcmp(path, dev_name)) { | ||||
|             PCIE_DEV_DEBUG_VERBOSE("get dev_name = %s, minor = %d\n", dev_name, i); | ||||
|             return rg_pci_dev; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int pcie_device_func_read(const char *path, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     int read_len; | ||||
|  | ||||
|     if (path == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("path NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("buf NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     rg_pci_dev = dev_match(path); | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("i2c_dev match failed. dev path = %s", path); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     read_len = pci_dev_read_tmp(rg_pci_dev, offset, buf, count); | ||||
|     if (read_len < 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("pci_dev_read_tmp failed, ret:%d.\n", read_len); | ||||
|     } | ||||
|     return read_len; | ||||
| } | ||||
| EXPORT_SYMBOL(pcie_device_func_read); | ||||
|  | ||||
| int pcie_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count) | ||||
| { | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     int write_len; | ||||
|  | ||||
|     if (path == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("path NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("buf NULL"); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     rg_pci_dev = dev_match(path); | ||||
|     if (rg_pci_dev == NULL) { | ||||
|         PCIE_DEV_DEBUG_ERROR("i2c_dev match failed. dev path = %s", path); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     write_len = pci_dev_write_tmp(rg_pci_dev, offset, buf, count); | ||||
|     if (write_len < 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("pci_dev_write_tmp failed, ret:%d.\n", write_len); | ||||
|     } | ||||
|     return write_len; | ||||
| } | ||||
| EXPORT_SYMBOL(pcie_device_func_write); | ||||
|  | ||||
| static int pci_setup_bars(rg_pci_dev_t *rg_pci_dev, struct pci_dev *dev) | ||||
| { | ||||
|     int ret; | ||||
|     uint32_t addr, len, flags; | ||||
|  | ||||
|     ret = 0; | ||||
|     addr = pci_resource_start(dev, rg_pci_dev->bar); | ||||
|     len = pci_resource_len(dev, rg_pci_dev->bar); | ||||
|     if (addr == 0 || len == 0) { | ||||
|         PCIE_DEV_DEBUG_ERROR("get bar addr failed. bar:%d, addr:0x%x, len:0x%x.\n", | ||||
|             rg_pci_dev->bar, addr, len); | ||||
|         return -EFAULT; | ||||
|     } | ||||
|     rg_pci_dev->bar_len = len; | ||||
|  | ||||
|     flags = pci_resource_flags(dev, rg_pci_dev->bar); | ||||
|     PCIE_DEV_DEBUG_VERBOSE("bar:%d, flag:0x%08x, phys addr:0x%x, len:0x%x\n", | ||||
|         rg_pci_dev->bar, flags, addr, len); | ||||
|     if (flags & IORESOURCE_MEM) { | ||||
|         rg_pci_dev->bar_flag = IORESOURCE_MEM; | ||||
|         rg_pci_dev->pci_mem_base = ioremap(addr, len); | ||||
|         PCIE_DEV_DEBUG_VERBOSE("pci mem base:%p.\n", rg_pci_dev->pci_mem_base); | ||||
|     } else if (flags & IORESOURCE_IO) { | ||||
|         rg_pci_dev->bar_flag = IORESOURCE_IO; | ||||
|         rg_pci_dev->pci_io_base = addr; | ||||
|         PCIE_DEV_DEBUG_VERBOSE("pci io base:0x%x.\n", rg_pci_dev->pci_io_base); | ||||
|     } else { | ||||
|         PCIE_DEV_DEBUG_ERROR("unknow pci bar flag:0x%08x.\n", flags); | ||||
|         ret = -EINVAL; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int pci_dev_probe(struct platform_device *pdev) | ||||
| { | ||||
|     int ret, devfn; | ||||
|     rg_pci_dev_t *rg_pci_dev; | ||||
|     struct pci_dev *pci_dev; | ||||
|     struct miscdevice *misc; | ||||
|     firmware_upg_t *firmware_upg; | ||||
|     pci_dev_device_t *pci_dev_device; | ||||
|  | ||||
|     rg_pci_dev = devm_kzalloc(&pdev->dev, sizeof(rg_pci_dev_t), GFP_KERNEL); | ||||
|     if (!rg_pci_dev) { | ||||
|         dev_err(&pdev->dev, "devm_kzalloc failed.\n"); | ||||
|         ret = -ENOMEM; | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     firmware_upg = &rg_pci_dev->firmware_upg; | ||||
|  | ||||
|     if (pdev->dev.of_node) { | ||||
|         ret = 0; | ||||
|         ret += of_property_read_string(pdev->dev.of_node, "pci_dev_name", &rg_pci_dev->name); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_domain", &rg_pci_dev->domain); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_bus", &rg_pci_dev->bus); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_slot", &rg_pci_dev->slot); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_fn", &rg_pci_dev->fn); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "pci_bar", &rg_pci_dev->bar); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "bus_width", &rg_pci_dev->bus_width); | ||||
|  | ||||
|         if (ret != 0) { | ||||
|             dev_err(&pdev->dev, "Failed to get dts config, ret:%d.\n", ret); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|  | ||||
|         ret = 0; | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "upg_ctrl_base", &firmware_upg->upg_ctrl_base); | ||||
|         ret += of_property_read_u32(pdev->dev.of_node, "upg_flash_base", &firmware_upg->upg_flash_base); | ||||
|         if (ret != 0) { | ||||
|             PCIE_DEV_DEBUG_VERBOSE("dts don't adaptive fpga upg related, ret:%d.\n", ret); | ||||
|             firmware_upg->upg_ctrl_base  = -1; | ||||
|             firmware_upg->upg_flash_base = -1; | ||||
|         } else { | ||||
|             PCIE_DEV_DEBUG_VERBOSE("upg_ctrl_base:0x%04x, upg_flash_base:0x%02x.\n", | ||||
|                 firmware_upg->upg_ctrl_base, firmware_upg->upg_flash_base); | ||||
|         } | ||||
|     } else { | ||||
|         if (pdev->dev.platform_data == NULL) { | ||||
|             dev_err(&pdev->dev, "Failed to get platform data config.\n"); | ||||
|             return -ENXIO; | ||||
|         } | ||||
|         pci_dev_device = pdev->dev.platform_data; | ||||
|         rg_pci_dev->name = pci_dev_device->pci_dev_name; | ||||
|         rg_pci_dev->domain = pci_dev_device->pci_domain; | ||||
|         rg_pci_dev->bus = pci_dev_device->pci_bus; | ||||
|         rg_pci_dev->slot = pci_dev_device->pci_slot; | ||||
|         rg_pci_dev->fn = pci_dev_device->pci_fn; | ||||
|         rg_pci_dev->bar = pci_dev_device->pci_bar; | ||||
|         rg_pci_dev->bus_width = pci_dev_device->bus_width; | ||||
|         firmware_upg->upg_ctrl_base = pci_dev_device->upg_ctrl_base; | ||||
|         firmware_upg->upg_flash_base = pci_dev_device->upg_flash_base; | ||||
|         PCIE_DEV_DEBUG_VERBOSE("upg_ctrl_base:0x%04x, upg_flash_base:0x%02x.\n", | ||||
|             firmware_upg->upg_ctrl_base, firmware_upg->upg_flash_base); | ||||
|     } | ||||
|  | ||||
|     PCIE_DEV_DEBUG_VERBOSE("name:%s, domain:0x%04x, bus:0x%02x, slot:0x%02x, fn:%u, bar:%u, bus_width:%d.\n", | ||||
|         rg_pci_dev->name, rg_pci_dev->domain, rg_pci_dev->bus, rg_pci_dev->slot, rg_pci_dev->fn, | ||||
|         rg_pci_dev->bar, rg_pci_dev->bus_width); | ||||
|  | ||||
|     devfn = PCI_DEVFN(rg_pci_dev->slot, rg_pci_dev->fn); | ||||
|     pci_dev = pci_get_domain_bus_and_slot(rg_pci_dev->domain, rg_pci_dev->bus, devfn); | ||||
|     if (pci_dev == NULL) { | ||||
|         dev_err(&pdev->dev, "Failed to find pci_dev, domain:0x%04x, bus:0x%02x, devfn:0x%x\n", | ||||
|             rg_pci_dev->domain, rg_pci_dev->bus, devfn); | ||||
|         return -ENXIO; | ||||
|     } | ||||
|     ret = pci_setup_bars(rg_pci_dev, pci_dev); | ||||
|     if (ret != 0) { | ||||
|         dev_err(&pdev->dev, "Failed to get pci bar address.\n"); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if (!rg_pci_dev->setreg || !rg_pci_dev->getreg) { | ||||
|         switch (rg_pci_dev->bus_width) { | ||||
|         case 1: | ||||
|             rg_pci_dev->setreg = pci_dev_setreg_8; | ||||
|             rg_pci_dev->getreg = pci_dev_getreg_8; | ||||
|             break; | ||||
|  | ||||
|         case 2: | ||||
|             rg_pci_dev->setreg = pci_dev_setreg_16; | ||||
|             rg_pci_dev->getreg = pci_dev_getreg_16; | ||||
|             break; | ||||
|  | ||||
|         case 4: | ||||
|             rg_pci_dev->setreg = pci_dev_setreg_32; | ||||
|             rg_pci_dev->getreg = pci_dev_getreg_32; | ||||
|             break; | ||||
|         default: | ||||
|             dev_err(&pdev->dev, "Error: unsupported I/O width (%d).\n", rg_pci_dev->bus_width); | ||||
|             ret = -EINVAL; | ||||
|             goto io_unmap; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     misc = &rg_pci_dev->misc; | ||||
|     misc->minor = MISC_DYNAMIC_MINOR; | ||||
|     misc->name = rg_pci_dev->name; | ||||
|     misc->fops = &pcie_dev_fops; | ||||
|     misc->mode = 0666; | ||||
|     if (misc_register(misc) != 0) { | ||||
|         dev_err(&pdev->dev, "Failed to register %s device.\n", misc->name); | ||||
|         ret = -ENXIO; | ||||
|         goto io_unmap; | ||||
|     } | ||||
|     if (misc->minor >= MAX_PCIE_NUM) { | ||||
|         dev_err(&pdev->dev, "Error: device minor[%d] more than max pcie num[%d].\n", | ||||
|             misc->minor, MAX_PCIE_NUM); | ||||
|         misc_deregister(misc); | ||||
|         ret = -EINVAL; | ||||
|         goto io_unmap; | ||||
|     } | ||||
|     pcie_dev_arry[misc->minor] = rg_pci_dev; | ||||
|     dev_info(&pdev->dev, "%04x:%02x:%02x.%d[bar%d: %s]: register %s device with minor:%d success.\n", | ||||
|         rg_pci_dev->domain, rg_pci_dev->bus, rg_pci_dev->slot, rg_pci_dev->fn, rg_pci_dev->bar, | ||||
|         rg_pci_dev->bar_flag == IORESOURCE_MEM ? "IORESOURCE_MEM" : "IORESOURCE_IO", | ||||
|         misc->name, misc->minor ); | ||||
|     return 0; | ||||
|  | ||||
| io_unmap: | ||||
|     if (rg_pci_dev->pci_mem_base) { | ||||
|         iounmap(rg_pci_dev->pci_mem_base); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int pci_dev_remove(struct platform_device *pdev) | ||||
| { | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < MAX_PCIE_NUM ; i++) { | ||||
|         if (pcie_dev_arry[i] != NULL) { | ||||
|             if (pcie_dev_arry[i]->pci_mem_base) { | ||||
|                 iounmap(pcie_dev_arry[i]->pci_mem_base); | ||||
|             } | ||||
|             misc_deregister(&pcie_dev_arry[i]->misc); | ||||
|             pcie_dev_arry[i] = NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static struct of_device_id pci_dev_match[] = { | ||||
|     { | ||||
|         .compatible = "ruijie,rg-pci-dev", | ||||
|     }, | ||||
|     {}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, pci_dev_match); | ||||
|  | ||||
| static struct platform_driver rg_pci_dev_driver = { | ||||
|     .probe      = pci_dev_probe, | ||||
|     .remove     = pci_dev_remove, | ||||
|     .driver     = { | ||||
|         .owner  = THIS_MODULE, | ||||
|         .name   = PROXY_NAME, | ||||
|         .of_match_table = pci_dev_match, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static int __init rg_pci_dev_init(void) | ||||
| { | ||||
|     return platform_driver_register(&rg_pci_dev_driver); | ||||
| } | ||||
|  | ||||
| static void __exit rg_pci_dev_exit(void) | ||||
| { | ||||
|     platform_driver_unregister(&rg_pci_dev_driver); | ||||
| } | ||||
|  | ||||
| module_init(rg_pci_dev_init); | ||||
| module_exit(rg_pci_dev_exit); | ||||
| MODULE_DESCRIPTION("pcie device driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| @@ -0,0 +1,23 @@ | ||||
| #ifndef __RG_PCIE_DEV_H__ | ||||
| #define __RG_PCIE_DEV_H__ | ||||
|  | ||||
| #define UPG_TYPE 'U' | ||||
| #define GET_FPGA_UPG_CTL_BASE              _IOR(UPG_TYPE, 0, int) | ||||
| #define GET_FPGA_UPG_FLASH_BASE            _IOR(UPG_TYPE, 1, int) | ||||
|  | ||||
| #define PCI_DEV_NAME_MAX_LEN (64) | ||||
|  | ||||
| typedef struct pci_dev_device_s { | ||||
|     char pci_dev_name[PCI_DEV_NAME_MAX_LEN]; | ||||
|     int pci_domain; | ||||
|     int pci_bus; | ||||
|     int pci_slot; | ||||
|     int pci_fn; | ||||
|     int pci_bar; | ||||
|     int bus_width; | ||||
|     int upg_ctrl_base; | ||||
|     int upg_flash_base; | ||||
|     int device_flag; | ||||
| } pci_dev_device_t; | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,20 @@ | ||||
| pes_parent_dir:=$(shell pwd)/$(lastword $(MAKEFILE_LIST)) | ||||
| pes_parent_dir:=$(shell dirname $(pes_parent_dir)) | ||||
|  | ||||
| SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "build") print $$9}') | ||||
| INC = -I./inc | ||||
|  | ||||
| all : CHECK $(SUBDIRS) | ||||
| CHECK : | ||||
| 	@echo $(pes_parent_dir) | ||||
|  | ||||
| $(SUBDIRS):ECHO | ||||
| 	#@echo $@ | ||||
| 	make -C $@ | ||||
|  | ||||
| ECHO: | ||||
| 	@echo $(SUBDIRS) | ||||
|  | ||||
| .PHONY : clean | ||||
| clean : | ||||
| 	-rm  -rf $(SYSFS_OUT_PUT) | ||||
| @@ -0,0 +1,31 @@ | ||||
| PWD		= $(shell pwd) | ||||
|  | ||||
| EXTRA_CFLAGS:= -I$(M)/include | ||||
| EXTRA_CFLAGS+= -Wall | ||||
| SUBDIR_CFG = cfg | ||||
| rg_plat_dfd-objs := dfd_module.o dfd_fan_driver.o \ | ||||
| dfd_syseeprom_driver.o \ | ||||
| dfd_cpld_driver.o \ | ||||
| dfd_led_driver.o \ | ||||
| dfd_slot_driver.o \ | ||||
| dfd_sensors_driver.o \ | ||||
| dfd_psu_driver.o \ | ||||
| dfd_sff_driver.o \ | ||||
| dfd_sfpbase.o \ | ||||
| $(SUBDIR_CFG)/dfd_cfg.o \ | ||||
| $(SUBDIR_CFG)/dfd_cfg_adapter.o \ | ||||
| $(SUBDIR_CFG)/dfd_cfg_file.o \ | ||||
| $(SUBDIR_CFG)/dfd_cfg_info.o \ | ||||
| $(SUBDIR_CFG)/dfd_cfg_listnode.o \ | ||||
| $(SUBDIR_CFG)/dfd_frueeprom.o \ | ||||
| $(SUBDIR_CFG)/dfd_tlveeprom.o \ | ||||
|  | ||||
| obj-m := rg_plat_dfd.o | ||||
| all: | ||||
| 	$(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules | ||||
| 	@if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi | ||||
| 	cp -p  $(PWD)/*.ko $(module_out_put_dir) | ||||
| clean: | ||||
| 	rm -f $(PWD)/*.o $(PWD)/$(SUBDIR_CFG)/*.o $(PWD)/*.ko $(PWD)/*.mod.c $(PWD)/.*.cmd $(PWD)/$(SUBDIR_CFG)/.*.cmd $(PWD)/*.mod | ||||
| 	rm -f $(PWD)/Module.markers $(PWD)/Module.symvers $(PWD)/modules.order | ||||
| 	rm -rf $(PWD)/.tmp_versions | ||||
| @@ -0,0 +1,815 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2015 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/list.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/uaccess.h> | ||||
|  | ||||
| #include "../include/dfd_module.h" | ||||
| #include "../include/dfd_cfg_file.h" | ||||
| #include "../include/dfd_cfg_listnode.h" | ||||
| #include "../include/dfd_cfg_info.h" | ||||
| #include "../include/dfd_cfg_adapter.h" | ||||
| #include "../include/dfd_cfg.h" | ||||
|  | ||||
| #ifdef DFD_CFG_ITEM | ||||
| #undef DFD_CFG_ITEM | ||||
| #endif | ||||
| #define DFD_CFG_ITEM(_id, _name, _index_min, _index_max)    _name, | ||||
| static char *dfd_cfg_item_name[] = { | ||||
|     DFD_CFG_ITEM_ALL | ||||
| }; | ||||
|  | ||||
| #ifdef DFD_CFG_ITEM | ||||
| #undef DFD_CFG_ITEM | ||||
| #endif | ||||
| #define DFD_CFG_ITEM(_id, _name, _index_min, _index_max)    {_index_min, _index_max}, | ||||
| static index_range_t dfd_cfg_item_index_range[] = { | ||||
|     DFD_CFG_ITEM_ALL | ||||
| }; | ||||
|  | ||||
| static lnode_root_t dfd_ko_cfg_list_root; | ||||
|  | ||||
| static void dfd_ko_cfg_del_space_lf_cr(char *str) | ||||
| { | ||||
|     int i, j; | ||||
|     int len; | ||||
|  | ||||
|     len = strlen(str); | ||||
|     for (i = 0; i < len; i++) { | ||||
|         if (str[i] == '\r' || str[i] == '\n' || str[i] == ' ') { | ||||
|             for (j = i; j < len - 1; j++) { | ||||
|                 str[j] = str[j + 1]; | ||||
|             } | ||||
|             str[j] = '\0'; | ||||
|             len--; | ||||
|             i--; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_get_value_from_char(char *value_str, int32_t *value, int line_num) | ||||
| { | ||||
|     int value_tmp = 0; | ||||
|  | ||||
|     if (strlen(value_str) == 0) { | ||||
|         DBG_DEBUG(DBG_WARN, "line%d: value str is empty\n", line_num); | ||||
|         *value = DFD_CFG_EMPTY_VALUE; | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if ((strlen(value_str) > 2) && (value_str[0] == '0') | ||||
|             && (value_str[1] == 'x' || value_str[1] == 'X')) { | ||||
|         value_tmp = (int32_t)simple_strtol(value_str, NULL, 16); | ||||
|     } else { | ||||
|         value_tmp = (int32_t)simple_strtol(value_str, NULL, 10); | ||||
|     } | ||||
|  | ||||
|     *value = value_tmp; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_index(char *index_str, int *index1, int *index2, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     char *index1_begin_char, *index2_begin_char; | ||||
|  | ||||
|     if (index_str[0] != '_') { | ||||
|         DBG_DEBUG(DBG_ERROR, "line%d: no '-' between name and index1\n", line_num); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     index1_begin_char = index_str; | ||||
|     rv = dfd_ko_cfg_get_value_from_char(++index1_begin_char, index1, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (index2 == NULL) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     index2_begin_char = strchr(index1_begin_char, '_'); | ||||
|     if (index2_begin_char == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "line%d: no '-' between index1 and index2\n", line_num); | ||||
|         return -1; | ||||
|     } else { | ||||
|         rv = dfd_ko_cfg_get_value_from_char(++index2_begin_char, index2, line_num); | ||||
|         if (rv < 0) { | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_check_array_index(index_range_t *index_range, int *index1, int *index2, | ||||
|             int line_num) | ||||
| { | ||||
|  | ||||
|     if ((*index1 < 0) || (*index1 > index_range->index1_max)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "line%d: index1[%d] invalid, max=%d\n", line_num, *index1, | ||||
|             index_range->index1_max); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (index2 == NULL) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if ((*index2 < 0) || (*index2 > index_range->index2_max)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "line%d: index2[%d] invalid, max=%d\n", line_num, *index2, | ||||
|             index_range->index2_max); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_get_index(char *index_str, index_range_t *index_range, int *index1, | ||||
|             int *index2, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|  | ||||
|     if (index_range->index2_max == INDEX_NOT_EXIST) { | ||||
|         index2 = NULL; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_cfg_analyse_index(index_str, index1, index2, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_cfg_check_array_index(index_range, index1, index2, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_add_int_item(int key, int value, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     int *int_cfg; | ||||
|  | ||||
|     int_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key); | ||||
|     if (int_cfg == NULL) { | ||||
|  | ||||
|         int_cfg = (int *)kmalloc(sizeof(int), GFP_KERNEL); | ||||
|         if (int_cfg == NULL) { | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: kmalloc int fail\n", line_num); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         *int_cfg = value; | ||||
|         rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, int_cfg); | ||||
|         if (rv == 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "line%d: add int item[%d] success, key=0x%08x\n", line_num, value, key); | ||||
|         } else { | ||||
|             kfree(int_cfg); | ||||
|             int_cfg = NULL; | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: add int item[%d] fail, key=0x%08x rv=%d \n", line_num, value, key, rv); | ||||
|             return -1; | ||||
|         } | ||||
|     } else { | ||||
|  | ||||
|         DBG_DEBUG(DBG_WARN, "line%d: replace int item[%d->%d], key=0x%08x\n", line_num, *int_cfg, value, key); | ||||
|         *int_cfg = value; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_int_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name, char *arg_value, | ||||
|             char *cfg_pre, index_range_t *index_range, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     int index1 = 0, index2 = 0; | ||||
|     int value, key; | ||||
|     char *arg_name_tmp; | ||||
|  | ||||
|     if (index_range->index1_max != INDEX_NOT_EXIST) { | ||||
|         arg_name_tmp = arg_name + strlen(cfg_pre); | ||||
|         rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num); | ||||
|         if (rv < 0) { | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_cfg_get_value_from_char(arg_value, &value, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(cfg_item_id, index1, index2); | ||||
|     rv = dfd_ko_cfg_add_int_item(key, value, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_add_str_item(int key, char *str, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     char *str_cfg; | ||||
|  | ||||
|     str_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key); | ||||
|     if (str_cfg == NULL) { | ||||
|  | ||||
|         str_cfg = (char *)kmalloc(DFD_CFG_STR_MAX_LEN, GFP_KERNEL); | ||||
|         if (str_cfg == NULL) { | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: kmalloc str[%lu] fail\n", line_num, strlen(str)); | ||||
|             return -1; | ||||
|         } | ||||
|         memset(str_cfg, 0, DFD_CFG_STR_MAX_LEN); | ||||
|         strncpy(str_cfg, str, DFD_CFG_STR_MAX_LEN - 1); | ||||
|  | ||||
|         rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, str_cfg); | ||||
|         if (rv == 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "line%d: add string item[%s] success, key=0x%08x\n", line_num, str_cfg, key); | ||||
|         } else { | ||||
|             kfree(str_cfg); | ||||
|             str_cfg = NULL; | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: add string item[%s] fail, key=0x%08x rv=%d \n", line_num, str_cfg, key, rv); | ||||
|             return -1; | ||||
|         } | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_WARN, "line%d: replace string item[%s->%s], key=0x%08x\n", line_num, str_cfg, str, key); | ||||
|         memset(str_cfg, 0, DFD_CFG_STR_MAX_LEN); | ||||
|         strncpy(str_cfg, str, DFD_CFG_STR_MAX_LEN - 1); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_str_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name, char *arg_value, | ||||
|             char *cfg_pre, index_range_t *index_range, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     int index1 = 0, index2 = 0; | ||||
|     int btree_key; | ||||
|     char *arg_name_tmp; | ||||
|  | ||||
|     if (index_range->index1_max != INDEX_NOT_EXIST) { | ||||
|         arg_name_tmp = arg_name + strlen(cfg_pre); | ||||
|         rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num); | ||||
|         if (rv < 0) { | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (strlen(arg_value) >= DFD_CFG_STR_MAX_LEN) { | ||||
|         DBG_DEBUG(DBG_ERROR, "line%d: string item[%s] is too long \n", line_num, arg_value); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     btree_key = DFD_CFG_KEY(cfg_item_id, index1, index2); | ||||
|     rv = dfd_ko_cfg_add_str_item(btree_key, arg_value, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_get_i2c_dev_member(char *member_str, dfd_i2c_dev_mem_t *member, int line_num) | ||||
| { | ||||
|     dfd_i2c_dev_mem_t mem_index; | ||||
|  | ||||
|     for (mem_index = DFD_I2C_DEV_MEM_BUS; mem_index < DFD_I2C_DEV_MEM_END; mem_index++) { | ||||
|         if (memcmp(member_str, g_dfd_i2c_dev_mem_str[mem_index], | ||||
|                 strlen(g_dfd_i2c_dev_mem_str[mem_index])) == 0) { | ||||
|             *member =  mem_index; | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_ERROR, "line%d: i2c dev member[%s] invalid\n", line_num, member_str); | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static void dfd_ko_cfg_set_i2c_dev_mem_value(dfd_i2c_dev_t *i2c_dev, dfd_i2c_dev_mem_t member, | ||||
|                 int value) | ||||
| { | ||||
|     switch (member) { | ||||
|     case DFD_I2C_DEV_MEM_BUS: | ||||
|         i2c_dev->bus = value; | ||||
|         break; | ||||
|     case DFD_I2C_DEV_MEM_ADDR: | ||||
|         i2c_dev->addr = value; | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_add_i2c_dev_item(int key, dfd_i2c_dev_mem_t member, int value, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     dfd_i2c_dev_t *i2c_dev_cfg; | ||||
|  | ||||
|     i2c_dev_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key); | ||||
|     if (i2c_dev_cfg == NULL) { | ||||
|  | ||||
|         i2c_dev_cfg = (dfd_i2c_dev_t *)kmalloc(sizeof(dfd_i2c_dev_t), GFP_KERNEL); | ||||
|         if (i2c_dev_cfg == NULL) { | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: kmalloc i2c_dev fail\n", line_num); | ||||
|             return -1; | ||||
|         } | ||||
|         memset(i2c_dev_cfg, 0, sizeof(dfd_i2c_dev_t)); | ||||
|  | ||||
|         dfd_ko_cfg_set_i2c_dev_mem_value(i2c_dev_cfg, member, value); | ||||
|         rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, i2c_dev_cfg); | ||||
|         if (rv == 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "line%d: add i2c_dev item[%s=%d] success, key=0x%08x\n", line_num, | ||||
|                 g_dfd_i2c_dev_mem_str[member], value, key); | ||||
|         } else { | ||||
|             kfree(i2c_dev_cfg); | ||||
|             i2c_dev_cfg = NULL; | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: add i2c_dev item[%s=%d] fail, key=0x%08x rv=%d\n", line_num, | ||||
|                 g_dfd_i2c_dev_mem_str[member], value, key, rv); | ||||
|             return -1; | ||||
|         } | ||||
|     } else { | ||||
|  | ||||
|         DBG_DEBUG(DBG_VERBOSE, "line%d: replace i2c_dev item[%s=%d], key=0x%08x\n", line_num, | ||||
|             g_dfd_i2c_dev_mem_str[member], value, key); | ||||
|         dfd_ko_cfg_set_i2c_dev_mem_value(i2c_dev_cfg, member, value); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_i2c_dev_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name, | ||||
|             char *arg_value, char *cfg_pre, index_range_t *index_range, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     int index1 = 0, index2 = 0; | ||||
|     int value, key; | ||||
|     char *arg_name_tmp; | ||||
|     dfd_i2c_dev_mem_t member; | ||||
|  | ||||
|     arg_name_tmp = arg_name + strlen(cfg_pre); | ||||
|     rv = dfd_ko_cfg_get_i2c_dev_member(arg_name_tmp, &member, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (index_range->index1_max != INDEX_NOT_EXIST) { | ||||
|         arg_name_tmp += strlen(g_dfd_i2c_dev_mem_str[member]); | ||||
|         rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num); | ||||
|         if (rv < 0) { | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_cfg_get_value_from_char(arg_value, &value, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(cfg_item_id, index1, index2); | ||||
|     rv = dfd_ko_cfg_add_i2c_dev_item(key, member, value, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_get_enum_value_by_str(char *enum_val_str[], int enum_val_end, char *buf) | ||||
| { | ||||
|     int i; | ||||
|     int enum_val; | ||||
|  | ||||
|     enum_val = DFD_CFG_INVALID_VALUE; | ||||
|     for (i = 0; i < enum_val_end; i++) { | ||||
|         if (memcmp(buf, enum_val_str[i], strlen(enum_val_str[i])) == 0) { | ||||
|             enum_val = i; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return enum_val; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_get_info_ctrl_member(char *member_str, info_ctrl_mem_t *member, int line_num) | ||||
| { | ||||
|     info_ctrl_mem_t mem_index; | ||||
|  | ||||
|     for (mem_index = INFO_CTRL_MEM_MODE; mem_index < INFO_CTRL_MEM_END; mem_index++) { | ||||
|         if (memcmp(member_str, g_info_ctrl_mem_str[mem_index], | ||||
|                 strlen(g_info_ctrl_mem_str[mem_index])) == 0) { | ||||
|             *member =  mem_index; | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_ERROR, "line%d: info ctrl member[%s] invalid\n", line_num, member_str); | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static void dfd_ko_cfg_set_info_ctrl_mem_value(info_ctrl_t *info_ctrl, info_ctrl_mem_t member, | ||||
|                 char *buf_val, int line_num) | ||||
| { | ||||
|     switch (member) { | ||||
|     case INFO_CTRL_MEM_MODE: | ||||
|         info_ctrl->mode = dfd_ko_cfg_get_enum_value_by_str(g_info_ctrl_mode_str, INFO_CTRL_MODE_END, buf_val);; | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_INT_CONS: | ||||
|         dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_cons), line_num); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_SRC: | ||||
|         info_ctrl->src = dfd_ko_cfg_get_enum_value_by_str(g_info_src_str, INFO_SRC_END, buf_val); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_FRMT: | ||||
|         info_ctrl->frmt = dfd_ko_cfg_get_enum_value_by_str(g_info_frmt_str, INFO_FRMT_END, buf_val); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_POLA: | ||||
|         info_ctrl->pola = dfd_ko_cfg_get_enum_value_by_str(g_info_pola_str, INFO_POLA_END, buf_val); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_FPATH: | ||||
|         memset(info_ctrl->fpath, 0, sizeof(info_ctrl->fpath)); | ||||
|         strncpy(info_ctrl->fpath, buf_val, sizeof(info_ctrl->fpath) - 1); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_ADDR: | ||||
|         dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->addr), line_num); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_LEN: | ||||
|         dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->len), line_num); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_BIT_OFFSET: | ||||
|         dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->bit_offset), line_num); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_STR_CONS: | ||||
|         memset(info_ctrl->str_cons, 0, sizeof(info_ctrl->str_cons)); | ||||
|         strncpy(info_ctrl->str_cons, buf_val, sizeof(info_ctrl->str_cons) - 1); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_INT_EXTRA1: | ||||
|         dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_extra1), line_num); | ||||
|         break; | ||||
|     case INFO_CTRL_MEM_INT_EXTRA2: | ||||
|         dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_extra2), line_num); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_add_info_ctrl_item(int key, info_ctrl_mem_t member, char *buf_val, | ||||
|             int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     info_ctrl_t *info_ctrl_cfg; | ||||
|  | ||||
|     info_ctrl_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key); | ||||
|     if (info_ctrl_cfg == NULL) { | ||||
|  | ||||
|         info_ctrl_cfg = (info_ctrl_t *)kmalloc(sizeof(info_ctrl_t), GFP_KERNEL); | ||||
|         if (info_ctrl_cfg == NULL) { | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: kmalloc info_ctrl fail\n", line_num); | ||||
|             return -1; | ||||
|         } | ||||
|         memset(info_ctrl_cfg, 0, sizeof(info_ctrl_t)); | ||||
|  | ||||
|         dfd_ko_cfg_set_info_ctrl_mem_value(info_ctrl_cfg, member, buf_val, line_num); | ||||
|         rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, info_ctrl_cfg); | ||||
|         if (rv == 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "line%d: add info_ctrl item[%s=%s] success, key=0x%08x\n", line_num, | ||||
|                 g_info_ctrl_mem_str[member], buf_val, key); | ||||
|         } else { | ||||
|             kfree(info_ctrl_cfg); | ||||
|             info_ctrl_cfg = NULL; | ||||
|             DBG_DEBUG(DBG_ERROR, "line%d: add info_ctrl item[%s=%s] fail, key=0x%08x rv=%d\n", line_num, | ||||
|                 g_info_ctrl_mem_str[member], buf_val, key, rv); | ||||
|             return -1; | ||||
|         } | ||||
|     } else { | ||||
|  | ||||
|         DBG_DEBUG(DBG_VERBOSE, "line%d: replace info_ctrl item[%s=%s], key=0x%08x\n", line_num, | ||||
|             g_info_ctrl_mem_str[member], buf_val, key); | ||||
|         dfd_ko_cfg_set_info_ctrl_mem_value(info_ctrl_cfg, member, buf_val, line_num); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_info_ctrl_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name, | ||||
|             char *arg_value, char *cfg_pre, index_range_t *index_range, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     int index1 = 0, index2 = 0; | ||||
|     int key; | ||||
|     char *arg_name_tmp; | ||||
|     info_ctrl_mem_t member; | ||||
|  | ||||
|     arg_name_tmp = arg_name + strlen(cfg_pre); | ||||
|     rv = dfd_ko_cfg_get_info_ctrl_member(arg_name_tmp, &member, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (index_range->index1_max != INDEX_NOT_EXIST) { | ||||
|         arg_name_tmp += strlen(g_info_ctrl_mem_str[member]); | ||||
|         rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num); | ||||
|         if (rv < 0) { | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(cfg_item_id, index1, index2); | ||||
|     rv = dfd_ko_cfg_add_info_ctrl_item(key, member, arg_value, line_num); | ||||
|     if (rv < 0) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_config(char *arg_name, char*arg_value, int line_num) | ||||
| { | ||||
|     int i, rv = 0; | ||||
|     int cfg_item_num; | ||||
|  | ||||
|     cfg_item_num = sizeof(dfd_cfg_item_name) / sizeof(dfd_cfg_item_name[0]); | ||||
|     for (i = 0; i < cfg_item_num; i++) { | ||||
|         if (memcmp(arg_name, dfd_cfg_item_name[i], strlen(dfd_cfg_item_name[i])) == 0){ | ||||
|             if (DFD_CFG_ITEM_IS_INT(i)) { | ||||
|                 rv = dfd_ko_cfg_analyse_int_item(i, arg_name, arg_value, dfd_cfg_item_name[i], | ||||
|                     &(dfd_cfg_item_index_range[i]), line_num); | ||||
|             } else if (DFD_CFG_ITEM_IS_STRING(i)) { | ||||
|                 rv = dfd_ko_cfg_analyse_str_item(i, arg_name, arg_value, dfd_cfg_item_name[i], | ||||
|                     &(dfd_cfg_item_index_range[i]), line_num); | ||||
|             } else if (DFD_CFG_ITEM_IS_I2C_DEV(i)) { | ||||
|                 rv = dfd_ko_cfg_analyse_i2c_dev_item(i, arg_name, arg_value, dfd_cfg_item_name[i], | ||||
|                     &(dfd_cfg_item_index_range[i]), line_num); | ||||
|             } else if (DFD_CFG_ITEM_IS_INFO_CTRL(i)) { | ||||
|                 rv = dfd_ko_cfg_analyse_info_ctrl_item(i, arg_name, arg_value, dfd_cfg_item_name[i], | ||||
|                     &(dfd_cfg_item_index_range[i]), line_num); | ||||
|             } else { | ||||
|                 rv = -1; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_cut_config_line(char *config_line, char *arg_name, char *arg_value) | ||||
| { | ||||
|     int i, j = 0, k = 0; | ||||
|     int len, name_value_flag = 0; | ||||
|  | ||||
|     len = strlen(config_line); | ||||
|     for (i = 0; i < len; i++) { | ||||
|         if (config_line[i] == '=') { | ||||
|             name_value_flag = 1; | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         if (name_value_flag == 0) { | ||||
|             arg_name[j++] = config_line[i]; | ||||
|         } else { | ||||
|             arg_value[k++] = config_line[i]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (name_value_flag == 0) { | ||||
|         return -1; | ||||
|     } else { | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_config_line(char *config_line, int line_num) | ||||
| { | ||||
|     int rv; | ||||
|     char arg_name[DFD_CFG_NAME_MAX_LEN] = {0}; | ||||
|     char arg_value[DFD_CFG_VALUE_MAX_LEN] = {0}; | ||||
|  | ||||
|     dfd_ko_cfg_del_space_lf_cr(config_line); | ||||
|  | ||||
|     if (strlen(config_line) == 0) { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "line%d: space line\n", line_num); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if (config_line[0] == '#') { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "line%d: comment line[%s]\n", line_num, config_line); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_cfg_cut_config_line(config_line, arg_name, arg_value); | ||||
|     if (rv < 0) { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "line%d: [%s]no '=' between name and value\n", line_num, config_line); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "line%d: config_line[%s] name[%s] value[%s]\n", line_num, config_line, arg_name, arg_value); | ||||
|     return dfd_ko_cfg_analyse_config(arg_name, arg_value, line_num); | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_analyse_config_file(char *fpath) | ||||
| { | ||||
|     int rv; | ||||
|     int line_num = 1; | ||||
|     kfile_ctrl_t kfile_ctrl; | ||||
|     char config_line[DFD_CFG_CMDLINE_MAX_LEN] = {0}; | ||||
|  | ||||
|     rv = kfile_open(fpath, &kfile_ctrl); | ||||
|     if (rv != KFILE_RV_OK) { | ||||
|         DBG_DEBUG(DBG_ERROR, "open config file[%s] fail, rv=%d\n", fpath, rv); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     while(kfile_gets(config_line, sizeof(config_line), &kfile_ctrl) > 0){ | ||||
|         rv = dfd_ko_cfg_analyse_config_line(config_line, line_num++); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "!!!!file[%s] config line[%d %s] analyse fail\n", fpath, line_num - 1, | ||||
|                 config_line); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         (void)memset(config_line, 0, sizeof(config_line)); | ||||
|  | ||||
|     } | ||||
|     kfile_close(&kfile_ctrl); | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| void *dfd_ko_cfg_get_item(int key) | ||||
| { | ||||
|     return lnode_find_node(&dfd_ko_cfg_list_root, key); | ||||
| } | ||||
|  | ||||
| static void dfd_ko_cfg_print_item(int key, const void *cfg) | ||||
| { | ||||
|     int item_id; | ||||
|     dfd_i2c_dev_t *i2c_dev; | ||||
|     info_ctrl_t *info_ctrl; | ||||
|  | ||||
|     if (cfg == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error\n"); | ||||
|         return; | ||||
|     } | ||||
|     printk(KERN_INFO "**************************\n"); | ||||
|     printk(KERN_INFO "key=0x%08x\n", key); | ||||
|  | ||||
|     item_id = DFD_CFG_ITEM_ID(key); | ||||
|     if (DFD_CFG_ITEM_IS_INT(item_id)) { | ||||
|         printk(KERN_INFO "int=%d\n", *((int *)cfg)); | ||||
|     } else if (DFD_CFG_ITEM_IS_I2C_DEV(item_id)) { | ||||
|         i2c_dev = (dfd_i2c_dev_t *)cfg; | ||||
|         printk(KERN_INFO ".bus=0x%02x\n", i2c_dev->bus); | ||||
|         printk(KERN_INFO ".addr=0x%02x\n", i2c_dev->addr); | ||||
|     } else if (DFD_CFG_ITEM_IS_INFO_CTRL(item_id)) { | ||||
|         info_ctrl = (info_ctrl_t *)cfg; | ||||
|         printk(KERN_INFO ".mode=%s\n", g_info_ctrl_mode_str[info_ctrl->mode]); | ||||
|         printk(KERN_INFO ".int_cons=%d\n", info_ctrl->int_cons); | ||||
|         printk(KERN_INFO ".src=%s\n", g_info_src_str[info_ctrl->src]); | ||||
|         printk(KERN_INFO ".frmt=%s\n", g_info_frmt_str[info_ctrl->frmt]); | ||||
|         printk(KERN_INFO ".pola=%s\n", g_info_pola_str[info_ctrl->pola]); | ||||
|         printk(KERN_INFO ".fpath=%s\n", info_ctrl->fpath); | ||||
|         printk(KERN_INFO ".addr=0x%02x\n", info_ctrl->addr); | ||||
|         printk(KERN_INFO ".len=%d\n", info_ctrl->len); | ||||
|         printk(KERN_INFO ".bit_offset=%d\n", info_ctrl->bit_offset); | ||||
|     } else { | ||||
|         printk(KERN_INFO "item[%d] error!\n", item_id); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void dfd_ko_cfg_show_item(int key) | ||||
| { | ||||
|     void *cfg; | ||||
|  | ||||
|     cfg = lnode_find_node(&dfd_ko_cfg_list_root, key); | ||||
|     if (cfg == 0) { | ||||
|         printk(KERN_INFO "item[0x%08x] not exist\n", key); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     dfd_ko_cfg_print_item(key, cfg); | ||||
| } | ||||
|  | ||||
| static int dfd_get_my_dev_type_by_file(void) | ||||
| { | ||||
|     struct file *fp; | ||||
|     loff_t pos; | ||||
|     int card_type; | ||||
|     char buf[DFD_PID_BUF_LEN]; | ||||
|     int ret; | ||||
|  | ||||
|     fp= filp_open(DFD_PUB_CARDTYPE_FILE, O_RDONLY, 0); | ||||
|     if (IS_ERR(fp)) { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "open file fail!\n"); | ||||
|         return -1; | ||||
|     } | ||||
|     memset(buf, 0, DFD_PID_BUF_LEN); | ||||
|     pos = 0; | ||||
|     ret = kernel_read(fp, buf, DFD_PRODUCT_ID_LENGTH + 1, &pos); | ||||
|     if (ret < 0) { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "kernel_read failed, path=%s, addr=0, size=%d, ret=%d\n", | ||||
|             DFD_PUB_CARDTYPE_FILE, DFD_PRODUCT_ID_LENGTH + 1, ret); | ||||
|         filp_close(fp, NULL); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     card_type = simple_strtoul(buf, NULL, 10); | ||||
|     DBG_DEBUG(DBG_VERBOSE, "card_type 0x%x.\n", card_type); | ||||
|  | ||||
|     filp_close(fp, NULL); | ||||
|     return card_type; | ||||
| } | ||||
|  | ||||
| static int drv_get_my_dev_type(void) | ||||
| { | ||||
|     static int type = -1; | ||||
|  | ||||
|     if (type > 0) { | ||||
|         return type; | ||||
|     } | ||||
|     type = dfd_get_my_dev_type_by_file(); | ||||
|     DBG_DEBUG(DBG_VERBOSE, "ko board type %d\n", type); | ||||
|     return type; | ||||
| } | ||||
|  | ||||
| static int dfd_ko_cfg_init(void) | ||||
| { | ||||
|     int rv; | ||||
|     int card_type; | ||||
|     char file_name[32] = {0}; | ||||
|     char fpath[128] = {0}; | ||||
|     kfile_ctrl_t kfile_ctrl; | ||||
|  | ||||
|     rv = lnode_init_root(&dfd_ko_cfg_list_root); | ||||
|     if (rv < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "init list root fail, rv=%d\n", rv); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     card_type = drv_get_my_dev_type(); | ||||
|     if (card_type > 0) { | ||||
|         snprintf(fpath, sizeof(fpath), "%s0x%x", DFD_KO_CFG_FILE_DIR, card_type); | ||||
|         rv = kfile_open(fpath, &kfile_ctrl); | ||||
|         if (rv != KFILE_RV_OK) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "open config file[%s] fail, rv=%d, maybe not exist\n", | ||||
|                 fpath, rv); | ||||
|  | ||||
|             rv = kfile_open(DFD_KO_CFG_FILE_NAME, &kfile_ctrl); | ||||
|             if (rv != KFILE_RV_OK) { | ||||
|                 DBG_DEBUG(DBG_ERROR, "open config file[%s] fail, rv=%d\n", DFD_KO_CFG_FILE_NAME, | ||||
|                     rv); | ||||
|                 return -1; | ||||
|             } | ||||
|             DBG_DEBUG(DBG_ERROR, "get config file from: %s, success.\n", DFD_KO_CFG_FILE_NAME); | ||||
|         } else { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "get config file from: %s, success.\n", fpath); | ||||
|         } | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "get board id failed, try to get config file from: %s\n", | ||||
|             DFD_KO_CFG_FILE_NAME); | ||||
|  | ||||
|         rv = kfile_open(DFD_KO_CFG_FILE_NAME, &kfile_ctrl); | ||||
|         if (rv != KFILE_RV_OK) { | ||||
|             DBG_DEBUG(DBG_ERROR, "open config file[%s] fail, rv=%d\n", DFD_KO_CFG_FILE_NAME, rv); | ||||
|             return -1; | ||||
|         } | ||||
|         DBG_DEBUG(DBG_ERROR, "get config file from: %s, success.\n", DFD_KO_CFG_FILE_NAME); | ||||
|     } | ||||
|  | ||||
|     while (kfile_gets(file_name, sizeof(file_name), &kfile_ctrl) > 0) { | ||||
|  | ||||
|         dfd_ko_cfg_del_space_lf_cr(file_name); | ||||
|         memset(fpath, 0, sizeof(fpath)); | ||||
|         snprintf(fpath, sizeof(fpath), "%s%s.cfg", DFD_KO_CFG_FILE_DIR, file_name); | ||||
|         DBG_DEBUG(DBG_VERBOSE, ">>>>start parsing config file[%s]\n", fpath); | ||||
|  | ||||
|         rv = dfd_ko_cfg_analyse_config_file(fpath); | ||||
|         if (rv < 0) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     kfile_close(&kfile_ctrl); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int32_t dfd_dev_cfg_init(void) | ||||
| { | ||||
|     return dfd_ko_cfg_init(); | ||||
| } | ||||
|  | ||||
| void dfd_dev_cfg_exit(void) | ||||
| { | ||||
|     lnode_free_list(&dfd_ko_cfg_list_root); | ||||
|     return; | ||||
| } | ||||
| @@ -0,0 +1,354 @@ | ||||
| /* | ||||
|  * Copyright(C) 2015 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/fs.h> | ||||
| #include <linux/slab.h> | ||||
| #include <asm/unistd.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/i2c.h> | ||||
|  | ||||
| #include "../include/dfd_module.h" | ||||
| #include "../include/dfd_cfg_file.h" | ||||
| #include "../include/dfd_cfg.h" | ||||
| #include "../include/dfd_cfg_adapter.h" | ||||
|  | ||||
| char *g_dfd_i2c_dev_mem_str[DFD_I2C_DEV_MEM_END] = { | ||||
|     ".bus", | ||||
|     ".addr", | ||||
| }; | ||||
|  | ||||
| static dfd_i2c_dev_t* dfd_ko_get_cpld_i2c_dev(int sub_slot, int cpld_id) | ||||
| { | ||||
|     int key; | ||||
|     dfd_i2c_dev_t *i2c_dev; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_I2C_DEV, sub_slot, cpld_id); | ||||
|     i2c_dev = dfd_ko_cfg_get_item(key); | ||||
|     if (i2c_dev == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get cpld[%d] i2c dev config fail, key=0x%08x\n", cpld_id, key); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     return i2c_dev; | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_i2c_smbus_transfer(int read_write, int bus, int addr, int offset, uint8_t *buf, uint32_t size) | ||||
| { | ||||
|     int rv; | ||||
|     struct i2c_adapter *i2c_adap; | ||||
|     union i2c_smbus_data data; | ||||
|  | ||||
|     i2c_adap = i2c_get_adapter(bus); | ||||
|     if (i2c_adap == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get i2c bus[%d] adapter fail\n", bus); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     if (read_write == I2C_SMBUS_WRITE) { | ||||
|         data.byte = *buf; | ||||
|     } else { | ||||
|         data.byte = 0; | ||||
|     } | ||||
|     rv = i2c_smbus_xfer(i2c_adap, addr, 0, read_write, offset, I2C_SMBUS_BYTE_DATA, &data); | ||||
|     if (rv < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "i2c dev[bus=%d addr=0x%x offset=0x%x size=%d rw=%d] transfer fail, rv=%d\n", | ||||
|             bus, addr, offset, size, read_write, rv); | ||||
|         rv = -DFD_RV_DEV_FAIL; | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "i2c dev[bus=%d addr=0x%x offset=0x%x size=%d rw=%d] transfer success\n", | ||||
|             bus, addr, offset, size, read_write); | ||||
|         rv = DFD_RV_OK; | ||||
|     } | ||||
|  | ||||
|     if (read_write == I2C_SMBUS_READ) { | ||||
|         if (rv == DFD_RV_OK) { | ||||
|             *buf = data.byte; | ||||
|         } else { | ||||
|             *buf = 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     i2c_put_adapter(i2c_adap); | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_i2c_read_data(int bus, int addr, int offset, uint8_t *buf, uint32_t size) | ||||
| { | ||||
|     int i, rv; | ||||
|     for (i = 0; i < DFD_KO_CPLD_I2C_RETRY_TIMES; i++) { | ||||
|         rv = dfd_ko_i2c_smbus_transfer(I2C_SMBUS_READ, bus, addr, offset, buf, size); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "[%d]cpld read[offset=0x%x] fail, rv %d\n", i, addr, rv); | ||||
|             msleep(DFD_KO_CPLD_I2C_RETRY_SLEEP); | ||||
|         } else { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "[%d]cpld read[offset=0x%x] success, value=0x%x\n", | ||||
|                 i, addr, *buf); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_i2c_write_data(int bus, int addr, int offset, uint8_t data, uint32_t size) | ||||
| { | ||||
|     int i, rv; | ||||
|     for (i = 0; i < DFD_KO_CPLD_I2C_RETRY_TIMES; i++) { | ||||
|         rv = dfd_ko_i2c_smbus_transfer(I2C_SMBUS_WRITE, bus, addr, offset, &data, size); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "[%d]cpld write[offset=0x%x] fail, rv=%d\n", i, addr, rv); | ||||
|             msleep(DFD_KO_CPLD_I2C_RETRY_SLEEP); | ||||
|         } else { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "[%d]cpld write[offset=0x%x, data=%d] success\n", i, addr, data); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_cpld_i2c_read(int32_t addr, uint8_t *buf) | ||||
| { | ||||
|     int rv; | ||||
|     int sub_slot, cpld_id, cpld_addr; | ||||
|     dfd_i2c_dev_t *i2c_dev; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error\n"); | ||||
|         return -DFD_RV_INDEX_INVALID; | ||||
|     } | ||||
|  | ||||
|     sub_slot = DFD_KO_CPLD_GET_SLOT(addr); | ||||
|     cpld_id = DFD_KO_CPLD_GET_ID(addr); | ||||
|     cpld_addr = DFD_KO_CPLD_GET_INDEX(addr); | ||||
|  | ||||
|     i2c_dev = dfd_ko_get_cpld_i2c_dev(sub_slot, cpld_id); | ||||
|     if (i2c_dev == NULL) { | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|     rv = dfd_ko_i2c_read_data(i2c_dev->bus, i2c_dev->addr, cpld_addr, buf, sizeof(uint8_t)); | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_cpld_i2c_write(int32_t addr, uint8_t data) | ||||
| { | ||||
|     int rv; | ||||
|     int sub_slot, cpld_id, cpld_addr; | ||||
|     dfd_i2c_dev_t *i2c_dev; | ||||
|  | ||||
|     sub_slot = DFD_KO_CPLD_GET_SLOT(addr); | ||||
|     cpld_id = DFD_KO_CPLD_GET_ID(addr); | ||||
|     cpld_addr = DFD_KO_CPLD_GET_INDEX(addr); | ||||
|  | ||||
|     i2c_dev = dfd_ko_get_cpld_i2c_dev(sub_slot, cpld_id); | ||||
|     if (i2c_dev == NULL) { | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_i2c_write_data(i2c_dev->bus, i2c_dev->addr, cpld_addr, data, sizeof(uint8_t)); | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_cpld_io_read(int32_t addr, uint8_t *buf) | ||||
| { | ||||
|     int cpld_id, sub_slot, offset; | ||||
|     int key; | ||||
|     int *tmp; | ||||
|     uint16_t io_port; | ||||
|  | ||||
|     sub_slot = DFD_KO_CPLD_GET_SLOT(addr); | ||||
|     cpld_id = DFD_KO_CPLD_GET_ID(addr); | ||||
|     offset = DFD_KO_CPLD_GET_INDEX(addr); | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_LPC_DEV, sub_slot, cpld_id); | ||||
|     tmp = dfd_ko_cfg_get_item(key); | ||||
|     if (tmp == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR,"get cpld io base config fail, key=0x%08x\n", key); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     io_port = (u16)(*tmp) + offset; | ||||
|     *buf = inb(io_port); | ||||
|     DBG_DEBUG(DBG_VERBOSE, "read cpld io port addr 0x%x, data 0x%x\n", io_port, *buf); | ||||
|  | ||||
|     return DFD_RV_OK; | ||||
|  | ||||
| } | ||||
|  | ||||
| static int32_t dfd_ko_cpld_io_write(int32_t addr, uint8_t data) | ||||
| { | ||||
|     int cpld_id, sub_slot, offset; | ||||
|     int key; | ||||
|     int *tmp; | ||||
|     uint16_t io_port; | ||||
|  | ||||
|     sub_slot = DFD_KO_CPLD_GET_SLOT(addr); | ||||
|     cpld_id = DFD_KO_CPLD_GET_ID(addr); | ||||
|     offset = DFD_KO_CPLD_GET_INDEX(addr); | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_LPC_DEV, sub_slot, cpld_id); | ||||
|     tmp = dfd_ko_cfg_get_item(key); | ||||
|     if (tmp == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get cpld io base config fail, key=0x%08x\n", key); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     io_port = (u16)(*tmp) + offset; | ||||
|     DBG_DEBUG(DBG_VERBOSE, "write cpld io port addr 0x%x, data 0x%x\n", io_port, data); | ||||
|     outb(data, (u16)io_port); | ||||
|  | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| static int dfd_cfg_get_cpld_mode(int sub_slot, int cpld_id, int *mode) | ||||
| { | ||||
|     int key; | ||||
|     char *name; | ||||
|  | ||||
|     if (mode == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error\n"); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_MODE, sub_slot, cpld_id); | ||||
|     name = dfd_ko_cfg_get_item(key); | ||||
|     if (name == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get cpld[%d] mode info ctrl fail, key=0x%08x\n", cpld_id, key); | ||||
|         return -DFD_RV_NODE_FAIL; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "cpld_id %d mode_name %s.\n", cpld_id, name); | ||||
|     if (!strncmp(name, DFD_KO_CPLD_MODE_I2C_STRING, strlen(DFD_KO_CPLD_MODE_I2C_STRING))) { | ||||
|         *mode = DFD_CPLD_MODE_I2C; | ||||
|     } else if (!strncmp(name, DFD_KO_CPLD_MODE_LPC_STRING, strlen(DFD_KO_CPLD_MODE_LPC_STRING))) { | ||||
|         *mode = DFD_CPLD_MODE_LPC; | ||||
|     } else { | ||||
|  | ||||
|         *mode = DFD_CPLD_MODE_I2C; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "cpld_id %d mode %d.\n", cpld_id, *mode); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int32_t dfd_ko_cpld_read(int32_t addr, uint8_t *buf) | ||||
| { | ||||
|     int ret; | ||||
|     int sub_slot, cpld_id; | ||||
|     int cpld_mode; | ||||
|  | ||||
|     sub_slot = DFD_KO_CPLD_GET_SLOT(addr); | ||||
|     cpld_id = DFD_KO_CPLD_GET_ID(addr); | ||||
|  | ||||
|     ret = dfd_cfg_get_cpld_mode(sub_slot, cpld_id, &cpld_mode); | ||||
|     if (ret) { | ||||
|         DBG_DEBUG(DBG_WARN, "drv_get_cpld_mode sub_slot %d cpldid %d faile, set default i2c mode.\n", sub_slot, cpld_id); | ||||
|         cpld_mode = DFD_CPLD_MODE_I2C; | ||||
|     } | ||||
|  | ||||
|     if (cpld_mode == DFD_CPLD_MODE_I2C) { | ||||
|         ret = dfd_ko_cpld_i2c_read(addr, buf); | ||||
|     } else if (cpld_mode == DFD_CPLD_MODE_LPC) { | ||||
|         ret = dfd_ko_cpld_io_read(addr, buf); | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_ERROR, "cpld_mode %d invalid.\n", cpld_mode); | ||||
|         ret = -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "addr 0x%x val 0x%x ret %d\n", addr, *buf, ret); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| int32_t dfd_ko_cpld_write(int32_t addr, uint8_t val) | ||||
| { | ||||
|     int ret; | ||||
|     int sub_slot, cpld_id, cpld_mode; | ||||
|  | ||||
|     sub_slot = DFD_KO_CPLD_GET_SLOT(addr); | ||||
|     cpld_id = DFD_KO_CPLD_GET_ID(addr); | ||||
|  | ||||
|     ret = dfd_cfg_get_cpld_mode(sub_slot, cpld_id, &cpld_mode); | ||||
|     if (ret) { | ||||
|         DBG_DEBUG(DBG_ERROR, "drv_get_cpld_mode sub_slot %d cpldid %d faile, set default local_bus mode.\n", sub_slot, cpld_id); | ||||
|         cpld_mode = DFD_CPLD_MODE_I2C; | ||||
|     } | ||||
|  | ||||
|     if (cpld_mode == DFD_CPLD_MODE_I2C) { | ||||
|         ret = dfd_ko_cpld_i2c_write(addr, val); | ||||
|     } else if (cpld_mode == DFD_CPLD_MODE_LPC) { | ||||
|         ret = dfd_ko_cpld_io_write(addr, val); | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_ERROR, "cpld_mode %d invalid.\n", cpld_mode); | ||||
|         ret = -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "addr 0x%x val 0x%x ret %d\n", addr, val, ret); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| int32_t dfd_ko_i2c_read(int bus, int addr, int offset, uint8_t *buf, uint32_t size) | ||||
| { | ||||
|     int i, rv; | ||||
|  | ||||
|     for (i = 0; i < size; i++) { | ||||
|         rv = dfd_ko_i2c_read_data(bus, addr, offset, &buf[i], sizeof(uint8_t)); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "dfd_ko_i2c_read[bus=%d addr=0x%x offset=0x%x]fail, rv=%d\n", | ||||
|                 bus, addr, offset, rv); | ||||
|             return rv; | ||||
|         } | ||||
|         offset++; | ||||
|     } | ||||
|  | ||||
|     return size; | ||||
| } | ||||
|  | ||||
| int32_t dfd_ko_i2c_write(int bus, int addr, int offset, uint8_t *buf, uint32_t size) | ||||
| { | ||||
|     int i, rv; | ||||
|  | ||||
|     for (i = 0; i < size; i++) { | ||||
|         rv = dfd_ko_i2c_write_data(bus, addr, offset, buf[i], sizeof(uint8_t)); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "dfd_ko_i2c_write[bus=%d addr=0x%x offset=0x%x]fail, rv=%d\n", | ||||
|                 bus, addr, offset, rv); | ||||
|             return rv; | ||||
|         } | ||||
|         offset++; | ||||
|     } | ||||
|  | ||||
|     return size; | ||||
|  | ||||
| } | ||||
|  | ||||
| int32_t dfd_ko_read_file(char *fpath, int32_t addr, uint8_t *val, int32_t read_bytes) | ||||
| { | ||||
|     int32_t ret; | ||||
|     struct file *filp; | ||||
|     loff_t pos; | ||||
|  | ||||
|     if ((fpath == NULL) || (val == NULL) || (addr < 0) || (read_bytes < 0)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error, addr=%d read_bytes=%d\n", addr, read_bytes); | ||||
|         return -DFD_RV_INDEX_INVALID; | ||||
|     } | ||||
|  | ||||
|     filp = filp_open(fpath, O_RDONLY, 0); | ||||
|     if (IS_ERR(filp)){ | ||||
|         DBG_DEBUG(DBG_ERROR, "open file[%s] fail\n", fpath); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     pos = addr; | ||||
|     ret = kernel_read(filp, val, read_bytes, &pos); | ||||
|     if (ret < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "kernel_read failed, path=%s, addr=%d, size=%d, ret=%d\n", fpath, addr, read_bytes, ret); | ||||
|         ret = -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     filp_close(filp, NULL); | ||||
|     return ret; | ||||
| } | ||||
| @@ -0,0 +1,239 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2015s Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <asm/unistd.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/stat.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
|  | ||||
| #include "../include/dfd_cfg_file.h" | ||||
| #include "../include/dfd_module.h" | ||||
|  | ||||
| struct getdents_callback { | ||||
|     struct dir_context ctx; | ||||
|     const char *obj_name; | ||||
|     char *match_name; | ||||
|     int dir_len; | ||||
|     int found; | ||||
| }; | ||||
|  | ||||
| int kfile_open(char *fname, kfile_ctrl_t *kfile_ctrl) | ||||
| { | ||||
|     int ret; | ||||
|     struct file *filp; | ||||
|     loff_t pos; | ||||
|  | ||||
|     if ((fname == NULL) || (kfile_ctrl == NULL)) { | ||||
|         return KFILE_RV_INPUT_ERR; | ||||
|     } | ||||
|  | ||||
|     filp = filp_open(fname, O_RDONLY, 0); | ||||
|     if (IS_ERR(filp)){ | ||||
|         return KFILE_RV_OPEN_FAIL; | ||||
|     } | ||||
|  | ||||
|     kfile_ctrl->size = filp->f_inode->i_size; | ||||
|  | ||||
|     kfile_ctrl->buf = kmalloc(kfile_ctrl->size, GFP_KERNEL); | ||||
|     if (kfile_ctrl->buf == NULL) { | ||||
|         ret = KFILE_RV_MALLOC_FAIL; | ||||
|         goto close_fp; | ||||
|     } | ||||
|     memset(kfile_ctrl->buf, 0, kfile_ctrl->size); | ||||
|  | ||||
|     pos = 0; | ||||
|     ret = kernel_read(filp, kfile_ctrl->buf, kfile_ctrl->size, &pos); | ||||
|     if (ret < 0) { | ||||
|         ret = KFILE_RV_RD_FAIL; | ||||
|         goto free_buf; | ||||
|     } | ||||
|  | ||||
|     kfile_ctrl->pos = 0; | ||||
|  | ||||
|     ret = KFILE_RV_OK; | ||||
|     goto close_fp; | ||||
|  | ||||
| free_buf: | ||||
|     kfree(kfile_ctrl->buf); | ||||
|     kfile_ctrl->buf = NULL; | ||||
|  | ||||
| close_fp: | ||||
|     filp_close(filp, NULL); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void kfile_close(kfile_ctrl_t *kfile_ctrl) | ||||
| { | ||||
|     if (kfile_ctrl == NULL) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     kfile_ctrl->size = 0; | ||||
|     kfile_ctrl->pos = 0; | ||||
|     if (kfile_ctrl->buf) { | ||||
|         kfree(kfile_ctrl->buf); | ||||
|         kfile_ctrl->buf = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| int kfile_gets(char *buf, int buf_size, kfile_ctrl_t *kfile_ctrl) | ||||
| { | ||||
|     int i; | ||||
|     int has_cr = 0; | ||||
|  | ||||
|     if ((buf == NULL) || (buf_size <= 0) || (kfile_ctrl == NULL) || (kfile_ctrl->buf == NULL) | ||||
|             || (kfile_ctrl->size <= 0)) { | ||||
|         return KFILE_RV_INPUT_ERR; | ||||
|     } | ||||
|  | ||||
|     memset(buf, 0, buf_size); | ||||
|     for (i = 0; i < buf_size; i++) { | ||||
|  | ||||
|         if (kfile_ctrl->pos >= kfile_ctrl->size) { | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         if (has_cr) { | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         if (IS_CR(kfile_ctrl->buf[kfile_ctrl->pos])) { | ||||
|             has_cr = 1; | ||||
|         } | ||||
|  | ||||
|         buf[i] = kfile_ctrl->buf[kfile_ctrl->pos]; | ||||
|         kfile_ctrl->pos++; | ||||
|     } | ||||
|  | ||||
|     return i; | ||||
| } | ||||
|  | ||||
| int kfile_read(int32_t addr, char *buf, int buf_size, kfile_ctrl_t *kfile_ctrl) | ||||
| { | ||||
|     int i; | ||||
|  | ||||
|     if ((buf == NULL) || (buf_size <= 0) || (kfile_ctrl == NULL) || (kfile_ctrl->buf == NULL) | ||||
|             || (kfile_ctrl->size <= 0)) { | ||||
|         return KFILE_RV_INPUT_ERR; | ||||
|     } | ||||
|  | ||||
|     if ((addr < 0) || (addr >= kfile_ctrl->size)) { | ||||
|         return KFILE_RV_ADDR_ERR; | ||||
|     } | ||||
|  | ||||
|     memset(buf, 0, buf_size); | ||||
|  | ||||
|     kfile_ctrl->pos = addr; | ||||
|     for (i = 0; i < buf_size; i++) { | ||||
|  | ||||
|         if (kfile_ctrl->pos >= kfile_ctrl->size) { | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         buf[i] = kfile_ctrl->buf[kfile_ctrl->pos]; | ||||
|         kfile_ctrl->pos++; | ||||
|     } | ||||
|  | ||||
|     return i; | ||||
| } | ||||
|  | ||||
| static int kfile_filldir_one(struct dir_context *ctx, const char * name, int len, | ||||
|             loff_t pos, u64 ino, unsigned int d_type) | ||||
| { | ||||
|     struct getdents_callback *buf ; | ||||
|     int result; | ||||
|     buf = container_of(ctx, struct getdents_callback, ctx); | ||||
|     result = 0; | ||||
|     if (strncmp(buf->obj_name, name, strlen(buf->obj_name)) == 0) { | ||||
|         if (buf->dir_len < len) { | ||||
|             DBG_DEBUG(DBG_ERROR, "match ok. dir name:%s, but buf_len %d small than dir len %d.\n", | ||||
|                 name, buf->dir_len, len); | ||||
|             buf->found = 0; | ||||
|             return -1; | ||||
|         } | ||||
|         memset(buf->match_name, 0 , buf->dir_len); | ||||
|         memcpy(buf->match_name, name, len); | ||||
|         buf->found = 1; | ||||
|         result = -1; | ||||
|     } | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| int kfile_iterate_dir(const char *dir_path, const char *obj_name, char *match_name, int len) | ||||
| { | ||||
|     int ret; | ||||
|     struct file *dir; | ||||
|     struct getdents_callback buffer = { | ||||
|         .ctx.actor = kfile_filldir_one, | ||||
|     }; | ||||
|  | ||||
|     if(!dir_path || !obj_name || !match_name) { | ||||
|         DBG_DEBUG(DBG_ERROR, "params error. \n"); | ||||
|         return KFILE_RV_INPUT_ERR; | ||||
|     } | ||||
|     buffer.obj_name = obj_name; | ||||
|     buffer.match_name = match_name; | ||||
|     buffer.dir_len = len; | ||||
|     buffer.found = 0; | ||||
|  | ||||
|     dir = filp_open(dir_path, O_RDONLY, 0); | ||||
|     if (IS_ERR(dir)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "filp_open error, dir path:%s\n", dir_path); | ||||
|         return KFILE_RV_OPEN_FAIL; | ||||
|     } | ||||
|     ret = iterate_dir(dir, &buffer.ctx); | ||||
|     if (buffer.found) { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "match ok, dir name:%s\n", match_name); | ||||
|         filp_close(dir, NULL); | ||||
|         return DFD_RV_OK; | ||||
|     } | ||||
|     filp_close(dir, NULL); | ||||
|     return -DFD_RV_NODE_FAIL; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
|  | ||||
| int kfile_write(char *fpath, int32_t addr, char *buf, int buf_size) | ||||
| { | ||||
|     int ret = KFILE_RV_OK; | ||||
|     struct file *filp; | ||||
|     mm_segment_t old_fs; | ||||
|     int wlen; | ||||
|  | ||||
|     if ((fpath == NULL) || (buf == NULL) || (buf_size <= 0)) { | ||||
|         return KFILE_RV_INPUT_ERR; | ||||
|     } | ||||
|  | ||||
|     if (addr < 0) { | ||||
|         return KFILE_RV_ADDR_ERR; | ||||
|     } | ||||
|  | ||||
|     filp = filp_open(fpath, O_RDWR, 0); | ||||
|     if (IS_ERR(filp)){ | ||||
|         return KFILE_RV_OPEN_FAIL; | ||||
|     } | ||||
|  | ||||
|     old_fs = get_fs(); | ||||
|     set_fs(KERNEL_DS); | ||||
|  | ||||
|     filp->f_op->llseek(filp,0,0); | ||||
|     filp->f_pos = addr; | ||||
|  | ||||
|     wlen = filp->f_op->write(filp, buf, buf_size, &(filp->f_pos)); | ||||
|     if (wlen < 0) { | ||||
|         ret = KFILE_RV_WR_FAIL; | ||||
|     } | ||||
|  | ||||
|     filp->f_op->llseek(filp,0,0); | ||||
|     set_fs(old_fs); | ||||
|     filp_close(filp, NULL); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
| #endif | ||||
| @@ -0,0 +1,590 @@ | ||||
| /* | ||||
|  * Copyright(C) 2013 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/string.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include "../include/dfd_module.h" | ||||
| #include "../include/dfd_cfg_adapter.h" | ||||
| #include "../include/dfd_cfg.h" | ||||
| #include "../include/dfd_cfg_info.h" | ||||
| #include "../include/dfd_cfg_file.h" | ||||
|  | ||||
| #define DFD_HWMON_NAME              "hwmon" | ||||
| #define DFD_GET_CPLD_VOLATGE_CODE_VALUE(value)        ((value >> 4)& 0xfff) | ||||
| #define DFD_GET_CPLD_VOLATGE_REAL_VALUE(code_val, k)  ((code_val * 16 * 33 * k) / ((65536 - 5000) * 10)) | ||||
|  | ||||
| char *g_info_ctrl_mem_str[INFO_CTRL_MEM_END] = { | ||||
|     ".mode", | ||||
|     ".int_cons", | ||||
|     ".src", | ||||
|     ".frmt", | ||||
|     ".pola", | ||||
|     ".fpath", | ||||
|     ".addr", | ||||
|     ".len", | ||||
|     ".bit_offset", | ||||
|     ".str_cons", | ||||
|     ".int_extra1", | ||||
|     ".int_extra2", | ||||
| }; | ||||
|  | ||||
| char *g_info_ctrl_mode_str[INFO_CTRL_MODE_END] = { | ||||
|     "none", | ||||
|     "config", | ||||
|     "constant", | ||||
|     "tlv", | ||||
|     "str_constant", | ||||
| }; | ||||
|  | ||||
| char *g_info_src_str[INFO_SRC_END] = { | ||||
|     "none", | ||||
|     "cpld", | ||||
|     "fpga", | ||||
|     "other_i2c", | ||||
|     "file", | ||||
| }; | ||||
|  | ||||
| char *g_info_frmt_str[INFO_FRMT_END] = { | ||||
|     "none", | ||||
|     "bit", | ||||
|     "byte", | ||||
|     "num_bytes", | ||||
|     "num_str", | ||||
|     "num_buf", | ||||
|     "buf", | ||||
| }; | ||||
|  | ||||
| char *g_info_pola_str[INFO_POLA_END] = { | ||||
|     "none", | ||||
|     "positive", | ||||
|     "negative", | ||||
| }; | ||||
|  | ||||
| static int dfd_read_info_from_cpld(int32_t addr, int read_bytes, uint8_t *val) | ||||
| { | ||||
|     int i, rv; | ||||
|  | ||||
|     for (i = 0; i < read_bytes; i++) { | ||||
|         rv = dfd_ko_cpld_read(addr, &(val[i])); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "read info[addr=0x%x read_bytes=%d] from cpld fail, reading_byte=%d rv=%d\n", | ||||
|                 addr, read_bytes, i, rv); | ||||
|             return rv; | ||||
|         } | ||||
|         addr++; | ||||
|     } | ||||
|  | ||||
|     return read_bytes; | ||||
| } | ||||
|  | ||||
| static int dfd_write_info_to_cpld(int32_t addr, int write_bytes, uint8_t *val, uint8_t bit_mask) | ||||
| { | ||||
|     int rv; | ||||
|     uint8_t val_tmp; | ||||
|  | ||||
|     if (bit_mask != 0xff) { | ||||
|         rv = dfd_ko_cpld_read(addr, &val_tmp); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "read original info[addr=0x%x] from cpld fail, rv=%d\n", addr, rv); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         val_tmp = (val_tmp & (~bit_mask)) | (val[0] & bit_mask); | ||||
|     } else { | ||||
|         val_tmp = val[0]; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_cpld_write(addr, val_tmp); | ||||
|     if (rv < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "write info[addr=0x%x val=0x%x] to cpld fail, rv=%d\n", addr, val_tmp, rv); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_read_info(info_src_t src, char *fpath, int32_t addr, int read_bytes, uint8_t *val) | ||||
| { | ||||
|     int rv = 0; | ||||
|  | ||||
|     switch (src) { | ||||
|     case INFO_SRC_CPLD: | ||||
|         rv = dfd_read_info_from_cpld(addr, read_bytes, val); | ||||
|         break; | ||||
|     case INFO_SRC_FPGA: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "not support read info from fpga\n"); | ||||
|         break; | ||||
|     case INFO_SRC_OTHER_I2C: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "not support read info from other i2c\n"); | ||||
|         break; | ||||
|     case INFO_SRC_FILE: | ||||
|         rv = dfd_ko_read_file(fpath, addr, val, read_bytes); | ||||
|         break; | ||||
|     default: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "info src[%d] error\n", src); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| static int dfd_write_info(info_src_t src, char *fpath, int32_t addr, int write_bytes, uint8_t *val, uint8_t bit_mask) | ||||
| { | ||||
|     int rv = 0; | ||||
|  | ||||
|     switch (src) { | ||||
|     case INFO_SRC_CPLD: | ||||
|         rv = dfd_write_info_to_cpld(addr, write_bytes, val, bit_mask); | ||||
|         break; | ||||
|     case INFO_SRC_FPGA: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "not support write info to fpga\n"); | ||||
|         break; | ||||
|     case INFO_SRC_OTHER_I2C: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "not support write info to other i2c\n"); | ||||
|         break; | ||||
|     case INFO_SRC_FILE: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "not support write info to file\n"); | ||||
|         break; | ||||
|     default: | ||||
|         rv = -1; | ||||
|         DBG_DEBUG(DBG_ERROR, "info src[%d] error\n", src); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return rv; | ||||
| } | ||||
|  | ||||
| int dfd_info_get_int(int key, int *ret, info_num_buf_to_value_f pfun) | ||||
| { | ||||
|     int i, rv; | ||||
|     int read_bytes, readed_bytes, int_tmp; | ||||
|     uint8_t byte_tmp, val[INFO_INT_MAX_LEN + 1] = {0}; | ||||
|     info_ctrl_t *info_ctrl; | ||||
|  | ||||
|     if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key)) || (ret == NULL)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_INDEX_INVALID; | ||||
|     } | ||||
|  | ||||
|     info_ctrl = dfd_ko_cfg_get_item(key); | ||||
|     if (info_ctrl == NULL) { | ||||
|         DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08x\n", key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     if (info_ctrl->mode == INFO_CTRL_MODE_CONS) { | ||||
|         *ret = info_ctrl->int_cons; | ||||
|         return DFD_RV_OK; | ||||
|     } else if (info_ctrl->mode == INFO_CTRL_MODE_TLV) { | ||||
|         return INFO_CTRL_MODE_TLV; | ||||
|     } | ||||
|  | ||||
|     if (IS_INFO_FRMT_BIT(info_ctrl->frmt)) { | ||||
|  | ||||
|         if (!INFO_BIT_OFFSET_VALID(info_ctrl->bit_offset)) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] bit_offsest[%d] invalid\n", | ||||
|                 key, info_ctrl->bit_offset); | ||||
|             return -DFD_RV_TYPE_ERR; | ||||
|         } | ||||
|  | ||||
|         read_bytes = 1; | ||||
|     } else if (IS_INFO_FRMT_BYTE(info_ctrl->frmt) || IS_INFO_FRMT_NUM_STR(info_ctrl->frmt) | ||||
|             || IS_INFO_FRMT_NUM_BUF(info_ctrl->frmt)) { | ||||
|  | ||||
|         if (!INFO_INT_LEN_VALAID(info_ctrl->len)) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] len[%d] invalid\n", key, info_ctrl->len); | ||||
|             return -DFD_RV_TYPE_ERR; | ||||
|         } | ||||
|         read_bytes = info_ctrl->len; | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] info format[%d] error\n", key, info_ctrl->frmt); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     readed_bytes = dfd_read_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, read_bytes, &(val[0])); | ||||
|     if (readed_bytes <= 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "read int info[key=0x%08x src=%s frmt=%s fpath=%s addr=0x%x read_bytes=%d] fail, rv=%d\n", | ||||
|             key, g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], info_ctrl->fpath, | ||||
|             info_ctrl->addr, read_bytes, readed_bytes); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     if (IS_INFO_FRMT_BIT(info_ctrl->frmt)) { | ||||
|  | ||||
|         if (info_ctrl->pola == INFO_POLA_NEGA) { | ||||
|             val[0] = ~val[0]; | ||||
|         } | ||||
|  | ||||
|         byte_tmp = (val[0] >> info_ctrl->bit_offset) & (~(0xff << info_ctrl->len)); | ||||
|  | ||||
|         if (pfun) { | ||||
|             rv = pfun(&byte_tmp, sizeof(byte_tmp), &int_tmp); | ||||
|             if (rv < 0) { | ||||
|                 DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] bit process fail, rv=%d\n", key, rv); | ||||
|                 return rv; | ||||
|             } | ||||
|         } else { | ||||
|             int_tmp = (int)byte_tmp; | ||||
|         } | ||||
|     } else if (IS_INFO_FRMT_BYTE(info_ctrl->frmt)) { | ||||
|  | ||||
|         int_tmp = 0; | ||||
|         for (i = 0; i < info_ctrl->len; i++) { | ||||
|             if (info_ctrl->pola == INFO_POLA_NEGA) { | ||||
|                 int_tmp |=  val[info_ctrl->len - i - 1]; | ||||
|             } else { | ||||
|                 int_tmp |=  val[i]; | ||||
|             } | ||||
|  | ||||
|             if (i != (info_ctrl->len - 1)) { | ||||
|                 int_tmp <<= 8; | ||||
|             } | ||||
|         } | ||||
|     } else if (IS_INFO_FRMT_NUM_STR(info_ctrl->frmt)) { | ||||
|  | ||||
|         val[readed_bytes] = '\0'; | ||||
|         int_tmp = simple_strtol((char *)(&(val[0])), NULL, 10); | ||||
|     } else { | ||||
|         if (pfun == NULL) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] number buf process function is null\n", key); | ||||
|             return -DFD_RV_INDEX_INVALID; | ||||
|         } | ||||
|  | ||||
|         rv = pfun(val, readed_bytes, &int_tmp); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] number buf process fail, rv=%d\n", key, rv); | ||||
|             return rv; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     *ret = int_tmp; | ||||
|     DBG_DEBUG(DBG_VERBOSE, "read int info[key=0x%08x src=%s frmt=%s pola=%s fpath=%s addr=0x%x len=%d bit_offset=%d] success, ret=%d\n", | ||||
|             key, g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], g_info_pola_str[info_ctrl->pola], | ||||
|             info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, info_ctrl->bit_offset, *ret); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_info_get_buf(int key, uint8_t *buf, int buf_len, info_buf_to_buf_f pfun) | ||||
| { | ||||
|     int rv; | ||||
|     int read_bytes, buf_real_len; | ||||
|     uint8_t buf_tmp[INFO_BUF_MAX_LEN]; | ||||
|     info_ctrl_t *info_ctrl; | ||||
|  | ||||
|     if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key)) || (buf == NULL)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_INDEX_INVALID; | ||||
|     } | ||||
|  | ||||
|     info_ctrl = dfd_ko_cfg_get_item(key); | ||||
|     if (info_ctrl == NULL) { | ||||
|         DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08x\n", key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     if (info_ctrl->mode != INFO_CTRL_MODE_CFG) { | ||||
|         DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] mode[%d] invalid\n", key, info_ctrl->mode); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     if (!IS_INFO_FRMT_BUF(info_ctrl->frmt) || !INFO_BUF_LEN_VALAID(info_ctrl->len) | ||||
|             || (buf_len <= info_ctrl->len)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] format=%d or len=%d invlaid, buf_len=%d\n", | ||||
|             key, info_ctrl->frmt, info_ctrl->len, buf_len); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     read_bytes = dfd_read_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, buf_tmp); | ||||
|     if (read_bytes <= 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "read buf info[key=0x%08x src=%s frmt=%s fpath=%s addr=0x%x len=%d] fail, rv=%d\n", | ||||
|             key, g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], info_ctrl->fpath, | ||||
|             info_ctrl->addr, info_ctrl->len, read_bytes); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     if (pfun) { | ||||
|         buf_real_len = buf_len; | ||||
|         rv = pfun(buf_tmp, read_bytes, buf, &buf_real_len); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] buf process fail, rv=%d\n", key, rv); | ||||
|             return -DFD_RV_DEV_NOTSUPPORT; | ||||
|         } | ||||
|     } else { | ||||
|         buf_real_len = read_bytes; | ||||
|         memcpy(buf, buf_tmp, read_bytes); | ||||
|     } | ||||
|  | ||||
|     return buf_real_len; | ||||
| } | ||||
|  | ||||
| static int dfd_2key_info_get_buf(info_ctrl_t *info_ctrl, uint8_t *buf, int buf_len, info_hwmon_buf_f pfun) | ||||
| { | ||||
|     int rv; | ||||
|     int read_bytes, buf_real_len; | ||||
|     uint8_t buf_tmp[INFO_BUF_MAX_LEN]; | ||||
|     char temp_fpath[INFO_FPATH_MAX_LEN]; | ||||
|  | ||||
|     if (!IS_INFO_FRMT_BUF(info_ctrl->frmt) || !INFO_BUF_LEN_VALAID(info_ctrl->len) | ||||
|             || (buf_len <= info_ctrl->len)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "key_path info ctrl format=%d or len=%d invlaid, buf_len=%d\n", | ||||
|             info_ctrl->frmt, info_ctrl->len, buf_len); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     memset(buf_tmp, 0 , sizeof(buf_tmp)); | ||||
|     rv = kfile_iterate_dir(info_ctrl->fpath, DFD_HWMON_NAME, buf_tmp, INFO_BUF_MAX_LEN); | ||||
|     if (rv < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "dir patch:%s ,can find name %s dir \n", | ||||
|             info_ctrl->fpath, DFD_HWMON_NAME); | ||||
|         return -DFD_RV_NO_NODE; | ||||
|     } | ||||
|     memset(temp_fpath, 0 , sizeof(temp_fpath)); | ||||
|     snprintf(temp_fpath, sizeof(temp_fpath), "%s%s/%s", | ||||
|         info_ctrl->fpath, buf_tmp, info_ctrl->str_cons); | ||||
|     DBG_DEBUG(DBG_VERBOSE, "match ok path = %s \n", temp_fpath); | ||||
|  | ||||
|     memset(buf_tmp, 0, sizeof(buf_tmp)); | ||||
|  | ||||
|     read_bytes = dfd_read_info(info_ctrl->src, temp_fpath, info_ctrl->addr, info_ctrl->len, buf_tmp); | ||||
|     if (read_bytes <= 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "read buf info[src=%s frmt=%s fpath=%s addr=0x%x len=%d] fail, rv=%d\n", | ||||
|             g_info_src_str[info_ctrl->src], g_info_src_str[info_ctrl->frmt], temp_fpath, | ||||
|             info_ctrl->addr, info_ctrl->len, read_bytes); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     if (pfun) { | ||||
|         buf_real_len = buf_len; | ||||
|         rv = pfun(buf_tmp, read_bytes, buf, &buf_real_len, info_ctrl); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl buf process fail, rv=%d\n", rv); | ||||
|             return -DFD_RV_DEV_NOTSUPPORT; | ||||
|         } | ||||
|     } else { | ||||
|         buf_real_len = read_bytes; | ||||
|         memcpy(buf, buf_tmp, buf_real_len); | ||||
|     } | ||||
|     return buf_real_len; | ||||
| } | ||||
|  | ||||
| int dfd_info_set_int(int key, int val) | ||||
| { | ||||
|     int rv; | ||||
|     int write_bytes; | ||||
|     uint8_t byte_tmp, bit_mask; | ||||
|     info_ctrl_t *info_ctrl; | ||||
|  | ||||
|     if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key))) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_INDEX_INVALID; | ||||
|     } | ||||
|  | ||||
|     info_ctrl = dfd_ko_cfg_get_item(key); | ||||
|     if (info_ctrl == NULL) { | ||||
|         DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08x\n", key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     if (info_ctrl->mode != INFO_CTRL_MODE_CFG) { | ||||
|         DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] mode[%d] warnning\n", key, info_ctrl->mode); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     if (IS_INFO_FRMT_BIT(info_ctrl->frmt)) { | ||||
|  | ||||
|         if (!INFO_BIT_OFFSET_VALID(info_ctrl->bit_offset)) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] bit_offsest[%d] invalid\n", | ||||
|                 key, info_ctrl->bit_offset); | ||||
|             return -DFD_RV_TYPE_ERR; | ||||
|         } | ||||
|  | ||||
|         write_bytes = 1; | ||||
|  | ||||
|         byte_tmp = (uint8_t)(val & 0xff); | ||||
|         byte_tmp <<= info_ctrl->bit_offset; | ||||
|         if (info_ctrl->pola == INFO_POLA_NEGA) { | ||||
|             byte_tmp = ~byte_tmp; | ||||
|         } | ||||
|  | ||||
|         bit_mask = (~(0xff << info_ctrl->len)) << info_ctrl->bit_offset; | ||||
|     } else if (IS_INFO_FRMT_BYTE(info_ctrl->frmt)) { | ||||
|  | ||||
|         if (!INFO_INT_LEN_VALAID(info_ctrl->len)) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] len[%d] invalid\n", key, info_ctrl->len); | ||||
|             return -DFD_RV_TYPE_ERR; | ||||
|         } | ||||
|  | ||||
|         write_bytes = 1; | ||||
|  | ||||
|         byte_tmp = (uint8_t)(val & 0xff); | ||||
|  | ||||
|         bit_mask = 0xff; | ||||
|     } else if (IS_INFO_FRMT_NUM_STR(info_ctrl->frmt)) { | ||||
|  | ||||
|         DBG_DEBUG(DBG_ERROR, "not support str int set\n"); | ||||
|         return -1; | ||||
|     } else if (IS_INFO_FRMT_NUM_BUF(info_ctrl->frmt)) { | ||||
|  | ||||
|         if (!INFO_INT_LEN_VALAID(info_ctrl->len)) { | ||||
|             DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] len[%d] invalid\n", key, info_ctrl->len); | ||||
|             return -DFD_RV_TYPE_ERR; | ||||
|         } | ||||
|  | ||||
|         write_bytes = 1; | ||||
|  | ||||
|         byte_tmp = (uint8_t)(val & 0xff); | ||||
|  | ||||
|         bit_mask = 0xff; | ||||
|     } else { | ||||
|         DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08x] format[%d] error\n", key, info_ctrl->frmt); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_write_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, write_bytes, | ||||
|             &byte_tmp, bit_mask); | ||||
|     if (rv < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "write int info[src=%s frmt=%s fpath=%s addr=0x%x len=%d val=%d] fail, rv=%d\n", | ||||
|             g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], info_ctrl->fpath, | ||||
|             info_ctrl->addr, info_ctrl->len, val, rv); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "write int info[src=%s frmt=%s pola=%s fpath=%s addr=0x%x len=%d bit_offset=%d val=%d] success\n", | ||||
|             g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], g_info_pola_str[info_ctrl->pola], | ||||
|             info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, info_ctrl->bit_offset, val); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| static int dfd_info_get_cpld_voltage(int key, int *value) | ||||
| { | ||||
|     int rv, addr_tmp; | ||||
|     int vol_ref_tmp, vol_ref; | ||||
|     int vol_curr_tmp, vol_curr; | ||||
|     info_ctrl_t *info_ctrl; | ||||
|  | ||||
|     info_ctrl = dfd_ko_cfg_get_item(key); | ||||
|     if (info_ctrl == NULL) { | ||||
|         DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08x\n", key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|      rv = dfd_info_get_int(key, &vol_curr_tmp, NULL); | ||||
|      if(rv < 0) { | ||||
|          DBG_DEBUG(DBG_ERROR, "get cpld current voltage error, addr:0x%x, rv =%d\n", info_ctrl->addr, rv); | ||||
|          return rv; | ||||
|      } | ||||
|      vol_curr_tmp = DFD_GET_CPLD_VOLATGE_CODE_VALUE(vol_curr_tmp); | ||||
|      if(info_ctrl->addr == info_ctrl->int_extra1) { | ||||
|  | ||||
|          vol_curr = DFD_GET_CPLD_VOLATGE_REAL_VALUE(vol_curr_tmp, info_ctrl->int_extra2); | ||||
|      } else { | ||||
|  | ||||
|          addr_tmp = info_ctrl->addr; | ||||
|          info_ctrl->addr = info_ctrl->int_extra1; | ||||
|          rv = dfd_info_get_int(key, &vol_ref_tmp, NULL); | ||||
|          info_ctrl->addr = addr_tmp; | ||||
|          if(rv < 0) { | ||||
|              DBG_DEBUG(DBG_ERROR, "get cpld reference voltage error, addr:0x%x rv:%d\n", info_ctrl->addr, rv); | ||||
|              return rv; | ||||
|          } | ||||
|          vol_ref = DFD_GET_CPLD_VOLATGE_CODE_VALUE(vol_ref_tmp); | ||||
|          vol_curr = (vol_curr_tmp * info_ctrl->int_extra2) / vol_ref; | ||||
|      } | ||||
|     *value = vol_curr; | ||||
|      return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| static int dfd_info_get_sensor_value(int key, uint8_t *buf, int buf_len, info_hwmon_buf_f pfun) | ||||
| { | ||||
|     int rv, buf_real_len; | ||||
|     int value; | ||||
|     uint8_t buf_tmp[INFO_BUF_MAX_LEN]; | ||||
|     info_ctrl_t *info_ctrl; | ||||
|  | ||||
|     info_ctrl = dfd_ko_cfg_get_item(key); | ||||
|     if (info_ctrl == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get info ctrl fail, key=0x%08x\n", key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     if ( DFD_CFG_ITEM_ID(key) == DFD_CFG_ITEM_HWMON_IN && info_ctrl->src == INFO_SRC_CPLD) { | ||||
|  | ||||
|         rv = dfd_info_get_cpld_voltage(key, &value); | ||||
|         if(rv < 0) { | ||||
|             DBG_DEBUG(DBG_ERROR, "get cpld voltage failed.key=0x%08x, rv:%d\n", key, rv); | ||||
|             return -DFD_RV_DEV_NOTSUPPORT; | ||||
|         } | ||||
|         DBG_DEBUG(DBG_VERBOSE, "get cpld voltage ok, value:%d\n", value); | ||||
|         memset(buf_tmp, 0 ,sizeof(buf_tmp)); | ||||
|         snprintf(buf_tmp, sizeof(buf_tmp), "%d\n", value); | ||||
|         buf_real_len = strlen(buf_tmp); | ||||
|         if(buf_len <= buf_real_len) { | ||||
|             DBG_DEBUG(DBG_ERROR, "length not enough.buf_len:%d,need length:%d\n", buf_len, buf_real_len); | ||||
|             return -DFD_RV_DEV_FAIL; | ||||
|         } | ||||
|         if (pfun) { | ||||
|             buf_real_len = buf_len; | ||||
|             rv = pfun(buf_tmp, strlen(buf_tmp), buf, &buf_real_len, info_ctrl); | ||||
|             if (rv < 0) { | ||||
|                 DBG_DEBUG(DBG_ERROR, "deal date error.org value:%s, buf_len:%d, rv=%d\n", | ||||
|                     buf_tmp, buf_len, rv); | ||||
|                 return -DFD_RV_DEV_NOTSUPPORT; | ||||
|             } | ||||
|         } else { | ||||
|             memcpy(buf, buf_tmp, buf_real_len); | ||||
|         } | ||||
|         return buf_real_len; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_ERROR, "not support mode. key:0x%08x\n", key); | ||||
|     return -DFD_RV_MODE_NOTSUPPORT; | ||||
| } | ||||
|  | ||||
| int dfd_info_get_sensor(uint32_t key, char *buf, int buf_len, info_hwmon_buf_f pfun) | ||||
| { | ||||
|     info_ctrl_t *key_info_ctrl; | ||||
|     int rv; | ||||
|  | ||||
|     if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key)) || | ||||
|         (buf == NULL) || buf_len <= 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "input arguments error, key_path=0x%08x, buf_len:%d.\n", | ||||
|             key, buf_len); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key_info_ctrl = dfd_ko_cfg_get_item(key); | ||||
|     if (key_info_ctrl == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "key_path info error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|     memset(buf, 0 , buf_len); | ||||
|  | ||||
|     if (key_info_ctrl->mode == INFO_CTRL_MODE_SRT_CONS) { | ||||
|         snprintf(buf, buf_len, "%s\n", key_info_ctrl->str_cons); | ||||
|         DBG_DEBUG(DBG_VERBOSE, "get sensor value through string config, key=0x%08x, value:%s\n", key, buf); | ||||
|         return strlen(buf); | ||||
|     } | ||||
|  | ||||
|     if (key_info_ctrl->mode == INFO_CTRL_MODE_CFG && key_info_ctrl->src == INFO_SRC_FILE) { | ||||
|         DBG_DEBUG(DBG_VERBOSE, "get sensor value through hwmon, key:0x%08x\n", key); | ||||
|         rv = dfd_2key_info_get_buf(key_info_ctrl, buf, buf_len, pfun); | ||||
|         if (rv < 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "get sensor value through hwmon failed, key:0x%08x, rv:%d\n", key, rv); | ||||
|         } | ||||
|         return rv; | ||||
|     } | ||||
|     rv = dfd_info_get_sensor_value(key, buf, buf_len, pfun); | ||||
|     if( rv < 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get sensor value failed, key=0x%08x, rv:%d.\n", key, rv); | ||||
|     } | ||||
|     return rv; | ||||
| } | ||||
| @@ -0,0 +1,85 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2015 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/list.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include "../include/dfd_cfg_listnode.h" | ||||
|  | ||||
| void *lnode_find_node(lnode_root_t *root, int key) | ||||
| { | ||||
|     lnode_node_t *lnode; | ||||
|  | ||||
|     if (root == NULL){ | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     list_for_each_entry(lnode, &(root->root), lst) { | ||||
|         if (lnode->key == key) { | ||||
|             return lnode->data; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| int lnode_insert_node(lnode_root_t *root, int key, void *data) | ||||
| { | ||||
|     lnode_node_t *lnode; | ||||
|     void *data_tmp; | ||||
|  | ||||
|     if ((root == NULL) || (data == NULL)) { | ||||
|         return LNODE_RV_INPUT_ERR; | ||||
|     } | ||||
|  | ||||
|     data_tmp = lnode_find_node(root, key); | ||||
|     if (data_tmp != NULL) { | ||||
|         return LNODE_RV_NODE_EXIST; | ||||
|     } | ||||
|  | ||||
|     lnode = kmalloc(sizeof(lnode_node_t), GFP_KERNEL); | ||||
|     if (lnode == NULL) { | ||||
|         return LNODE_RV_NOMEM; | ||||
|     } | ||||
|  | ||||
|     lnode->key = key; | ||||
|     lnode->data = data; | ||||
|     list_add_tail(&(lnode->lst), &(root->root)); | ||||
|  | ||||
|     return LNODE_RV_OK; | ||||
| } | ||||
|  | ||||
| int lnode_init_root(lnode_root_t *root) | ||||
| { | ||||
|     if (root == NULL) { | ||||
|         return LNODE_RV_INPUT_ERR; | ||||
|     } | ||||
|  | ||||
|     INIT_LIST_HEAD(&(root->root)); | ||||
|  | ||||
|     return LNODE_RV_OK; | ||||
| } | ||||
|  | ||||
| void lnode_free_list(lnode_root_t *root) | ||||
| { | ||||
|     lnode_node_t *lnode, *lnode_next; | ||||
|  | ||||
|     if (root == NULL){ | ||||
|         return ; | ||||
|     } | ||||
|  | ||||
|     list_for_each_entry_safe(lnode, lnode_next, &(root->root), lst) { | ||||
|         if ( lnode->data ) { | ||||
|             kfree(lnode->data); | ||||
|             lnode->data = NULL; | ||||
|             lnode->key = 0; | ||||
|         } | ||||
|         list_del(&lnode->lst); | ||||
|         kfree(lnode); | ||||
|         lnode = NULL; | ||||
|     } | ||||
|  | ||||
|     return ; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,496 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2012 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/slab.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/string.h> | ||||
|  | ||||
| #include "../include/dfd_frueeprom.h" | ||||
| #include "../include/dfd_cfg_adapter.h" | ||||
| #include "../include/dfd_module.h" | ||||
| #include "../../rg_dev_sysfs/include/rg_sysfs_common.h" | ||||
|  | ||||
| int g_dfd_fru_dbg_level = 0; | ||||
| module_param(g_dfd_fru_dbg_level, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| /** | ||||
|  * Takes the pointer to stream of bytes and length | ||||
|  * and returns the 8 bit checksum | ||||
|  * This algo is per IPMI V2.0 spec | ||||
|  */ | ||||
| static unsigned char ipmi_calculate_crc(const unsigned char *data, size_t len) | ||||
| { | ||||
|     char crc = 0; | ||||
|     size_t byte = 0; | ||||
|  | ||||
|     for(byte = 0; byte < len; byte++) | ||||
|     { | ||||
|         crc += *data++; | ||||
|     } | ||||
|  | ||||
|     return(-crc); | ||||
| } | ||||
|  | ||||
| /* Validates the data for crc and mandatory fields */ | ||||
| static int ipmi_verify_fru_data(const uint8_t *data, const size_t len) | ||||
| { | ||||
|     uint8_t checksum = 0; | ||||
|     int rc = -DFD_RV_TYPE_ERR; | ||||
|  | ||||
|     /* Validate for first byte to always have a value of [1] */ | ||||
|     if(data[0] != IPMI_FRU_HDR_BYTE_ZERO) | ||||
|     { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid entry:[%d] in byte-0\n",data[0]); | ||||
|         return rc; | ||||
|     } else { | ||||
|         DBG_FRU_DEBUG(DBG_VERBOSE, "SUCCESS: Validated [0x%X] in entry_1 of fru_data\n",data[0]); | ||||
|     } | ||||
|  | ||||
|     /* See if the calculated CRC matches with the embedded one. | ||||
|      * CRC to be calculated on all except the last one that is CRC itself.*/ | ||||
|     checksum = ipmi_calculate_crc(data, len - 1); | ||||
|     if(checksum != data[len-1]) | ||||
|     { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Checksum mismatch." | ||||
|                 " Calculated:[0x%X], Embedded:[0x%X]\n", | ||||
|                 checksum, data[len - 1]); | ||||
|         return rc; | ||||
|     } else { | ||||
|         DBG_FRU_DEBUG(DBG_VERBOSE, "SUCCESS: Checksum matches:[0x%X]\n",checksum); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /* private method to parse type/length */ | ||||
| static int ipmi_parse_type_length (const void *areabuf, | ||||
|                     unsigned int areabuflen, | ||||
|                     unsigned int current_area_offset, | ||||
|                     uint8_t *number_of_data_bytes, | ||||
|                     ipmi_fru_field_t *field) | ||||
| { | ||||
|     const uint8_t *areabufptr = (const uint8_t*) areabuf; | ||||
|     uint8_t type_length; | ||||
|     uint8_t type_code; | ||||
|  | ||||
|     type_length = areabufptr[current_area_offset]; | ||||
|  | ||||
|     /* ipmi workaround | ||||
|      * | ||||
|      * dell p weredge r610 | ||||
|      * | ||||
|      * my reading of the fru spec is that all non-custom fields are | ||||
|      * required to be listed by the vendor.  however, on this | ||||
|      * motherboard, some areas list this, indicating that there is | ||||
|      * no more data to be parsed.  so now, for "required" fields, i | ||||
|      * check to see if the type-length field is a sentinel before | ||||
|      * calling this function. | ||||
|      */ | ||||
|  | ||||
|     type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT; | ||||
|     (*number_of_data_bytes) = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK; | ||||
|  | ||||
|     /* special case: this shouldn't be a length of 0x01 (see type/length | ||||
|      * byte format in fru information storage definition). | ||||
|      */ | ||||
|     DBG_FRU_DEBUG(DBG_VERBOSE, "areabuflen:%d, current_area_offset:0x%x, type_code:0x%x, number_of_data_bytes:%d\n", | ||||
|             areabuflen, current_area_offset, type_code, *number_of_data_bytes ); | ||||
|     if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE | ||||
|         && (*number_of_data_bytes) == 0x01) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "fru type length error.value:0x%x\n", type_length); | ||||
|         return (-1); | ||||
|     } | ||||
|  | ||||
|     if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "buf length error. current_area_offset:0x%x, need length:%d, total length:0x%x\n", | ||||
|             current_area_offset, *number_of_data_bytes, areabuflen ); | ||||
|         return (-1); | ||||
|     } | ||||
|  | ||||
|     if (field) { | ||||
|         memset (field->type_length_field, '\0', IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX); | ||||
|         memcpy (field->type_length_field, &areabufptr[current_area_offset + 1], *number_of_data_bytes); | ||||
|         DBG_FRU_DEBUG(DBG_VERBOSE, "fru parse ok. value:%s\n", field->type_length_field); | ||||
|         field->type_length_field_length = *number_of_data_bytes; | ||||
|     } | ||||
|  | ||||
|     return (0); | ||||
| } | ||||
|  | ||||
| static int ipmi_fru_product_info_area(const void *areabuf, | ||||
|                 unsigned int areabuflen, ipmi_product_info_t *ipmi_product_info) | ||||
| { | ||||
|     const uint8_t *areabufptr = (const uint8_t*) areabuf; | ||||
|     unsigned int area_offset = 2; | ||||
|     uint8_t number_of_data_bytes; | ||||
|     int rv; | ||||
|     ipmi_fru_field_t **ipmi_fru_field_point; | ||||
|     int ipmi_fru_field_len, i; | ||||
|  | ||||
|     if (!areabuf || !areabuflen || !ipmi_product_info) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid Parameter.\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     /* Verify the crc and size */ | ||||
|     rv = ipmi_verify_fru_data(areabuf, areabuflen); | ||||
|     if(rv < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Failed to validate fru product info data\n"); | ||||
|         return rv; | ||||
|     } | ||||
|  | ||||
|     ipmi_fru_field_len = (sizeof(ipmi_product_info_t) - sizeof(uint8_t *)) /(sizeof(ipmi_fru_field_t *)); | ||||
|  | ||||
|     if (ipmi_product_info->language_code) { | ||||
|         (*ipmi_product_info->language_code) = areabufptr[area_offset]; | ||||
|     } | ||||
|     area_offset++; | ||||
|     ipmi_fru_field_point = (ipmi_fru_field_t **)((uint8_t *)ipmi_product_info + sizeof(uint8_t *)); | ||||
|     for(i = 0; i < ipmi_fru_field_len; i++) { | ||||
|         if (*ipmi_fru_field_point) { | ||||
|             memset(*ipmi_fru_field_point, '\0', sizeof(ipmi_fru_field_t)); | ||||
|         } | ||||
|  | ||||
|         if ((areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE) || (area_offset == areabuflen - 1)) { | ||||
|             rv = 0; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         rv = ipmi_parse_type_length(areabufptr, areabuflen, area_offset, &number_of_data_bytes, *ipmi_fru_field_point); | ||||
|         if (rv < 0) { | ||||
|             DBG_FRU_DEBUG(DBG_ERROR, "[%d] _parse_type_length area_offset[%d] rv=%d \n", i, area_offset, rv); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         area_offset += 1;          /* type/length byte */ | ||||
|         area_offset += number_of_data_bytes; | ||||
|         ipmi_fru_field_point++; | ||||
|       } | ||||
|  | ||||
|     return (rv); | ||||
| } | ||||
|  | ||||
| static int ipmi_fru_board_info_area(const void *areabuf, | ||||
|                 unsigned int areabuflen, ipmi_board_info_t *ipmi_board_info) | ||||
| { | ||||
|     const uint8_t *areabufptr = (const uint8_t*) areabuf; | ||||
|     unsigned int area_offset = 2; | ||||
|     uint8_t number_of_data_bytes; | ||||
|     int rv; | ||||
|     ipmi_fru_field_t **ipmi_fru_field_point; | ||||
|     int ipmi_fru_field_len, i; | ||||
|  | ||||
|     if (!areabuf || !areabuflen || !ipmi_board_info) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid Parameter.\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     /* Verify the crc and size */ | ||||
|     rv = ipmi_verify_fru_data(areabuf, areabuflen); | ||||
|     if(rv < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Failed to validate fru product info data\n"); | ||||
|         return rv; | ||||
|     } | ||||
|  | ||||
|     ipmi_fru_field_len = (sizeof(ipmi_board_info_t) - sizeof(uint8_t *) - sizeof(uint8_t *)) /(sizeof(ipmi_fru_field_t *)); | ||||
|  | ||||
|     if (ipmi_board_info->language_code) { | ||||
|         (*ipmi_board_info->language_code) = areabufptr[area_offset]; | ||||
|     } | ||||
|     area_offset++; | ||||
|  | ||||
|     if (ipmi_board_info->mfg_time) { | ||||
|         memcpy(ipmi_board_info->mfg_time, &areabufptr[area_offset], IPMI_FRU_BOARD_INFO_MFG_TIME_LENGTH); | ||||
|     } | ||||
|     area_offset += IPMI_FRU_BOARD_INFO_MFG_TIME_LENGTH; | ||||
|     ipmi_fru_field_point = (ipmi_fru_field_t **)((uint8_t *)ipmi_board_info + sizeof(uint8_t *) + sizeof(uint8_t *)); | ||||
|     for(i = 0; i < ipmi_fru_field_len; i++) { | ||||
|         if (*ipmi_fru_field_point) { | ||||
|             memset(*ipmi_fru_field_point, '\0', sizeof(ipmi_fru_field_t)); | ||||
|         } | ||||
|  | ||||
|         if ((areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE) || (area_offset == areabuflen - 1)) { | ||||
|             rv = 0; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         rv = ipmi_parse_type_length(areabufptr, areabuflen, area_offset, &number_of_data_bytes, *ipmi_fru_field_point); | ||||
|         if (rv < 0) { | ||||
|             DBG_FRU_DEBUG(DBG_ERROR, "[%d] _parse_type_length area_offset[%d] rv=%d \n", i, area_offset, rv); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         area_offset += 1;          /* type/length byte */ | ||||
|         area_offset += number_of_data_bytes; | ||||
|         ipmi_fru_field_point++; | ||||
|       } | ||||
|  | ||||
|     return (rv); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates the fru data per ipmi common header constructs. | ||||
|  * Returns with updated common_hdr and also file_size | ||||
|  */ | ||||
| static int ipmi_validate_common_hdr(const uint8_t *fru_data, const size_t data_len) | ||||
| { | ||||
|     int rc = -1; | ||||
|  | ||||
|     uint8_t common_hdr[sizeof(fru_common_header_t)] = {0}; | ||||
|     if(data_len >= sizeof(common_hdr)) | ||||
|     { | ||||
|         memcpy(common_hdr, fru_data, sizeof(common_hdr)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Incomplete fru data file. Size:[%zd]\n", data_len); | ||||
|         return rc; | ||||
|     } | ||||
|  | ||||
|     /* Verify the crc and size */ | ||||
|     rc = ipmi_verify_fru_data(common_hdr, sizeof(common_hdr)); | ||||
|     if(rc < 0) | ||||
|     { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Failed to validate common header\n"); | ||||
|         return rc; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int dfd_get_frue2prom_info(int bus, int dev_addr, fru_common_header_t *info) | ||||
| { | ||||
|     int ret; | ||||
|     uint8_t fru_common_header_info[sizeof(fru_common_header_t)]; | ||||
|  | ||||
|     if (info == NULL) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_ko_i2c_read(bus, dev_addr, 0, (uint8_t *)info, sizeof(fru_common_header_t)); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Read eeprom head info error(bus: %d, addr: 0x%02x).\n", bus, dev_addr); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     memcpy(fru_common_header_info, (uint8_t *)info, sizeof(fru_common_header_t)); | ||||
|  | ||||
|     if (ipmi_validate_common_hdr(fru_common_header_info, sizeof(fru_common_header_t)) != 0) { | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|  | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| static int dfd_set_fru_product_info(ipmi_product_info_t *ipmi_product_info, ipmi_fru_field_t *vpd_info, int type) | ||||
| { | ||||
|     int ret; | ||||
|     ret = DFD_RV_OK; | ||||
|     if (ipmi_product_info == NULL || vpd_info == NULL) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     memset((uint8_t *)ipmi_product_info, 0, sizeof(ipmi_product_info_t)); | ||||
|     switch(type) { | ||||
|     case DFD_DEV_INFO_TYPE_SN: | ||||
|         ipmi_product_info->product_serial_number = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_NAME: | ||||
|         ipmi_product_info->product_name = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_DEV_TYPE: | ||||
|         ipmi_product_info->product_type_fields = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_HW_INFO: | ||||
|         ipmi_product_info->product_version = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_PART_NAME: | ||||
|         ipmi_product_info->product_part_model_number = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_PART_NUMBER: | ||||
|         ipmi_product_info->product_part_model_number = vpd_info; | ||||
|         break; | ||||
|     default: | ||||
|         ret = -1; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int dfd_set_fru_board_info(ipmi_board_info_t *ipmi_board_info, ipmi_fru_field_t *vpd_info, int type) | ||||
| { | ||||
|     int ret; | ||||
|     ret = DFD_RV_OK; | ||||
|     if (ipmi_board_info == NULL || vpd_info == NULL) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     memset((uint8_t *)ipmi_board_info, 0, sizeof(ipmi_board_info_t)); | ||||
|     switch(type) { | ||||
|     case DFD_DEV_INFO_TYPE_SN: | ||||
|         ipmi_board_info->board_serial_number = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_NAME: | ||||
|         ipmi_board_info->board_product_name = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_HW_INFO: | ||||
|         ipmi_board_info->board_custom_fields = vpd_info; | ||||
|         break; | ||||
|     case DFD_DEV_INFO_TYPE_PART_NUMBER: | ||||
|         ipmi_board_info->board_part_number = vpd_info; | ||||
|         break; | ||||
|     default: | ||||
|         ret = -1; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| int dfd_get_fru_data(int bus, int dev_addr, int type, uint8_t *buf, uint32_t buf_len) | ||||
| { | ||||
|     fru_common_header_t info; | ||||
|     uint8_t *fru_data; | ||||
|     int ret; | ||||
|     uint8_t fru_len; | ||||
|     ipmi_product_info_t ipmi_product_info; | ||||
|     ipmi_fru_field_t vpd_info; | ||||
|     int product_offset; | ||||
|     int fru_len_tmp; | ||||
|  | ||||
|     if (buf == NULL || buf_len <= 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     DBG_FRU_DEBUG(DBG_VERBOSE, "Read fru eeprom (bus: %d, addr: 0x%02x, type:%d, buf: %p, len: %d).\n", | ||||
|                   bus, dev_addr, type, buf, buf_len); | ||||
|  | ||||
|     ret = dfd_get_frue2prom_info(bus, dev_addr, &info); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Read eeprom info head error(bus: %d, addr: 0x%02x, buf: %p, len: %d).\n", | ||||
|                   bus, dev_addr, buf, buf_len); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     product_offset = info.product_offset * IPMI_EIGHT_BYTES; | ||||
|     ret = dfd_ko_i2c_read(bus, dev_addr, product_offset + 1, &fru_len, 1); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "read eeprom info product_offset(bus: %d, addr: 0x%02x, product offset:%d).\n", | ||||
|                   bus, dev_addr, info.product_offset); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     fru_len_tmp = fru_len * IPMI_EIGHT_BYTES; | ||||
|     fru_data = (uint8_t *)kmalloc(sizeof(uint8_t) * fru_len_tmp, GFP_KERNEL); | ||||
|     if (fru_data == NULL) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Allocate buffer(len:%d) error!\n", fru_len_tmp); | ||||
|         return -DFD_RV_NO_MEMORY; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_ko_i2c_read(bus, dev_addr, product_offset, fru_data, fru_len_tmp); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Get FRU data error.\n"); | ||||
|         kfree(fru_data); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     memset((uint8_t *)&vpd_info, 0, sizeof(ipmi_fru_field_t)); | ||||
|     ret = dfd_set_fru_product_info(&ipmi_product_info, &vpd_info, type); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Not support to get info: %d.\n", type); | ||||
|         kfree(fru_data); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     ret = ipmi_fru_product_info_area(fru_data, fru_len_tmp, &ipmi_product_info); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "analysis FRU product info error.\n"); | ||||
|         kfree(fru_data); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     kfree(fru_data); | ||||
|  | ||||
|     buf_len = buf_len < vpd_info.type_length_field_length ? buf_len : vpd_info.type_length_field_length; | ||||
|     memcpy(buf, (uint8_t *)&vpd_info, buf_len); | ||||
|  | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_fru_board_data(int bus, int dev_addr, int type, uint8_t *buf, uint32_t buf_len) | ||||
| { | ||||
|     fru_common_header_t info; | ||||
|     uint8_t *fru_data; | ||||
|     int ret; | ||||
|     uint8_t fru_len; | ||||
|     ipmi_board_info_t ipmi_board_info; | ||||
|     ipmi_fru_field_t vpd_info; | ||||
|     int board_offset; | ||||
|     int fru_len_tmp; | ||||
|  | ||||
|     if (buf == NULL || buf_len <= 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     DBG_FRU_DEBUG(DBG_VERBOSE, "Read fru eeprom (bus: %d, addr: 0x%02x, type:%d, buf: %p, len: %d).\n", | ||||
|                   bus, dev_addr, type, buf, buf_len); | ||||
|  | ||||
|     ret = dfd_get_frue2prom_info(bus, dev_addr, &info); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Read eeprom info head error(bus: %d, addr: 0x%02x, buf: %p, len: %d).\n", | ||||
|                   bus, dev_addr, buf, buf_len); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     board_offset = info.board_offset * IPMI_EIGHT_BYTES; | ||||
|     ret = dfd_ko_i2c_read(bus, dev_addr, board_offset + 1, &fru_len, 1); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "read eeprom info product_offset(bus: %d, addr: 0x%02x, product offset:%d).\n", | ||||
|                   bus, dev_addr, info.board_offset); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     fru_len_tmp = fru_len * IPMI_EIGHT_BYTES; | ||||
|     fru_data = (uint8_t *)kmalloc(sizeof(uint8_t) * fru_len_tmp, GFP_KERNEL); | ||||
|     if (fru_data == NULL) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Allocate buffer(len:%d) error!\n", fru_len_tmp); | ||||
|         return -DFD_RV_NO_MEMORY; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_ko_i2c_read(bus, dev_addr, board_offset, fru_data, fru_len_tmp); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Get FRU data error.\n"); | ||||
|         kfree(fru_data); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     memset((uint8_t *)&vpd_info, 0, sizeof(ipmi_fru_field_t)); | ||||
|     ret = dfd_set_fru_board_info(&ipmi_board_info, &vpd_info, type); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "Not support to get info: %d.\n", type); | ||||
|         kfree(fru_data); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     ret = ipmi_fru_board_info_area(fru_data, fru_len_tmp, &ipmi_board_info); | ||||
|     if (ret < 0) { | ||||
|         DBG_FRU_DEBUG(DBG_ERROR, "analysis FRU product info error.\n"); | ||||
|         kfree(fru_data); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     kfree(fru_data); | ||||
|  | ||||
|     buf_len = buf_len < vpd_info.type_length_field_length ? buf_len : vpd_info.type_length_field_length; | ||||
|     memcpy(buf, (uint8_t *)&vpd_info, buf_len); | ||||
|  | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
| @@ -0,0 +1,474 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2014 FreeIPMI Core Team | ||||
|  * | ||||
|  * 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 3 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. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| /*****************************************************************************\ | ||||
|  *  Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC. | ||||
|  *  Copyright (C) 2007 The Regents of the University of California. | ||||
|  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). | ||||
|  *  Written by Albert Chu <chu11@llnl.gov> | ||||
|  *  UCRL-CODE-232183 | ||||
|  * | ||||
|  *  This file is part of Ipmi-fru, a tool used for retrieving | ||||
|  *  motherboard field replaceable unit (FRU) information. For details, | ||||
|  *  see http://www.llnl.gov/linux/. | ||||
|  * | ||||
|  *  Ipmi-fru 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 3 of the License, or (at your | ||||
|  *  option) any later version. | ||||
|  * | ||||
|  *  Ipmi-fru is distributed in the hope that it will be useful, but | ||||
|  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||||
|  *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | ||||
|  *  for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License along | ||||
|  *  with Ipmi-fru.  If not, see <http://www.gnu.org/licenses/>. | ||||
| \*****************************************************************************/ | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include "../include/dfd_tlveeprom.h" | ||||
| #include "../include/dfd_module.h" | ||||
| #include "../../rg_dev_sysfs/include/rg_sysfs_common.h" | ||||
|  | ||||
| /* using in is_valid_tlvinfo_header */ | ||||
| static uint32_t g_eeprom_size; | ||||
|  | ||||
| /* | ||||
|  *  List of TLV codes and names. | ||||
|  */ | ||||
| static const struct tlv_code_desc tlv_code_list[] = { | ||||
|     { TLV_CODE_PRODUCT_NAME      , "Product Name"}, | ||||
|     { TLV_CODE_PART_NUMBER       , "Part Number"}, | ||||
|     { TLV_CODE_SERIAL_NUMBER     , "Serial Number"}, | ||||
|     { TLV_CODE_MAC_BASE          , "Base MAC Address"}, | ||||
|     { TLV_CODE_MANUF_DATE        , "Manufacture Date"}, | ||||
|     { TLV_CODE_DEVICE_VERSION    , "Device Version"}, | ||||
|     { TLV_CODE_LABEL_REVISION    , "Label Revision"}, | ||||
|     { TLV_CODE_PLATFORM_NAME     , "Platform Name"}, | ||||
|     { TLV_CODE_ONIE_VERSION      , "ONIE Version"}, | ||||
|     { TLV_CODE_MAC_SIZE          , "MAC Addresses"}, | ||||
|     { TLV_CODE_MANUF_NAME        , "Manufacturer"}, | ||||
|     { TLV_CODE_MANUF_COUNTRY     , "Country Code"}, | ||||
|     { TLV_CODE_VENDOR_NAME       , "Vendor Name"}, | ||||
|     { TLV_CODE_DIAG_VERSION      , "Diag Version"}, | ||||
|     { TLV_CODE_SERVICE_TAG       , "Service Tag"}, | ||||
|     { TLV_CODE_VENDOR_EXT        , "Vendor Extension"}, | ||||
|     { TLV_CODE_CRC_32            , "CRC-32"}, | ||||
| }; | ||||
|  | ||||
| #define TLV_CODE_NUM (sizeof(tlv_code_list) / sizeof(tlv_code_list[0])) | ||||
|  | ||||
| const unsigned long g_crc_table[] = { | ||||
|     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | ||||
|     0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | ||||
|     0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | ||||
|     0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | ||||
|     0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | ||||
|     0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | ||||
|     0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | ||||
|     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | ||||
|     0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | ||||
|     0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | ||||
|     0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | ||||
|     0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | ||||
|     0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | ||||
|     0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | ||||
|     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | ||||
|     0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | ||||
|     0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | ||||
|     0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | ||||
|     0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | ||||
|     0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | ||||
|     0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | ||||
|     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | ||||
|     0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | ||||
|     0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | ||||
|     0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | ||||
|     0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | ||||
|     0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | ||||
|     0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | ||||
|     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | ||||
|     0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | ||||
|     0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | ||||
|     0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, | ||||
| }; | ||||
|  | ||||
| static unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len) | ||||
| { | ||||
|     unsigned i; | ||||
|     if (len < 1) | ||||
|         return 0xffffffff; | ||||
|  | ||||
|     for (i = 0; i != len; ++i) | ||||
|     { | ||||
|         crc = g_crc_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); | ||||
|     } | ||||
|  | ||||
|     crc = crc ^ 0xffffffff; | ||||
|  | ||||
|     return crc; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  is_valid_tlv | ||||
|  * | ||||
|  *  Perform basic sanity checks on a TLV field. The TLV is pointed to | ||||
|  *  by the parameter provided. | ||||
|  *      1. The type code is not reserved (0x00 or 0xFF) | ||||
|  */ | ||||
| static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv) | ||||
| { | ||||
|     return ((tlv->type != 0x00) && (tlv->type != 0xFF)); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  is_valid_tlvinfo_header | ||||
|  * | ||||
|  *  Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM | ||||
|  *  data pointed to by the parameter: | ||||
|  *      1. First 8 bytes contain null-terminated ASCII string "TlvInfo" | ||||
|  *      2. Version byte is 1 | ||||
|  *      3. Total length bytes contain value which is less than or equal | ||||
|  *         to the allowed maximum (2048-11) | ||||
|  * | ||||
|  */ | ||||
| static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr) | ||||
| { | ||||
|     int max_size = g_eeprom_size; | ||||
|     return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) && | ||||
|        (hdr->version == TLV_INFO_VERSION) && | ||||
|        (be16_to_cpu(hdr->totallen) <= max_size) ); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  decode_tlv_value | ||||
|  * | ||||
|  *  Decode a single TLV value into a string. | ||||
|  | ||||
|  *  The validity of EEPROM contents and the TLV field have been verified | ||||
|  *  prior to calling this function. | ||||
|  */ | ||||
| static void decode_tlv_value(tlvinfo_tlv_t *tlv, tlv_decode_value_t *decode_value) | ||||
| { | ||||
|     int i; | ||||
|     char *value; | ||||
|     uint32_t length; | ||||
|  | ||||
|     value = (char *)decode_value->value; | ||||
|  | ||||
|     switch (tlv->type) { | ||||
|     case TLV_CODE_PRODUCT_NAME: | ||||
|     case TLV_CODE_PART_NUMBER: | ||||
|     case TLV_CODE_SERIAL_NUMBER: | ||||
|     case TLV_CODE_MANUF_DATE: | ||||
|     case TLV_CODE_LABEL_REVISION: | ||||
|     case TLV_CODE_PLATFORM_NAME: | ||||
|     case TLV_CODE_ONIE_VERSION: | ||||
|     case TLV_CODE_MANUF_NAME: | ||||
|     case TLV_CODE_MANUF_COUNTRY: | ||||
|     case TLV_CODE_VENDOR_NAME: | ||||
|     case TLV_CODE_DIAG_VERSION: | ||||
|     case TLV_CODE_SERVICE_TAG: | ||||
|         memcpy(value, tlv->value, tlv->length); | ||||
|         value[tlv->length] = 0; | ||||
|         length = tlv->length; | ||||
|         break; | ||||
|     case TLV_CODE_MAC_BASE: | ||||
|         length = sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X", | ||||
|                 tlv->value[0], tlv->value[1], tlv->value[2], | ||||
|                 tlv->value[3], tlv->value[4], tlv->value[5]); | ||||
|         break; | ||||
|     case TLV_CODE_DEVICE_VERSION: | ||||
|         length = sprintf(value, "%u", tlv->value[0]); | ||||
|         break; | ||||
|     case TLV_CODE_MAC_SIZE: | ||||
|         length = sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]); | ||||
|         break; | ||||
|     case TLV_CODE_VENDOR_EXT: | ||||
|         value[0] = 0; | ||||
|         length = 0; | ||||
|         for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) { | ||||
|             length += sprintf(value, "%s %02X", value, tlv->value[i]); | ||||
|         } | ||||
|         break; | ||||
|     case TLV_CODE_CRC_32: | ||||
|         length = sprintf(value, "0x%02X%02X%02X%02X", tlv->value[0], | ||||
|                 tlv->value[1], tlv->value[2], tlv->value[3]); | ||||
|         break; | ||||
|     default: | ||||
|         value[0] = 0; | ||||
|         length = 0; | ||||
|         for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) { | ||||
|             length += sprintf(value, "%s 0x%02X", value, tlv->value[i]); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     decode_value->length = length; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  is_checksum_valid | ||||
|  * | ||||
|  *  Validate the checksum in the provided TlvInfo EEPROM data. First, | ||||
|  *  verify that the TlvInfo header is valid, then make sure the last | ||||
|  *  TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data | ||||
|  *  and compare it to the value stored in the EEPROM CRC-32 TLV. | ||||
|  */ | ||||
| static bool is_checksum_valid(uint8_t *eeprom) | ||||
| { | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     tlvinfo_tlv_t *eeprom_crc; | ||||
|     unsigned int calc_crc; | ||||
|     unsigned int stored_crc; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|  | ||||
|     /* Is the eeprom header valid? */ | ||||
|     if (!is_valid_tlvinfo_header(eeprom_hdr)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /* Is the last TLV a CRC? */ | ||||
|     eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) + | ||||
|         be16_to_cpu(eeprom_hdr->totallen) - (sizeof(tlvinfo_tlv_t) + 4)]; | ||||
|     if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /* Calculate the checksum */ | ||||
|     calc_crc = crc32(0xffffffffL, (const unsigned char *)eeprom, sizeof(tlvinfo_header_t) + | ||||
|              be16_to_cpu(eeprom_hdr->totallen) - 4); | ||||
|     stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) | | ||||
|           (eeprom_crc->value[2] <<  8) | eeprom_crc->value[3]); | ||||
|  | ||||
|     return (calc_crc == stored_crc); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  tlvinfo_find_tlv | ||||
|  * | ||||
|  *  This function finds the TLV with the supplied code in the EERPOM. | ||||
|  *  An offset from the beginning of the EEPROM is returned in the | ||||
|  *  eeprom_index parameter if the TLV is found. | ||||
|  */ | ||||
| static bool tlvinfo_find_tlv(uint8_t *eeprom, uint8_t tcode, int *eeprom_index) | ||||
| { | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     tlvinfo_tlv_t    *eeprom_tlv; | ||||
|     int eeprom_end; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|  | ||||
|     /* Search through the TLVs, looking for the first one which matches the | ||||
|      * supplied type code. */ | ||||
|     *eeprom_index = sizeof(tlvinfo_header_t); | ||||
|     eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen); | ||||
|     while (*eeprom_index < eeprom_end) { | ||||
|         eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index]; | ||||
|         if (!is_valid_tlv(eeprom_tlv)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (eeprom_tlv->type == tcode) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  tlvinfo_decode_tlv | ||||
|  * | ||||
|  *  This function finds the TLV with the supplied code in the EERPOM | ||||
|  *  and decodes the value into the buffer provided. | ||||
|  */ | ||||
| static bool tlvinfo_decode_tlv(uint8_t *eeprom, uint8_t tcode, tlv_decode_value_t *decode_value) | ||||
| { | ||||
|     int eeprom_index; | ||||
|     tlvinfo_tlv_t *eeprom_tlv; | ||||
|  | ||||
|     /* Find the TLV and then decode it */ | ||||
|     if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) { | ||||
|         eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index]; | ||||
|         decode_tlv_value(eeprom_tlv, decode_value); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  *  parse_tlv_eeprom | ||||
|  * | ||||
|  *  parse the EEPROM into memory, if it hasn't already been read. | ||||
|  */ | ||||
| int parse_tlv_eeprom(uint8_t *eeprom, uint32_t size) | ||||
| { | ||||
|     unsigned int i; | ||||
|     bool ret; | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     tlv_decode_value_t decode_value; | ||||
|     int j; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|     g_eeprom_size = size; /* eeprom real size */ | ||||
|  | ||||
|     if (!is_valid_tlvinfo_header(eeprom_hdr)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "Failed to check tlv header.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (!is_checksum_valid(eeprom)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "Failed to check tlv crc.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < TLV_CODE_NUM; i++) { | ||||
|         memset((void *)&decode_value, 0, sizeof(tlv_decode_value_t)); | ||||
|         ret = tlvinfo_decode_tlv(eeprom, tlv_code_list[i].m_code, &decode_value); | ||||
|         if (!ret) { | ||||
|             DBG_DEBUG(DBG_ERROR, "No found type: %s\n", tlv_code_list[i].m_name); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         DBG_DEBUG(DBG_VERBOSE, "i: %d,Found type: %s tlv[%d]:%s\n", i, tlv_code_list[i].m_name, tlv_code_list[i].m_code, | ||||
|             decode_value.value); | ||||
|         for (j = 0; j < decode_value.length; j++) { | ||||
|             if ((j % 16) == 0) { | ||||
|                 DBG_DEBUG(DBG_VERBOSE, "\n"); | ||||
|             } | ||||
|             DBG_DEBUG(DBG_VERBOSE, "%02x ", decode_value.value[j]); | ||||
|         } | ||||
|         DBG_DEBUG(DBG_VERBOSE, "\n\n"); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| static int dfd_parse_tlv_eeprom(uint8_t *eeprom, uint32_t size, uint8_t main_type, tlv_decode_value_t *decode_value) | ||||
| { | ||||
|     bool ret; | ||||
|     tlvinfo_header_t *eeprom_hdr; | ||||
|     int j; | ||||
|  | ||||
|     eeprom_hdr = (tlvinfo_header_t *) eeprom; | ||||
|     g_eeprom_size = size; /* eeprom real size */ | ||||
|  | ||||
|     if (!is_valid_tlvinfo_header(eeprom_hdr)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "Failed to check tlv header.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (!is_checksum_valid(eeprom)) { | ||||
|         DBG_DEBUG(DBG_ERROR, "Failed to check tlv crc.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     ret = tlvinfo_decode_tlv(eeprom, main_type, decode_value); | ||||
|     if (!ret) { | ||||
|         DBG_DEBUG(DBG_ERROR, "No found type: %d\n", main_type); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "Found type: %d, value: %s\n", main_type,decode_value->value); | ||||
|     for (j = 0; j < decode_value->length; j++) { | ||||
|         if ((j % 16) == 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "\n"); | ||||
|         } | ||||
|         DBG_DEBUG(DBG_VERBOSE, "%02x ", decode_value->value[j]); | ||||
|     } | ||||
|     DBG_DEBUG(DBG_VERBOSE, "\n\n"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| #if 0 | ||||
|  | ||||
| static int tlvinfo_find_rg_ext_tlv(tlv_decode_value_t *ext_tlv_value, uint8_t ext_type, | ||||
|     uint8_t *buf, uint32_t *buf_len) | ||||
| { | ||||
|     tlvinfo_tlv_t    *eeprom_tlv; | ||||
|     int eeprom_end, eeprom_index; | ||||
|  | ||||
|     /* Search through the TLVs, looking for the first one which matches the | ||||
|      * supplied type code.*/ | ||||
|     DBG_DEBUG(DBG_VERBOSE, "ext_tlv_value->length: %d.\n", ext_tlv_value->length); | ||||
|     for (eeprom_index = 0; eeprom_index < ext_tlv_value->length; eeprom_index++) { | ||||
|         if ((eeprom_index % 16) == 0) { | ||||
|             DBG_DEBUG(DBG_VERBOSE, "\n"); | ||||
|         } | ||||
|         DBG_DEBUG(DBG_VERBOSE, "%02x ", ext_tlv_value->value[eeprom_index]); | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "\n"); | ||||
|  | ||||
|     eeprom_index = 0; | ||||
|     eeprom_end = ext_tlv_value->length; | ||||
|     while (eeprom_index < eeprom_end) { | ||||
|         eeprom_tlv = (tlvinfo_tlv_t *) &(ext_tlv_value->value[eeprom_index]); | ||||
|         if (!is_valid_tlv(eeprom_tlv)) { | ||||
|             DBG_DEBUG(DBG_ERROR, "tlv is not valid, eeprom_tlv->type 0x%x.\n", eeprom_tlv->type); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         DBG_DEBUG(DBG_VERBOSE, "eeprom_tlv->length %d.\n", eeprom_tlv->length); | ||||
|         if (eeprom_tlv->type == ext_type) { | ||||
|             if (*buf_len >= eeprom_tlv->length) { | ||||
|                 memcpy(buf, eeprom_tlv->value, eeprom_tlv->length); | ||||
|                 DBG_DEBUG(DBG_VERBOSE, "eeprom_tlv->length %d.\n", eeprom_tlv->length); | ||||
|                 *buf_len = eeprom_tlv->length; | ||||
|                 return 0; | ||||
|             } | ||||
|             DBG_DEBUG(DBG_VERBOSE, "buf_len %d small than info_len %d.\n", *buf_len, eeprom_tlv->length); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "ext_type %d: tlv is not found.\n", ext_type); | ||||
|     return -1; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| int dfd_tlvinfo_get_e2prom_info(uint8_t *eeprom, uint32_t size, dfd_tlv_type_t *tlv_type, uint8_t* buf, uint32_t *buf_len) | ||||
| { | ||||
|     tlv_decode_value_t decode_value; | ||||
|     int ret; | ||||
|  | ||||
|     if (eeprom == NULL || tlv_type == NULL || buf == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "Input para invalid.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     memset((void *)&decode_value, 0, sizeof(tlv_decode_value_t)); | ||||
|     ret = dfd_parse_tlv_eeprom(eeprom, size, tlv_type->main_type, &decode_value); | ||||
|     if (ret) { | ||||
|         DBG_DEBUG(DBG_ERROR, "dfd_parse_tlv_eeprom failed ret %d.\n", ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if (*buf_len >= decode_value.length) { | ||||
|         memcpy(buf, decode_value.value, decode_value.length); | ||||
|         *buf_len = decode_value.length; | ||||
|         return 0; | ||||
|     } | ||||
|     DBG_DEBUG(DBG_ERROR, "buf_len %d small than info_len %d.\n", *buf_len, decode_value.length); | ||||
|     return -1; | ||||
| } | ||||
| @@ -0,0 +1,117 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2012 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include "./include/dfd_module.h" | ||||
| #include "./include/dfd_cfg.h" | ||||
| #include "./include/dfd_cfg_adapter.h" | ||||
| #include "./include/dfd_cfg_info.h" | ||||
| #include "./include/dfd_frueeprom.h" | ||||
|  | ||||
| int g_dfd_cpld_dbg_level = 0; | ||||
| module_param(g_dfd_cpld_dbg_level, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| ssize_t dfd_get_cpld_name(unsigned int cpld_index, char *buf) | ||||
| { | ||||
|     int key; | ||||
|     char *cpld_name; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "param error. buf is NULL.cpld index:%d", cpld_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     memset(buf, 0, PAGE_SIZE); | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_NAME, cpld_index, 0); | ||||
|     cpld_name = dfd_ko_cfg_get_item(key); | ||||
|     if (cpld_name == NULL) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "cpld name config error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_NODE_FAIL; | ||||
|     } | ||||
|  | ||||
|     DBG_CPLD_DEBUG(DBG_VERBOSE, "%s\n", cpld_name); | ||||
|     snprintf(buf, PAGE_SIZE, "%s\n", cpld_name); | ||||
|     return strlen(buf); | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_cpld_type(unsigned int cpld_index, char *buf) | ||||
| { | ||||
|     int key; | ||||
|     char *cpld_type; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "param error. buf is NULL.cpld index:%d\n", cpld_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     memset(buf, 0, PAGE_SIZE); | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_TYPE, cpld_index, 0); | ||||
|     cpld_type = dfd_ko_cfg_get_item(key); | ||||
|     if (cpld_type == NULL) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "cpld type config error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_NODE_FAIL; | ||||
|     } | ||||
|  | ||||
|     DBG_CPLD_DEBUG(DBG_VERBOSE, "%s\n", cpld_type); | ||||
|     snprintf(buf, PAGE_SIZE, "%s\n", cpld_type); | ||||
|     return strlen(buf); | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_cpld_version(unsigned int cpld_index, char *buf) | ||||
| { | ||||
|     int key, rv; | ||||
|     uint32_t value; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "param error. buf is NULL."); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     memset(buf, 0, PAGE_SIZE); | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_VERSION, cpld_index, 0); | ||||
|     rv = dfd_info_get_int(key, &value, NULL); | ||||
|     if (rv < 0) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "cpld version config error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_NODE_FAIL; | ||||
|     } | ||||
|  | ||||
|     DBG_CPLD_DEBUG(DBG_VERBOSE, "%x\n", value); | ||||
|     snprintf(buf, PAGE_SIZE, "%08x\n", value); | ||||
|     return strlen(buf); | ||||
| } | ||||
|  | ||||
| int dfd_set_cpld_testreg(unsigned int cpld_index, int value) | ||||
| { | ||||
|     int key, ret; | ||||
|  | ||||
|     if (value < 0 || value > 0xff) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "can not set cpld test register value = 0x%02x.\n", value); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_TEST_REG, cpld_index, 0); | ||||
|     ret = dfd_info_set_int(key, value); | ||||
|     if (ret < 0) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "set cpld test register error, key:0x%x,ret:%d\n",key, ret); | ||||
|         return ret; | ||||
|     } | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_cpld_testreg(unsigned int cpld_index, int *value) | ||||
| { | ||||
|     int key, ret; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_TEST_REG, cpld_index, 0); | ||||
|     ret = dfd_info_get_int(key, value, NULL); | ||||
|     if (ret < 0) { | ||||
|         DBG_CPLD_DEBUG(DBG_ERROR, "get cpld test register error, key:0x%x,ret:%d\n",key, ret); | ||||
|         return ret; | ||||
|     } | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
| @@ -0,0 +1,487 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2012 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/slab.h> | ||||
|  | ||||
| #include "./include/dfd_module.h" | ||||
| #include "./include/dfd_cfg.h" | ||||
| #include "./include/dfd_cfg_adapter.h" | ||||
| #include "./include/dfd_cfg_info.h" | ||||
| #include "./include/dfd_frueeprom.h" | ||||
| #include "../rg_dev_sysfs/include/rg_sysfs_common.h" | ||||
|  | ||||
| #define DFD_FAN_EEPROM_MODE_TLV_STRING    "tlv" | ||||
| #define DFD_FAN_EEPROM_MODE_FRU_STRING    "fru" | ||||
| #define FAN_SIZE                          (256) | ||||
|  | ||||
| typedef enum fan_status_e { | ||||
|     FAN_ABSENT = 0, | ||||
|     FAN_OK     = 1, | ||||
|     FAN_NOT_OK = 2, | ||||
| } fan_status_t; | ||||
|  | ||||
| typedef enum fan_present_status_e { | ||||
|     ABSENT  = 0, | ||||
|     PRESENT = 1, | ||||
| } fan_present_status_t; | ||||
|  | ||||
| typedef enum fan_motor_status_e { | ||||
|     MOTOR_STALL = 0, | ||||
|     MOTOR_ROLL  = 1, | ||||
| } fan_motor_status_t; | ||||
|  | ||||
| typedef enum fan_eeprom_mode_e { | ||||
|     FAN_EEPROM_MODE_TLV,     /* TLV */ | ||||
|     FAN_EEPROM_MODE_FRU,      /*FRU*/ | ||||
| } fan_eeprom_mode_t; | ||||
|  | ||||
| typedef struct  dfd_dev_head_info_s { | ||||
|     uint8_t   ver; | ||||
|     uint8_t   flag; | ||||
|     uint8_t   hw_ver; | ||||
|     uint8_t   type; | ||||
|     int16_t   tlv_len; | ||||
| } dfd_dev_head_info_t; | ||||
|  | ||||
| typedef struct dfd_dev_tlv_info_s { | ||||
|     uint8_t  type; | ||||
|     uint8_t  len; | ||||
|     uint8_t  data[0]; | ||||
| } dfd_dev_tlv_info_t; | ||||
|  | ||||
| typedef enum fan_direction_e { | ||||
|     FRONT_TO_BACK  = 0, | ||||
|     BACK_TO_FRONT  = 1, | ||||
|     FAN_DIRECTION_END  = 2, | ||||
| } fan_direction_t; | ||||
|  | ||||
| int g_dfd_fan_dbg_level = 0; | ||||
| module_param(g_dfd_fan_dbg_level, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| static int dfd_get_fan_eeprom_mode(void) | ||||
| { | ||||
|     int key, mode; | ||||
|     char *name; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_E2_MODE, 0, 0); | ||||
|     name = dfd_ko_cfg_get_item(key); | ||||
|     if (name == NULL) { | ||||
|  | ||||
|         DFD_FAN_DEBUG(DBG_WARN, "get fan eeprom mode fail, key=0x%08x\n", key); | ||||
|         return FAN_EEPROM_MODE_TLV; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan eeprom mode_name %s.\n", name); | ||||
|     if (!strncmp(name, DFD_FAN_EEPROM_MODE_TLV_STRING, strlen(DFD_FAN_EEPROM_MODE_TLV_STRING))) { | ||||
|         mode = FAN_EEPROM_MODE_TLV; | ||||
|     } else if (!strncmp(name, DFD_FAN_EEPROM_MODE_FRU_STRING, strlen(DFD_FAN_EEPROM_MODE_FRU_STRING))) { | ||||
|         mode = FAN_EEPROM_MODE_FRU; | ||||
|     } else { | ||||
|  | ||||
|         mode = FAN_EEPROM_MODE_TLV; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan eeprom mode %d.\n", mode); | ||||
|     return mode; | ||||
| } | ||||
|  | ||||
| static int dfd_fan_tlv_eeprom_read(int bus, int addr, uint8_t cmd, char *buf) | ||||
| { | ||||
|     dfd_dev_head_info_t info; | ||||
|     char tmp_tlv_len[sizeof(uint16_t)]; | ||||
|     char *tlv_data; | ||||
|     dfd_dev_tlv_info_t *tlv; | ||||
|     int buf_len; | ||||
|     int rv, match_flag; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL\n"); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     rv = dfd_ko_i2c_read(bus, addr, 0, (uint8_t *)&info, sizeof(dfd_dev_head_info_t)); | ||||
|     if (rv < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan may not present.\n"); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     memcpy(tmp_tlv_len, (uint8_t *)&info.tlv_len, sizeof(uint16_t)); | ||||
|     info.tlv_len = (tmp_tlv_len[0] << 8) + tmp_tlv_len[1]; | ||||
|  | ||||
|     if ((info.tlv_len <= 0 ) || (info.tlv_len > 0xFF)) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan maybe not set mac.\n"); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "info.tlv_len:%d\n", info.tlv_len); | ||||
|  | ||||
|     tlv_data = (uint8_t *)kmalloc(info.tlv_len, GFP_KERNEL); | ||||
|     if (tlv_data == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "tlv_data kmalloc failed \n"); | ||||
|         return -DFD_RV_NO_MEMORY; | ||||
|     } | ||||
|     memset(tlv_data, 0, info.tlv_len); | ||||
|  | ||||
|     rv = dfd_ko_i2c_read(bus, addr, sizeof(dfd_dev_head_info_t), tlv_data, info.tlv_len); | ||||
|     if (rv < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR,"fan eeprom read failed\n"); | ||||
|         kfree(tlv_data); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|  | ||||
|     buf_len = FAN_SIZE - 1; | ||||
|     match_flag = 0; | ||||
|     for(tlv = (dfd_dev_tlv_info_t *)tlv_data; (ulong)tlv < (ulong)tlv_data + info.tlv_len;) { | ||||
|          DFD_FAN_DEBUG(DBG_VERBOSE, "tlv: %p, tlv->type: 0x%x, tlv->len: 0x%x info->tlv_len: 0x%x\n", | ||||
|             tlv, tlv->type, tlv->len, info.tlv_len); | ||||
|          if (tlv->type == cmd && tlv->len <= buf_len ) { | ||||
|             DFD_FAN_DEBUG(DBG_VERBOSE, "find tlv data, copy...\n"); | ||||
|             memcpy(buf, (uint8_t *)tlv->data, tlv->len); | ||||
|             buf_len = (uint32_t)tlv->len; | ||||
|             match_flag = 1; | ||||
|             break; | ||||
|          } | ||||
|         tlv = (dfd_dev_tlv_info_t *)((uint8_t* )tlv + sizeof(dfd_dev_tlv_info_t) + tlv->len); | ||||
|     } | ||||
|     kfree(tlv_data); | ||||
|     if (match_flag == 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR,"can't find fan tlv date. bus:%d, addr:0x%02x, tlv type:%d.\n", bus, addr, cmd); | ||||
|         return -DFD_RV_TYPE_ERR; | ||||
|     } | ||||
|     return buf_len; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_roll_status(unsigned int fan_index, unsigned int motor_index) | ||||
| { | ||||
|     int key, ret; | ||||
|     int status; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_ROLL_STATUS, fan_index, motor_index); | ||||
|     ret = dfd_info_get_int(key, &status, NULL); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan roll status error, fan:%d,motor:%d\n", | ||||
|             fan_index, motor_index); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan%u motor%u get fan roll status success, status:%d.\n", | ||||
|         fan_index, motor_index, status); | ||||
|     return status; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_present_status(unsigned int fan_index) | ||||
| { | ||||
|     int key, ret; | ||||
|     int status; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_DEV_PRESENT_STATUS, RG_MAIN_DEV_FAN, fan_index); | ||||
|     ret = dfd_info_get_int(key, &status, NULL); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan%u get present status error, key:0x%x\n", fan_index, key); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan%u get present status success, status:%d.\n", fan_index, status); | ||||
|     return status; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_status(unsigned int fan_index) | ||||
| { | ||||
|     int motor_num, motor_index, status, errcnt; | ||||
|  | ||||
|     status = dfd_get_fan_present_status(fan_index); | ||||
|     if(status != PRESENT ) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan index:%d, status:%d\n",fan_index, status); | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
|     motor_num = dfd_get_dev_number(RG_MAIN_DEV_FAN, RG_MINOR_DEV_MOTOR); | ||||
|     if(motor_num <= 0 ) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get motor number error:%d\n",motor_num); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|     errcnt = 0; | ||||
|     for(motor_index = 0; motor_index < motor_num; motor_index++) { | ||||
|         status = dfd_get_fan_roll_status(fan_index, motor_index); | ||||
|         if(status < 0) { | ||||
|             DFD_FAN_DEBUG(DBG_ERROR,  "get fan roll status error, fan index:%d, motor index:%d, status:%d\n", | ||||
|                 fan_index, motor_index, status); | ||||
|             return status; | ||||
|         } | ||||
|         if(status != MOTOR_ROLL) { | ||||
|             DFD_FAN_DEBUG(DBG_ERROR, | ||||
|                 "stall:fan index:%d, motor index:%d, status:%d\n",fan_index, motor_index, status); | ||||
|             errcnt++; | ||||
|         } | ||||
|     } | ||||
|     if (errcnt > 0) { | ||||
|         return FAN_NOT_OK; | ||||
|     } | ||||
|     return FAN_OK; | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_fan_status_str(unsigned int fan_index, char *buf) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     if(buf == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "params error.fan_index:%d.",fan_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_get_fan_status(fan_index); | ||||
|     if(ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan status error,ret:%d, fan_index:%d\n", ret, fan_index); | ||||
|         return ret; | ||||
|     } | ||||
|     memset(buf, 0, PAGE_SIZE); | ||||
|     return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", ret); | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_fan_info(unsigned int fan_index, uint8_t cmd, char *buf) | ||||
| { | ||||
|     int key, rv, eeprom_mode; | ||||
|     char fan_buf[FAN_SIZE]; | ||||
|     dfd_i2c_dev_t *i2c_dev; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index:%d, cmd:0x%x.\n", fan_index, cmd); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     memset(buf, 0, PAGE_SIZE); | ||||
|     memset(fan_buf, 0, FAN_SIZE); | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_OTHER_I2C_DEV, RG_MAIN_DEV_FAN, fan_index); | ||||
|     i2c_dev = dfd_ko_cfg_get_item(key); | ||||
|     if (i2c_dev == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan i2c dev config error, key=0x%08x\n", key); | ||||
|         return -DFD_RV_NODE_FAIL; | ||||
|     } | ||||
|  | ||||
|     eeprom_mode = dfd_get_fan_eeprom_mode(); | ||||
|     if(eeprom_mode == FAN_EEPROM_MODE_TLV) { | ||||
|         rv = dfd_fan_tlv_eeprom_read(i2c_dev->bus, i2c_dev->addr, cmd, fan_buf); | ||||
|     } else { | ||||
|         rv = dfd_get_fru_data(i2c_dev->bus, i2c_dev->addr, cmd, fan_buf, FAN_SIZE); | ||||
|     } | ||||
|  | ||||
|     if (rv < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan eeprom read failed"); | ||||
|         return -DFD_RV_DEV_FAIL; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "%s\n", fan_buf); | ||||
|     snprintf(buf, FAN_SIZE, "%s\n", fan_buf); | ||||
|     return strlen(buf); | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_fan_speed(unsigned int fan_index, unsigned int motor_index,unsigned int *speed) | ||||
| { | ||||
|     int key, ret, speed_tmp; | ||||
|  | ||||
|     if (speed == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_SPEED, fan_index, motor_index); | ||||
|     ret = dfd_info_get_int(key, &speed_tmp, NULL); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan speed error, key:0x%x,ret:%d\n",key, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if (speed_tmp == 0 || speed_tmp == 0xffff) { | ||||
|         *speed = 0; | ||||
|     } else { | ||||
|         *speed = 15000000 / speed_tmp; | ||||
|     } | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_set_fan_speed_level(unsigned int fan_index, unsigned int motor_index, int level) | ||||
| { | ||||
|     int key, ret; | ||||
|  | ||||
|     if (level < 0 || level > 0xff) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan:%u, motor:%u, can not set fan speed level: %d.\n", | ||||
|             fan_index, motor_index, level); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_RATIO, fan_index, motor_index); | ||||
|     ret = dfd_info_set_int(key, level); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan:%u, motor:%u, set fan level 0x%02x error, key:0x%x,ret:%d\n", | ||||
|             fan_index, motor_index, level, key, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan:%u, motor:%u, set fan speed level 0x%02x success.\n", | ||||
|         fan_index, motor_index, level); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_set_fan_pwm(unsigned int fan_index, unsigned int motor_index, int pwm) | ||||
| { | ||||
|     int ret, data; | ||||
|  | ||||
|     if (pwm < 0 || pwm > 100) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan:%u, motor:%u, can't set pwm: %d.\n", | ||||
|             fan_index, motor_index, pwm); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     data = pwm * 255 / 100; | ||||
|     ret = dfd_set_fan_speed_level(fan_index, motor_index, data); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan:%u, motor:%u, set fan ratio:%d error, ret:%d\n", | ||||
|             fan_index, motor_index, data, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan:%u, motor:%u, set fan ratio %d success.\n", | ||||
|         fan_index, motor_index, data); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_speed_level(unsigned int fan_index, unsigned int motor_index, int *level) | ||||
| { | ||||
|     int key, ret, speed_level; | ||||
|  | ||||
|     if (level == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_RATIO, fan_index, motor_index); | ||||
|     ret = dfd_info_get_int(key, &speed_level, NULL); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan:%u, motor:%u, get fan speed level error, key:0x%x,ret:%d\n", | ||||
|             fan_index, motor_index, key, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan:%u, motor:%u, get fan speed level success, value:0x%02x.\n", | ||||
|         fan_index, motor_index, speed_level); | ||||
|     *level = speed_level; | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_pwm(unsigned int fan_index, unsigned int motor_index, int *pwm) | ||||
| { | ||||
|     int ret, level; | ||||
|  | ||||
|     if (pwm == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_get_fan_speed_level(fan_index, motor_index, &level); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "fan:%u, motor:%u, get fan pwm error, ret:%d\n", | ||||
|             fan_index, motor_index, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if ((level * 100) % 255 > 0) { | ||||
|         *pwm = level * 100 / 255 + 1; | ||||
|     } else { | ||||
|         *pwm = level * 100 / 255; | ||||
|     } | ||||
|  | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "fan:%u, motor:%u, get fan pwm success, value:%d.\n", | ||||
|         fan_index, motor_index, *pwm); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_speed_tolerance(unsigned int fan_index, unsigned int motor_index, int *value) | ||||
| { | ||||
|     int key; | ||||
|     int *p_fan_speed_tolerance; | ||||
|  | ||||
|     if (value == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_SPEED_TOLERANCE, fan_index, motor_index); | ||||
|     p_fan_speed_tolerance = dfd_ko_cfg_get_item(key); | ||||
|     if (p_fan_speed_tolerance == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan speed tolerance failed, key:0x%x\n",key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|     *value = *p_fan_speed_tolerance; | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "get fan speed tolerance ok, key:0x%x, value:%d\n",key, *value); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_speed_target(unsigned int fan_index, unsigned int motor_index, int *value) | ||||
| { | ||||
|     int key; | ||||
|     int *p_fan_speed_target; | ||||
|  | ||||
|     if (value == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_SPEED_TARGET, fan_index, motor_index); | ||||
|     p_fan_speed_target = dfd_ko_cfg_get_item(key); | ||||
|     if (p_fan_speed_target == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan speed target failed, key:0x%x\n",key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|     *value = *p_fan_speed_target; | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "get fan speed target ok, key:0x%x, value:%d\n",key, *value); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| int dfd_get_fan_direction(unsigned int fan_index, unsigned int motor_index, int *value) | ||||
| { | ||||
|     int key; | ||||
|     int *p_fan_direction; | ||||
|  | ||||
|     if (value == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_DIRECTION, fan_index, motor_index); | ||||
|     p_fan_direction = dfd_ko_cfg_get_item(key); | ||||
|     if (p_fan_direction == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan direction failed, key:0x%x\n",key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|     *value = *p_fan_direction; | ||||
|     DFD_FAN_DEBUG(DBG_VERBOSE, "get fan direction ok, key:0x%x, value:%d\n",key, *value); | ||||
|     return DFD_RV_OK; | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_fan_direction_str(unsigned int fan_index, unsigned int motor_index, char *buf) | ||||
| { | ||||
|     int ret, value; | ||||
|  | ||||
|     if (buf == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "param error. buf is NULL. fan index:%d, motor index:%d.\n", | ||||
|             fan_index, motor_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_get_fan_direction(fan_index, motor_index, &value); | ||||
|     if (ret < 0) { | ||||
|         DFD_FAN_DEBUG(DBG_ERROR, "get fan direction string failed, ret:%d, fan_index:%d, motor_index:%d\n", | ||||
|             ret, fan_index, motor_index); | ||||
|         return ret; | ||||
|     } | ||||
|     memset(buf, 0, PAGE_SIZE); | ||||
|     return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", value); | ||||
| } | ||||
| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2012 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include "./include/dfd_module.h" | ||||
| #include "./include/dfd_cfg.h" | ||||
| #include "./include/dfd_cfg_info.h" | ||||
| #include "./include/dfd_cfg_adapter.h" | ||||
|  | ||||
| #define LED_STATUS_MEM                       (9) | ||||
|  | ||||
| int g_dfd_sysled_dbg_level = 0; | ||||
| module_param(g_dfd_sysled_dbg_level, int, S_IRUGO | S_IWUSR); | ||||
|  | ||||
| typedef enum dfd_led_status_e { | ||||
|     DFD_LED_DARK         = 0, | ||||
|     DFD_LED_GREEN        = 1, | ||||
|     DFD_LED_YELLOW       = 2, | ||||
|     DFD_LED_RED          = 3, | ||||
|     DFD_LED_GREEN_FLASH  = 4, | ||||
|     DFD_LED_YELLOW_FLASH = 5, | ||||
|     DFD_LED_RED_FLASH    = 6, | ||||
|     DFD_LED_BLUE         = 7, | ||||
|     DFD_LED_END          = 8, | ||||
| } dfd_led_status_t; | ||||
|  | ||||
| static int g_dfd_rg_led_status[LED_STATUS_MEM] = { | ||||
|     DFD_LED_DARK, | ||||
|     DFD_LED_RED_FLASH, | ||||
|     DFD_LED_RED, | ||||
|     DFD_LED_GREEN_FLASH, | ||||
|     DFD_LED_GREEN, | ||||
|     DFD_LED_YELLOW_FLASH, | ||||
|     DFD_LED_YELLOW, | ||||
|     DFD_LED_DARK, | ||||
|     DFD_LED_BLUE, | ||||
| }; | ||||
|  | ||||
| static int dfd_get_led_status_value(uint16_t led_id, uint8_t led_index, int *value) | ||||
| { | ||||
|     int key, ori_value, ret, value_tmp; | ||||
|     int *p_decode_value; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_LED_STATUS, led_id, led_index); | ||||
|     ret = dfd_info_get_int(key, &ori_value, NULL); | ||||
|     if (ret < 0) { | ||||
|         DBG_SYSLED_DEBUG(DBG_ERROR, "get led status error, key:0x%x,ret:%d\n", key, ret); | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_LED_STATUS_DECODE, led_id, ori_value); | ||||
|     p_decode_value = dfd_ko_cfg_get_item(key); | ||||
|     if (p_decode_value == NULL) { | ||||
|         DFD_FAN_DEBUG(DBG_VERBOSE, "led id:%d index:%d, status needn't decode.value:0x%x\n", led_id, led_index, ori_value); | ||||
|         value_tmp = ori_value; | ||||
|     } else { | ||||
|         DFD_FAN_DEBUG(DBG_VERBOSE, "led id:%d index:%d,, ori_value:0x%x,decode value:0x%x\n", led_id, led_index, ori_value, *p_decode_value); | ||||
|         value_tmp = *p_decode_value; | ||||
|     } | ||||
|     if(value_tmp >=0 && value_tmp < LED_STATUS_MEM) { | ||||
|         *value = g_dfd_rg_led_status[value_tmp]; | ||||
|         return DFD_RV_OK; | ||||
|     } | ||||
|     return -DFD_RV_INVALID_VALUE; | ||||
| } | ||||
|  | ||||
| ssize_t dfd_get_led_status(uint16_t led_id, uint8_t led_index, char *buf) | ||||
| { | ||||
|     int ret, led_value; | ||||
|  | ||||
|     if(buf == NULL) { | ||||
|         DBG_SYSLED_DEBUG(DBG_ERROR, "param error, buf is NULL. led_id:%d, led_index:%d\n", | ||||
|             led_id, led_index); | ||||
|         return -DFD_RV_INVALID_VALUE; | ||||
|     } | ||||
|  | ||||
|     ret = dfd_get_led_status_value(led_id, led_index, &led_value); | ||||
|     if(ret < 0) { | ||||
|         DBG_SYSLED_DEBUG(DBG_ERROR, "get led status error,ret:%d, led_id:%d, led_index:%d\n", ret, led_id, led_index); | ||||
|         return ret; | ||||
|     } | ||||
|     memset(buf, 0 , PAGE_SIZE); | ||||
|     return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", led_value); | ||||
| } | ||||
| @@ -0,0 +1,134 @@ | ||||
| /* | ||||
|  * Copyright(C) 2001-2012 Ruijie Network. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include "../rg_dev_sysfs/include/rg_sysfs_common.h" | ||||
| #include "./include/dfd_module.h" | ||||
| #include "./include/dfd_cfg.h" | ||||
| #include "./include/dfd_fan_driver.h" | ||||
| #include "./include/dfd_syseeprom_driver.h" | ||||
| #include "./include/dfd_cpld_driver.h" | ||||
| #include "./include/dfd_led_driver.h" | ||||
| #include "./include/dfd_slot_driver.h" | ||||
| #include "./include/dfd_sensors_driver.h" | ||||
| #include "./include/dfd_psu_driver.h" | ||||
| #include "./include/dfd_sff_driver.h" | ||||
|  | ||||
| typedef enum dfd_dev_init_fail_s { | ||||
|     DFD_KO_INIT_CPLD_FAIL       = 1, | ||||
|     DFD_KO_INIT_FPGA_FAIL       = 2, | ||||
|     DFD_KO_INIT_IRQ_FAIL        = 3, | ||||
|     DFD_KO_INIT_CFG_FAIL        = 4, | ||||
|     DFD_KO_INIT_DATA_FAIL       = 5, | ||||
| } dfd_dev_init_fail_t; | ||||
|  | ||||
| int g_dfd_dbg_level = 0; | ||||
|  | ||||
| char *g_status_mem_str[STATUS_MEM_END] = { | ||||
|     "ABSENT", | ||||
|     "OK", | ||||
|     "NOT OK", | ||||
| }; | ||||
|  | ||||
| int dfd_get_dev_number(unsigned int main_dev_id, unsigned int minor_dev_id) | ||||
| { | ||||
|     int key,dev_num; | ||||
|     int *p_dev_num; | ||||
|  | ||||
|     key = DFD_CFG_KEY(DFD_CFG_ITEM_DEV_NUM, main_dev_id, minor_dev_id); | ||||
|     p_dev_num = dfd_ko_cfg_get_item(key); | ||||
|     if (p_dev_num == NULL) { | ||||
|         DBG_DEBUG(DBG_ERROR, "get device number failed, key:0x%x\n",key); | ||||
|         return -DFD_RV_DEV_NOTSUPPORT; | ||||
|     } | ||||
|     dev_num = *p_dev_num; | ||||
|     DBG_DEBUG(DBG_VERBOSE, "get device number ok, number:%d\n",dev_num); | ||||
|     return dev_num; | ||||
| } | ||||
|  | ||||
| static struct switch_drivers_t switch_drivers= { | ||||
|     .get_dev_number = dfd_get_dev_number, | ||||
|     /* fan */ | ||||
|     .get_fan_status = dfd_get_fan_status, | ||||
|     .get_fan_info = dfd_get_fan_info, | ||||
|     .get_fan_speed = dfd_get_fan_speed, | ||||
|     .get_fan_pwm = dfd_get_fan_pwm, | ||||
|     .set_fan_pwm = dfd_set_fan_pwm, | ||||
|     .get_fan_speed_tolerance = dfd_get_fan_speed_tolerance, | ||||
|     .get_fan_speed_target = dfd_get_fan_speed_target, | ||||
|     .get_fan_direction = dfd_get_fan_direction, | ||||
|     .get_fan_status_str = dfd_get_fan_status_str, | ||||
|     .get_fan_direction_str = dfd_get_fan_direction_str, | ||||
|     .get_fan_present_status = dfd_get_fan_present_status, | ||||
|     .get_fan_roll_status = dfd_get_fan_roll_status, | ||||
|     .get_fan_speed_level = dfd_get_fan_speed_level, | ||||
|     .set_fan_speed_level = dfd_set_fan_speed_level, | ||||
|     /* syseeprom */ | ||||
|     .get_syseeprom_info = dfd_get_syseeprom_info, | ||||
|     /* cpld */ | ||||
|     .get_cpld_name = dfd_get_cpld_name, | ||||
|     .get_cpld_type = dfd_get_cpld_type, | ||||
|     .get_cpld_version = dfd_get_cpld_version, | ||||
|     .get_cpld_testreg = dfd_get_cpld_testreg, | ||||
|     .set_cpld_testreg = dfd_set_cpld_testreg, | ||||
|     /* led */ | ||||
|     .get_led_status = dfd_get_led_status, | ||||
|     /* slot */ | ||||
|     .get_slot_status_str = dfd_get_slot_status_str, | ||||
|     .get_slot_info = dfd_get_slot_info, | ||||
|     /* sensors */ | ||||
|     .get_temp_info = dfd_get_temp_info, | ||||
|     .get_voltage_info = dfd_get_voltage_info, | ||||
|     /* psu */ | ||||
|     .get_psu_info = dfd_get_psu_info, | ||||
|     .get_psu_status_str = dfd_get_psu_status_str, | ||||
|     .get_psu_sensor_info = dfd_get_psu_sensor_info, | ||||
|     .get_psu_present_status = dfd_get_psu_present_status, | ||||
|     .get_psu_output_status = dfd_get_psu_output_status, | ||||
|     .get_psu_alert_status = dfd_get_psu_alert_status, | ||||
|     /* sff */ | ||||
|     .get_sff_id = dfd_get_sff_id, | ||||
|     .set_sff_cpld_info = dfd_set_sff_cpld_info, | ||||
|     .get_sff_cpld_info = dfd_get_sff_cpld_info, | ||||
|     .get_sff_eeprom_info = dfd_get_sff_eeprom_info, | ||||
|     .get_sff_dir_name = dfd_get_sff_dir_name, | ||||
|     .get_sff_polling_size = dfd_get_sff_polling_size, | ||||
|     .get_sff_polling_data = dfd_get_sff_polling_data, | ||||
| }; | ||||
|  | ||||
| struct switch_drivers_t * dfd_plat_driver_get(void) { | ||||
|     return &switch_drivers; | ||||
| } | ||||
|  | ||||
| static int32_t __init dfd_dev_init(void) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "Enter.\n"); | ||||
|  | ||||
|     ret = dfd_dev_cfg_init(); | ||||
|     if (ret != 0) { | ||||
|         DBG_DEBUG(DBG_ERROR, "dfd_dev_cfg_init failed ret %d.\n", ret); | ||||
|         ret = -DFD_KO_INIT_CFG_FAIL; | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     DBG_DEBUG(DBG_VERBOSE, "success.\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void __exit dfd_dev_exit(void) | ||||
| { | ||||
|     DBG_DEBUG(DBG_VERBOSE, "dfd_dev_exit.\n"); | ||||
|     dfd_dev_cfg_exit(); | ||||
|     return ; | ||||
| } | ||||
|  | ||||
| module_init(dfd_dev_init); | ||||
| module_exit(dfd_dev_exit); | ||||
| module_param(g_dfd_dbg_level, int, S_IRUGO | S_IWUSR); | ||||
| EXPORT_SYMBOL(dfd_plat_driver_get); | ||||
| MODULE_AUTHOR("sonic_rd <sonic_rd@ruijie.com.cn>"); | ||||
| MODULE_LICENSE("GPL"); | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 tianshangfei
					tianshangfei