#ifndef _AQ_HW_H_
#define _AQ_HW_H_
#include <sys/types.h>
#include <sys/cdefs.h>
#include <machine/cpufunc.h>
#include <sys/endian.h>
#include <net/ethernet.h>
#include "aq_common.h"
#define AQ_WRITE_REG(hw, reg, value) writel(((hw)->hw_addr + (reg)), htole32(value))
#define AQ_READ_REG(hw, reg) le32toh(readl((hw)->hw_addr + reg))
#define AQ_WRITE_REG_BIT(hw, reg, msk, shift, value) do { \
if (msk ^ ~0) { \
uint32_t reg_old, reg_new = 0U; \
reg_old = AQ_READ_REG(hw, reg); \
reg_new = (reg_old & (~msk)) | (value << shift); \
if (reg_old != reg_new) \
AQ_WRITE_REG(hw, reg, reg_new); \
} else { \
AQ_WRITE_REG(hw, reg, value); \
} \
} while(0)
#define AQ_READ_REG_BIT(a, reg, msk, shift) ( \
((AQ_READ_REG(a, reg) & msk) >> shift))
#define AQ_HW_FLUSH() { (void)AQ_READ_REG(hw, 0x10); }
#define aq_hw_write_reg_bit AQ_WRITE_REG_BIT
#define aq_hw_write_reg AQ_WRITE_REG
struct aq_hw_stats {
uint64_t crcerrs;
};
struct aq_hw_stats_s {
uint32_t uprc;
uint32_t mprc;
uint32_t bprc;
uint32_t erpt;
uint32_t uptc;
uint32_t mptc;
uint32_t bptc;
uint32_t erpr;
uint32_t mbtc;
uint32_t bbtc;
uint32_t mbrc;
uint32_t bbrc;
uint32_t ubrc;
uint32_t ubtc;
uint32_t ptc;
uint32_t prc;
uint32_t dpc;
uint32_t cprc;
} __attribute__((__packed__));
union ip_addr {
struct {
uint8_t addr[16];
} v6;
struct {
uint8_t padding[12];
uint8_t addr[4];
} v4;
} __attribute__((__packed__));
struct aq_hw_fw_mbox {
uint32_t version;
uint32_t transaction_id;
int error;
struct aq_hw_stats_s stats;
} __attribute__((__packed__));
typedef struct aq_hw_fw_version {
union {
struct {
uint16_t build_number;
uint8_t minor_version;
uint8_t major_version;
};
uint32_t raw;
};
} aq_hw_fw_version;
enum aq_hw_irq_type {
aq_irq_invalid = 0,
aq_irq_legacy = 1,
aq_irq_msi = 2,
aq_irq_msix = 3,
};
struct aq_hw_fc_info {
bool fc_rx;
bool fc_tx;
};
struct aq_hw {
void *aq_dev;
uint8_t *hw_addr;
uint32_t regs_size;
uint8_t mac_addr[ETHER_ADDR_LEN];
enum aq_hw_irq_type irq_type;
struct aq_hw_fc_info fc;
uint16_t link_rate;
uint16_t device_id;
uint16_t subsystem_vendor_id;
uint16_t subsystem_device_id;
uint16_t vendor_id;
uint8_t revision_id;
int itr;
aq_hw_fw_version fw_version;
const struct aq_firmware_ops* fw_ops;
bool rbl_enabled;
bool fast_start_enabled;
bool flash_present;
uint32_t chip_features;
uint64_t fw_caps;
bool lro_enabled;
uint32_t mbox_addr;
struct aq_hw_fw_mbox mbox;
};
#define aq_hw_s aq_hw
#define AQ_HW_MAC 0U
#define AQ_HW_MAC_MIN 1U
#define AQ_HW_MAC_MAX 33U
#define HW_ATL_B0_MIN_RXD 32U
#define HW_ATL_B0_MIN_TXD 32U
#define HW_ATL_B0_MAX_RXD 4096U
#define HW_ATL_B0_MAX_TXD 4096U
#define HW_ATL_B0_MTU_JUMBO 16352U
#define HW_ATL_B0_TSO_SIZE (160*1024)
#define HW_ATL_B0_RINGS_MAX 32U
#define HW_ATL_B0_LRO_RXD_MAX 16U
#define AQ_HW_FW_SM_RAM 0x2U
#define AQ_HW_MPI_STATE_MSK 0x00FFU
#define AQ_HW_MPI_STATE_SHIFT 0U
#define AQ_HW_MPI_CONTROL_ADR 0x0368U
#define AQ_HW_MPI_STATE_ADR 0x036CU
#define HW_ATL_RSS_INDIRECTION_TABLE_MAX 64U
#define HW_ATL_RSS_HASHKEY_SIZE 40U
#define AQ_HW_PCI_REG_CONTROL_6_ADR 0x1014U
#define AQ_HW_TX_DMA_TOTAL_REQ_LIMIT_ADR 0x00007b20U
#define AQ_HW_TXBUF_MAX 160U
#define AQ_HW_RXBUF_MAX 320U
#define L2_FILTER_ACTION_DISCARD (0x0)
#define L2_FILTER_ACTION_HOST (0x1)
#define AQ_HW_UCP_0X370_REG (0x370)
#define AQ_HW_CHIP_MIPS 0x00000001U
#define AQ_HW_CHIP_TPO2 0x00000002U
#define AQ_HW_CHIP_RPF2 0x00000004U
#define AQ_HW_CHIP_MPI_AQ 0x00000010U
#define AQ_HW_CHIP_REVISION_A0 0x01000000U
#define AQ_HW_CHIP_REVISION_B0 0x02000000U
#define AQ_HW_CHIP_REVISION_B1 0x04000000U
#define IS_CHIP_FEATURE(HW, _F_) (AQ_HW_CHIP_##_F_ & \
(HW)->chip_features)
#define AQ_HW_FW_VER_EXPECTED 0x01050006U
#define AQ_RX_RSS_TYPE_NONE 0x0
#define AQ_RX_RSS_TYPE_IPV4 0x2
#define AQ_RX_RSS_TYPE_IPV6 0x3
#define AQ_RX_RSS_TYPE_IPV4_TCP 0x4
#define AQ_RX_RSS_TYPE_IPV6_TCP 0x5
#define AQ_RX_RSS_TYPE_IPV4_UDP 0x6
#define AQ_RX_RSS_TYPE_IPV6_UDP 0x7
enum hw_atl_rx_action_with_traffic {
HW_ATL_RX_DISCARD,
HW_ATL_RX_HOST,
HW_ATL_RX_MNGMNT,
HW_ATL_RX_HOST_AND_MNGMNT,
HW_ATL_RX_WOL
};
struct aq_rx_filter_vlan {
uint8_t enable;
uint8_t location;
uint16_t vlan_id;
uint8_t queue;
};
#define AQ_HW_VLAN_MAX_FILTERS 16U
#define AQ_HW_ETYPE_MAX_FILTERS 16U
struct aq_rx_filter_l2 {
uint8_t enable;
int8_t queue;
uint8_t location;
uint8_t user_priority_en;
uint8_t user_priority;
uint16_t ethertype;
};
enum hw_atl_rx_ctrl_registers_l2 {
HW_ATL_RX_ENABLE_UNICAST_MNGNT_QUEUE_L2 = BIT(19),
HW_ATL_RX_ENABLE_UNICAST_FLTR_L2 = BIT(31)
};
struct aq_rx_filter_l3l4 {
uint32_t cmd;
uint8_t location;
uint32_t ip_dst[4];
uint32_t ip_src[4];
uint16_t p_dst;
uint16_t p_src;
bool is_ipv6;
};
enum hw_atl_rx_protocol_value_l3l4 {
HW_ATL_RX_TCP,
HW_ATL_RX_UDP,
HW_ATL_RX_SCTP,
HW_ATL_RX_ICMP
};
enum hw_atl_rx_ctrl_registers_l3l4 {
HW_ATL_RX_ENABLE_MNGMNT_QUEUE_L3L4 = BIT(22),
HW_ATL_RX_ENABLE_QUEUE_L3L4 = BIT(23),
HW_ATL_RX_ENABLE_ARP_FLTR_L3 = BIT(24),
HW_ATL_RX_ENABLE_CMP_PROT_L4 = BIT(25),
HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 = BIT(26),
HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4 = BIT(27),
HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3 = BIT(28),
HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3 = BIT(29),
HW_ATL_RX_ENABLE_L3_IPv6 = BIT(30),
HW_ATL_RX_ENABLE_FLTR_L3L4 = BIT(31)
};
#define HW_ATL_RX_BOFFSET_PROT_FL3L4 0U
#define HW_ATL_RX_BOFFSET_QUEUE_FL3L4 8U
#define HW_ATL_RX_BOFFSET_ACTION_FL3F4 16U
#define HW_ATL_RX_CNT_REG_ADDR_IPV6 4U
#define HW_ATL_GET_REG_LOCATION_FL3L4(location) \
((location) - AQ_RX_FIRST_LOC_FL3L4)
enum aq_hw_fw_mpi_state_e {
MPI_DEINIT = 0,
MPI_RESET = 1,
MPI_INIT = 2,
MPI_POWER = 4,
};
int aq_hw_get_mac_permanent(struct aq_hw *hw, uint8_t *mac);
int aq_hw_mac_addr_set(struct aq_hw *hw, uint8_t *mac_addr, uint8_t index);
int aq_hw_get_link_state(struct aq_hw *hw, uint32_t *link_speed,
struct aq_hw_fc_info *fc_neg);
int aq_hw_set_link_speed(struct aq_hw *hw, uint32_t speed);
int aq_hw_fw_downld_dwords(struct aq_hw *hw, uint32_t a, uint32_t *p, uint32_t cnt);
int aq_hw_reset(struct aq_hw *hw);
int aq_hw_mpi_create(struct aq_hw *hw);
int aq_hw_mpi_read_stats(struct aq_hw *hw, struct aq_hw_fw_mbox *pmbox);
int aq_hw_init(struct aq_hw *hw, uint8_t *mac_addr, uint8_t adm_irq, bool msix);
int aq_hw_start(struct aq_hw *hw);
int aq_hw_interrupt_moderation_set(struct aq_hw *hw);
int aq_hw_get_fw_version(struct aq_hw *hw, uint32_t *fw_version);
int aq_hw_deinit(struct aq_hw *hw);
int aq_hw_ver_match(const aq_hw_fw_version* ver_expected,
const aq_hw_fw_version* ver_actual);
void aq_hw_set_promisc(struct aq_hw_s *self, bool l2_promisc, bool vlan_promisc,
bool mc_promisc);
int aq_hw_set_power(struct aq_hw *hw, unsigned int power_state);
int aq_hw_err_from_flags(struct aq_hw *hw);
int hw_atl_b0_hw_vlan_promisc_set(struct aq_hw_s *self, bool promisc);
int hw_atl_b0_hw_vlan_set(struct aq_hw_s *self,
struct aq_rx_filter_vlan *aq_vlans);
int aq_hw_rss_hash_set(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]);
int aq_hw_rss_hash_get(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]);
int aq_hw_rss_set(struct aq_hw_s *self, uint8_t rss_table[HW_ATL_RSS_INDIRECTION_TABLE_MAX]);
int aq_hw_udp_rss_enable(struct aq_hw_s *self, bool enable);
#endif