-
Notifications
You must be signed in to change notification settings - Fork 35
System device interface
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.
- 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 theopx-sdi-api/inc
repository.
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.
The main components of the SDI implementation include:
- SDI core framework
- SDI system abstraction layer
- Device drivers
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.
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.
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 |
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
andentity.xml
) for the new platform
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);
}
The SDI implementation uses two XML configuration files:
device.xml
entity.xml
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.
<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
.
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.
<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>
© 2019 OpenSwitch project. All information is contributed to and made available by OPX under the Creative Commons Attribution 4.0 International License (available at http://creativecommons.org/licenses/by/4.0/).
- Home
- System overview
- Software releases
- Hardware support
- FAQs
- Install
- Build
- Configure
- Develop
- Administer
- Troubleshoot
- Software compatibility
- Contribute
- DevOps
- Join