Skip to content

System device interface

Amy Buck edited this page Aug 7, 2017 · 19 revisions

The system device interface (SDI) API provides an abstraction of all hardware devices that realize a switching platform — except for network processors. This allows the upper software layers to be independent of lower level hardware details. The platform abstraction service (PAS) component is the main user of the SDI API. The SDI is implemented as a library and the PAS provides process context for execution.

SDI API definitions

  • Entities — aggregate resources into higher-level abstractions
  • Resources — hardware devices that an entity aggregates

Entities represent physical objects that can be replaced or represented as a single unit — power supply units (PSUs), fan trays, and the system board. Entities are identifiable with unique part numbers.

NOTE: Entities and resources are defined in the sdi_entity.h file which is located in the opx-sdi-api/inc repository.

Design concepts

The SDI component implements the SDI API. Since the ADI API is an abstract layer, any other SDI implementation that provides the functions, entities, and resources defined in the SDI API can theoretically be used.

To illustrate how entities and resources are related to one another, consider the case of a fan tray unit. The SDI API represents the fan tray unit as an entity — this is the only object that an application (PAS) interacts with. Internally, the SDI implementation for the fan tray entity of a specific hardware platform may aggregate the following:

  • Fan-specific resources — provided by a fan controller device driver
  • Fan tray presence — provided by a CPLD or GPIO pin (optional)
  • Fan tray LED failure — provided by a CPLD pin (optional)

Other platforms and/or fan tray devices may also provide temperature sensors. In this case, a temperature sensor resource is also added to the fan tray.

CAUTION: The OpenSwitch OPX SDI library is intended to be used by the PAS process only. Using the library concurrently from other applications may lead to undesired race conditions (such as accessing the i2C/SMBus).

Aggregation of resources and corresponding device drivers into entities is defined in configuration files (see SDI configuration files below for more information). The aggregation is not hard coded — you can customize it for any particular hardware platform or devices.

Components

The main components of the SDI implementation include:

  • SDI core framework
  • SDI system abstraction layer
  • Device drivers

SDI core framework

The SDI core provides a framework for SDI resources and drivers. This component provides a south-bound (hardware facing) API for device drivers to register with the core framework — hardware resources and driver callback functions.

The north-bound SDI core framework SDI provides a generic set of query, set, and control functions implemented by the device drivers callback functions. These APIs are used to aggregate devices and their resources into platform-independent logical SDI entities.

At initialization time, device drivers register with the SDI core framework as plugins. Registration is performed based on the platform configuration files.

SDI system abstraction layer

The SDI system entity abstraction layer provides abstract implementation for resources (such as thermal, fans, LEDs, media/transceivers, and so on), and a generic implementation of SDI entities which is platform-independent. The SDI abstraction layer implementation calls the functions registered by the device driver layer with the SDI core framework.

This component maps resources to entities and also ensures that every API defined for an entity is translated to the appropriate resource/driver API. The devices and resources that makeup a specific entity are specified using the entity.xml configuration file.

Device drivers

The SDI device drivers component provides low-level, chip-specific implementation for hardware access. Drivers are responsible for initializing devices and representing their functionality as a set of SDI resources. Device drivers are executed in Linux user space.

Each device driver implements the following:

  • Driver registration function
  • Driver initialization function

These functions are provided as callbacks in the sdi_driver_t structure. Each device driver must export a function with the sdi_<driver_name>_query_callbacks name that returns a pointer to the sdi_driver_t structure for that particular driver. The driver name must match the name of the driver provided in the configuration file — the SDI core framework reads the configuration file, then invokes the sdi_<driver_name>_query_callbacks function to initialize and register that particular driver.

Repository Description
opx-pas-config-<platform_name>/cfg/sdi Configuration files for a specific platform
opx-sdi-device-driver SDI device drivers
opx-sdi-framework SDI core framework
opx-sdi-sdi SDI API definitions (header files)
opx-sdi-sys SDI abstraction layer

New hardware platform portability

When porting the SDI to a new platform, you must consider the following:

  • Determine if the current device drivers support all hardware devices of the new platform. If not, new device drivers must be implemented (such as a new fan controller or temperature sensor device driver)
  • Create an SDI configuration file (device.xml and entity.xml) for the new platform

Writing an SDI device driver

The current SDI implementation provides device drivers for the following which must be maintained in XML configuration files:

  • Temperature sensors
  • Fan controllers
  • Transceivers (QSFPs and SFPs)
  • EEPROM
  • PSU controllers
  • CPLD
  • I2C bus devices and multiplexors

Implementing a new driver requires:

  • Driver initialization function (perform chipset and driver data structure initialization functions as needed)
  • Driver registration function
  • Driver-specific callback functions

Consider a device driver for a temperature sensor — sdi_max6699.c. The driver implements and exports the registration and initialization functions:

/*
 * Every driver must export a function with name sdi_<driver_name>_query_callbacks
 * so that the driver framework is able to look up and invoke it to get the callbacks
 */
const sdi_driver_t * sdi_max6699_entry_callbacks(void)
{
    /*Export Driver table*/
    static const sdi_driver_t max6699_entry = {
        sdi_max6699_register,
        sdi_max6699_init
    };

    return &max6699_entry;
}

The SDI driver framework (sdi_driver_framework.c and sdi_get_device_driver function) calls sdi_max_6699_entry_callbacks at initialization time when loading the driver library (assuming the max6699 device is configured for the current platform). The callbacks field of the sdi_device_hdl_t SDI driver framework (sdi_driver_framework.c and sdi_device_init function) invokes sdi_max6699_init as a callback (device > callbacks > init).

All temperature sensor drivers must implement a set of temperature sensor-specific functions:

  • Resource initialization (for data structures and temperature sensor resources)
  • Get temperature
  • Threshold set/get functions (for temperature sensor alerts and actions)
  • Get status

The sdi_max6699_init driver registration function registers these functions with the SDI driver framework as callbacks:

static temperature_sensor_t max6699_sensor={
        sdi_max6699_resource_init,
        sdi_max6699_temperature_get,
        sdi_max6699_threshold_get,
        sdi_max6699_threshold_set,
        sdi_max6699_status_get
};
…
static void sdi_max6699_device_database_init(
    std_config_node_t cur_node, void *dev)
{
…
   sdi_resource_add(SDI_RESOURCE_TEMPERATURE,
      max6699_data->alias[sensor_id],
      sdi_max6699_create_resource_hdl(dev_hdl,sensor_id),
      &max6699_sensor);
}

The sdi_max6699_device_database_init function is called from sdi_max6699_register at driver registration time. A node corresponds to a device (temperature sensor resource) in the platform configuration file. Similar callback structures are defined for other driver types (fan controllers, PSUs, transceivers such as SFPs and QSFPs, and so on).

NOTE: Each temperature sensor resource is registered according to the XML configuration file.

static t_std_error sdi_max6699_register(
    std_config_node_t node, void *bus_handle,
    sdi_device_hdl_t* device_hdl)
{
…
    std_config_for_each_node(node, 
         sdi_max6699_device_database_init, dev_hdl);
}

SDI configuration files

The SDI implementation uses two XML configuration files:

  • device.xml
  • entity.xml

Device configuration file

Each device is identified by an XML node in the device.xml configuration file. A device typically requires per-platform configuration after which the device could export specific resources. XML nodes (devices) can embed other devices such as an IC2 bus or multiplexor (MUX) devices can embed temperature sensors and other devices — the relationship describes which I2C devices can be accessed using a given I2C bus or MUX.

device.xml — multiple temperature sensor devices

<root>
…

     <sys_i2c instance="3" sysfs_name="i2c-1-mux (chan_id 1)" bus_name="smbus3" dev_name="/dev/i2c-3">
          <max6699 instance="0" addr="0x1a">
            <temp_sensor instance="1" low_threshold="10" high_threshold="100" />
            <temp_sensor instance="2" low_threshold="10" high_threshold="100" />
          </max6699>
     </sys_i2c>

    <sys_i2c instance="11" sysfs_name="i2c-8-mux (chan_id 1)" bus_name="smbus11" dev_name="/dev/i2c-11">
        <max6699 instance="1" addr="0x1a">
            <temp_sensor instance="0" low_threshold="10" high_threshold="100" />
            <temp_sensor instance="1" low_threshold="10" high_threshold="100" />
            <temp_sensor instance="2" low_threshold="10" high_threshold="100" />
            <temp_sensor instance="3" low_threshold="10" high_threshold="100" />
            <temp_sensor instance="4" low_threshold="10" high_threshold="100" />
        </max6699>
   </sys_i2c>
…
</root>

A max6699 temperature sensor device driver can contain up to five sensor instances. In this example, there are two devices (instance 0 and instance 1) — one of them accessed using I2C bus instance 3 (Linux device /dev/i2c-3) and the other one accessed through I2C bus instance 11 (Linux device /dev/i2c-11).

The sensor device is addressed using the 0x1a I2C address in both cases. Only two of the sensors are used for the max6699 device instance 0.

Entity configuration file

The entity.xml configuration file identifies devices and resources associated with each entity. An entity node in the file contains a list of associated resources specified using a reference attribute value. The values of the reference attribute refer to device names and instances defined in the device.xml file.

entity.xml — system board with multiple temperature sensor resources

<root>
…
    <entity instance="1" type="SDI_ENTITY_SYSTEM_BOARD" presence="FIXED_SLOT" alias="System Board" cold_reset="0xaa" cold_reset_register="software_reset_control">
        <resource reference="max6699-0-1" name="CPU Front to Rear temp sensor" />
        <resource reference="max6699-0-2" name="CPU Rear to Front temp sensor" />
        <resource reference="max6699-1-0" name="Rear to Front Inlet Ambient sensor" />
        <resource reference="max6699-1-1" name="Rear to Front Helix shutdown sensor" />
        <resource reference="max6699-1-2" name="Front to Rear right Inlet Ambient sensor" />
        <resource reference="max6699-1-3" name="Front to Rear Helix shutdown sensor" />
        <resource reference="max6699-1-4" name="Front to Rear left Inlet Ambient sensor" />
…
    </entity instance>
</root>

Note the values of each resource reference attribute. max6699-0-1 refers to the temp_sensor instance 1 node, and max6699-0-2 refers to the temp_sensor instance 2 node in the device.xml file.

<max6699 instance="0" addr="0x1a">
    <temp_sensor instance="1" low_threshold="10" high_threshold="100" />
    <temp_sensor instance="2" low_threshold="10" high_threshold="100" />
</max6699>
Clone this wiki locally