/*	$NetBSD: if_athn_usb.h,v 1.6 2019/09/14 12:36:35 maxv Exp $	*/
/*	$OpenBSD: if_athn_usb.h,v 1.3 2012/11/10 14:35:06 mikeb Exp $	*/

/*-
 * Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _IF_ATHN_USB_H_
#define _IF_ATHN_USB_H_

/* Maximum number of STAs firmware can handle. */
#define AR_USB_MAX_STA	8

#define AR_USB_DEFAULT_NF	(-95)

/* USB requests. */
#define AR_FW_DOWNLOAD		0x30
#define AR_FW_DOWNLOAD_COMP	0x31

/* USB endpoints addresses. */
#define AR_PIPE_TX_DATA	(UE_DIR_OUT | 1)
#define AR_PIPE_RX_DATA	(UE_DIR_IN  | 2)
#define AR_PIPE_RX_INTR	(UE_DIR_IN  | 3)
#define AR_PIPE_TX_INTR	(UE_DIR_OUT | 4)

/* Wireless module interface commands. */
#define AR_WMI_CMD_ECHO			0x001
#define AR_WMI_CMD_ACCESS_MEMORY	0x002
#define AR_WMI_CMD_DISABLE_INTR		0x003
#define AR_WMI_CMD_ENABLE_INTR		0x004
#define AR_WMI_CMD_RX_LINK		0x005
#define AR_WMI_CMD_ATH_INIT		0x006
#define AR_WMI_CMD_ABORT_TXQ		0x007
#define AR_WMI_CMD_STOP_TX_DMA		0x008
#define AR_WMI_CMD_STOP_DMA_RECV	0x009
#define AR_WMI_CMD_ABORT_TX_DMA		0x00a
#define AR_WMI_CMD_DRAIN_TXQ		0x00b
#define AR_WMI_CMD_DRAIN_TXQ_ALL	0x00c
#define AR_WMI_CMD_START_RECV		0x00d
#define AR_WMI_CMD_STOP_RECV		0x00e
#define AR_WMI_CMD_FLUSH_RECV		0x00f
#define AR_WMI_CMD_SET_MODE		0x010
#define AR_WMI_CMD_RESET		0x011
#define AR_WMI_CMD_NODE_CREATE		0x012
#define AR_WMI_CMD_NODE_REMOVE		0x013
#define AR_WMI_CMD_VAP_REMOVE		0x014
#define AR_WMI_CMD_VAP_CREATE		0x015
#define AR_WMI_CMD_BEACON_UPDATE	0x016
#define AR_WMI_CMD_REG_READ		0x017
#define AR_WMI_CMD_REG_WRITE		0x018
#define AR_WMI_CMD_RC_STATE_CHANGE	0x019
#define AR_WMI_CMD_RC_RATE_UPDATE	0x01a
#define AR_WMI_CMD_DEBUG_INFO		0x01b
#define AR_WMI_CMD_HOST_ATTACH		0x01c
#define AR_WMI_CMD_TARGET_IC_UPDATE	0x01d
#define AR_WMI_CMD_TGT_STATS		0x01e
#define AR_WMI_CMD_TX_AGGR_ENABLE	0x01f
#define AR_WMI_CMD_TGT_DETACH		0x020
#define AR_WMI_CMD_TGT_TXQ_ENABLE	0x021
#define AR_WMI_CMD_AGGR_LIMIT		0x026
/* Wireless module interface events. */
/*
 * XXX: the 3.7.4 Linux kernel differs with this.  This matches the
 * 2.6.36 kernel.
 */
#if 1	/* Linux 2.6.26 */
#define AR_WMI_EVT_TGT_RDY		0x001
#define AR_WMI_EVT_SWBA			0x002
#define AR_WMI_EVT_FATAL		0x003
#define AR_WMI_EVT_TXTO			0x004
#define AR_WMI_EVT_BMISS		0x005
#define AR_WMI_EVT_WLAN_TXCOMP		0x006
#define AR_WMI_EVT_DELBA		0x007
#define AR_WMI_EVT_TXRATE		0x008
#else	/* Linux 3.7.4 */
#define AR_WMI_EVT_TGT_RDY		0x001
#define AR_WMI_EVT_SWBA			0x002
#define AR_WMI_EVT_FATAL		0x003
#define AR_WMI_EVT_TXTO			0x004
#define AR_WMI_EVT_BMISS		0x005
#define AR_WMI_EVT_DELBA		0x006
#define AR_WMI_EVT_TXSTATUS		0x007
#endif

/* Structure for service AR_SVC_WMI_CONTROL. */
struct ar_wmi_cmd_hdr {
	uint16_t	cmd_id;
#define AR_WMI_EVT_FLAG	0x1000

	uint16_t	seq_no;
} __packed;

/* Values for AR_WMI_CMD_SET_MODE. */
#define AR_HTC_MODE_AUTO	0
#define AR_HTC_MODE_11A		1
#define AR_HTC_MODE_11B		2
#define AR_HTC_MODE_11G		3
#define AR_HTC_MODE_FH		4
#define AR_HTC_MODE_TURBO_A	5
#define AR_HTC_MODE_TURBO_G	6
#define AR_HTC_MODE_11NA	7
#define AR_HTC_MODE_11NG	8

#define AR_MAX_WRITE_COUNT	32
/* Structure for command AR_WMI_CMD_REG_WRITE. */
struct ar_wmi_cmd_reg_write {
	uint32_t	addr;
	uint32_t	val;
} __packed;

/* Structure for command AR_WMI_CMD_NODE_{CREATE,REMOVE}. */
struct ar_htc_target_sta {
	uint16_t	associd;
	uint16_t	txpower;
	uint32_t	pariwisekey;
	uint8_t		macaddr[IEEE80211_ADDR_LEN];
	uint8_t		bssid[IEEE80211_ADDR_LEN];
	uint8_t		sta_index;
	uint8_t		vif_index;
	uint8_t		vif_sta;
	uint16_t	flags;
#define AR_HTC_STA_AUTH	0x0001
#define AR_HTC_STA_QOS	0x0002
#define AR_HTC_STA_ERP	0x0004
#define AR_HTC_STA_HT	0x0008

	uint16_t	htcap;
	uint8_t		valid;
	uint16_t	capinfo;
	uint32_t	reserved[2];
	uint16_t	txseqmgmt;
	uint8_t		is_vif_sta;
	uint16_t	maxampdu;
	uint16_t	iv16;
	uint32_t	iv32;
} __packed;

/* Structures for command AR_WMI_CMD_RC_RATE_UPDATE. */
#define AR_HTC_RATE_MAX	30
struct ar_htc_rateset {
	uint8_t		rs_nrates;
	uint8_t		rs_rates[AR_HTC_RATE_MAX];
} __packed;

struct ar_htc_target_rate {
	uint8_t			sta_index;
	uint8_t			isnew;
	uint32_t		capflags;
#define AR_RC_DS_FLAG	0x00000001
#define AR_RC_TS_FLAG	0x00000002
#define AR_RC_40_FLAG	0x00000004
#define AR_RC_SGI_FLAG	0x00000008
#define AR_RC_HT_FLAG	0x00000010

	struct ar_htc_rateset	lg_rates;
	struct ar_htc_rateset	ht_rates;
} __packed;

/* Structure for command AR_WMI_CMD_TX_AGGR_ENABLE. */
struct ar_htc_target_aggr {
	uint8_t		sta_index;
	uint8_t		tidno;
	uint8_t		aggr_enable;
	uint8_t		padding;
} __packed;

/* Structure for command AR_WMI_CMD_VAP_CREATE. */
struct ar_htc_target_vif {
	uint8_t		index;
	uint8_t		des_bssid[IEEE80211_ADDR_LEN];
	uint32_t	opmode;
#define AR_HTC_M_IBSS		0
#define AR_HTC_M_STA		1
#define AR_HTC_M_WDS		2
#define AR_HTC_M_AHDEMO		3
#define AR_HTC_M_HOSTAP		6
#define AR_HTC_M_MONITOR	8

	uint8_t		myaddr[IEEE80211_ADDR_LEN];
	uint8_t		bssid[IEEE80211_ADDR_LEN];
	uint32_t	flags;
	uint32_t	flags_ext;
	uint16_t	ps_sta;
	uint16_t	rtsthreshold;
	uint8_t		ath_cap;
	int8_t		mcast_rate;
} __packed;

/* Structure for command AM_WMI_CMD_TARGET_IC_UPDATE. */
struct ar_htc_cap_target {
	uint32_t	flags;
	uint32_t	flags_ext;
	uint32_t	ampdu_limit;
	uint8_t		ampdu_subframes;
	uint8_t		ht_txchainmask;
	uint8_t		lg_txchainmask;
	uint8_t		rtscts_ratecode;
	uint8_t		protmode;
} __packed;

/* Structure for event AR_WMI_EVT_TXRATE. */
struct ar_wmi_evt_txrate {
	uint32_t	txrate;
	uint8_t		rssi_thresh;
	uint8_t		per;
} __packed;

/* HTC header. */
struct ar_htc_frame_hdr {
	uint8_t		endpoint_id;
	uint8_t		flags;
#define AR_HTC_FLAG_TRAILER	0x02

	uint16_t	payload_len;
	uint8_t		control[4];
} __packed;

/* Structure for HTC enpoint id 0. */
struct ar_htc_msg_hdr {
	uint16_t	msg_id;
#define AR_HTC_MSG_READY		0x0001
#define AR_HTC_MSG_CONN_SVC		0x0002
#define AR_HTC_MSG_CONN_SVC_RSP		0x0003
#define AR_HTC_MSG_SETUP_COMPLETE	0x0004
#define AR_HTC_MSG_CONF_PIPE		0x0005
#define AR_HTC_MSG_CONF_PIPE_RSP	0x0006
} __packed;

/* Structure for services AR_SVC_WMI_DATA_{VO,VI,BE,BK}. */
struct ar_tx_frame {
	uint8_t		data_type;
#define AR_HTC_AMPDU	1
#define AR_HTC_NORMAL	2

	uint8_t		node_idx;
	uint8_t		vif_idx;
	uint8_t		tid;
	uint32_t	flags;
#define AR_HTC_TX_CTSONLY	0x00000001
#define AR_HTC_TX_RTSCTS	0x00000002
#define AR_HTC_TX_USE_MIN_RATE	0x00000100

	uint8_t		key_type;
	uint8_t		key_idx;
	uint8_t		reserved[26];
} __packed;

/* Structure for service AR_SVC_WMI_MGMT. */
struct ar_tx_mgmt {
	uint8_t		node_idx;
	uint8_t		vif_idx;
	uint8_t		tid;
	uint8_t		flags;
	uint8_t		key_type;
	uint8_t		key_idx;
	uint16_t	reserved;
} __packed;

/* Structure for service AR_SVC_WMI_BEACON. */
struct ar_tx_bcn {
	uint8_t		len_changed;
	uint8_t		vif_idx;
	uint16_t	rev;
} __packed;

/* Structure for message AR_HTC_MSG_READY. */
struct ar_htc_msg_ready {
	uint16_t	credits;
	uint16_t	credits_size;
	uint8_t		max_endpoints;
	uint8_t		reserved;
} __packed;

/* Structure for message AR_HTC_MSG_CONF_PIPE. */
struct ar_htc_msg_config_pipe {
	uint8_t		pipe_id;
	uint8_t		credits;
} __packed;

/* Structure for message AR_HTC_MSG_CONN_SVC. */
struct ar_htc_msg_conn_svc {
	uint16_t	svc_id;
	uint16_t	conn_flags;
	uint8_t		dl_pipeid;
	uint8_t		ul_pipeid;
	uint8_t		svc_meta_len;
	uint8_t		reserved;
} __packed;

/* Structure for message AR_HTC_MSG_CONN_SVC_RSP. */
struct ar_htc_msg_conn_svc_rsp {
	uint16_t	svc_id;
	uint8_t		status;
#define AR_HTC_SVC_SUCCESS	0
#define AR_HTC_SVC_NOT_FOUND	1
#define AR_HTC_SVC_FAILED	2
#define AR_HTC_SVC_NO_RESOURCES	3
#define AR_HTC_SVC_NO_MORE_EP	4

	uint8_t		endpoint_id;
	uint16_t	max_msg_len;
	uint8_t		svc_meta_len;
	uint8_t		reserved;
} __packed;

#define AR_SVC(grp, idx)	((grp) << 8 | (idx))
#define AR_SVC_IDX(svc)		((svc) & 0xff)
/* Service groups. */
#define AR_SVC_GRP_RSVD		0
#define AR_SVC_GRP_WMI		1
/* Service identifiers for WMI group. */
#define AR_SVC_WMI_CONTROL	AR_SVC(AR_SVC_GRP_WMI, 0)
#define AR_SVC_WMI_BEACON	AR_SVC(AR_SVC_GRP_WMI, 1)
#define AR_SVC_WMI_CAB		AR_SVC(AR_SVC_GRP_WMI, 2)
#define AR_SVC_WMI_UAPSD	AR_SVC(AR_SVC_GRP_WMI, 3)
#define AR_SVC_WMI_MGMT		AR_SVC(AR_SVC_GRP_WMI, 4)
#define AR_SVC_WMI_DATA_VO	AR_SVC(AR_SVC_GRP_WMI, 5)
#define AR_SVC_WMI_DATA_VI	AR_SVC(AR_SVC_GRP_WMI, 6)
#define AR_SVC_WMI_DATA_BE	AR_SVC(AR_SVC_GRP_WMI, 7)
#define AR_SVC_WMI_DATA_BK	AR_SVC(AR_SVC_GRP_WMI, 8)

struct ar_stream_hdr {
	uint16_t	len;
	uint16_t	tag;
#define AR_USB_RX_STREAM_TAG	0x4e00
#define AR_USB_TX_STREAM_TAG	0x697e
} __packed __attribute__((aligned(4)));

#define AR_MAX_CHAINS	3

/* Rx descriptor. */
struct ar_rx_status {
	uint64_t	rs_tstamp;
	uint16_t	rs_datalen;
	uint8_t		rs_status;
	uint8_t		rs_phyerr;
	int8_t		rs_rssi;
	int8_t		rs_rssi_ctl[AR_MAX_CHAINS];
	int8_t		rs_rssi_ext[AR_MAX_CHAINS];
	uint8_t		rs_keyix;
	uint8_t		rs_rate;
	uint8_t		rs_antenna;
	uint8_t		rs_more;
	uint8_t		rs_isaggr;
	uint8_t		rs_moreaggr;
	uint8_t		rs_num_delims;
	uint8_t		rs_flags;
#define AR_RXS_FLAG_GI		0x04
#define AR_RXS_FLAG_2040	0x08

	uint8_t		rs_dummy;
	uint32_t	rs_evm[AR_MAX_CHAINS];
} __packed __attribute__((aligned(4)));


/*
 * Driver definitions.
 */
#define ATHN_USB_RX_LIST_COUNT	1
#define ATHN_USB_TX_LIST_COUNT	(8 + 1)		/* NB: +1 for beacons. */

#define ATHN_USB_HOST_CMD_RING_COUNT	32

#define ATHN_USB_RXBUFSZ	(8 * 1024)	/* XXX Linux 16K */
#define ATHN_USB_TXBUFSZ			\
	((sizeof(struct ar_stream_hdr) +	\
	  sizeof(struct ar_htc_frame_hdr) +	\
	  sizeof(struct ar_tx_frame) +		\
	  IEEE80211_MAX_LEN + 3) & ~3)
#define ATHN_USB_TXCMDSZ	512

#define ATHN_USB_TX_TIMEOUT	5000	/* ms */
#define ATHN_USB_CMD_TIMEOUT	1000	/* ms */

struct athn_usb_softc;

struct athn_usb_rx_stream {
	struct mbuf	*m;
	int		moff;
	int		left;
};

struct athn_usb_rx_data {
	struct athn_usb_softc	*sc;
	struct usbd_xfer	*xfer;
	uint8_t			*buf;
};

struct athn_usb_tx_data {
	struct athn_usb_softc		*sc;
	struct usbd_xfer		*xfer;
	uint8_t				*buf;
	TAILQ_ENTRY(athn_usb_tx_data)	next;
};

struct athn_usb_host_cmd {
	void	(*cb)(struct athn_usb_softc *, void *);
	uint8_t	data[256];
};

struct athn_usb_cmd_newstate {
	enum ieee80211_state	state;
	int			arg;
};

struct athn_usb_cmd_key {
	struct ieee80211_node	*ni;
	struct ieee80211_key	*key;
};

struct athn_usb_aggr_cmd {
	uint8_t	sta_index;
	uint8_t	tid;
};

struct athn_usb_host_cmd_ring {
	struct athn_usb_host_cmd	cmd[ATHN_USB_HOST_CMD_RING_COUNT];
	int				cur;
	int				next;
	int				queued;
};

struct athn_usb_node {
	struct athn_node		aun_an;
	/* our stuff */
};

struct athn_usb_softc {
	struct athn_softc		usc_sc;
#define usc_dev		usc_sc.sc_dev

	enum {
		ATHN_INIT_NONE,
		ATHN_INIT_INITED
	} usc_init_state;
	int				usc_athn_attached;

	kmutex_t			usc_lock;
	kcondvar_t			usc_wmi_cv;
	kcondvar_t			usc_htc_cv;

	kmutex_t			usc_msg_mtx;
	kcondvar_t			usc_msg_cv;
	kmutex_t			usc_cmd_mtx;
	kcondvar_t			usc_cmd_cv;

	kcondvar_t			usc_task_cv;
	kmutex_t			usc_task_mtx;
	kmutex_t			usc_tx_mtx;

	/* USB specific goo. */
	struct usbd_device		*usc_udev;
	struct usbd_interface		*usc_iface;
	struct usb_task			usc_task;
	int				usc_dying;

	u_int				usc_flags;
#define ATHN_USB_FLAG_NONE	0x00
#define ATHN_USB_FLAG_AR7010	0x01

	struct athn_usb_rx_stream	usc_rx_stream;

	struct usbd_pipe		*usc_tx_data_pipe;
	struct usbd_pipe		*usc_rx_data_pipe;
	struct usbd_pipe		*usc_rx_intr_pipe;
	struct usbd_pipe		*usc_tx_intr_pipe;
	uint8_t 			*usc_ibuf;
	size_t				usc_ibufsize;

	struct ar_wmi_cmd_reg_write	usc_wbuf[AR_MAX_WRITE_COUNT];
	int				usc_wcount;

	bool				usc_wmiactive;
	bool				usc_htcactive;
	uint16_t			usc_wmi_seq_no;
	uint16_t			usc_wait_cmd_id;
	uint16_t			usc_wait_msg_id;
	void				*usc_obuf;
	struct ar_htc_msg_conn_svc_rsp	*usc_msg_conn_svc_rsp;

	struct athn_usb_host_cmd_ring	usc_cmdq;
	struct athn_usb_rx_data		usc_rx_data[ATHN_USB_RX_LIST_COUNT];
	struct athn_usb_tx_data		usc_tx_data[ATHN_USB_TX_LIST_COUNT];
	TAILQ_HEAD(, athn_usb_tx_data)	usc_tx_free_list;
	struct athn_usb_tx_data		usc_tx_cmd;
	struct athn_usb_tx_data		usc_tx_msg;
	struct athn_usb_tx_data		*usc_tx_bcn;

	uint8_t				usc_ep_ctrl;
	uint8_t				usc_ep_bcn;
	uint8_t				usc_ep_cab;
	uint8_t				usc_ep_uapsd;
	uint8_t				usc_ep_mgmt;
	uint8_t				usc_ep_data[WME_NUM_AC];
	void			(*usc_node_cleanup)(struct ieee80211_node *);
};

#endif /* _IF_ATHN_USB_H_ */
