21dc0e09b3
Add chip::load_firmware(): validates the xow_dongle.bin header, DMAs the ILM and DLM images in 0x3800-byte chunks over EP 0x04 OUT with FCE completion polling, then loads the IVB and waits for the firmware to start. Probe now issues a USB reset first (port of usb_reset_device), matching xone_dongle_probe. The chip keeps its firmware across a USB reset on macOS and does not set the upstream reset-complete bit, so load_firmware falls back to the running firmware when the chip is still alive. Verified on hardware: fresh load and re-plug both return success. Add scripts/download-firmware.sh (port of install/firmware.sh), which fetches the driver CAB from Windows Update and extracts firmware/xow_dongle.bin, hash-verified. Co-Authored-By: qwen3.8-27b@q2_k_xl: ported firmware load and download script
117 lines
4.0 KiB
C++
117 lines
4.0 KiB
C++
#pragma once
|
|
|
|
// ==============================================================================
|
|
// MT76 chip register definitions (port of transport/mt76_defs.h)
|
|
// ==============================================================================
|
|
// Only the registers needed so far are ported; the rest land with the radio
|
|
// init and firmware load increments.
|
|
// ==============================================================================
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
#include "common/types.hpp"
|
|
|
|
namespace xone::mt76 {
|
|
|
|
// Bitfield helpers (port of the kernel BIT/GENMASK/FIELD_PREP macros).
|
|
inline constexpr auto bit(std::uint32_t n) -> std::uint32_t
|
|
{
|
|
return 1u << n;
|
|
}
|
|
|
|
inline constexpr auto genmask(std::uint32_t hi, std::uint32_t lo) -> std::uint32_t
|
|
{
|
|
return (~0u << lo) & (~0u >> (31 - hi));
|
|
}
|
|
|
|
inline constexpr auto field_prep(std::uint32_t mask, std::uint32_t val) -> std::uint32_t
|
|
{
|
|
return (val << __builtin_ctz(mask)) & mask;
|
|
}
|
|
|
|
// Register address flag: use the config-space vendor request codes.
|
|
constexpr std::uint32_t mt_vend_type_cfg = bit(30);
|
|
|
|
// EFUSE control register.
|
|
constexpr std::uint32_t mt_efuse_ctrl = 0x0024;
|
|
constexpr std::uint32_t mt_efuse_ctrl_aout = genmask(5, 0);
|
|
constexpr std::uint32_t mt_efuse_ctrl_mode = genmask(7, 6);
|
|
constexpr std::uint32_t mt_efuse_ctrl_ldo_off_time = genmask(13, 8);
|
|
constexpr std::uint32_t mt_efuse_ctrl_ldo_on_time = genmask(15, 14);
|
|
constexpr std::uint32_t mt_efuse_ctrl_ain = genmask(25, 16);
|
|
constexpr std::uint32_t mt_efuse_ctrl_kick = bit(30);
|
|
constexpr std::uint32_t mt_efuse_ctrl_sel = bit(31);
|
|
|
|
// EFUSE data registers (one per 32-bit word of the 16-byte block).
|
|
constexpr std::uint32_t mt_efuse_data_base = 0x0028;
|
|
|
|
// EFUSE block addresses.
|
|
constexpr std::uint16_t mt_ee_chip_id = 0x0000;
|
|
constexpr std::uint16_t mt_ee_version = 0x0002;
|
|
constexpr std::uint16_t mt_ee_mac_addr = 0x0004;
|
|
|
|
// EFUSE read modes (MT_EFUSE_CTRL_MODE field).
|
|
enum efuse_mode : std::uint32_t {
|
|
efuse_read = 0,
|
|
efuse_physical_read,
|
|
};
|
|
|
|
// MCU message header fields.
|
|
constexpr std::uint32_t mt_mcu_msg_len = genmask(15, 0);
|
|
constexpr std::uint32_t mt_mcu_msg_cmd_seq = genmask(19, 16);
|
|
constexpr std::uint32_t mt_mcu_msg_cmd_type = genmask(26, 20);
|
|
constexpr std::uint32_t mt_mcu_msg_port = genmask(29, 27);
|
|
constexpr std::uint32_t mt_mcu_msg_type = genmask(31, 30);
|
|
constexpr std::uint32_t mt_mcu_msg_type_cmd = bit(30);
|
|
|
|
// DMA message ports (MT_MCU_MSG_PORT field).
|
|
enum dma_msg_port : std::uint32_t {
|
|
wlan_port = 0,
|
|
cpu_rx_port,
|
|
cpu_tx_port,
|
|
host_port,
|
|
virtual_cpu_rx_port,
|
|
virtual_cpu_tx_port,
|
|
discard,
|
|
};
|
|
|
|
// MCU message header length (port of MT_CMD_HDR_LEN).
|
|
constexpr std::size_t cmd_hdr_len = 4;
|
|
|
|
// FCE DMA registers.
|
|
constexpr std::uint32_t mt_fce_dma_addr = 0x0230;
|
|
constexpr std::uint32_t mt_fce_dma_len = 0x0234;
|
|
|
|
// Firmware load registers and constants (port of XONE_MT_FW_*).
|
|
constexpr std::uint32_t xone_mt_rf_patch = 0x0130;
|
|
constexpr std::uint32_t fw_load_ivb = 0x12;
|
|
constexpr std::uint32_t fw_ilm_offset = 0x080000;
|
|
constexpr std::uint32_t fw_dlm_offset = 0x110800;
|
|
constexpr std::size_t fw_chunk_size = 0x3800;
|
|
|
|
// USB DMA control register and bits.
|
|
constexpr std::uint32_t mt_usb_u3dma_cfg = 0x9018;
|
|
constexpr std::uint32_t mt_usb_dma_cfg_rx_bulk_en = bit(22);
|
|
constexpr std::uint32_t mt_usb_dma_cfg_tx_bulk_en = bit(23);
|
|
|
|
// Firmware load configuration registers.
|
|
constexpr std::uint32_t mt_fce_pse_ctrl = 0x0800;
|
|
constexpr std::uint32_t mt_tx_cpu_from_fce_base_ptr = 0x09a0;
|
|
constexpr std::uint32_t mt_tx_cpu_from_fce_max_count = 0x09a4;
|
|
constexpr std::uint32_t mt_tx_cpu_from_fce_cpu_desc_idx = 0x09a8;
|
|
constexpr std::uint32_t mt_fce_pdma_global_conf = 0x09c4;
|
|
constexpr std::uint32_t mt_fce_skip_fs = 0x0a6c;
|
|
|
|
// Firmware file header (port of struct mt76_fw_header).
|
|
struct fw_header {
|
|
std::uint32_t ilm_len; // little-endian on disk
|
|
std::uint32_t dlm_len; // little-endian on disk
|
|
std::uint16_t build_ver;
|
|
std::uint16_t fw_ver;
|
|
std::uint8_t pad[4];
|
|
char build_time[16];
|
|
} XONE_PACKED;
|
|
|
|
} // namespace xone::mt76
|