|
9 | 9 | from ..xcvr_api import XcvrApi
|
10 | 10 |
|
11 | 11 | import logging
|
| 12 | +from ...codes.public.cmis import CmisCodes |
| 13 | +from ...codes.public.sff8024 import Sff8024 |
12 | 14 | from ...fields import consts
|
13 | 15 | from ..xcvr_api import XcvrApi
|
14 | 16 | from .cmisCDB import CmisCdbApi
|
@@ -50,6 +52,12 @@ def get_module_type(self):
|
50 | 52 | '''
|
51 | 53 | return self.xcvr_eeprom.read(consts.ID_FIELD)
|
52 | 54 |
|
| 55 | + def get_module_type_abbreviation(self): |
| 56 | + ''' |
| 57 | + This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6 |
| 58 | + ''' |
| 59 | + return self.xcvr_eeprom.read(consts.ID_ABBRV_FIELD) |
| 60 | + |
53 | 61 | def get_connector_type(self):
|
54 | 62 | '''
|
55 | 63 | This function returns module connector. Table 4-3 in SFF-8024 Rev4.6
|
@@ -134,10 +142,10 @@ def get_transceiver_info(self):
|
134 | 142 | "nominal_bit_rate": 0, # Not supported
|
135 | 143 | "specification_compliance": admin_info[consts.MEDIA_TYPE_FIELD],
|
136 | 144 | "vendor_date": admin_info[consts.VENDOR_DATE_FIELD],
|
137 |
| - "vendor_oui": admin_info[consts.VENDOR_OUI_FIELD], |
138 |
| - # TODO |
139 |
| - "application_advertisement": "N/A", |
| 145 | + "vendor_oui": admin_info[consts.VENDOR_OUI_FIELD] |
140 | 146 | }
|
| 147 | + appl_advt = self.get_application_advertisement() |
| 148 | + xcvr_info['application_advertisement'] = str(appl_advt) if len(appl_advt) > 0 else 'N/A' |
141 | 149 | xcvr_info['host_electrical_interface'] = self.get_host_electrical_interface()
|
142 | 150 | xcvr_info['media_interface_code'] = self.get_module_media_interface()
|
143 | 151 | xcvr_info['host_lane_count'] = self.get_host_lane_count()
|
@@ -876,6 +884,24 @@ def reset_module(self, reset = False):
|
876 | 884 | else:
|
877 | 885 | return True
|
878 | 886 |
|
| 887 | + def reset(self): |
| 888 | + """ |
| 889 | + Reset SFP and return all user module settings to their default state. |
| 890 | +
|
| 891 | + Returns: |
| 892 | + A boolean, True if successful, False if not |
| 893 | + """ |
| 894 | + if self.reset_module(True): |
| 895 | + # minimum waiting time for the TWI to be functional again |
| 896 | + time.sleep(2) |
| 897 | + # buffer time |
| 898 | + for retries in range(5): |
| 899 | + state = self.get_module_state() |
| 900 | + if state in ['ModuleReady', 'ModuleLowPwr']: |
| 901 | + return True |
| 902 | + time.sleep(1) |
| 903 | + return False |
| 904 | + |
879 | 905 | def get_lpmode(self):
|
880 | 906 | '''
|
881 | 907 | Retrieves Low power module status
|
@@ -1745,4 +1771,176 @@ def get_transceiver_loopback(self):
|
1745 | 1771 | for lane in range(1, self.NUM_CHANNELS+1):
|
1746 | 1772 | trans_loopback['host_input_loopback_lane%d' % lane] = 'N/A'
|
1747 | 1773 | return trans_loopback
|
| 1774 | + |
| 1775 | + def set_datapath_init(self, channel): |
| 1776 | + """ |
| 1777 | + Put the CMIS datapath into the initialized state |
| 1778 | +
|
| 1779 | + Args: |
| 1780 | + channel: |
| 1781 | + Integer, a bitmask of the lanes on the host side |
| 1782 | + e.g. 0x5 for lane 0 and lane 2. |
| 1783 | +
|
| 1784 | + Returns: |
| 1785 | + Boolean, true if success otherwise false |
| 1786 | + """ |
| 1787 | + cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION) |
| 1788 | + data = self.xcvr_eeprom.read(consts.DATAPATH_DEINIT_FIELD) |
| 1789 | + for lane in range(self.NUM_CHANNELS): |
| 1790 | + if ((1 << lane) & channel) == 0: |
| 1791 | + continue |
| 1792 | + if cmis_major >= 4: # CMIS v4 onwards |
| 1793 | + data &= ~(1 << lane) |
| 1794 | + else: # CMIS v3 |
| 1795 | + data |= (1 << lane) |
| 1796 | + self.xcvr_eeprom.write(consts.DATAPATH_DEINIT_FIELD, data) |
| 1797 | + |
| 1798 | + def set_datapath_deinit(self, channel): |
| 1799 | + """ |
| 1800 | + Put the CMIS datapath into the de-initialized state |
| 1801 | +
|
| 1802 | + Args: |
| 1803 | + channel: |
| 1804 | + Integer, a bitmask of the lanes on the host side |
| 1805 | + e.g. 0x5 for lane 0 and lane 2. |
| 1806 | +
|
| 1807 | + Returns: |
| 1808 | + Boolean, true if success otherwise false |
| 1809 | + """ |
| 1810 | + cmis_major = self.xcvr_eeprom.read(consts.CMIS_MAJOR_REVISION) |
| 1811 | + data = self.xcvr_eeprom.read(consts.DATAPATH_DEINIT_FIELD) |
| 1812 | + for lane in range(self.NUM_CHANNELS): |
| 1813 | + if ((1 << lane) & channel) == 0: |
| 1814 | + continue |
| 1815 | + if cmis_major >= 4: # CMIS v4 onwards |
| 1816 | + data |= (1 << lane) |
| 1817 | + else: # CMIS v3 |
| 1818 | + data &= ~(1 << lane) |
| 1819 | + self.xcvr_eeprom.write(consts.DATAPATH_DEINIT_FIELD, data) |
| 1820 | + |
| 1821 | + def get_application_advertisement(self): |
| 1822 | + """ |
| 1823 | + Get the application advertisement of the CMIS transceiver |
| 1824 | +
|
| 1825 | + Returns: |
| 1826 | + Dictionary, the application advertisement |
| 1827 | + """ |
| 1828 | + map = { |
| 1829 | + Sff8024.MODULE_MEDIA_TYPE[1]: consts.MODULE_MEDIA_INTERFACE_850NM, |
| 1830 | + Sff8024.MODULE_MEDIA_TYPE[2]: consts.MODULE_MEDIA_INTERFACE_SM, |
| 1831 | + Sff8024.MODULE_MEDIA_TYPE[3]: consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, |
| 1832 | + Sff8024.MODULE_MEDIA_TYPE[4]: consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, |
| 1833 | + Sff8024.MODULE_MEDIA_TYPE[5]: consts.MODULE_MEDIA_INTERFACE_BASE_T |
| 1834 | + } |
| 1835 | + |
| 1836 | + ret = {} |
| 1837 | + dic = self.xcvr_eeprom.read(consts.APPLS_ADVT_FIELD) |
| 1838 | + for app in range(1, 16): |
| 1839 | + buf = {} |
| 1840 | + |
| 1841 | + key = "{}_{}".format(consts.HOST_ELECTRICAL_INTERFACE, app) |
| 1842 | + val = dic.get(key) |
| 1843 | + if val in [None, 'Unknown', 'Undefined']: |
| 1844 | + break |
| 1845 | + buf['host_electrical_interface_id'] = val |
| 1846 | + |
| 1847 | + prefix = map.get(self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD)) |
| 1848 | + if prefix is None: |
| 1849 | + break |
| 1850 | + key = "{}_{}".format(prefix, app) |
| 1851 | + val = dic.get(key) |
| 1852 | + if val in [None, 'Unknown', 'Undefined']: |
| 1853 | + break |
| 1854 | + buf['module_media_interface_id'] = val |
| 1855 | + |
| 1856 | + key = "{}_{}".format(consts.MEDIA_LANE_COUNT, app) |
| 1857 | + val = dic.get(key) |
| 1858 | + if val is None: |
| 1859 | + break |
| 1860 | + buf['media_lane_count'] = val |
| 1861 | + |
| 1862 | + key = "{}_{}".format(consts.HOST_LANE_COUNT, app) |
| 1863 | + val = dic.get(key) |
| 1864 | + if val is None: |
| 1865 | + break |
| 1866 | + buf['host_lane_count'] = val |
| 1867 | + |
| 1868 | + key = "{}_{}".format(consts.HOST_LANE_ASSIGNMENT_OPTION, app) |
| 1869 | + val = dic.get(key) |
| 1870 | + if val is None: |
| 1871 | + break |
| 1872 | + buf['host_lane_assignment_options'] = val |
| 1873 | + |
| 1874 | + ret[app] = buf |
| 1875 | + return ret |
| 1876 | + |
| 1877 | + def get_application(self, lane): |
| 1878 | + """ |
| 1879 | + Get the CMIS selected application code of a host lane |
| 1880 | +
|
| 1881 | + Args: |
| 1882 | + lane: |
| 1883 | + Integer, the zero-based lane id on the host side |
| 1884 | +
|
| 1885 | + Returns: |
| 1886 | + Integer, the transceiver-specific application code |
| 1887 | + """ |
| 1888 | + appl = 0 |
| 1889 | + if lane in range(self.NUM_CHANNELS) and not self.is_flat_memory(): |
| 1890 | + name = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1) |
| 1891 | + appl = self.xcvr_eeprom.read(name) >> 4 |
| 1892 | + |
| 1893 | + return (appl & 0xf) |
| 1894 | + |
| 1895 | + def set_application(self, channel, appl_code): |
| 1896 | + """ |
| 1897 | + Update the selected application code to the specified lanes on the host side |
| 1898 | +
|
| 1899 | + Args: |
| 1900 | + channel: |
| 1901 | + Integer, a bitmask of the lanes on the host side |
| 1902 | + e.g. 0x5 for lane 0 and lane 2. |
| 1903 | + appl_code: |
| 1904 | + Integer, the desired application code |
| 1905 | +
|
| 1906 | + Returns: |
| 1907 | + Boolean, true if success otherwise false |
| 1908 | + """ |
| 1909 | + # Update the application selection |
| 1910 | + lane_first = -1 |
| 1911 | + for lane in range(self.NUM_CHANNELS): |
| 1912 | + if ((1 << lane) & channel) == 0: |
| 1913 | + continue |
| 1914 | + if lane_first < 0: |
| 1915 | + lane_first = lane |
| 1916 | + addr = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1) |
| 1917 | + data = (appl_code << 4) | (lane_first << 1) |
| 1918 | + self.xcvr_eeprom.write(addr, data) |
| 1919 | + |
| 1920 | + # Apply DataPathInit |
| 1921 | + return self.xcvr_eeprom.write("%s_%d" % (consts.STAGED_CTRL_APPLY_DPINIT_FIELD, 0), channel) |
| 1922 | + |
| 1923 | + def get_error_description(self): |
| 1924 | + dp_state = self.get_datapath_state() |
| 1925 | + conf_state = self.get_config_datapath_hostlane_status() |
| 1926 | + for lane in range(self.NUM_CHANNELS): |
| 1927 | + name = "{}_{}_{}".format(consts.STAGED_CTRL_APSEL_FIELD, 0, lane + 1) |
| 1928 | + appl = self.xcvr_eeprom.read(name) |
| 1929 | + if (appl is None) or ((appl >> 4) == 0): |
| 1930 | + continue |
| 1931 | + |
| 1932 | + name = "DP{}State".format(lane + 1) |
| 1933 | + if dp_state[name] != CmisCodes.DATAPATH_STATE[4]: |
| 1934 | + return dp_state[name] |
| 1935 | + |
| 1936 | + name = "ConfigStatusLane{}".format(lane + 1) |
| 1937 | + if conf_state[name] != CmisCodes.CONFIG_STATUS[1]: |
| 1938 | + return conf_state[name] |
| 1939 | + |
| 1940 | + state = self.get_module_state() |
| 1941 | + if state != CmisCodes.MODULE_STATE[3]: |
| 1942 | + return state |
| 1943 | + |
| 1944 | + return None |
| 1945 | + |
1748 | 1946 | # TODO: other XcvrApi methods
|
0 commit comments