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:
@@ -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, ®) == 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
|
||||
Reference in New Issue
Block a user