Thin firmware spec
This documents the thin firmware commands as found on the XO-1. For the XO-1.5 libertas_tf driver and firmware, we will follow this spec. Any deviations and changes will be marked below as we progress.
Command summary
The following table summaries the commands found in libertas_tf, and details where they are used.
To determine the above matrix, we started with the command definitions defined in libertastf.h. We then did searches to collate these commands with where they appeared in libertastf and in both the XO1 Thin Firmware and the XO 1.5 Full Firmware. As expected, several commands that were added to the XO1 Thin Firmware were not present in the XO 1.5 Full Firmware. A big surprise however, was the command CMD_802_11_RF_TX_POWER which was defined in the header, supported by both firmwares, yet never implemented in libertastf.
Command details
Common
Each command packet starts with an 8 byte header, struct cmd_header which contains the basic information such as the command, the size of the packet, seqnum and result. The result code is not used in sending a command to the firmware, it should be set to 0.
struct cmd_header { __le16 command; __le16 size; __le16 seqnum; __le16 result; } __attribute__ ((packed));
All fields that are 16 or 32 bit are stored in little endian. cpu_to_le16() is typically used.
It is unfortunately common for unused values to not be properly zeroed out by the driver before sending commands to the firmware. Unused fields are generally ignored, but we still shouldn't be sending garbage data in those fields, especially in cases where the Marvell documentation states to set fields to a specific value (typically 0). This should be fixed.
CMD_GET_HW_SPEC
- 0x0003
- This command queries hardware and other configuration data from the
WLAN SoC, including the MAC address, multicast address list size, and hardware version number. In query, set all values to 0. The reply will return the information as per Marvell specification
Sample:
03 00 2e 00 02 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Structure:
- struct cmd_ds_get_hw_spec {
struct cmd_header hdr;
/* HW Interface version number */ __le16 hwifversion; /* HW version number */ __le16 version; /* Max number of TxPD FW can handle */ __le16 nr_txpd; /* Max no of Multicast address */ __le16 nr_mcast_adr; /* MAC address */ u8 permanentaddr[6];
/* region Code */ __le16 regioncode;
/* Number of antenna used */ __le16 nr_antenna;
/* FW release number, example 0x01030304 = 2.3.4p1 */ __le32 fwrelease;
/* Base Address of TxPD queue */ __le32 wcb_base; /* Read Pointer of RxPd queue */ __le32 rxpd_rdptr;
/* Write Pointer of RxPd queue */ __le32 rxpd_wrptr;
/*FW/HW capability */ __le32 fwcapinfo; } __attribute__ ((packed)); Use in libertas_tf:
- Used in the 80211 ops .start
CMD_802_11_RESET
- 0x0005
- Reboots the SoC. Note that this is not documented in the Marvell
documentation.
- "action" is set to CMD_ACT_HALT (0x0003). However, the firmware
seems to do a direct reboot call on receiving the RESET command and doesn't look at the action. Structure:
- struct cmd_ds_802_11_reset {
struct cmd_header hdr;
__le16 action; }; Use in libertas_tf:
- Used by if_usb_reset_device()
CMD_MAC_MULTICAST_ADR
- 0x0010
- This command is used to program multicast MAC address into the
hardware filter table in the WLAN SoC. The packets sent from these multicast MAC addresses are accepted.
- "action" is either CMD_ACT_GET (0x0000) or CMD_ACT_SET (0x0001)
- The 8388 may have a maximum of 32 multicast addresses set.
- The driver only ever sets the multicast addresses, it never reads the
table. Sample:
Structure:
- struct cmd_ds_mac_multicast_addr {
struct cmd_header hdr;
__le16 action; __le16 nr_of_adrs; u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; }; Use in libertas_tf:
- Used in the 80211 ops .configure_filter
CMD_802_11_RADIO_CONTROL
- 0x001c
- This command is used to control the PHY
- "action" may be either CMD_ACT_GET (0x0000) or CMD_ACT_SET (0x0001)
- "control" may either be RADIO_ON (0x0001) or RADIO_OFF (0x0000)
- While the documentation specifies that control bits [15:1] as
reserved and set to 0, I saw the driver set control to 0x0005. The driver seems to have a series of constants that it ORs with this parameter: SET_AUTO_PREAMBLE, SET_SHORT_PREAMBLE, SET_LONG_PREAMBLE. These may no longer be required, require a different command to set, or are customizations in the Firmware. Sample:
- 1c 00 0c 00 08 00 00 00 01 00 01 00
Structure:
- struct cmd_ds_802_11_radio_control {
struct cmd_header hdr;
__le16 action; __le16 control; }; Use in libertas_tf:
- Used in the 80211 ops .start
- Used in the 80211 ops .stop
- Used in 802.11 ops .bss_info_changed
CMD_802_11_RF_CHANNEL
- 0x001d
- This command gets or sets the current channel value.
- "action" may be either CMD_ACT_GET (0x0000) or CMD_ACT_SET (0x0001)
- "channel" is the current channel number to set or get.
- "rftype", "reserved" and "channellist" are all listed as reserved or
not used and should be set to 0.
- The driver doesn't properly clear out the memory used by the
structure, hence command dumps of this command show random data in rftype, reserved, and channellist fields. Sample:
- 1d 00 30 00 09 00 00 00 01 00 01 00 00 00 00 00
01 00 00 00 8c 2b 18 cc 22 18 60 c0 00 38 17 cc 00 00 00 00 00 38 17 cc 20 34 f8 c7 00 00 00 00 Structure:
- struct cmd_ds_802_11_rf_channel {
struct cmd_header hdr;
__le16 action; __le16 channel; __le16 rftype; /* unused */ __le16 reserved; /* unused */ u8 channellist[32]; /* unused */ }; Use in libertas_tf:
- Used in the 80211 ops .config
CMD_802_11_RF_TX_POWER
- 0x001e
- This command gets or sets the transmit power level.
- "action" may be either CMD_ACT_GET (0x0000) or CMD_ACT_SET (0x0001)
- "CurrentLevel" defines the power level. See Marvell documentation
for details.
- This command is unused in the current libertas_tf driver.
CMD_MAC_CONTROL
- 0x0028
- This command is used to control the hardware MAC.
- "action" is a set of bitfields. See documentation for details.
- Note: documentation and the defines in libertastf.h don't seem to
agree. Sample:
- 28 00 0c 00 03 00 00 00 03 00 00 00
Structure:
- struct cmd_ds_mac_control {
struct cmd_header hdr; __le16 action; u16 reserved; }; Use in libertas_tf:
- Used in lbtf_setup_firmware, called from 80211 ops .start
- Used in the 80211 ops .configure_filter
CMD_802_11_MAC_ADDRESS
- 0x004d
- Set or get the MAC address.
- "action" may be either CMD_ACT_GET (0x0000) or CMD_ACT_SET (0x0001)
- "macadd" is the MAC address to set.
Sample:
- 4d 00 10 00 06 00 00 00 01 00 00 17 c4 14 68 7a
Structure:
- struct cmd_ds_802_11_mac_address {
struct cmd_header hdr;
__le16 action; uint8_t macadd[ETH_ALEN]; }; Use in libertas_tf:
- Used in the 80211 ops .add_interface
CMD_SET_BOOT2_VER
- 0x00a5
- Set the boot2 version id.
- This command was added for the libertas_tf. It simply sets a version
id in the firmware, I am unsure of exactly why it's necessary or what its purpose is.
- "action" is 0.
- "version" is the boot2 version to set. Note that this is not
converted into little endian. Sample:
- a5 00 0c 00 01 00 00 00 00 00 07 31
Structure:
- struct cmd_ds_set_boot2_ver {
struct cmd_header hdr;
__le16 action; __le16 version; }; Use in libertas_tf:
- Called during firmware loading.
CMD_802_11_BEACON_CTRL
- 0x00b0
- Enable or disable the beacon, and set the interval.
- "action" may be either CMD_ACT_GET (0x0000) or CMD_ACT_SET (0x0001).
It looks like only SET is implmented in the thin firmware.
- "beacon_enable" may either be 0 to disable, or non-0 to enable.
- "period" is the beacon interval to set.
Sample:
Structure:
- struct cmd_ds_802_11_beacon_control {
struct cmd_header hdr;
__le16 action; __le16 beacon_enable; __le16 beacon_period; }; Use in libertas_tf:
- Used in the 80211 ops .config_interface
- Used in the 80211 ops .remove_interface
CMD_802_11_BEACON_SET
- 0x00cb
- Set the beacon.
- "len" is the length of the data in "beacon".
- "beacon" is the beacon to set.
Sample:
Structure:
- struct cmd_ds_802_11_beacon_set {
struct cmd_header hdr;
__le16 len; u8 beacon[MRVL_MAX_BCN_SIZE]; }; Use in libertas_tf:
- Used in the 80211 ops .config_interface
- Used in the 80211 ops .set_tim
CMD_802_11_SET_MODE
- 0x00cc
- Set the mode.
- "mode" may be one of LBTF_PASSIVE_MODE, LBTF_STA_MODE, LBTF_AP_MODE.
Sample:
- cc 00 0a 00 05 00 00 00 01 00
Structure:
- struct cmd_ds_set_mode {
struct cmd_header hdr;
__le16 mode; }; Use in libertas_tf:
- Used in the 80211 ops .add_interface
- Used in the 80211 ops .remove_interface
CMD_802_11_SET_BSSID
- 0x00cd
- Set the bssid.
- "bssid" is the bssid to set.
- "activate" is non-zero to activate.
Sample:
- cd 00 0f 00 07 00 00 00 00 00 00 00 00 00 01
Structure:
- struct cmd_ds_set_bssid {
struct cmd_header hdr;
u8 bssid[6]; u8 activate; }; Use in libertas_tf:
- Called during device startup.
- Used in the 80211 ops .config_interface (to activate and set bssid)
- Used in the 80211 ops .remove_interface (to deactivate)