2929 sys .exit ("This operating system is not supported." )
3030
3131# To determine what functionality is present
32- I2C_FUNC_I2C = 0x00000001
32+ I2C_FUNC_SMBUS_QUICK = 0x00010000
33+ I2C_FUNC_SMBUS_READ_BYTE = 0x00020000
34+ I2C_FUNC_SMBUS_WRITE_BYTE = 0x00040000
35+ I2C_FUNC_SMBUS_READ_BYTE_DATA = 0x00080000
36+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA = 0x00100000
37+ I2C_FUNC_SMBUS_READ_WORD_DATA = 0x00200000
38+ I2C_FUNC_SMBUS_WRITE_WORD_DATA = 0x00400000
39+
40+ REQUIRED_FUNC = I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE | \
41+ I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA | \
42+ I2C_FUNC_SMBUS_QUICK
3343
3444# Data for SMBus Messages
3545class i2c_smbus_data (ctypes .Union ):
@@ -105,6 +115,10 @@ def print_usage():
105115 print (" -w write data to SPD EEPROM (input from file)" )
106116 print (" -d DIMM DIMM slot index (0 - 7)" )
107117 print (" -f FILE input or output file path" )
118+ print ()
119+ print ("Environment Variables:" )
120+ print (" SPD_EEPROM_SMBUS specify the SMBus index to use (e.g. 1 for /dev/i2c-1)" )
121+ print ()
108122
109123def spd_set_page (fd , page ):
110124 try :
@@ -213,48 +227,75 @@ def smbus_probe(dimm_slot = None):
213227 except Exception :
214228 pass
215229
216- smbus_idx = ""
230+ fd = None
231+ smbus_idx = None
217232
218233 files = os .listdir ("/dev" )
219234 files = list (filter (lambda x : x .startswith ("i2c-" ), files ))
220235
221- for entry in files :
222- fd = os .open ("/dev/" + entry , os .O_RDWR )
223- if not i2c_smbus_get_funcs (fd ) & I2C_FUNC_I2C :
224- smbus_idx = entry [4 :]
225- break
226-
227- if smbus_idx .isdigit ():
228- smbus_idx = int (smbus_idx )
236+ if os .getenv ("SPD_EEPROM_SMBUS" ) is not None :
237+ fd , smbus_idx , n = try_smbus ("i2c-" + os .getenv ("SPD_EEPROM_SMBUS" ), dimm_slot )
238+ if fd is None :
239+ sys .exit ("Could not access SMBus %s." % os .getenv ("SPD_EEPROM_SMBUS" ))
240+ else :
241+ return fd , smbus_idx
229242 else :
230- sys .exit ("No SMBus adapter found." )
231-
232- if dimm_slot == None :
233- print ("Probing for SPD EEPROM on SMBus %d" % smbus_idx )
243+ rets = [try_smbus (x , dimm_slot ) for x in files ]
244+ rets = list (filter (lambda x : x [0 ] is not None , rets ))
245+ rets = sorted (rets , key = lambda x : x [2 ], reverse = True )
246+ if len (rets ) == 0 :
247+ sys .exit ("No supported SMBus found." )
248+ else :
249+ fd , smbus_idx = rets [0 ][0 ], rets [0 ][1 ]
250+ print ("Selecting /dev/i2c-%d by EEPROM count" % smbus_idx )
251+ return fd , smbus_idx
252+
253+
254+ def try_smbus (file : str , dimm_slot = None ):
255+ fd = os .open ("/dev/" + file , os .O_RDWR )
256+ smbus_name : str = file [4 :]
257+ if i2c_smbus_get_funcs (fd ) & REQUIRED_FUNC != REQUIRED_FUNC :
258+ print ("I2C adapter %s does not support required SMBus functions." % file )
234259 print ()
260+ os .close (fd )
261+ return None , None , None
235262
263+ if smbus_name .isdigit ():
264+ smbus_idx : int = int (smbus_name )
265+ else :
266+ print ("Invalid SMBus index: %s" % smbus_name )
267+ return None , None , None
268+
269+ print ("Probing for SPD EEPROM on SMBus %d" % smbus_idx )
270+ if dimm_slot is None :
236271 eeprom = 0
237272 ee1004 = spd_set_page (fd , 0 )
238273
239274 for slot in range (0 , 8 ):
240275 try :
241276 i2c_smbus_read_byte (fd , 0x50 + slot )
242-
243277 print ("DIMM slot %d: %s SPD EEPROM" % (slot , "512 Byte EE1004" if ee1004 else "256 Byte AT24" ))
244-
245278 eeprom += 1
246279 except IOError :
247280 pass
248281
249282 if eeprom == 0 :
250- print ("No SPD EEPROM detected." )
283+ print ("No SPD EEPROM detected on SMBus %d." % smbus_idx )
284+ print ()
285+ os .close (fd )
286+ return None , None , None
251287 else :
252288 try :
253289 i2c_smbus_read_byte (fd , 0x50 + dimm_slot )
290+ eeprom = 1
254291 except IOError :
255- sys .exit ("DIMM slot %d is empty." % dimm_slot )
292+ print ("DIMM slot %d is empty." % dimm_slot )
293+ os .close (fd )
294+ print ()
295+ return None , None , None
256296
257- return fd , smbus_idx
297+ print ()
298+ return fd , smbus_idx , eeprom
258299
259300def main ():
260301 if os .getuid ():
@@ -266,7 +307,7 @@ def main():
266307 sys .exit (print_usage ())
267308
268309 op_code = 0
269- dimm_slot = ""
310+ dimm_slot = None
270311 file_path = ""
271312
272313 for opt , arg in opts :
@@ -282,7 +323,9 @@ def main():
282323 file_path = arg
283324
284325 if op_code == 1 and len (opts ) == 1 :
285- smbus_probe ()
326+ _ , smbus_idx = smbus_probe ()
327+ print ("To save time for next time, you can specify the SMBus index" \
328+ " by: `export SPD_EEPROM_SMBUS=%d`." % smbus_idx )
286329 elif op_code != 0 \
287330 and len (opts ) == 3 \
288331 and len (file_path ) != 0 \
0 commit comments