User Interface

This page outlines the low-level mechanisms via which the AMI kernel driver exposes functionality to userspace code.

Refer to AVED Management Interface userguide (ami_tool) for details of how to use ami_tool (the command line interface tool).

Character Device Files

Each compatible PCI device gets its own character device file under /dev/amiX where ‘X’ may be an arbitrary number. There is one special device file at /dev/ami0 which is a global file created only once during driver initialisation. Currently, usage of this file is not supported and may be removed in the future.

Example cdev tree:

. /dev/
├── ami0
├── ami1
├── ami2
├── ami3
├── ami4

SYSFS

See sysfs - _The_ filesystem for exporting kernel objects — The Linux Kernel documentation

Where possible, device attributes are exposed via the sysfs subsystem. This is an easy-to-use mechanism that maps driver attributes to objects which look and behave like standard Linux files. These can be opened, read, and (depending on permissions) written to.

When a user reads or writes to a sysfs node, a callback is triggered in the driver code. A sysfs tree is created automatically for each PCI device with some standard attributes. This is located at a path that looks like /sys/devices/pci0000:c0/0000:c0:01.1/0000:c1:00.0.

The domain (0000) and device (c1:00.0) may be different depending on your setup. Note that the sysfs tree may also be accessed at /sys/class/hwmon/hwmonX/device or /sys/bus/pci/devices/0000:c1:00.0; this may be more useful, especially if you refer to the ami_tool overview command.

Example sysfs tree (standard PCI attributes have been stripped):

. /sys/class/hwmon/hwmon3/device
├── logic_uuid
├── hwmon
│   └── hwmon3
│       ├── curr1_average
│       ├── curr1_input
│       ├── curr1_label
│       ├── curr1_max
│       ├── curr1_status
│       ├── curr2_average
│       ├── curr2_input
│       ├── curr2_label
│       ├── curr2_max
│       ├── curr2_status
│       ├── curr3_average
│       ├── curr3_input
│       ├── curr3_label
│       ├── curr3_max
│       ├── curr3_status
│       ├── device -> ../../../0000:c1:00.0
│       ├── in0_average
│       ├── in0_input
│       ├── in0_label
│       ├── in0_max
│       ├── in0_status
│       ├── in1_average
│       ├── in1_input
│       ├── in1_label
│       ├── in1_max
│       ├── in1_status
│       ├── in2_average
│       ├── in2_input
│       ├── in2_label
│       ├── in2_max
│       ├── in2_status
│       ├── name
│       ├── power
│       │   ├── async
│       │   ├── autosuspend_delay_ms
│       │   ├── control
│       │   ├── runtime_active_kids
│       │   ├── runtime_active_time
│       │   ├── runtime_enabled
│       │   ├── runtime_status
│       │   ├── runtime_suspended_time
│       │   └── runtime_usage
│       ├── power1_average
│       ├── power1_input
│       ├── power1_label
│       ├── power1_max
│       ├── power1_status
│       ├── subsystem -> ../../../../../../class/hwmon
│       ├── temp1_input
│       ├── temp1_label
│       ├── temp1_max
│       ├── temp1_status
│       ├── temp2_input
│       ├── temp2_label
│       ├── temp2_max
│       ├── temp2_status
│       ├── temp3_input
│       ├── temp3_label
│       ├── temp3_max
│       ├── temp3_status
│       ├── uevent
│       └── update_interval

Driver Attributes

Typically, SYSFS is used to expose device attributes, however, the driver itself may also expose some of its own global attributes. These can be located at /sys/bus/pci/drivers/ami. Currently, the following attributes are supported:

  • devices - when read, returns a map of all PCI devices registered with the driver in the format “<BDF> <cdev_num> <hwmon_num>”. This map can be used to determine where to look for the device you are interested in. For example, the map “c1:00.0 3 4” means that the device with BDF c1:00.0 has a character device file at /dev/ami3 and a hwmon tree at /sys/class/hwmon/hwmon4. A hwmon number value of -1 means that the device does not support the functionality. All devices will have a vaild character device, however. The first line read from the ‘devices’ file is a number representing the total number of devices attached to the driver.

  • version - when read, returns the current driver version in the format “MAJOR.MINOR.PATCH +COMMITS *STATUS”.

HWMON

See The Linux Hardware Monitoring kernel API — The Linux Kernel documentation

HWMON builds on the sysfs subsystem to provide sensor monitoring. This creates an attribute tree at /sys/class/hwmon/hwmonX.

For an example of the HWMON interface see the section above. For all intents and purposes, hwmon behaves exactly the same as sysfs.

IOCTL

IOCTL provides a way to perform arbitrary actions on character device files. An IOCTL is uniquely defined by a magic number and is executed with the ioctl() call. Each IOCTL can be thought of as a unique (and undocumented) system call which can take any arbitrary argument and copy memory between kernel/user space.

These are used sparingly and only when no other solution exists. The below table defines the IOCTL calls supported by the AMI driver.

#define AMI_IOC_MAGIC ‘a’

IOCTLDefinitionInputOutputRequires Elevated PermissionsSuperuser OnlyRequired Device State
AMI_IOC_DOWNLOAD_PDI_IOW(AMI_IOC_MAGIC, 0, struct ami_ioc_data_payload*)struct ami_ioc_data_payload* populated with the PDI image dataN/AYesNoREADY/COMPAT
AMI_IOC_READ_BAR_IOWR(AMI_IOC_MAGIC, 1, struct ami_ioc_bar_data*)struct ami_ioc_bar_data* with attributes appropriately setData will be copied to buffer at the given addressYesNoAny state except INIT and SHUTDOWN
AMI_IOC_WRITE_BAR_IOW(AMI_IOC_MAGIC, 2, struct ami_ioc_bar_data*)struct ami_ioc_bar_data* with attributes appropriately set - buffer at given address must be populated with data to writeN/AYesNoAny state except INIT and SHUTDOWN
AMI_IOC_GET_SENSOR_VALUE_IOWR(AMI_IOC_MAGIC, 3, struct ami_ioc_sensor_value*)struct ami_ioc_sensor_value* with "hwmon_channel" and "sensor_type" set appropriately"val", "status", and "fresh" attributes of the given struct will be populatedNoNoREADY only
AMI_IOC_DEVICE_BOOT_IOW(AMI_IOC_MAGIC, 4, struct ami_ioc_data_payload*)struct ami_ioc_data_payload* with "partition" field setN/AYesNoREADY/COMPAT
AMI_IOC_COPY_PARTITION_IOW(AMI_IOC_MAGIC, 5, struct ami_ioc_data_payload*)struct ami_ioc_data_payload* with "src" and "dest" fields setN/AYesNoREADY only
AMI_IOC_SET_SENSOR_REFRESH_IOW(AMI_IOC_MAGIC, 6, uint16_t)new sensor refresh specifiedN/ANoNoREADY only
AMI_IOC_GET_FPT_HDR_IOR(AMI_IOC_MAGIC, 7, struct ami_ioc_fpt_hdr_value*)struct ami_ioc_fpt_hdr_value*Provided struct is populatedNoNoREADY only
AMI_IOC_GET_FPT_PARTITION_IOWR(AMI_IOC_MAGIC, 8, struct ami_ioc_fpt_partition_value*)struct ami_ioc_fpt_partition_value* with "partition" field setRemaining fields in provided struct are populatedNoNoREADY only
AMI_IOC_GET_MFG_INFO_IOR(AMI_IOC_MAGIC, 9, struct ami_ioc_mfg_info_payload*)struct ami_ioc_mfg_info_payload*Provided struct is populatedNoNoREADY only
AMI_IOC_READ_EERPOM_IOWR(AMI_IOC_MAGIC, 10, struct ami_ioc_eeprom_data*)struct ami_ioc_eeprom_data* with "len", "addr", and "offset" fields setData copied to buffer at given addressNoNoREADY only
AMI_IOC_WRITE_EEPROM_IOW(AMI_IOC_MAGIC, 11, struct ami_ioc_eeprom_data*)struct ami_ioc_eeprom_data* with "len", "addr", and "offset" fields setN/ANoNoREADY only

Page Revision: v. 19