Copied marvell88w8335 driver from vender/freebsd/RELEASE_8_0_0 and made it

compiling fine. So linking still needs to be worked on.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34517 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Colin Günther
2009-12-06 11:17:50 +00:00
parent caadca9182
commit a3915b9de0
9 changed files with 4531 additions and 0 deletions
@@ -8,4 +8,5 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi3945 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi4965 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8363 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8335 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ralinkwifi ;
@@ -0,0 +1,24 @@
SubDir HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8335 ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ;
UsePrivateHeaders net system ;
UsePrivateKernelHeaders ;
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ]
-Wno-format
-Wno-unused
-Wno-uninitialized ;
UseHeaders [ FDirName $(SUBDIR) ] : true ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev malo ] ;
KernelAddon marvell88w8335 :
if_malo_pci.c
if_malo.c
if_malohal.c
:
libfreebsd_wlan.a
libfreebsd_network.a
;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,585 @@
/*-
* Copyright (c) 2007 Marvell Semiconductor, Inc.
* Copyright (c) 2007 Sam Leffler, Errno Consulting
* Copyright (c) 2008 Weongyo Jeong <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
* $FreeBSD$
*/
/*
* Definitions for the Marvell 88W8335 Wireless LAN controller.
*/
#ifndef _DEV_MALO_H
#define _DEV_MALO_H
#include <net80211/ieee80211_radiotap.h>
#include <dev/malo/if_malohal.h>
#include <dev/malo/if_maloioctl.h>
#ifndef MALO_TXBUF
#define MALO_TXBUF 256 /* number of TX descriptors/buffers */
#endif
#ifndef MALO_RXBUF
#define MALO_RXBUF 256 /* number of RX descriptors/buffers */
#endif
#define MALO_TXDESC 1 /* max tx descriptors/segments */
#define MALO_RXSIZE PAGE_SIZE
#define MALO_RSSI_DUMMY_MARKER 127
#define MALO_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */
#define MALO_REG_INT_CODE 0x00000C14
/* From host to ARM */
#define MALO_REG_H2A_INTERRUPT_EVENTS 0x00000C18
/* bit definitions for MALO_REG_H2A_INTERRUPT_CAUSE */
#define MALO_H2ARIC_BIT_PPA_READY 0x00000001
#define MALO_H2ARIC_BIT_DOOR_BELL 0x00000002 /* bit 1 */
#define MALO_H2ARIC_BIT_PS 0x00000004
#define MALO_H2ARIC_BIT_PSPOLL 0x00000008 /* bit 3 */
/* From ARM to host */
#define MALO_REG_A2H_INTERRUPT_CAUSE 0x00000C30
#define MALO_REG_A2H_INTERRUPT_MASK 0x00000C34
#define MALO_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38
#define MALO_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C
/* bit definitions for MALO_REG_A2H_INTERRUPT_CAUSE */
#define MALO_A2HRIC_BIT_TX_DONE 0x00000001 /* bit 0 */
#define MALO_A2HRIC_BIT_RX_RDY 0x00000002 /* bit 1 */
#define MALO_A2HRIC_BIT_OPC_DONE 0x00000004
#define MALO_A2HRIC_BIT_MAC_EVENT 0x00000008
#define MALO_A2HRIC_BIT_RX_PROBLEM 0x00000010
#define MALO_A2HRIC_BIT_RADIO_OFF 0x00000020 /* bit 5 */
#define MALO_A2HRIC_BIT_RADIO_ON 0x00000040
#define MALO_A2HRIC_BIT_RADAR_DETECT 0x00000080
#define MALO_A2HRIC_BIT_ICV_ERROR 0x00000100
#define MALO_A2HRIC_BIT_MIC_ERROR 0x00000200 /* bit 9 */
#define MALO_A2HRIC_BIT_QUEUE_EMPTY 0x00000400
#define MALO_A2HRIC_BIT_QUEUE_FULL 0x00000800
#define MALO_A2HRIC_BIT_CHAN_SWITCH 0x00001000
#define MALO_A2HRIC_BIT_TX_WATCHDOG 0x00002000
#define MALO_A2HRIC_BIT_BA_WATCHDOG 0x00004000
#define MALO_ISR_SRC_BITS \
(MALO_A2HRIC_BIT_RX_RDY | \
MALO_A2HRIC_BIT_TX_DONE | \
MALO_A2HRIC_BIT_OPC_DONE | \
MALO_A2HRIC_BIT_MAC_EVENT | \
MALO_A2HRIC_BIT_MIC_ERROR | \
MALO_A2HRIC_BIT_ICV_ERROR | \
MALO_A2HRIC_BIT_RADAR_DETECT | \
MALO_A2HRIC_BIT_CHAN_SWITCH | \
MALO_A2HRIC_BIT_TX_WATCHDOG | \
MALO_A2HRIC_BIT_QUEUE_EMPTY)
#define MALO_ISR_RESET (1<<15)
#define MALO_A2HRIC_BIT_MASK MALO_ISR_SRC_BITS
/* map to 0x80000000 on BAR1 */
#define MALO_REG_GEN_PTR 0x00000C10
#define MALO_REG_INT_CODE 0x00000C14
#define MALO_REG_SCRATCH 0x00000C40
/*
* define OpMode for SoftAP/Station mode
*
* the following mode signature has to be written to PCI scratch register#0
* right after successfully downloading the last block of firmware and
* before waiting for firmware ready signature
*/
#define MALO_HOSTCMD_STA_MODE 0x5A
#define MALO_HOSTCMD_STA_FWRDY_SIGNATURE 0xF0F1F2F4
/*
* 16 bit host command code
*/
#define MALO_HOSTCMD_NONE 0x0000
#define MALO_HOSTCMD_CODE_DNLD 0x0001
#define MALO_HOSTCMD_GET_HW_SPEC 0x0003
#define MALO_HOSTCMD_SET_HW_SPEC 0x0004
#define MALO_HOSTCMD_MAC_MULTICAST_ADR 0x0010
#define MALO_HOSTCMD_SET_WEPKEY 0x0013
#define MALO_HOSTCMD_802_11_RADIO_CONTROL 0x001c
#define MALO_HOSTCMD_802_11_RF_TX_POWER 0x001e
#define MALO_HOSTCMD_802_11_RF_ANTENNA 0x0020
#define MALO_HOSTCMD_SET_PRE_SCAN 0x0107
#define MALO_HOSTCMD_SET_POST_SCAN 0x0108
#define MALO_HOSTCMD_SET_RF_CHANNEL 0x010a
#define MALO_HOSTCMD_SET_AID 0x010d
#define MALO_HOSTCMD_SET_RATE 0x0110
#define MALO_HOSTCMD_SET_SLOT 0x0114
/* define DFS lab commands */
#define MALO_HOSTCMD_SET_FIXED_RATE 0x0126
#define MALO_HOSTCMD_SET_REGION_POWER 0x0128
#define MALO_HOSTCMD_GET_CALTABLE 0x1134
/*
* definition of action or option for each command.
*/
/* define general purpose action */
#define MALO_HOSTCMD_ACT_GEN_GET 0x0000
#define MALO_HOSTCMD_ACT_GEN_SET 0x0001
#define MALO_HOSTCMD_ACT_GEN_SET_LIST 0x0002
/* define action or option for HostCmd_FW_USE_FIXED_RATE */
#define MALO_HOSTCMD_ACT_USE_FIXED_RATE 0x0001
#define MALO_HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002
/* INT code register event definition */
#define MALO_INT_CODE_CMD_FINISHED 0x00000005
struct malo_cmd_header {
uint16_t cmd;
uint16_t length;
uint16_t seqnum;
uint16_t result;
} __packed;
struct malo_cmd_caltable {
struct malo_cmd_header cmdhdr;
uint8_t annex;
uint8_t index;
uint8_t len;
uint8_t reserverd;
#define MALO_CAL_TBL_SIZE 160
uint8_t caltbl[MALO_CAL_TBL_SIZE];
} __packed;
struct malo_cmd_get_hwspec {
struct malo_cmd_header cmdhdr;
u_int8_t version; /* version of the HW */
u_int8_t hostif; /* host interface */
/* Max. number of WCB FW can handle */
u_int16_t num_wcb;
/* MaxNbr of MC addresses FW can handle */
u_int16_t num_mcastaddr;
/* MAC address programmed in HW */
u_int8_t permaddr[6];
u_int16_t regioncode;
/* Number of antenna used */
u_int16_t num_antenna;
/* 4 byte of FW release number */
u_int32_t fw_releasenum;
u_int32_t wcbbase0;
u_int32_t rxpdwr_ptr;
u_int32_t rxpdrd_ptr;
u_int32_t ul_fw_awakecookie;
u_int32_t wcbbase1;
u_int32_t wcbbase2;
u_int32_t wcbbase3;
} __packed;
struct malo_cmd_set_hwspec {
struct malo_cmd_header cmdhdr;
uint8_t version; /* HW revision */
uint8_t hostif; /* Host interface */
/* Max. number of Multicast address FW can handle */
uint16_t num_mcastaddr;
uint8_t permaddr[6]; /* MAC address */
uint16_t regioncode; /* Region Code */
/* 4 byte of FW release number */
uint32_t fwreleasenum;
/* Firmware awake cookie */
uint32_t ul_fw_awakecookie;
/* Device capabilities (see above) */
uint32_t devicecaps;
uint32_t rxpdwrptr; /* Rx shared memory queue */
/* # TX queues in WcbBase array */
uint32_t num_txqueues;
/* TX WCB Rings */
uint32_t wcbbase[MALO_MAX_TXWCB_QUEUES];
uint32_t flags;
uint32_t txwcbnum_per_queue;
uint32_t total_rxwcb;
} __packed;
/* DS 802.11 */
struct malo_cmd_rf_antenna {
struct malo_cmd_header cmdhdr;
uint16_t action;
/* Number of antennas or 0xffff (diversity) */
uint16_t mode;
} __packed;
struct malo_cmd_radio_control {
struct malo_cmd_header cmdhdr;
uint16_t action;
/*
* bit 0 : 1 = on, 0 = off
* bit 1 : 1 = long, 0 = short
* bit 2 : 1 = auto, 0 = fix
*/
uint16_t control;
uint16_t radio_on;
} __packed;
struct malo_cmd_fw_set_wmmmode {
struct malo_cmd_header cmdhdr;
uint16_t action; /* 0 -> unset, 1 -> set */
} __packed;
struct malo_cmd_fw_set_rf_channel {
struct malo_cmd_header cmdhdr;
uint16_t action;
uint8_t cur_channel; /* channel # */
} __packed;
#define MALO_TX_POWER_LEVEL_TOTAL 8
struct malo_cmd_rf_tx_power {
struct malo_cmd_header cmdhdr;
uint16_t action;
uint16_t support_txpower_level;
uint16_t current_txpower_level;
uint16_t reserved;
uint16_t power_levellist[MALO_TX_POWER_LEVEL_TOTAL];
} __packed;
struct malo_fixrate_flag {
/* lower rate after the retry count. 0 = legacy, 1 = HT */
uint32_t type;
/* 0: retry count is not valid, 1: use retry count specified */
uint32_t retrycount_valid;
} __packed;
struct malo_fixed_rate_entry {
struct malo_fixrate_flag typeflags;
/* legacy rate(not index) or an MCS code. */
uint32_t fixedrate;
uint32_t retrycount;
} __packed;
struct malo_cmd_fw_use_fixed_rate {
struct malo_cmd_header cmdhdr;
/*
* MALO_HOSTCMD_ACT_GEN_GET 0x0000
* MALO_HOSTCMD_ACT_GEN_SET 0x0001
* MALO_HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002
*/
uint32_t action;
/* use fixed rate specified but firmware can drop to */
uint32_t allowratedrop;
uint32_t entrycount;
struct malo_fixed_rate_entry fixedrate_table[4];
uint8_t multicast_rate;
uint8_t multirate_txtype;
uint8_t management_rate;
} __packed;
#define MALO_RATE_INDEX_MAX_ARRAY 14
struct malo_cmd_fw_set_aid {
struct malo_cmd_header cmdhdr;
uint16_t associd;
uint8_t macaddr[6]; /* AP's Mac Address(BSSID) */
uint32_t gprotection;
uint8_t aprates[MALO_RATE_INDEX_MAX_ARRAY];
} __packed;
struct malo_cmd_prescan {
struct malo_cmd_header cmdhdr;
} __packed;
struct malo_cmd_postscan {
struct malo_cmd_header cmdhdr;
uint32_t isibss;
uint8_t bssid[6];
} __packed;
struct malo_cmd_fw_setslot {
struct malo_cmd_header cmdhdr;
uint16_t action;
/* slot = 0 if regular, slot = 1 if short. */
uint8_t slot;
};
struct malo_cmd_set_rate {
struct malo_cmd_header cmdhdr;
uint8_t dataratetype;
uint8_t rateindex;
uint8_t aprates[14];
} __packed;
struct malo_cmd_wepkey {
struct malo_cmd_header cmdhdr;
uint16_t action;
uint8_t len;
uint8_t flags;
uint16_t index;
uint8_t value[IEEE80211_KEYBUF_SIZE];
uint8_t txmickey[IEEE80211_WEP_MICLEN];
uint8_t rxmickey[IEEE80211_WEP_MICLEN];
uint64_t rxseqctr;
uint64_t txseqctr;
} __packed;
struct malo_cmd_mcast {
struct malo_cmd_header cmdhdr;
uint16_t action;
uint16_t numaddr;
#define MALO_HAL_MCAST_MAX 32
uint8_t maclist[6*32];
} __packed;
/*
* DMA state for tx/rx descriptors.
*/
/*
* Common "base class" for tx/rx descriptor resources
* allocated using the bus dma api.
*/
struct malo_descdma {
const char* dd_name;
void *dd_desc; /* descriptors */
bus_addr_t dd_desc_paddr; /* physical addr of dd_desc */
bus_size_t dd_desc_len; /* size of dd_desc */
bus_dma_segment_t dd_dseg;
int dd_dnseg; /* number of segments */
bus_dma_tag_t dd_dmat; /* bus DMA tag */
bus_dmamap_t dd_dmamap; /* DMA map for descriptors */
void *dd_bufptr; /* associated buffers */
};
/*
* Hardware tx/rx descriptors.
*
* NB: tx descriptor size must match f/w expected size
* because f/w prefetch's the next descriptor linearly
* and doesn't chase the next pointer.
*/
struct malo_txdesc {
uint32_t status;
#define MALO_TXD_STATUS_IDLE 0x00000000
#define MALO_TXD_STATUS_USED 0x00000001
#define MALO_TXD_STATUS_OK 0x00000001
#define MALO_TXD_STATUS_OK_RETRY 0x00000002
#define MALO_TXD_STATUS_OK_MORE_RETRY 0x00000004
#define MALO_TXD_STATUS_MULTICAST_TX 0x00000008
#define MALO_TXD_STATUS_BROADCAST_TX 0x00000010
#define MALO_TXD_STATUS_FAILED_LINK_ERROR 0x00000020
#define MALO_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040
#define MALO_TXD_STATUS_FAILED_XRETRY MALO_TXD_STATUS_FAILED_EXCEED_LIMIT
#define MALO_TXD_STATUS_FAILED_AGING 0x00000080
#define MALO_TXD_STATUS_FW_OWNED 0x80000000
uint8_t datarate;
uint8_t txpriority;
uint16_t qosctrl;
uint32_t pktptr;
uint16_t pktlen;
uint8_t destaddr[6];
uint32_t physnext;
uint32_t sap_pktinfo;
uint16_t format;
#define MALO_TXD_FORMAT 0x0001 /* frame format/rate */
#define MALO_TXD_FORMAT_LEGACY 0x0000 /* legacy rate frame */
#define MALO_TXD_RATE 0x01f8 /* tx rate (legacy)/ MCS */
#define MALO_TXD_RATE_S 3
/* NB: 3 is reserved */
#define MALO_TXD_ANTENNA 0x1800 /* antenna select */
#define MALO_TXD_ANTENNA_S 11
uint16_t pad; /* align to 4-byte boundary */
} __packed;
#define MALO_TXDESC_SYNC(txq, ds, how) do { \
bus_dmamap_sync((txq)->dma.dd_dmat, (txq)->dma.dd_dmamap, how); \
} while(0)
struct malo_rxdesc {
uint8_t rxcontrol; /* control element */
#define MALO_RXD_CTRL_DRIVER_OWN 0x00
#define MALO_RXD_CTRL_OS_OWN 0x04
#define MALO_RXD_CTRL_DMA_OWN 0x80
uint8_t snr; /* signal to noise ratio */
uint8_t status; /* status field w/ USED bit */
#define MALO_RXD_STATUS_IDLE 0x00
#define MALO_RXD_STATUS_OK 0x01
#define MALO_RXD_STATUS_MULTICAST_RX 0x02
#define MALO_RXD_STATUS_BROADCAST_RX 0x04
#define MALO_RXD_STATUS_FRAGMENT_RX 0x08
#define MALO_RXD_STATUS_GENERAL_DECRYPT_ERR 0xff
#define MALO_RXD_STATUS_DECRYPT_ERR_MASK 0x80
#define MALO_RXD_STATUS_TKIP_MIC_DECRYPT_ERR 0x02
#define MALO_RXD_STATUS_WEP_ICV_DECRYPT_ERR 0x04
#define MALO_RXD_STATUS_TKIP_ICV_DECRYPT_ERR 0x08
uint8_t channel; /* channel # pkt received on */
uint16_t pktlen; /* total length of received data */
uint8_t nf; /* noise floor */
uint8_t rate; /* received data rate */
uint32_t physbuffdata; /* physical address of payload data */
uint32_t physnext; /* physical address of next RX desc */
uint16_t qosctrl; /* received QosCtrl field variable */
uint16_t htsig2; /* like name states */
} __packed;
#define MALO_RXDESC_SYNC(sc, ds, how) do { \
bus_dmamap_sync((sc)->malo_rxdma.dd_dmat, \
(sc)->malo_rxdma.dd_dmamap, how); \
} while (0)
struct malo_rxbuf {
STAILQ_ENTRY(malo_rxbuf) bf_list;
void *bf_desc; /* h/w descriptor */
bus_addr_t bf_daddr; /* physical addr of desc */
bus_dmamap_t bf_dmamap;
bus_addr_t bf_data; /* physical addr of rx data */
struct mbuf *bf_m; /* jumbo mbuf */
};
typedef STAILQ_HEAD(, malo_rxbuf) malo_rxbufhead;
/*
* Software backed version of tx/rx descriptors. We keep
* the software state out of the h/w descriptor structure
* so that may be allocated in uncached memory w/o paying
* performance hit.
*/
struct malo_txbuf {
STAILQ_ENTRY(malo_txbuf) bf_list;
void *bf_desc; /* h/w descriptor */
bus_addr_t bf_daddr; /* physical addr of desc */
bus_dmamap_t bf_dmamap; /* DMA map for descriptors */
int bf_nseg;
bus_dma_segment_t bf_segs[MALO_TXDESC];
struct mbuf *bf_m;
struct ieee80211_node *bf_node;
struct malo_txq *bf_txq; /* backpointer to tx q/ring */
};
typedef STAILQ_HEAD(, malo_txbuf) malo_txbufhead;
/*
* TX/RX ring definitions. There are 4 tx rings, one
* per AC, and 1 rx ring. Note carefully that transmit
* descriptors are treated as a contiguous chunk and the
* firmware pre-fetches descriptors. This means that we
* must preserve order when moving descriptors between
* the active+free lists; otherwise we may stall transmit.
*/
struct malo_txq {
struct malo_descdma dma; /* bus dma resources */
struct mtx lock; /* tx q lock */
char name[12]; /* e.g. "malo0_txq4" */
int qnum; /* f/w q number */
int txpri; /* f/w tx priority */
int nfree; /* # buffers on free list */
malo_txbufhead free; /* queue of free buffers */
malo_txbufhead active; /* queue of active buffers */
};
#define MALO_TXQ_LOCK_INIT(_sc, _tq) do { \
snprintf((_tq)->name, sizeof((_tq)->name), "%s_txq%u", \
device_get_nameunit((_sc)->malo_dev), (_tq)->qnum); \
mtx_init(&(_tq)->lock, (_tq)->name, NULL, MTX_DEF); \
} while (0)
#define MALO_TXQ_LOCK_DESTROY(_tq) mtx_destroy(&(_tq)->lock)
#define MALO_TXQ_LOCK(_tq) mtx_lock(&(_tq)->lock)
#define MALO_TXQ_UNLOCK(_tq) mtx_unlock(&(_tq)->lock)
#define MALO_TXQ_LOCK_ASSERT(_tq) mtx_assert(&(_tq)->lock, MA_OWNED)
/*
* Each packet has fixed front matter: a 2-byte length
* of the payload, followed by a 4-address 802.11 header
* (regardless of the actual header and always w/o any
* QoS header). The payload then follows.
*/
struct malo_txrec {
uint16_t fwlen;
struct ieee80211_frame_addr4 wh;
} __packed;
struct malo_vap {
struct ieee80211vap malo_vap;
int (*malo_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
};
#define MALO_VAP(vap) ((struct malo_vap *)(vap))
struct malo_softc {
device_t malo_dev;
struct ifnet *malo_ifp; /* interface common */
struct mtx malo_mtx; /* master lock (recursive) */
struct taskqueue *malo_tq; /* private task queue */
bus_dma_tag_t malo_dmat; /* bus DMA tag */
bus_space_handle_t malo_io0h; /* BAR 0 */
bus_space_tag_t malo_io0t;
bus_space_handle_t malo_io1h; /* BAR 1 */
bus_space_tag_t malo_io1t;
unsigned int malo_invalid : 1,/* disable hardware accesses */
malo_recvsetup : 1, /* recv setup */
malo_fixedrate: 1; /* use fixed tx rate */
struct malo_hal *malo_mh; /* h/w access layer */
struct malo_hal_hwspec malo_hwspecs; /* h/w capabilities */
struct malo_hal_txrxdma malo_hwdma; /* h/w dma setup */
uint32_t malo_imask; /* interrupt mask copy */
struct malo_hal_channel malo_curchan;
u_int16_t malo_rxantenna; /* rx antenna */
u_int16_t malo_txantenna; /* tx antenna */
struct malo_descdma malo_rxdma; /* rx bus dma resources */
malo_rxbufhead malo_rxbuf; /* rx buffers */
struct malo_rxbuf *malo_rxnext; /* next rx buffer to process */
struct task malo_rxtask; /* rx int processing */
struct malo_txq malo_txq[MALO_NUM_TX_QUEUES];
struct task malo_txtask; /* tx int processing */
struct malo_tx_radiotap_header malo_tx_th;
struct malo_rx_radiotap_header malo_rx_th;
struct malo_stats malo_stats; /* interface statistics */
int malo_debug;
};
#define MALO_LOCK_INIT(_sc) \
mtx_init(&(_sc)->malo_mtx, device_get_nameunit((_sc)->malo_dev), \
NULL, MTX_DEF | MTX_RECURSE)
#define MALO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->malo_mtx)
#define MALO_LOCK(_sc) mtx_lock(&(_sc)->malo_mtx)
#define MALO_UNLOCK(_sc) mtx_unlock(&(_sc)->malo_mtx)
#define MALO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->malo_mtx, MA_OWNED)
#define MALO_RXFREE_INIT(_sc) \
mtx_init(&(_sc)->malo_rxlock, device_get_nameunit((_sc)->malo_dev), \
NULL, MTX_DEF)
#define MALO_RXFREE_DESTROY(_sc) mtx_destroy(&(_sc)->malo_rxlock)
#define MALO_RXFREE_LOCK(_sc) mtx_lock(&(_sc)->malo_rxlock)
#define MALO_RXFREE_UNLOCK(_sc) mtx_unlock(&(_sc)->malo_rxlock)
#define MALO_RXFREE_ASSERT(_sc) mtx_assert(&(_sc)->malo_rxlock, \
MA_OWNED)
int malo_attach(uint16_t, struct malo_softc *);
int malo_intr(void *);
int malo_detach(struct malo_softc *);
void malo_shutdown(struct malo_softc *);
void malo_suspend(struct malo_softc *);
void malo_resume(struct malo_softc *);
#endif
@@ -0,0 +1,374 @@
/*-
* Copyright (c) 2007 Marvell Semiconductor, Inc.
* Copyright (c) 2007 Sam Leffler, Errno Consulting
* Copyright (c) 2008 Weongyo Jeong <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/cdefs.h>
#ifdef __FreeBSD__
__FBSDID("$FreeBSD$");
#endif
/*
* PCI front-end for the Marvell 88W8335 Wireless LAN controller driver.
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <machine/bus.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <dev/malo/if_malo.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
/*
* PCI glue.
*/
#define MALO_RESOURCE_MAX 2
#define MALO_MSI_MESSAGES 1
struct malo_pci_softc {
struct malo_softc malo_sc;
struct resource_spec *malo_mem_spec;
struct resource *malo_res_mem[MALO_RESOURCE_MAX];
struct resource_spec *malo_irq_spec;
struct resource *malo_res_irq[MALO_MSI_MESSAGES];
void *malo_intrhand[MALO_MSI_MESSAGES];
int malo_msi;
};
/*
* Tunable variables.
*/
SYSCTL_DECL(_hw_malo);
SYSCTL_NODE(_hw_malo, OID_AUTO, pci, CTLFLAG_RD, 0,
"Marvell 88W8335 driver PCI parameters");
static int msi_disable = 0; /* MSI disabled */
SYSCTL_INT(_hw_malo_pci, OID_AUTO, msi_disable, CTLFLAG_RW, &msi_disable,
0, "MSI disabled");
TUNABLE_INT("hw.malo.pci.msi_disable", &msi_disable);
/*
* Devices supported by this driver.
*/
#define VENDORID_MARVELL 0X11AB
#define DEVICEID_MRVL_88W8310 0X1FA7
#define DEVICEID_MRVL_88W8335R1 0X1FAA
#define DEVICEID_MRVL_88W8335R2 0X1FAB
static struct malo_product {
uint16_t mp_vendorid;
uint16_t mp_deviceid;
const char *mp_name;
} malo_products[] = {
{ VENDORID_MARVELL, DEVICEID_MRVL_88W8310,
"Marvell Libertas 88W8310 802.11g Wireless Adapter" },
{ VENDORID_MARVELL, DEVICEID_MRVL_88W8335R1,
"Marvell Libertas 88W8335 802.11g Wireless Adapter" },
{ VENDORID_MARVELL, DEVICEID_MRVL_88W8335R2,
"Marvell Libertas 88W8335 802.11g Wireless Adapter" }
};
static struct resource_spec malo_res_spec_mem[] = {
{ SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE },
{ SYS_RES_MEMORY, PCIR_BAR(1), RF_ACTIVE },
{ -1, 0, 0 }
};
static struct resource_spec malo_res_spec_legacy[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
{ -1, 0, 0 }
};
static struct resource_spec malo_res_spec_msi[] = {
{ SYS_RES_IRQ, 1, RF_ACTIVE },
{ -1, 0, 0 }
};
static int malo_pci_detach(device_t);
static int
malo_pci_probe(device_t dev)
{
#define N(a) (sizeof(a) / sizeof((a)[0]))
struct malo_product *mp;
uint16_t vendor, devid;
int i;
vendor = pci_get_vendor(dev);
devid = pci_get_device(dev);
mp = malo_products;
for (i = 0; i < N(malo_products); i++, mp++) {
if (vendor == mp->mp_vendorid && devid == mp->mp_deviceid) {
device_set_desc(dev, mp->mp_name);
return (BUS_PROBE_DEFAULT);
}
}
return (ENXIO);
#undef N
}
static int
malo_pci_setup(device_t dev)
{
/*
* Enable memory mapping and bus mastering.
*/
if (pci_enable_busmaster(dev) != 0)
return -1;
if (pci_enable_io(dev, SYS_RES_MEMORY) != 0)
return -1;
return 0;
}
static int
malo_pci_attach(device_t dev)
{
int error = ENXIO, i, msic, reg;
struct malo_pci_softc *psc = device_get_softc(dev);
struct malo_softc *sc = &psc->malo_sc;
sc->malo_dev = dev;
/*
* Enable memory mapping and bus mastering.
*/
if (malo_pci_setup(dev))
return (ENXIO);
/*
* Setup memory-mapping of PCI registers.
*/
psc->malo_mem_spec = malo_res_spec_mem;
error = bus_alloc_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);
if (error) {
device_printf(dev, "couldn't allocate memory resources\n");
return (ENXIO);
}
/*
* Arrange and allocate interrupt line.
*/
sc->malo_invalid = 1;
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
msic = pci_msi_count(dev);
if (bootverbose)
device_printf(dev, "MSI count : %d\n", msic);
} else
msic = 0;
psc->malo_irq_spec = malo_res_spec_legacy;
if (msic == MALO_MSI_MESSAGES && msi_disable == 0) {
if (pci_alloc_msi(dev, &msic) == 0) {
if (msic == MALO_MSI_MESSAGES) {
device_printf(dev, "Using %d MSI messages\n",
msic);
psc->malo_irq_spec = malo_res_spec_msi;
psc->malo_msi = 1;
} else
pci_release_msi(dev);
}
}
error = bus_alloc_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
if (error) {
device_printf(dev, "couldn't allocate IRQ resources\n");
goto bad;
}
if (psc->malo_msi == 0)
error = bus_setup_intr(dev, psc->malo_res_irq[0],
INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc,
&psc->malo_intrhand[0]);
else {
for (i = 0; i < MALO_MSI_MESSAGES; i++) {
error = bus_setup_intr(dev, psc->malo_res_irq[i],
INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc,
&psc->malo_intrhand[i]);
if (error != 0)
break;
}
}
/*
* Setup DMA descriptor area.
*/
if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
BUS_SPACE_MAXADDR, /* maxsize */
0, /* nsegments */
BUS_SPACE_MAXADDR, /* maxsegsize */
0, /* flags */
NULL, /* lockfunc */
NULL, /* lockarg */
&sc->malo_dmat)) {
device_printf(dev, "cannot allocate DMA tag\n");
goto bad1;
}
sc->malo_io0t = rman_get_bustag(psc->malo_res_mem[0]);
sc->malo_io0h = rman_get_bushandle(psc->malo_res_mem[0]);
sc->malo_io1t = rman_get_bustag(psc->malo_res_mem[1]);
sc->malo_io1h = rman_get_bushandle(psc->malo_res_mem[1]);
error = malo_attach(pci_get_device(dev), sc);
if (error != 0)
goto bad2;
return (error);
bad2:
bus_dma_tag_destroy(sc->malo_dmat);
bad1:
if (psc->malo_msi == 0)
bus_teardown_intr(dev, psc->malo_res_irq[0],
psc->malo_intrhand[0]);
else {
for (i = 0; i < MALO_MSI_MESSAGES; i++)
bus_teardown_intr(dev, psc->malo_res_irq[i],
psc->malo_intrhand[i]);
}
bus_release_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
bad:
if (psc->malo_msi != 0)
pci_release_msi(dev);
bus_release_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);
return (error);
}
static int
malo_pci_detach(device_t dev)
{
int i;
struct malo_pci_softc *psc = device_get_softc(dev);
struct malo_softc *sc = &psc->malo_sc;
/* check if device was removed */
sc->malo_invalid = !bus_child_present(dev);
malo_detach(sc);
bus_generic_detach(dev);
if (psc->malo_msi == 0)
bus_teardown_intr(dev, psc->malo_res_irq[0],
psc->malo_intrhand[0]);
else {
for (i = 0; i < MALO_MSI_MESSAGES; i++)
bus_teardown_intr(dev, psc->malo_res_irq[i],
psc->malo_intrhand[i]);
pci_release_msi(dev);
}
bus_release_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
bus_dma_tag_destroy(sc->malo_dmat);
bus_release_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);
return (0);
}
static int
malo_pci_shutdown(device_t dev)
{
struct malo_pci_softc *psc = device_get_softc(dev);
malo_shutdown(&psc->malo_sc);
return (0);
}
static int
malo_pci_suspend(device_t dev)
{
struct malo_pci_softc *psc = device_get_softc(dev);
malo_suspend(&psc->malo_sc);
return (0);
}
static int
malo_pci_resume(device_t dev)
{
struct malo_pci_softc *psc = device_get_softc(dev);
if (!malo_pci_setup(dev))
return ENXIO;
malo_resume(&psc->malo_sc);
return (0);
}
static device_method_t malo_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, malo_pci_probe),
DEVMETHOD(device_attach, malo_pci_attach),
DEVMETHOD(device_detach, malo_pci_detach),
DEVMETHOD(device_shutdown, malo_pci_shutdown),
DEVMETHOD(device_suspend, malo_pci_suspend),
DEVMETHOD(device_resume, malo_pci_resume),
{ 0,0 }
};
static driver_t malo_pci_driver = {
"malo",
malo_pci_methods,
sizeof(struct malo_pci_softc)
};
static devclass_t malo_devclass;
DRIVER_MODULE(malo, pci, malo_pci_driver, malo_devclass, 0, 0);
MODULE_VERSION(malo, 1);
MODULE_DEPEND(malo, wlan, 1, 1, 1); /* 802.11 media layer */
MODULE_DEPEND(malo, malofw_fw, 1, 1, 1);
@@ -0,0 +1,917 @@
/*-
* Copyright (c) 2007 Marvell Semiconductor, Inc.
* Copyright (c) 2007 Sam Leffler, Errno Consulting
* Copyright (c) 2008 Weongyo Jeong <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/cdefs.h>
#ifdef __FreeBSD__
__FBSDID("$FreeBSD$");
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/firmware.h>
#include <sys/socket.h>
#include <machine/bus.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net80211/ieee80211_var.h>
#include <dev/malo/if_malo.h>
#define MALO_WAITOK 1
#define MALO_NOWAIT 0
#define _CMD_SETUP(pCmd, _type, _cmd) do { \
pCmd = (_type *)&mh->mh_cmdbuf[0]; \
memset(pCmd, 0, sizeof(_type)); \
pCmd->cmdhdr.cmd = htole16(_cmd); \
pCmd->cmdhdr.length = htole16(sizeof(_type)); \
} while (0)
static __inline uint32_t
malo_hal_read4(struct malo_hal *mh, bus_size_t off)
{
return bus_space_read_4(mh->mh_iot, mh->mh_ioh, off);
}
static __inline void
malo_hal_write4(struct malo_hal *mh, bus_size_t off, uint32_t val)
{
bus_space_write_4(mh->mh_iot, mh->mh_ioh, off, val);
}
static void
malo_hal_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
bus_addr_t *paddr = (bus_addr_t*) arg;
KASSERT(error == 0, ("error %u on bus_dma callback", error));
*paddr = segs->ds_addr;
}
/*
* Setup for communication with the device. We allocate
* a command buffer and map it for bus dma use. The pci
* device id is used to identify whether the device has
* SRAM on it (in which case f/w download must include a
* memory controller reset). All bus i/o operations happen
* in BAR 1; the driver passes in the tag and handle we need.
*/
struct malo_hal *
malo_hal_attach(device_t dev, uint16_t devid,
bus_space_handle_t ioh, bus_space_tag_t iot, bus_dma_tag_t tag)
{
int error;
struct malo_hal *mh;
mh = malloc(sizeof(struct malo_hal), M_DEVBUF, M_NOWAIT | M_ZERO);
if (mh == NULL)
return NULL;
mh->mh_dev = dev;
mh->mh_ioh = ioh;
mh->mh_iot = iot;
snprintf(mh->mh_mtxname, sizeof(mh->mh_mtxname),
"%s_hal", device_get_nameunit(dev));
mtx_init(&mh->mh_mtx, mh->mh_mtxname, NULL, MTX_DEF);
/*
* Allocate the command buffer and map into the address
* space of the h/w. We request "coherent" memory which
* will be uncached on some architectures.
*/
error = bus_dma_tag_create(tag, /* parent */
PAGE_SIZE, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
MALO_CMDBUF_SIZE, /* maxsize */
1, /* nsegments */
MALO_CMDBUF_SIZE, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
NULL, /* lockfunc */
NULL, /* lockarg */
&mh->mh_dmat);
if (error != 0) {
device_printf(dev, "unable to allocate memory for cmd tag, "
"error %u\n", error);
goto fail;
}
/* allocate descriptors */
error = bus_dmamap_create(mh->mh_dmat, BUS_DMA_NOWAIT, &mh->mh_dmamap);
if (error != 0) {
device_printf(dev, "unable to create dmamap for cmd buffers, "
"error %u\n", error);
goto fail;
}
error = bus_dmamem_alloc(mh->mh_dmat, (void**) &mh->mh_cmdbuf,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
&mh->mh_dmamap);
if (error != 0) {
device_printf(dev, "unable to allocate memory for cmd buffer, "
"error %u\n", error);
goto fail;
}
error = bus_dmamap_load(mh->mh_dmat, mh->mh_dmamap,
mh->mh_cmdbuf, MALO_CMDBUF_SIZE,
malo_hal_load_cb, &mh->mh_cmdaddr,
BUS_DMA_NOWAIT);
if (error != 0) {
device_printf(dev, "unable to load cmd buffer, error %u\n",
error);
goto fail;
}
return (mh);
fail:
if (mh->mh_dmamap != NULL) {
bus_dmamap_unload(mh->mh_dmat, mh->mh_dmamap);
if (mh->mh_cmdbuf != NULL)
bus_dmamem_free(mh->mh_dmat, mh->mh_cmdbuf,
mh->mh_dmamap);
bus_dmamap_destroy(mh->mh_dmat, mh->mh_dmamap);
}
if (mh->mh_dmat)
bus_dma_tag_destroy(mh->mh_dmat);
free(mh, M_DEVBUF);
return (NULL);
}
/*
* Low level firmware cmd block handshake support.
*/
static void
malo_hal_send_cmd(struct malo_hal *mh)
{
uint32_t dummy;
bus_dmamap_sync(mh->mh_dmat, mh->mh_dmamap,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
malo_hal_write4(mh, MALO_REG_GEN_PTR, mh->mh_cmdaddr);
dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
malo_hal_write4(mh, MALO_REG_H2A_INTERRUPT_EVENTS,
MALO_H2ARIC_BIT_DOOR_BELL);
}
static int
malo_hal_waitforcmd(struct malo_hal *mh, uint16_t cmd)
{
#define MAX_WAIT_FW_COMPLETE_ITERATIONS 10000
int i;
for (i = 0; i < MAX_WAIT_FW_COMPLETE_ITERATIONS; i++) {
if (mh->mh_cmdbuf[0] == le16toh(cmd))
return 1;
DELAY(1 * 1000);
}
return 0;
#undef MAX_WAIT_FW_COMPLETE_ITERATIONS
}
static int
malo_hal_execute_cmd(struct malo_hal *mh, unsigned short cmd)
{
MALO_HAL_LOCK_ASSERT(mh);
if ((mh->mh_flags & MHF_FWHANG) &&
(mh->mh_debug & MALO_HAL_DEBUG_IGNHANG) == 0) {
device_printf(mh->mh_dev, "firmware hung, skipping cmd 0x%x\n",
cmd);
return ENXIO;
}
if (malo_hal_read4(mh, MALO_REG_INT_CODE) == 0xffffffff) {
device_printf(mh->mh_dev, "%s: device not present!\n",
__func__);
return EIO;
}
malo_hal_send_cmd(mh);
if (!malo_hal_waitforcmd(mh, cmd | 0x8000)) {
device_printf(mh->mh_dev,
"timeout waiting for f/w cmd 0x%x\n", cmd);
mh->mh_flags |= MHF_FWHANG;
return ETIMEDOUT;
}
bus_dmamap_sync(mh->mh_dmat, mh->mh_dmamap,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
return 0;
}
static int
malo_hal_get_cal_table(struct malo_hal *mh, uint8_t annex, uint8_t index)
{
struct malo_cmd_caltable *cmd;
int ret;
MALO_HAL_LOCK_ASSERT(mh);
_CMD_SETUP(cmd, struct malo_cmd_caltable, MALO_HOSTCMD_GET_CALTABLE);
cmd->annex = annex;
cmd->index = index;
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_GET_CALTABLE);
if (ret == 0 && cmd->caltbl[0] != annex && annex != 0 && annex != 255)
ret = EIO;
return ret;
}
static int
malo_hal_get_pwrcal_table(struct malo_hal *mh, struct malo_hal_caldata *cal)
{
const uint8_t *data;
int len;
MALO_HAL_LOCK(mh);
/* NB: we hold the lock so it's ok to use cmdbuf */
data = ((const struct malo_cmd_caltable *) mh->mh_cmdbuf)->caltbl;
if (malo_hal_get_cal_table(mh, 33, 0) == 0) {
len = (data[2] | (data[3] << 8)) - 12;
/* XXX validate len */
memcpy(cal->pt_ratetable_20m, &data[12], len);
}
mh->mh_flags |= MHF_CALDATA;
MALO_HAL_UNLOCK(mh);
return 0;
}
/*
* Reset internal state after a firmware download.
*/
static int
malo_hal_resetstate(struct malo_hal *mh)
{
/*
* Fetch cal data for later use.
* XXX may want to fetch other stuff too.
*/
if ((mh->mh_flags & MHF_CALDATA) == 0)
malo_hal_get_pwrcal_table(mh, &mh->mh_caldata);
return 0;
}
static void
malo_hal_fw_reset(struct malo_hal *mh)
{
if (malo_hal_read4(mh, MALO_REG_INT_CODE) == 0xffffffff) {
device_printf(mh->mh_dev, "%s: device not present!\n",
__func__);
return;
}
malo_hal_write4(mh, MALO_REG_H2A_INTERRUPT_EVENTS, MALO_ISR_RESET);
mh->mh_flags &= ~MHF_FWHANG;
}
static void
malo_hal_trigger_pcicmd(struct malo_hal *mh)
{
uint32_t dummy;
bus_dmamap_sync(mh->mh_dmat, mh->mh_dmamap, BUS_DMASYNC_PREWRITE);
malo_hal_write4(mh, MALO_REG_GEN_PTR, mh->mh_cmdaddr);
dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
malo_hal_write4(mh, MALO_REG_INT_CODE, 0x00);
dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
malo_hal_write4(mh, MALO_REG_H2A_INTERRUPT_EVENTS,
MALO_H2ARIC_BIT_DOOR_BELL);
dummy = malo_hal_read4(mh, MALO_REG_INT_CODE);
}
static int
malo_hal_waitfor(struct malo_hal *mh, uint32_t val)
{
int i;
for (i = 0; i < MALO_FW_MAX_NUM_CHECKS; i++) {
DELAY(MALO_FW_CHECK_USECS);
if (malo_hal_read4(mh, MALO_REG_INT_CODE) == val)
return 0;
}
return -1;
}
/*
* Firmware block xmit when talking to the boot-rom.
*/
static int
malo_hal_send_helper(struct malo_hal *mh, int bsize,
const void *data, size_t dsize, int waitfor)
{
mh->mh_cmdbuf[0] = htole16(MALO_HOSTCMD_CODE_DNLD);
mh->mh_cmdbuf[1] = htole16(bsize);
memcpy(&mh->mh_cmdbuf[4], data , dsize);
malo_hal_trigger_pcicmd(mh);
if (waitfor == MALO_NOWAIT)
goto pass;
/* XXX 2000 vs 200 */
if (malo_hal_waitfor(mh, MALO_INT_CODE_CMD_FINISHED) != 0) {
device_printf(mh->mh_dev,
"%s: timeout waiting for CMD_FINISHED, INT_CODE 0x%x\n",
__func__, malo_hal_read4(mh, MALO_REG_INT_CODE));
return ETIMEDOUT;
}
pass:
malo_hal_write4(mh, MALO_REG_INT_CODE, 0);
return (0);
}
static int
malo_hal_fwload_helper(struct malo_hal *mh, char *helper)
{
const struct firmware *fw;
int error;
fw = firmware_get(helper);
if (fw == NULL) {
device_printf(mh->mh_dev, "could not read microcode %s!\n",
helper);
return (EIO);
}
device_printf(mh->mh_dev, "load %s firmware image (%zu bytes)\n",
helper, fw->datasize);
error = malo_hal_send_helper(mh, fw->datasize, fw->data, fw->datasize,
MALO_WAITOK);
if (error != 0)
goto fail;
/* tell the card we're done and... */
error = malo_hal_send_helper(mh, 0, NULL, 0, MALO_NOWAIT);
fail:
firmware_put(fw, FIRMWARE_UNLOAD);
return (error);
}
/*
* Firmware block xmit when talking to the 1st-stage loader.
*/
static int
malo_hal_send_main(struct malo_hal *mh, const void *data, size_t dsize,
uint16_t seqnum, int waitfor)
{
mh->mh_cmdbuf[0] = htole16(MALO_HOSTCMD_CODE_DNLD);
mh->mh_cmdbuf[1] = htole16(dsize);
mh->mh_cmdbuf[2] = htole16(seqnum);
mh->mh_cmdbuf[3] = 0;
memcpy(&mh->mh_cmdbuf[4], data, dsize);
malo_hal_trigger_pcicmd(mh);
if (waitfor == MALO_NOWAIT)
goto pass;
if (malo_hal_waitfor(mh, MALO_INT_CODE_CMD_FINISHED) != 0) {
device_printf(mh->mh_dev,
"%s: timeout waiting for CMD_FINISHED, INT_CODE 0x%x\n",
__func__, malo_hal_read4(mh, MALO_REG_INT_CODE));
return ETIMEDOUT;
}
pass:
malo_hal_write4(mh, MALO_REG_INT_CODE, 0);
return 0;
}
static int
malo_hal_fwload_main(struct malo_hal *mh, char *firmware)
{
const struct firmware *fw;
const uint8_t *fp;
int error;
size_t count;
uint16_t seqnum;
uint32_t blocksize;
error = 0;
fw = firmware_get(firmware);
if (fw == NULL) {
device_printf(mh->mh_dev, "could not read firmware %s!\n",
firmware);
return (EIO);
}
device_printf(mh->mh_dev, "load %s firmware image (%zu bytes)\n",
firmware, fw->datasize);
seqnum = 1;
for (count = 0; count < fw->datasize; count += blocksize) {
blocksize = MIN(256, fw->datasize - count);
fp = (const uint8_t *)fw->data + count;
error = malo_hal_send_main(mh, fp, blocksize, seqnum++,
MALO_NOWAIT);
if (error != 0)
goto fail;
DELAY(500);
}
/*
* send a command with size 0 to tell that the firmware has been
* uploaded
*/
error = malo_hal_send_main(mh, NULL, 0, seqnum++, MALO_NOWAIT);
DELAY(100);
fail:
firmware_put(fw, FIRMWARE_UNLOAD);
return (error);
}
int
malo_hal_fwload(struct malo_hal *mh, char *helper, char *firmware)
{
int error, i;
uint32_t fwreadysig, opmode;
/*
* NB: now malo(4) supports only STA mode. It will be better if it
* supports AP mode.
*/
fwreadysig = MALO_HOSTCMD_STA_FWRDY_SIGNATURE;
opmode = MALO_HOSTCMD_STA_MODE;
malo_hal_fw_reset(mh);
malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_CLEAR_SEL,
MALO_A2HRIC_BIT_MASK);
malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_CAUSE, 0x00);
malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_MASK, 0x00);
malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_STATUS_MASK,
MALO_A2HRIC_BIT_MASK);
error = malo_hal_fwload_helper(mh, helper);
if (error != 0) {
device_printf(mh->mh_dev, "failed to load bootrom loader.\n");
goto fail;
}
DELAY(200 * MALO_FW_CHECK_USECS);
error = malo_hal_fwload_main(mh, firmware);
if (error != 0) {
device_printf(mh->mh_dev, "failed to load firmware.\n");
goto fail;
}
/*
* Wait for firmware to startup; we monitor the INT_CODE register
* waiting for a signature to written back indicating it's ready to go.
*/
mh->mh_cmdbuf[1] = 0;
if (opmode != MALO_HOSTCMD_STA_MODE)
malo_hal_trigger_pcicmd(mh);
for (i = 0; i < MALO_FW_MAX_NUM_CHECKS; i++) {
malo_hal_write4(mh, MALO_REG_GEN_PTR, opmode);
DELAY(MALO_FW_CHECK_USECS);
if (malo_hal_read4(mh, MALO_REG_INT_CODE) == fwreadysig) {
malo_hal_write4(mh, MALO_REG_INT_CODE, 0x00);
return malo_hal_resetstate(mh);
}
}
return ETIMEDOUT;
fail:
malo_hal_fw_reset(mh);
return (error);
}
/*
* Return "hw specs". Note this must be the first cmd MUST be done after
* a firmware download or the f/w will lockup.
*/
int
malo_hal_gethwspecs(struct malo_hal *mh, struct malo_hal_hwspec *hw)
{
struct malo_cmd_get_hwspec *cmd;
int ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_get_hwspec, MALO_HOSTCMD_GET_HW_SPEC);
memset(&cmd->permaddr[0], 0xff, IEEE80211_ADDR_LEN);
cmd->ul_fw_awakecookie = htole32((unsigned int)mh->mh_cmdaddr + 2048);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_GET_HW_SPEC);
if (ret == 0) {
IEEE80211_ADDR_COPY(hw->macaddr, cmd->permaddr);
hw->wcbbase[0] = le32toh(cmd->wcbbase0) & 0x0000ffff;
hw->wcbbase[1] = le32toh(cmd->wcbbase1) & 0x0000ffff;
hw->wcbbase[2] = le32toh(cmd->wcbbase2) & 0x0000ffff;
hw->wcbbase[3] = le32toh(cmd->wcbbase3) & 0x0000ffff;
hw->rxdesc_read = le32toh(cmd->rxpdrd_ptr)& 0x0000ffff;
hw->rxdesc_write = le32toh(cmd->rxpdwr_ptr)& 0x0000ffff;
hw->regioncode = le16toh(cmd->regioncode) & 0x00ff;
hw->fw_releasenum = le32toh(cmd->fw_releasenum);
hw->maxnum_wcb = le16toh(cmd->num_wcb);
hw->maxnum_mcaddr = le16toh(cmd->num_mcastaddr);
hw->num_antenna = le16toh(cmd->num_antenna);
hw->hwversion = cmd->version;
hw->hostinterface = cmd->hostif;
}
MALO_HAL_UNLOCK(mh);
return ret;
}
void
malo_hal_detach(struct malo_hal *mh)
{
bus_dmamem_free(mh->mh_dmat, mh->mh_cmdbuf, mh->mh_dmamap);
bus_dmamap_destroy(mh->mh_dmat, mh->mh_dmamap);
bus_dma_tag_destroy(mh->mh_dmat);
mtx_destroy(&mh->mh_mtx);
free(mh, M_DEVBUF);
}
/*
* Configure antenna use. Takes effect immediately.
*
* XXX tx antenna setting ignored
* XXX rx antenna setting should always be 3 (for now)
*/
int
malo_hal_setantenna(struct malo_hal *mh, enum malo_hal_antenna dirset, int ant)
{
struct malo_cmd_rf_antenna *cmd;
int ret;
if (!(dirset == MHA_ANTENNATYPE_RX || dirset == MHA_ANTENNATYPE_TX))
return EINVAL;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_rf_antenna,
MALO_HOSTCMD_802_11_RF_ANTENNA);
cmd->action = htole16(dirset);
if (ant == 0) { /* default to all/both antennae */
/* XXX never reach now. */
ant = 3;
}
cmd->mode = htole16(ant);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_802_11_RF_ANTENNA);
MALO_HAL_UNLOCK(mh);
return ret;
}
/*
* Configure radio. Takes effect immediately.
*
* XXX preamble installed after set fixed rate cmd
*/
int
malo_hal_setradio(struct malo_hal *mh, int onoff,
enum malo_hal_preamble preamble)
{
struct malo_cmd_radio_control *cmd;
int ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_radio_control,
MALO_HOSTCMD_802_11_RADIO_CONTROL);
cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET);
if (onoff == 0)
cmd->control = 0;
else
cmd->control = htole16(preamble);
cmd->radio_on = htole16(onoff);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_802_11_RADIO_CONTROL);
MALO_HAL_UNLOCK(mh);
return ret;
}
/*
* Set the interrupt mask.
*/
void
malo_hal_intrset(struct malo_hal *mh, uint32_t mask)
{
malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_MASK, 0);
(void)malo_hal_read4(mh, MALO_REG_INT_CODE);
mh->mh_imask = mask;
malo_hal_write4(mh, MALO_REG_A2H_INTERRUPT_MASK, mask);
(void)malo_hal_read4(mh, MALO_REG_INT_CODE);
}
int
malo_hal_setchannel(struct malo_hal *mh, const struct malo_hal_channel *chan)
{
struct malo_cmd_fw_set_rf_channel *cmd;
int ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_fw_set_rf_channel,
MALO_HOSTCMD_SET_RF_CHANNEL);
cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET);
cmd->cur_channel = chan->channel;
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_RF_CHANNEL);
MALO_HAL_UNLOCK(mh);
return ret;
}
int
malo_hal_settxpower(struct malo_hal *mh, const struct malo_hal_channel *c)
{
struct malo_cmd_rf_tx_power *cmd;
const struct malo_hal_caldata *cal = &mh->mh_caldata;
uint8_t chan = c->channel;
uint16_t pow;
int i, idx, ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_rf_tx_power,
MALO_HOSTCMD_802_11_RF_TX_POWER);
cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET_LIST);
for (i = 0; i < 4; i++) {
idx = (chan - 1) * 4 + i;
pow = cal->pt_ratetable_20m[idx];
cmd->power_levellist[i] = htole16(pow);
}
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_802_11_RF_TX_POWER);
MALO_HAL_UNLOCK(mh);
return ret;
}
int
malo_hal_setpromisc(struct malo_hal *mh, int enable)
{
/* XXX need host cmd */
return 0;
}
int
malo_hal_setassocid(struct malo_hal *mh,
const uint8_t bssid[IEEE80211_ADDR_LEN], uint16_t associd)
{
struct malo_cmd_fw_set_aid *cmd;
int ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_fw_set_aid,
MALO_HOSTCMD_SET_AID);
cmd->cmdhdr.seqnum = 1;
cmd->associd = htole16(associd);
IEEE80211_ADDR_COPY(&cmd->macaddr[0], bssid);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_AID);
MALO_HAL_UNLOCK(mh);
return ret;
}
/*
* Kick the firmware to tell it there are new tx descriptors
* for processing. The driver says what h/w q has work in
* case the f/w ever gets smarter.
*/
void
malo_hal_txstart(struct malo_hal *mh, int qnum)
{
bus_space_write_4(mh->mh_iot, mh->mh_ioh,
MALO_REG_H2A_INTERRUPT_EVENTS, MALO_H2ARIC_BIT_PPA_READY);
(void) bus_space_read_4(mh->mh_iot, mh->mh_ioh, MALO_REG_INT_CODE);
}
/*
* Return the current ISR setting and clear the cause.
*/
void
malo_hal_getisr(struct malo_hal *mh, uint32_t *status)
{
uint32_t cause;
cause = bus_space_read_4(mh->mh_iot, mh->mh_ioh,
MALO_REG_A2H_INTERRUPT_CAUSE);
if (cause == 0xffffffff) { /* card removed */
cause = 0;
} else if (cause != 0) {
/* clear cause bits */
bus_space_write_4(mh->mh_iot, mh->mh_ioh,
MALO_REG_A2H_INTERRUPT_CAUSE, cause &~ mh->mh_imask);
(void) bus_space_read_4(mh->mh_iot, mh->mh_ioh,
MALO_REG_INT_CODE);
cause &= mh->mh_imask;
}
*status = cause;
}
/*
* Callback from the driver on a cmd done interrupt. Nothing to do right
* now as we spin waiting for cmd completion.
*/
void
malo_hal_cmddone(struct malo_hal *mh)
{
/* NB : do nothing. */
}
int
malo_hal_prescan(struct malo_hal *mh)
{
struct malo_cmd_prescan *cmd;
int ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_prescan, MALO_HOSTCMD_SET_PRE_SCAN);
cmd->cmdhdr.seqnum = 1;
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_PRE_SCAN);
MALO_HAL_UNLOCK(mh);
return ret;
}
int
malo_hal_postscan(struct malo_hal *mh, uint8_t *macaddr, uint8_t ibsson)
{
struct malo_cmd_postscan *cmd;
int ret;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_postscan, MALO_HOSTCMD_SET_POST_SCAN);
cmd->cmdhdr.seqnum = 1;
cmd->isibss = htole32(ibsson);
IEEE80211_ADDR_COPY(&cmd->bssid[0], macaddr);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_POST_SCAN);
MALO_HAL_UNLOCK(mh);
return ret;
}
int
malo_hal_set_slot(struct malo_hal *mh, int is_short)
{
int ret;
struct malo_cmd_fw_setslot *cmd;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_fw_setslot, MALO_HOSTCMD_SET_SLOT);
cmd->action = htole16(MALO_HOSTCMD_ACT_GEN_SET);
cmd->slot = (is_short == 1 ? 1 : 0);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_SLOT);
MALO_HAL_UNLOCK(mh);
return ret;
}
int
malo_hal_set_rate(struct malo_hal *mh, uint16_t curmode, uint8_t rate)
{
int i, ret;
struct malo_cmd_set_rate *cmd;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_set_rate, MALO_HOSTCMD_SET_RATE);
cmd->aprates[0] = 2;
cmd->aprates[1] = 4;
cmd->aprates[2] = 11;
cmd->aprates[3] = 22;
if (curmode == IEEE80211_MODE_11G) {
cmd->aprates[4] = 0; /* XXX reserved? */
cmd->aprates[5] = 12;
cmd->aprates[6] = 18;
cmd->aprates[7] = 24;
cmd->aprates[8] = 36;
cmd->aprates[9] = 48;
cmd->aprates[10] = 72;
cmd->aprates[11] = 96;
cmd->aprates[12] = 108;
}
if (rate != 0) {
/* fixed rate */
for (i = 0; i < 13; i++) {
if (cmd->aprates[i] == rate) {
cmd->rateindex = i;
cmd->dataratetype = 1;
break;
}
}
}
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_SET_RATE);
MALO_HAL_UNLOCK(mh);
return ret;
}
int
malo_hal_setmcast(struct malo_hal *mh, int nmc, const uint8_t macs[])
{
struct malo_cmd_mcast *cmd;
int ret;
if (nmc > MALO_HAL_MCAST_MAX)
return EINVAL;
MALO_HAL_LOCK(mh);
_CMD_SETUP(cmd, struct malo_cmd_mcast, MALO_HOSTCMD_MAC_MULTICAST_ADR);
memcpy(cmd->maclist, macs, nmc * IEEE80211_ADDR_LEN);
cmd->numaddr = htole16(nmc);
cmd->action = htole16(0xffff);
ret = malo_hal_execute_cmd(mh, MALO_HOSTCMD_MAC_MULTICAST_ADR);
MALO_HAL_UNLOCK(mh);
return ret;
}
@@ -0,0 +1,234 @@
/*-
* Copyright (c) 2007 Marvell Semiconductor, Inc.
* Copyright (c) 2007 Sam Leffler, Errno Consulting
* Copyright (c) 2008 Weongyo Jeong <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
* $FreeBSD$
*/
#ifndef _DEV_MALOHAL_H
#define _DEV_MALOHAL_H
#define MALO_NUM_TX_QUEUES 1
#define MALO_MAX_TXWCB_QUEUES MALO_NUM_TX_QUEUES
/* size of f/w command buffer */
#define MALO_CMDBUF_SIZE 0x4000
#define MALO_FW_CHECK_USECS (5 * 1000) /* 5ms */
#define MALO_FW_MAX_NUM_CHECKS 200
/*
* Calibration data builtin to the firmware. The firmware image
* has a single set of calibration tables that we retrieve right
* after download. This can be overriden by the driver (e.g. for
* a different regdomain and/or tx power setup).
*/
struct malo_hal_caldata {
/* pt is short for `power target'. */
#define MALO_PWTAGETRATETABLE20M (14 * 4)
uint8_t pt_ratetable_20m[MALO_PWTAGETRATETABLE20M];
};
/*
* Get Hardware/Firmware capabilities.
*/
struct malo_hal_hwspec {
uint8_t hwversion; /* version of the HW */
uint8_t hostinterface; /* host interface */
uint16_t maxnum_wcb; /* max # of WCB FW handles */
/* max # of mcast addresses FW handles*/
uint16_t maxnum_mcaddr;
uint16_t maxnum_tx_wcb; /* max # of tx descs per WCB */
/* MAC address programmed in HW */
uint8_t macaddr[6];
uint16_t regioncode; /* EEPROM region code */
uint16_t num_antenna; /* Number of antenna used */
uint32_t fw_releasenum; /* firmware release number */
uint32_t wcbbase0;
uint32_t rxdesc_read;
uint32_t rxdesc_write;
uint32_t ul_fw_awakecookie;
uint32_t wcbbase[4];
};
/*
* Supply tx/rx dma-related settings to the firmware.
*/
struct malo_hal_txrxdma {
uint32_t maxnum_wcb; /* max # of WCB FW handles */
uint32_t maxnum_txwcb; /* max # of tx descs per WCB */
uint32_t rxdesc_read;
uint32_t rxdesc_write;
uint32_t wcbbase[4];
};
/*
* Get Hardware Statistics.
*
* Items marked with ! are deprecated and not ever updated. In
* some cases this is because work has been moved to the host (e.g.
* rx defragmentation).
*
* XXX low/up cases.
*/
struct malo_hal_hwstats {
uint32_t TxRetrySuccesses; /* tx success w/ 1 retry */
uint32_t TxMultipleRetrySuccesses;/* tx success w/ >1 retry */
uint32_t TxFailures; /* tx fail due to no ACK */
uint32_t RTSSuccesses; /* CTS rx'd for RTS */
uint32_t RTSFailures; /* CTS not rx'd for RTS */
uint32_t AckFailures; /* same as TxFailures */
uint32_t RxDuplicateFrames; /* rx discard for dup seqno */
uint32_t FCSErrorCount; /* rx discard for bad FCS */
uint32_t TxWatchDogTimeouts; /* MAC tx hang (f/w recovery) */
uint32_t RxOverflows; /* no f/w buffer for rx data */
uint32_t RxFragErrors; /* !rx fail due to defrag */
uint32_t RxMemErrors; /* out of mem or desc corrupted
in some way */
uint32_t RxPointerErrors; /* MAC internal ptr problem */
uint32_t TxUnderflows; /* !tx underflow on dma */
uint32_t TxDone; /* MAC tx ops completed
(possibly w/ error) */
uint32_t TxDoneBufTryPut; /* ! */
uint32_t TxDoneBufPut; /* same as TxDone */
uint32_t Wait4TxBuf; /* !no f/w buf avail when
supplied a tx descriptor */
uint32_t TxAttempts; /* tx descriptors processed */
uint32_t TxSuccesses; /* tx attempts successful */
uint32_t TxFragments; /* tx with fragmentation */
uint32_t TxMulticasts; /* tx multicast frames */
uint32_t RxNonCtlPkts; /* rx non-control frames */
uint32_t RxMulticasts; /* rx multicast frames */
uint32_t RxUndecryptableFrames; /* rx failed due to crypto */
uint32_t RxICVErrors; /* rx failed due to ICV check */
uint32_t RxExcludedFrames; /* rx discarded, e.g. bssid */
};
/*
* Set Antenna Configuration (legacy operation).
*
* The RX antenna can be selected using the the bitmask
* ant (bit 0 = antenna 1, bit 1 = antenna 2, etc.)
* (diversity?XXX)
*/
enum malo_hal_antenna {
MHA_ANTENNATYPE_RX = 1,
MHA_ANTENNATYPE_TX = 2,
};
/*
* Set Radio Configuration.
*
* onoff != 0 turns radio on; otherwise off.
* if radio is enabled, the preamble is set too.
*/
enum malo_hal_preamble {
MHP_LONG_PREAMBLE = 1,
MHP_SHORT_PREAMBLE = 3,
MHP_AUTO_PREAMBLE = 5,
};
struct malo_hal_channel_flags {
uint32_t freqband : 6,
#define MALO_FREQ_BAND_2DOT4GHZ 0x1
: 26; /* reserved */
};
struct malo_hal_channel {
uint32_t channel;
struct malo_hal_channel_flags flags;
};
struct malo_hal_txrate {
uint8_t mcastrate; /* rate for multicast frames */
uint8_t mgtrate; /* rate for management frames */
struct {
uint8_t trycount; /* try this many times */
uint8_t rate; /* use this tx rate */
} rateseries[4]; /* rate series */
};
struct malo_hal {
device_t mh_dev;
bus_space_handle_t mh_ioh; /* BAR 1 copied from softc */
bus_space_tag_t mh_iot;
uint32_t mh_imask; /* interrupt mask */
int mh_flags;
#define MHF_CALDATA 0x0001 /* cal data retrieved */
#define MHF_FWHANG 0x0002 /* fw appears hung */
char mh_mtxname[12];
struct mtx mh_mtx;
bus_dma_tag_t mh_dmat; /* bus DMA tag for cmd buffer */
bus_dmamap_t mh_dmamap; /* DMA map for cmd buffer */
uint16_t *mh_cmdbuf; /* f/w cmd buffer */
bus_addr_t mh_cmdaddr; /* physaddr of cmd buffer */
struct malo_hal_caldata mh_caldata;
int mh_debug;
#define MALO_HAL_DEBUG_SENDCMD 0x00000001
#define MALO_HAL_DEBUG_CMDDONE 0x00000002
#define MALO_HAL_DEBUG_IGNHANG 0X00000004
};
#define MALO_HAL_LOCK(mh) mtx_lock(&mh->mh_mtx)
#define MALO_HAL_LOCK_ASSERT(mh) mtx_assert(&mh->mh_mtx, MA_OWNED)
#define MALO_HAL_UNLOCK(mh) mtx_unlock(&mh->mh_mtx)
struct malo_hal *malo_hal_attach(device_t, uint16_t,
bus_space_handle_t, bus_space_tag_t,
bus_dma_tag_t);
int malo_hal_fwload(struct malo_hal *, char *, char *);
int malo_hal_gethwspecs(struct malo_hal *,
struct malo_hal_hwspec *);
void malo_hal_detach(struct malo_hal *);
void malo_hal_intrset(struct malo_hal *, uint32_t);
int malo_hal_setantenna(struct malo_hal *,
enum malo_hal_antenna, int);
int malo_hal_setradio(struct malo_hal *, int,
enum malo_hal_preamble);
int malo_hal_setchannel(struct malo_hal *,
const struct malo_hal_channel *);
int malo_hal_setmaxtxpwr(struct malo_hal *, uint16_t);
int malo_hal_settxpower(struct malo_hal *, const struct malo_hal_channel *);
int malo_hal_setpromisc(struct malo_hal *, int);
int malo_hal_setassocid(struct malo_hal *,
const uint8_t[], uint16_t);
void malo_hal_txstart(struct malo_hal *, int);
void malo_hal_getisr(struct malo_hal *, uint32_t *);
void malo_hal_cmddone(struct malo_hal *);
int malo_hal_prescan(struct malo_hal *);
int malo_hal_postscan(struct malo_hal *, uint8_t *, uint8_t);
int malo_hal_set_slot(struct malo_hal *, int);
int malo_hal_set_rate(struct malo_hal *, uint16_t, uint8_t);
int malo_hal_setmcast(struct malo_hal *, int, const uint8_t[]);
#endif
@@ -0,0 +1,114 @@
/*-
* Copyright (c) 2007 Marvell Semiconductor, Inc.
* Copyright (c) 2007 Sam Leffler, Errno Consulting
* Copyright (c) 2008 Weongyo Jeong <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
* $FreeBSD$
*/
/*
* Ioctl-related defintions for the Marvel Wireless LAN controller driver.
*/
#ifndef _DEV_MALO_MVIOCTL_H
#define _DEV_MALO_MVIOCTL_H
struct malo_stats {
struct malo_hal_hwstats hw_stats; /* XXX tied to h/w defs */
uint32_t mst_failure; /* generic hardware failure */
uint32_t mst_rx_badtkipicv;
uint32_t mst_tx_discard;
uint32_t mst_tx_qstop;
uint32_t mst_tx_encap;
uint32_t mst_tx_mgmt;
uint32_t mst_rx_nombuf;
uint32_t mst_rx_busdma;
uint32_t mst_rx_tooshort;
uint32_t mst_tx_busdma;
uint32_t mst_tx_linear;
uint32_t mst_tx_nombuf;
uint32_t mst_tx_nodata;
uint32_t mst_tx_shortpre;
uint32_t mst_tx_retries;
uint32_t mst_tx_mretries;
uint32_t mst_tx_linkerror;
uint32_t mst_tx_xretries;
uint32_t mst_tx_aging;
uint32_t mst_watchdog;
uint32_t mst_tx_packets;
uint32_t mst_rx_packets;
int8_t mst_rx_rssi;
int8_t mst_rx_noise;
uint8_t mst_tx_rate;
uint32_t mst_ant_tx[4];
uint32_t mst_ant_rx[4];
};
#define SIOCGMVSTATS _IOWR('i', 137, struct ifreq)
/*
* Radio capture format.
*/
#define MALO_RX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_ANTENNA) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \
0)
struct malo_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
u_int8_t wr_flags;
u_int8_t wr_rate;
u_int16_t wr_chan_freq;
u_int16_t wr_chan_flags;
int8_t wr_antsignal;
int8_t wr_antnoise;
u_int8_t wr_antenna;
};
#define MALO_TX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \
(1 << IEEE80211_RADIOTAP_ANTENNA) | \
0)
struct malo_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
u_int8_t wt_flags;
u_int8_t wt_rate;
u_int16_t wt_chan_freq;
u_int16_t wt_chan_flags;
u_int8_t wt_txpower;
u_int8_t wt_antenna;
};
#endif /* _DEV_MALO_MVIOCTL_H */
@@ -0,0 +1 @@
//#define MALO_DEBUG 1