-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for Z9100 to check SFP Presence, toggling lpmode, reset… #1087
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,329 @@ | ||
#!/usr/bin/env python | ||
#!/usr/bin/python | ||
# sfputil.py | ||
# | ||
# Platform-specific SFP transceiver interface for SONiC | ||
# | ||
|
||
try: | ||
from sonic_sfp.sfputilbase import sfputilbase | ||
except ImportError, e: | ||
raise ImportError (str(e) + "- required module not found") | ||
|
||
|
||
class sfputil(sfputilbase): | ||
"""Platform specific sfputil class""" | ||
|
||
port_start = 0 | ||
port_end = 31 | ||
ports_in_block = 32 | ||
|
||
port_to_eeprom_mapping = {} | ||
port_to_i2c_mapping = { | ||
0: 18, | ||
1: 19, | ||
2: 20, | ||
3: 21, | ||
4: 22, | ||
5: 23, | ||
6: 24, | ||
7: 25, | ||
8: 26, | ||
9: 27, | ||
10: 28, | ||
11: 29, | ||
12: 31, | ||
13: 30, | ||
14: 33, | ||
15: 32, | ||
16: 34, | ||
17: 35, | ||
18: 36, | ||
19: 37, | ||
20: 38, | ||
21: 39, | ||
22: 40, | ||
23: 41, | ||
24: 42, | ||
25: 43, | ||
26: 44, | ||
27: 45, | ||
28: 46, | ||
29: 47, | ||
30: 48, | ||
31: 49 | ||
} | ||
|
||
_qsfp_ports = range(0, ports_in_block + 1) | ||
|
||
def __init__(self, port_num): | ||
# Override port_to_eeprom_mapping for class initialization | ||
eeprom_path = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom' | ||
for x in range(0, self.port_end + 1): | ||
port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) | ||
self.port_to_eeprom_mapping[x] = port_eeprom_path | ||
sfputilbase.__init__(self, port_num) | ||
import time | ||
from sonic_sfp.sfputilbase import SfpUtilBase | ||
except ImportError as e: | ||
raise ImportError("%s - required module not found" % str(e)) | ||
|
||
|
||
class SfpUtil(SfpUtilBase): | ||
"""Platform-specific SfpUtil class""" | ||
|
||
PORT_START = 0 | ||
PORT_END = 31 | ||
PORTS_IN_BLOCK = 32 | ||
|
||
IOM_1_PORT_START = 0 | ||
IOM_1_PORT_END = 11 | ||
IOM_2_PORT_START = 12 | ||
IOM_2_PORT_END = 21 | ||
IOM_3_PORT_START = 22 | ||
IOM_3_PORT_END = 31 | ||
|
||
BASE_VAL_PATH="/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" | ||
|
||
_port_to_eeprom_mapping = {} | ||
_port_to_i2c_mapping = { | ||
0: [9,18], | ||
1: [9,19], | ||
2: [9,20], | ||
3: [9,21], | ||
4: [9,22], | ||
5: [9,23], | ||
6: [9,24], | ||
7: [9,25], | ||
8: [8,26], | ||
9: [8,27], | ||
10: [8,28], | ||
11: [8,29], | ||
12: [8,31],#reordered | ||
13: [8,30], | ||
14: [8,33],#reordered | ||
15: [8,32], | ||
16: [7,34], | ||
17: [7,35], | ||
18: [7,36], | ||
19: [7,37], | ||
20: [7,38], | ||
21: [7,39], | ||
22: [7,40], | ||
23: [7,41], | ||
24: [6,42], | ||
25: [6,43], | ||
26: [6,44], | ||
27: [6,45], | ||
28: [6,46], | ||
29: [6,47], | ||
30: [6,48], | ||
31: [6,49] | ||
} | ||
|
||
@property | ||
def port_start(self): | ||
return self.PORT_START | ||
|
||
@property | ||
def port_end(self): | ||
return self.PORT_END | ||
|
||
@property | ||
def qsfp_ports(self): | ||
return range(0, self.PORTS_IN_BLOCK + 1) | ||
|
||
@property | ||
def iom1_port_start(self): | ||
return self.IOM_1_PORT_START | ||
|
||
@property | ||
def iom1_port_end(self): | ||
return self.IOM_1_PORT_END | ||
|
||
@property | ||
def iom2_port_start(self): | ||
return self.IOM_2_PORT_START | ||
|
||
@property | ||
def iom2_port_end(self): | ||
return self.IOM_2_PORT_END | ||
|
||
@property | ||
def iom3_port_start(self): | ||
return self.IOM_3_PORT_START | ||
|
||
@property | ||
def iom3_port_end(self): | ||
return self.IOM_3_PORT_END | ||
|
||
@property | ||
def port_to_eeprom_mapping(self): | ||
return self._port_to_eeprom_mapping | ||
|
||
@property | ||
def port_to_i2c_mapping(self): | ||
return self._port_to_i2c_mapping | ||
|
||
|
||
def __init__(self): | ||
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" | ||
|
||
for x in range(0, self.port_end+1): | ||
self.port_to_eeprom_mapping[x] = eeprom_path.format(self.port_to_i2c_mapping[x][0], self.port_to_i2c_mapping[x][1]) | ||
|
||
SfpUtilBase.__init__(self) | ||
|
||
def get_presence(self, port_num): | ||
|
||
global i2c_line | ||
|
||
# Check for invalid port_num | ||
if port_num < self.port_start or port_num > self.port_end: | ||
return False | ||
|
||
#port_num and i2c match | ||
if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end: | ||
i2c_line=14 | ||
elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
i2c_line=15 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
i2c_line=16 | ||
|
||
try: | ||
qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_modprs" | ||
reg_file = open(qsfp_path, "r") | ||
|
||
except IOError as e: | ||
print "Error: unable to open file: %s" % str(e) | ||
return False | ||
|
||
content = reg_file.readline().rstrip() | ||
|
||
#Absence of IOM throws read error | ||
if (content == 'read error'): | ||
return False | ||
|
||
# content is a string containing the hex representation of the register | ||
reg_value = int(content, 16) | ||
|
||
#Rationalize port settings | ||
if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
port_num=port_num%12 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
port_num=port_num%22 | ||
|
||
# Mask off the bit corresponding to our port | ||
mask = (1 << port_num) | ||
|
||
# ModPrsL is active low | ||
if reg_value & mask == 0: | ||
return True | ||
|
||
return False | ||
|
||
def get_low_power_mode(self, port_num): | ||
|
||
# Check for invalid port_num | ||
if port_num < self.port_start or port_num > self.port_end: | ||
return False | ||
|
||
#port_num and i2c match | ||
if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end: | ||
i2c_line=14 | ||
elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
i2c_line=15 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
i2c_line=16 | ||
|
||
try: | ||
qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" | ||
reg_file = open(qsfp_path, "r") | ||
|
||
except IOError as e: | ||
print "Error: unable to open file: %s" % str(e) | ||
return False | ||
|
||
content = reg_file.readline().rstrip() | ||
|
||
#Absence of IOM throws read error | ||
if (content == 'read error'): | ||
return False | ||
|
||
# content is a string containing the hex representation of the register | ||
reg_value = int(content, 16) | ||
|
||
#Rationalize port settings | ||
if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
port_num=port_num%12 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
port_num=port_num%22 | ||
|
||
# Mask off the bit corresponding to our port | ||
mask = (1 << port_num) | ||
|
||
# LPMode is active high | ||
if reg_value & mask == 0: | ||
return False | ||
|
||
return True | ||
|
||
def set_low_power_mode(self, port_num, lpmode): | ||
|
||
# Check for invalid port_num | ||
if port_num < self.port_start or port_num > self.port_end: | ||
return False | ||
|
||
#port_num and i2c match | ||
if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end: | ||
i2c_line=14 | ||
elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
i2c_line=15 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
i2c_line=16 | ||
|
||
try: | ||
qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" | ||
reg_file = open(qsfp_path, "r+") | ||
|
||
except IOError as e: | ||
print "Error: unable to open file: %s" % str(e) | ||
return False | ||
|
||
content = reg_file.readline().rstrip() | ||
|
||
#Absence of IOM throws read error | ||
if (content == 'read error'): | ||
return False | ||
|
||
# content is a string containing the hex representation of the register | ||
reg_value = int(content, 16) | ||
|
||
#Rationalize port settings | ||
if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
port_num=port_num%12 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
port_num=port_num%22 | ||
|
||
# Mask off the bit corresponding to our port | ||
mask = (1 << port_num) | ||
|
||
# LPMode is active high; set or clear the bit accordingly | ||
if lpmode is True: | ||
reg_value = reg_value | mask | ||
else: | ||
reg_value = reg_value & ~mask | ||
|
||
# Convert our register value back to a hex string and write back | ||
content = hex(reg_value) | ||
|
||
reg_file.seek(0) | ||
reg_file.write(content) | ||
reg_file.close() | ||
|
||
return True | ||
|
||
def reset(self, port_num): | ||
|
||
# Check for invalid port_num | ||
if port_num < self.port_start or port_num > self.port_end: | ||
return False | ||
|
||
#port_num and i2c match | ||
if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end: | ||
i2c_line=14 | ||
elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
i2c_line=15 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
i2c_line=16 | ||
|
||
try: | ||
qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" | ||
reg_file = open(qsfp_path, "r+") | ||
|
||
except IOError as e: | ||
print "Error: unable to open file: %s" % str(e) | ||
return False | ||
|
||
content = reg_file.readline().rstrip() | ||
|
||
# File content is a string containing the hex representation of the register | ||
reg_value = int(content, 16) | ||
|
||
#Rationalize port settings | ||
if port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: | ||
port_num=port_num%12 | ||
elif port_num >= self.iom3_port_start and port_num <= self.iom3_port_end: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace tab with 4 spaces. |
||
port_num=port_num%22 | ||
|
||
# Mask off the bit corresponding to our port | ||
mask = (1 << port_num) | ||
|
||
# ResetL is active low | ||
reg_value = reg_value & ~mask | ||
|
||
# Convert our register value back to a hex string and write back | ||
reg_file.seek(0) | ||
reg_file.write(hex(reg_value)) | ||
reg_file.close() | ||
|
||
# Sleep 1 second to allow it to settle | ||
time.sleep(1) | ||
|
||
# Flip the bit back high and write back to the register to take port out of reset | ||
try: | ||
qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" | ||
reg_file = open(qsfp_path, "w+") | ||
|
||
except IOError as e: | ||
print "Error: unable to open file: %s" % str(e) | ||
return False | ||
|
||
reg_value = reg_value | mask | ||
reg_file.seek(0) | ||
reg_file.write(hex(reg_value)) | ||
reg_file.close() | ||
|
||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shebang can be removed altogether, as this file is a plugin, and is not executable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.. Thanks for the catch..