aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVipin Mehta <vmehta@atheros.com>2010-09-01 12:06:33 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-09-02 11:43:26 -0700
commit30295c8936f3a426985e99bebb17d72bd7847910 (patch)
tree28ff0c23bfa931b73a35e7b11df1bf104260c6fa
parent9b9913d80b2896ecd9e0a1a8f167ccad66fac79c (diff)
downloadmrst-s0i3-test-30295c8936f3a426985e99bebb17d72bd7847910.tar.gz
mrst-s0i3-test-30295c8936f3a426985e99bebb17d72bd7847910.tar.xz
mrst-s0i3-test-30295c8936f3a426985e99bebb17d72bd7847910.zip
staging: add ath6kl driver for AR6003 chip
AR6003 is a single stream, SDIO based 802.11 chipset from Atheros optimized for mobile and embedded devices. ath6kl is a cfg80211 driver for AR6003 and supports both the station and AP mode of operation. Station mode supports 802.11 a/b/g/n with HT20 on 2.4/5GHz and HT40 only on 5GHz. Some of the other features include WPA/WPA2, WPS, WMM, WMM-PS, and BT coexistence. AP mode can be operated only in b/g mode with support for a subset of features mentioned above. The driver supports cfg80211 but comes with its own set of wext ioctls which have historically supported some of our customers with features like BT 3.0 and AP mode of operation. For further details, please refer to: http://wireless.kernel.org/en/users/Drivers/ath6kl The driver requires firmware that runs on the chip's network processor. The majority of it is stored in ROM. The binaries that are downloaded and executed from RAM are as follows: 1) Patch against the code in ROM for bug fixes and feature enhancements. 2) Code to copy the data from the OTP region of the memory into RAM. 3) Calibration file carrying board specific data. The above files need to be present in the directory '/lib/firmware/ath6k/AR6003/hw2.0/' for the driver to initialize the chip upon enumeration. The files can be downloaded from the link specified at the following location: http://wireless.kernel.org/en/users/Drivers/ath6kl#Download This driver is only provided in the interim while we work on the mac80211 replacement, ath6k. Once the mac80211 driver achieves feature parity with the ath6kl driver, the ath6kl will be deprecated and removed from staging. Signed-off-by: Vipin Mehta <vmehta@atheros.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/ath6kl/Kconfig163
-rw-r--r--drivers/staging/ath6kl/Makefile159
-rw-r--r--drivers/staging/ath6kl/TODO8
-rw-r--r--drivers/staging/ath6kl/bmi/include/bmi_internal.h55
-rw-r--r--drivers/staging/ath6kl/bmi/src/bmi.c1010
-rw-r--r--drivers/staging/ath6kl/hif/common/hif_sdio_common.h87
-rw-r--r--drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h134
-rw-r--r--drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c1298
-rw-r--r--drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c393
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k.c1471
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k.h398
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c784
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c756
-rw-r--r--drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c1280
-rw-r--r--drivers/staging/ath6kl/htc2/htc.c579
-rw-r--r--drivers/staging/ath6kl/htc2/htc_debug.h38
-rw-r--r--drivers/staging/ath6kl/htc2/htc_internal.h220
-rw-r--r--drivers/staging/ath6kl/htc2/htc_recv.c1578
-rw-r--r--drivers/staging/ath6kl/htc2/htc_send.c1023
-rw-r--r--drivers/staging/ath6kl/htc2/htc_services.c450
-rw-r--r--drivers/staging/ath6kl/include/a_config.h53
-rw-r--r--drivers/staging/ath6kl/include/a_debug.h224
-rw-r--r--drivers/staging/ath6kl/include/a_drv.h54
-rw-r--r--drivers/staging/ath6kl/include/a_drv_api.h232
-rw-r--r--drivers/staging/ath6kl/include/a_osapi.h61
-rw-r--r--drivers/staging/ath6kl/include/a_types.h58
-rw-r--r--drivers/staging/ath6kl/include/aggr_recv_api.h140
-rw-r--r--drivers/staging/ath6kl/include/ar3kconfig.h65
-rw-r--r--drivers/staging/ath6kl/include/ar6000_api.h54
-rw-r--r--drivers/staging/ath6kl/include/ar6000_diag.h48
-rw-r--r--drivers/staging/ath6kl/include/ar6kap_common.h44
-rw-r--r--drivers/staging/ath6kl/include/athbtfilter.h135
-rw-r--r--drivers/staging/ath6kl/include/athendpack.h52
-rw-r--r--drivers/staging/ath6kl/include/athstartpack.h55
-rw-r--r--drivers/staging/ath6kl/include/bmi.h135
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h60
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h52
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/addrs.h90
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_intf_reg.h64
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_reg.h1932
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/apb_map.h13
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/gpio_reg.h977
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/mbox_host_reg.h386
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/mbox_reg.h481
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/rtc_reg.h1163
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/si_reg.h186
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/uart_reg.h327
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw.0/vmc_reg.h76
l---------drivers/staging/ath6kl/include/common/AR6002/hw2.0/hw1
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/analog_intf_ares_reg.h3291
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/analog_intf_athr_wlan_reg.h3674
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/analog_intf_reg.h37
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_athr_wlan_map.h40
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/apb_map.h48
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/bb_lc_reg.h7076
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/efuse_reg.h108
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/gpio_athr_wlan_reg.h1253
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/gpio_reg.h1094
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mac_dma_reg.h605
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mac_pcu_reg.h3065
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_host_reg.h37
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_reg.h560
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_host_reg.h522
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/mbox_wlan_reg.h638
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rdma_reg.h564
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_reg.h975
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/rtc_wlan_reg.h2065
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/si_reg.h209
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/uart_reg.h260
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/umbox_reg.h37
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/umbox_wlan_reg.h322
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/vmc_reg.h167
-rw-r--r--drivers/staging/ath6kl/include/common/AR6002/hw4.0/hw/vmc_wlan_reg.h195
-rw-r--r--drivers/staging/ath6kl/include/common/a_hci.h682
-rw-r--r--drivers/staging/ath6kl/include/common/athdefs.h84
-rw-r--r--drivers/staging/ath6kl/include/common/bmi_msg.h241
-rw-r--r--drivers/staging/ath6kl/include/common/btcoexGpio.h86
-rw-r--r--drivers/staging/ath6kl/include/common/cnxmgmt.h36
-rw-r--r--drivers/staging/ath6kl/include/common/dbglog.h134
-rw-r--r--drivers/staging/ath6kl/include/common/dbglog_id.h558
-rw-r--r--drivers/staging/ath6kl/include/common/discovery.h75
-rw-r--r--drivers/staging/ath6kl/include/common/dset_internal.h63
-rw-r--r--drivers/staging/ath6kl/include/common/dsetid.h134
-rw-r--r--drivers/staging/ath6kl/include/common/epping_test.h120
-rw-r--r--drivers/staging/ath6kl/include/common/gmboxif.h78
-rw-r--r--drivers/staging/ath6kl/include/common/gpio.h45
-rw-r--r--drivers/staging/ath6kl/include/common/htc.h236
-rw-r--r--drivers/staging/ath6kl/include/common/htc_services.h52
-rw-r--r--drivers/staging/ath6kl/include/common/ini_dset.h82
-rw-r--r--drivers/staging/ath6kl/include/common/pkt_log.h45
-rw-r--r--drivers/staging/ath6kl/include/common/regDb.h29
-rw-r--r--drivers/staging/ath6kl/include/common/regdump.h59
-rw-r--r--drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h237
-rw-r--r--drivers/staging/ath6kl/include/common/regulatory/reg_dbvalues.h504
-rw-r--r--drivers/staging/ath6kl/include/common/roaming.h41
-rw-r--r--drivers/staging/ath6kl/include/common/targaddrs.h245
-rw-r--r--drivers/staging/ath6kl/include/common/testcmd.h185
-rw-r--r--drivers/staging/ath6kl/include/common/tlpm.h38
-rw-r--r--drivers/staging/ath6kl/include/common/wlan_defs.h79
-rw-r--r--drivers/staging/ath6kl/include/common/wlan_dset.h33
-rw-r--r--drivers/staging/ath6kl/include/common/wmi.h3119
-rw-r--r--drivers/staging/ath6kl/include/common/wmi_thin.h347
-rw-r--r--drivers/staging/ath6kl/include/common/wmix.h279
-rw-r--r--drivers/staging/ath6kl/include/common_drv.h108
-rw-r--r--drivers/staging/ath6kl/include/dbglog_api.h52
-rw-r--r--drivers/staging/ath6kl/include/dl_list.h153
-rw-r--r--drivers/staging/ath6kl/include/dset_api.h65
-rw-r--r--drivers/staging/ath6kl/include/gpio_api.h59
-rw-r--r--drivers/staging/ath6kl/include/hci_transport_api.h259
-rw-r--r--drivers/staging/ath6kl/include/hif.h458
-rw-r--r--drivers/staging/ath6kl/include/host_version.h52
-rw-r--r--drivers/staging/ath6kl/include/htc_api.h575
-rw-r--r--drivers/staging/ath6kl/include/htc_packet.h227
-rw-r--r--drivers/staging/ath6kl/include/target_reg_table.h244
-rw-r--r--drivers/staging/ath6kl/include/wlan_api.h128
-rw-r--r--drivers/staging/ath6kl/include/wmi_api.h441
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kconfig.c566
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c572
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h79
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c980
-rw-r--r--drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h127
-rw-r--r--drivers/staging/ath6kl/miscdrv/common_drv.c1027
-rw-r--r--drivers/staging/ath6kl/miscdrv/credit_dist.c418
-rw-r--r--drivers/staging/ath6kl/miscdrv/miscdrv.h42
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_android.c413
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_drv.c6453
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_pm.c731
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6000_raw_if.c455
-rw-r--r--drivers/staging/ath6kl/os/linux/ar6k_pal.c481
-rw-r--r--drivers/staging/ath6kl/os/linux/cfg80211.c1478
-rw-r--r--drivers/staging/ath6kl/os/linux/eeprom.c576
-rw-r--r--drivers/staging/ath6kl/os/linux/export_hci_transport.c125
-rw-r--r--drivers/staging/ath6kl/os/linux/hci_bridge.c1144
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6000_drv.h770
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6k_pal.h36
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h197
-rw-r--r--drivers/staging/ath6kl/os/linux/include/athdrv_linux.h1219
-rw-r--r--drivers/staging/ath6kl/os/linux/include/athendpack_linux.h0
-rw-r--r--drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h0
-rw-r--r--drivers/staging/ath6kl/os/linux/include/athtypes_linux.h53
-rw-r--r--drivers/staging/ath6kl/os/linux/include/cfg80211.h50
-rw-r--r--drivers/staging/ath6kl/os/linux/include/config_linux.h60
-rw-r--r--drivers/staging/ath6kl/os/linux/include/debug_linux.h50
-rw-r--r--drivers/staging/ath6kl/os/linux/include/export_hci_transport.h76
-rw-r--r--drivers/staging/ath6kl/os/linux/include/ieee80211_ioctl.h179
-rw-r--r--drivers/staging/ath6kl/os/linux/include/osapi_linux.h387
-rw-r--r--drivers/staging/ath6kl/os/linux/include/wlan_config.h111
-rw-r--r--drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h293
-rw-r--r--drivers/staging/ath6kl/os/linux/ioctl.c4649
-rw-r--r--drivers/staging/ath6kl/os/linux/netbuf.c236
-rw-r--r--drivers/staging/ath6kl/os/linux/wireless_ext.c2725
-rw-r--r--drivers/staging/ath6kl/reorder/aggr_rx_internal.h116
-rw-r--r--drivers/staging/ath6kl/reorder/rcv_aggr.c666
-rw-r--r--drivers/staging/ath6kl/wlan/include/ieee80211.h401
-rw-r--r--drivers/staging/ath6kl/wlan/include/ieee80211_node.h93
-rw-r--r--drivers/staging/ath6kl/wlan/src/wlan_node.c636
-rw-r--r--drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c200
-rw-r--r--drivers/staging/ath6kl/wlan/src/wlan_utils.c61
-rw-r--r--drivers/staging/ath6kl/wmi/wmi.c6672
-rw-r--r--drivers/staging/ath6kl/wmi/wmi_host.h102
162 files changed, 92419 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index a3897c52afa..b9d81eaf1b2 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -157,5 +157,7 @@ source "drivers/staging/westbridge/Kconfig"
source "drivers/staging/sbe-2t3e3/Kconfig"
+source "drivers/staging/ath6kl/Kconfig"
+
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index dd2c66fdf97..64ec1e9a40b 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -59,3 +59,4 @@ obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
obj-$(CONFIG_WESTBRIDGE_ASTORIA) += westbridge/astoria/
obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/
+obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/
diff --git a/drivers/staging/ath6kl/Kconfig b/drivers/staging/ath6kl/Kconfig
new file mode 100644
index 00000000000..ae2cdf48b74
--- /dev/null
+++ b/drivers/staging/ath6kl/Kconfig
@@ -0,0 +1,163 @@
+config ATH6K_LEGACY
+ tristate "Atheros AR6003 support (non mac80211)"
+ depends on MMC && WLAN
+ select WIRELESS_EXT
+ select WEXT_PRIV
+ help
+ This module adds support for wireless adapters based on Atheros AR6003 chipset running over SDIO. If you choose to build it as a module, it will be called ath6kl. Pls note that AR6002 and AR6001 are not supported by this driver.
+
+choice
+ prompt "AR6003 Board Data Configuration"
+ depends on ATH6K_LEGACY
+ default AR600x_SD31_XXX
+ help
+ Select the appropriate board data template from the list below that matches your AR6003 based reference design.
+
+config AR600x_SD31_XXX
+ bool "SD31-xxx"
+ help
+ Board Data file for a standard SD31 reference design (File: bdata.SD31.bin)
+
+config AR600x_WB31_XXX
+ bool "WB31-xxx"
+ help
+ Board Data file for a standard WB31 (BT/WiFi) reference design (File: bdata.WB31.bin)
+
+config AR600x_SD32_XXX
+ bool "SD32-xxx"
+ help
+ Board Data file for a standard SD32 (5GHz) reference design (File: bdata.SD32.bin)
+
+config AR600x_CUSTOM_XXX
+ bool "CUSTOM-xxx"
+ help
+ Board Data file for a custom reference design (File: should be named as bdata.CUSTOM.bin)
+endchoice
+
+config ATH6KL_ENABLE_COEXISTENCE
+ bool "BT Coexistence support"
+ depends on ATH6K_LEGACY
+ help
+ Enables WLAN/BT coexistence support. Select the apprpriate configuration from below.
+
+choice
+ prompt "Front-End Antenna Configuration"
+ depends on ATH6KL_ENABLE_COEXISTENCE
+ default AR600x_DUAL_ANTENNA
+ help
+ Indicates the number of antennas being used by BT and WLAN. Select the appropriate configuration from the list below that matches your AR6003 based reference design.
+
+config AR600x_DUAL_ANTENNA
+ bool "Dual Antenna"
+ help
+ Dual Antenna Design
+
+config AR600x_SINGLE_ANTENNA
+ bool "Single Antenna"
+ help
+ Single Antenna Design
+endchoice
+
+choice
+ prompt "Collocated Bluetooth Type"
+ depends on ATH6KL_ENABLE_COEXISTENCE
+ default AR600x_BT_AR3001
+ help
+ Select the appropriate configuration from the list below that matches your AR6003 based reference design.
+
+config AR600x_BT_QCOM
+ bool "Qualcomm BTS4020X"
+ help
+ Qualcomm BT (3 Wire PTA)
+
+config AR600x_BT_CSR
+ bool "CSR BC06"
+ help
+ CSR BT (3 Wire PTA)
+
+config AR600x_BT_AR3001
+ bool "Atheros AR3001"
+ help
+ Atheros BT (3 Wire PTA)
+endchoice
+
+config ATH6KL_HCI_BRIDGE
+ bool "HCI over SDIO support"
+ depends on ATH6K_LEGACY
+ help
+ Enables BT over SDIO. Applicable only for combo designs (eg: WB31)
+
+config ATH6KL_CONFIG_GPIO_BT_RESET
+ bool "Configure BT Reset GPIO"
+ depends on ATH6KL_HCI_BRIDGE
+ help
+ Configure a WLAN GPIO for use with BT.
+
+config AR600x_BT_RESET_PIN
+ int "GPIO"
+ depends on ATH6KL_CONFIG_GPIO_BT_RESET
+ default 22
+ help
+ WLAN GPIO to be used for resetting BT
+
+config ATH6KL_CFG80211
+ bool "CFG80211 support"
+ depends on ATH6K_LEGACY
+ help
+ Enables support for CFG80211 APIs. The default option is to use WEXT. Even with this option enabled, WEXT is not explicitly disabled and the onus of not exercising WEXT lies on the application(s) running in the user space.
+
+config ATH6KL_HTC_RAW_INTERFACE
+ bool "RAW HTC support"
+ depends on ATH6K_LEGACY
+ help
+ Enables raw HTC interface. Allows application to directly talk to the HTC interface via the ioctl interface
+
+config ATH6KL_VIRTUAL_SCATTER_GATHER
+ bool "Virtual Scatter-Gather support"
+ depends on ATH6K_LEGACY
+ help
+ Enables virtual scatter gather support for the hardware that does not support it natively.
+
+config ATH6KL_SKIP_ABI_VERSION_CHECK
+ bool "Skip ABI version check support"
+ depends on ATH6K_LEGACY
+ help
+ Forces the driver to disable ABI version check. Caution: Incompatilbity between the host driver and target firmware may lead to unknown side effects.
+
+config ATH6KL_BT_UART_FC_POLARITY
+ int "UART Flow Control Polarity"
+ depends on ATH6KL_LEGACY
+ default 0
+ help
+ Configures the polarity of UART Flow Control. A value of 0 implies active low and is the default setting. Set it to 1 for active high.
+
+config ATH6KL_DEBUG
+ bool "Debug support"
+ depends on ATH6K_LEGACY
+ help
+ Enables debug support
+
+config ATH6KL_ENABLE_HOST_DEBUG
+ bool "Host Debug support"
+ depends on ATH6KL_DEBUG
+ help
+ Enables debug support in the driver
+
+config ATH6KL_ENABLE_TARGET_DEBUG_PRINTS
+ bool "Target Debug support - Enable UART prints"
+ depends on ATH6KL_DEBUG
+ help
+ Enables uart prints
+
+config AR600x_DEBUG_UART_TX_PIN
+ int "GPIO"
+ depends on ATH6KL_ENABLE_TARGET_DEBUG_PRINTS
+ default 8
+ help
+ WLAN GPIO to be used for Debug UART (Tx)
+
+config ATH6KL_DISABLE_TARGET_DBGLOGS
+ bool "Target Debug support - Disable Debug logs"
+ depends on ATH6KL_DEBUG
+ help
+ Enables debug logs
diff --git a/drivers/staging/ath6kl/Makefile b/drivers/staging/ath6kl/Makefile
new file mode 100644
index 00000000000..ab68078699f
--- /dev/null
+++ b/drivers/staging/ath6kl/Makefile
@@ -0,0 +1,159 @@
+#------------------------------------------------------------------------------
+# Copyright (c) 2004-2010 Atheros Communications Inc.
+# All rights reserved.
+#
+#
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+#
+#
+# Author(s): ="Atheros"
+#------------------------------------------------------------------------------
+
+ccflags-y += -I$(obj)/include
+ccflags-y += -I$(obj)/include/common
+ccflags-y += -I$(obj)/wlan/include
+ccflags-y += -I$(obj)/os/linux/include
+ccflags-y += -I$(obj)/os
+ccflags-y += -I$(obj)/bmi/include
+ccflags-y += -I$(obj)/include/common/AR6002/hw4.0
+
+ifeq ($(CONFIG_AR600x_SD31_XXX),y)
+ccflags-y += -DAR600x_SD31_XXX
+endif
+
+ifeq ($(CONFIG_AR600x_WB31_XXX),y)
+ccflags-y += -DAR600x_WB31_XXX
+endif
+
+ifeq ($(CONFIG_AR600x_SD32_XXX),y)
+ccflags-y += -DAR600x_SD32_XXX
+endif
+
+ifeq ($(CONFIG_AR600x_CUSTOM_XXX),y)
+ccflags-y += -DAR600x_CUSTOM_XXX
+endif
+
+ifeq ($(CONFIG_ATH6KL_ENABLE_COEXISTENCE),y)
+ccflags-y += -DENABLE_COEXISTENCE
+endif
+
+ifeq ($(CONFIG_AR600x_DUAL_ANTENNA),y)
+ccflags-y += -DAR600x_DUAL_ANTENNA
+endif
+
+ifeq ($(CONFIG_AR600x_SINGLE_ANTENNA),y)
+ccflags-y += -DAR600x_SINGLE_ANTENNA
+endif
+
+ifeq ($(CONFIG_AR600x_BT_QCOM),y)
+ccflags-y += -DAR600x_BT_QCOM
+endif
+
+ifeq ($(CONFIG_AR600x_BT_CSR),y)
+ccflags-y += -DAR600x_BT_CSR
+endif
+
+ifeq ($(CONFIG_AR600x_BT_AR3001),y)
+ccflags-y += -DAR600x_BT_AR3001
+endif
+
+ifeq ($(CONFIG_ATH6KL_HCI_BRIDGE),y)
+ccflags-y += -DATH_AR6K_ENABLE_GMBOX
+ccflags-y += -DHCI_TRANSPORT_SDIO
+ccflags-y += -DSETUPHCI_ENABLED
+ccflags-y += -DSETUPBTDEV_ENABLED
+ath6kl-y += htc2/AR6000/ar6k_gmbox.o
+ath6kl-y += htc2/AR6000/ar6k_gmbox_hciuart.o
+ath6kl-y += miscdrv/ar3kconfig.o
+ath6kl-y += miscdrv/ar3kps/ar3kpsconfig.o
+ath6kl-y += miscdrv/ar3kps/ar3kpsparser.o
+endif
+
+ifeq ($(CONFIG_ATH6KL_CONFIG_GPIO_BT_RESET),y)
+ccflags-y += -DATH6KL_CONFIG_GPIO_BT_RESET
+endif
+
+ifeq ($(CONFIG_ATH6KL_CFG80211),y)
+ccflags-y += -DATH6K_CONFIG_CFG80211
+ath6kl-y += os/linux/cfg80211.o
+endif
+
+ifeq ($(CONFIG_ATH6KL_HTC_RAW_INTERFACE),y)
+ccflags-y += -DHTC_RAW_INTERFACE
+endif
+
+ifeq ($(CONFIG_ATH6KL_ENABLE_HOST_DEBUG),y)
+ccflags-y += -DDEBUG
+ccflags-y += -DATH_DEBUG_MODULE
+endif
+
+ifeq ($(CONFIG_ATH6KL_ENABLE_TARGET_DEBUG_PRINTS),y)
+ccflags-y += -DENABLEUARTPRINT_SET
+endif
+
+ifeq ($(CONFIG_ATH6KL_DISABLE_TARGET_DBGLOGS),y)
+ccflags-y += -DATH6KL_DISABLE_TARGET_DBGLOGS
+endif
+
+ifeq ($(CONFIG_ATH6KL_VIRTUAL_SCATTER_GATHER),y)
+ccflags-y += -DATH6KL_CONFIG_HIF_VIRTUAL_SCATTER
+endif
+
+ifeq ($(CONFIG_ATH6KL_SKIP_ABI_VERSION_CHECK),y)
+ccflags-y += -DATH6KL_SKIP_ABI_VERSION_CHECK
+endif
+
+ccflags-y += -DLINUX -DKERNEL_2_6
+ccflags-y += -DTCMD
+ccflags-y += -DSEND_EVENT_TO_APP
+ccflags-y += -DUSER_KEYS
+ccflags-y += -DNO_SYNC_FLUSH
+ccflags-y += -DHTC_EP_STAT_PROFILING
+ccflags-y += -DATH_AR6K_11N_SUPPORT
+ccflags-y += -DWAPI_ENABLE
+ccflags-y += -DCHECKSUM_OFFLOAD
+ccflags-y += -DWLAN_HEADERS
+ccflags-y += -DINIT_MODE_DRV_ENABLED
+ccflags-y += -DBMIENABLE_SET
+
+obj-$(CONFIG_ATH6K_LEGACY) := ath6kl.o
+ath6kl-y += htc2/AR6000/ar6k.o
+ath6kl-y += htc2/AR6000/ar6k_events.o
+ath6kl-y += htc2/htc_send.o
+ath6kl-y += htc2/htc_recv.o
+ath6kl-y += htc2/htc_services.o
+ath6kl-y += htc2/htc.o
+ath6kl-y += bmi/src/bmi.o
+ath6kl-y += os/linux/ar6000_drv.o
+ath6kl-y += os/linux/ar6000_raw_if.o
+ath6kl-y += os/linux/ar6000_pm.o
+ath6kl-y += os/linux/netbuf.o
+ath6kl-y += os/linux/wireless_ext.o
+ath6kl-y += os/linux/ioctl.o
+ath6kl-y += os/linux/hci_bridge.o
+ath6kl-y += os/linux/ar6k_pal.o
+ath6kl-y += miscdrv/common_drv.o
+ath6kl-y += miscdrv/credit_dist.o
+ath6kl-y += wmi/wmi.o
+ath6kl-y += reorder/rcv_aggr.o
+ath6kl-y += wlan/src/wlan_node.o
+ath6kl-y += wlan/src/wlan_recv_beacon.o
+ath6kl-y += wlan/src/wlan_utils.o
+
+# ATH_HIF_TYPE := sdio
+ccflags-y += -I$(obj)/hif/sdio/linux_sdio/include
+ccflags-y += -DSDIO
+ath6kl-y += hif/sdio/linux_sdio/src/hif.o
+ath6kl-y += hif/sdio/linux_sdio/src/hif_scatter.o
diff --git a/drivers/staging/ath6kl/TODO b/drivers/staging/ath6kl/TODO
new file mode 100644
index 00000000000..d4629274397
--- /dev/null
+++ b/drivers/staging/ath6kl/TODO
@@ -0,0 +1,8 @@
+- The driver is a stop-gap measure until a proper mac80211 driver is available.
+- The driver does not conform to the Linux coding style.
+- The driver has been tested on a wide variety of embedded platforms running different versions of the Linux kernel but may still have bringup/performance issues with a new platform.
+- Pls use the following link to get information about the driver's architecture, exposed APIs, supported features, limitations, testing, hardware availability and other details.
+ http://wireless.kernel.org/en/users/Drivers/ath6kl
+- Pls send any patches to
+ - Greg Kroah-Hartman <greg@kroah.com>
+ - Vipin Mehta <vmehta@atheros.com>
diff --git a/drivers/staging/ath6kl/bmi/include/bmi_internal.h b/drivers/staging/ath6kl/bmi/include/bmi_internal.h
new file mode 100644
index 00000000000..a44027cee4e
--- /dev/null
+++ b/drivers/staging/ath6kl/bmi/include/bmi_internal.h
@@ -0,0 +1,55 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2004-2010 Atheros Communications Inc.
+// All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef BMI_INTERNAL_H
+#define BMI_INTERNAL_H
+
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "a_osapi.h"
+#define ATH_MODULE_NAME bmi
+#include "a_debug.h"
+#include "AR6002/hw2.0/hw/mbox_host_reg.h"
+#include "bmi_msg.h"
+
+#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
+
+
+#define BMI_COMMUNICATION_TIMEOUT 100000
+
+/* ------ Global Variable Declarations ------- */
+static A_BOOL bmiDone;
+
+A_STATUS
+bmiBufferSend(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length);
+
+A_STATUS
+bmiBufferReceive(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length,
+ A_BOOL want_timeout);
+
+#endif
diff --git a/drivers/staging/ath6kl/bmi/src/bmi.c b/drivers/staging/ath6kl/bmi/src/bmi.c
new file mode 100644
index 00000000000..f17f5636f5b
--- /dev/null
+++ b/drivers/staging/ath6kl/bmi/src/bmi.c
@@ -0,0 +1,1010 @@
+//------------------------------------------------------------------------------
+// <copyright file="bmi.c" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+//
+// Author(s): ="Atheros"
+//==============================================================================
+
+
+#ifdef THREAD_X
+#include <string.h>
+#endif
+
+#include "hif.h"
+#include "bmi.h"
+#include "htc_api.h"
+#include "bmi_internal.h"
+
+#ifdef ATH_DEBUG_MODULE
+static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
+ { ATH_DEBUG_BMI , "BMI Tracing"},
+};
+
+ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
+ "bmi",
+ "Boot Manager Interface",
+ ATH_DEBUG_MASK_DEFAULTS,
+ ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
+ bmi_debug_desc);
+
+#endif
+
+/*
+Although we had envisioned BMI to run on top of HTC, this is not how the
+final implementation ended up. On the Target side, BMI is a part of the BSP
+and does not use the HTC protocol nor even DMA -- it is intentionally kept
+very simple.
+*/
+
+static A_BOOL pendingEventsFuncCheck = FALSE;
+static A_UINT32 *pBMICmdCredits;
+static A_UCHAR *pBMICmdBuf;
+#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
+ sizeof(A_UINT32) /* cmd */ + \
+ sizeof(A_UINT32) /* addr */ + \
+ sizeof(A_UINT32))/* length */
+#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
+
+/* APIs visible to the driver */
+void
+BMIInit(void)
+{
+ bmiDone = FALSE;
+ pendingEventsFuncCheck = FALSE;
+
+ /*
+ * On some platforms, it's not possible to DMA to a static variable
+ * in a device driver (e.g. Linux loadable driver module).
+ * So we need to A_MALLOC space for "command credits" and for commands.
+ *
+ * Note: implicitly relies on A_MALLOC to provide a buffer that is
+ * suitable for DMA (or PIO). This buffer will be passed down the
+ * bus stack.
+ */
+ if (!pBMICmdCredits) {
+ pBMICmdCredits = (A_UINT32 *)A_MALLOC_NOWAIT(4);
+ A_ASSERT(pBMICmdCredits);
+ }
+
+ if (!pBMICmdBuf) {
+ pBMICmdBuf = (A_UCHAR *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
+ A_ASSERT(pBMICmdBuf);
+ }
+
+ A_REGISTER_MODULE_DEBUG_INFO(bmi);
+}
+
+void
+BMICleanup(void)
+{
+ if (pBMICmdCredits) {
+ A_FREE(pBMICmdCredits);
+ pBMICmdCredits = NULL;
+ }
+
+ if (pBMICmdBuf) {
+ A_FREE(pBMICmdBuf);
+ pBMICmdBuf = NULL;
+ }
+}
+
+A_STATUS
+BMIDone(HIF_DEVICE *device)
+{
+ A_STATUS status;
+ A_UINT32 cid;
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
+ return A_OK;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
+ bmiDone = TRUE;
+ cid = BMI_DONE;
+
+ status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ if (pBMICmdCredits) {
+ A_FREE(pBMICmdCredits);
+ pBMICmdCredits = NULL;
+ }
+
+ if (pBMICmdBuf) {
+ A_FREE(pBMICmdBuf);
+ pBMICmdBuf = NULL;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
+
+ return A_OK;
+}
+
+A_STATUS
+BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
+{
+ A_STATUS status;
+ A_UINT32 cid;
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
+ cid = BMI_GET_TARGET_INFO;
+
+ status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
+ sizeof(targ_info->target_ver), TRUE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
+ return A_ERROR;
+ }
+
+ if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
+ /* Determine how many bytes are in the Target's targ_info */
+ status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
+ sizeof(targ_info->target_info_byte_count), TRUE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
+ return A_ERROR;
+ }
+
+ /*
+ * The Target's targ_info doesn't match the Host's targ_info.
+ * We need to do some backwards compatibility work to make this OK.
+ */
+ A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
+
+ /* Read the remainder of the targ_info */
+ status = bmiBufferReceive(device,
+ ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
+ sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), TRUE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
+ targ_info->target_info_byte_count));
+ return A_ERROR;
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
+ targ_info->target_ver, targ_info->target_type));
+
+ return A_OK;
+}
+
+A_STATUS
+BMIReadMemory(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+ A_UINT32 remaining, rxlen;
+
+ A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
+ memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
+ device, address, length));
+
+ cid = BMI_READ_MEMORY;
+
+ remaining = length;
+
+ while (remaining)
+ {
+ rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
+ offset += sizeof(length);
+
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+ status = bmiBufferReceive(device, pBMICmdBuf, rxlen, TRUE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
+ return A_ERROR;
+ }
+ A_MEMCPY(&buffer[length - remaining], pBMICmdBuf, rxlen);
+ remaining -= rxlen; address += rxlen;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
+ return A_OK;
+}
+
+A_STATUS
+BMIWriteMemory(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+ A_UINT32 remaining, txlen;
+ const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
+ A_UCHAR alignedBuffer[BMI_DATASZ_MAX];
+ A_UCHAR *src;
+
+ A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
+ memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
+ device, address, length));
+
+ cid = BMI_WRITE_MEMORY;
+
+ remaining = length;
+ while (remaining)
+ {
+ src = &buffer[length - remaining];
+ if (remaining < (BMI_DATASZ_MAX - header)) {
+ if (remaining & 3) {
+ /* align it with 4 bytes */
+ remaining = remaining + (4 - (remaining & 3));
+ memcpy(alignedBuffer, src, remaining);
+ src = alignedBuffer;
+ }
+ txlen = remaining;
+ } else {
+ txlen = (BMI_DATASZ_MAX - header);
+ }
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
+ offset += sizeof(txlen);
+ A_MEMCPY(&(pBMICmdBuf[offset]), src, txlen);
+ offset += txlen;
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+ remaining -= txlen; address += txlen;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
+
+ return A_OK;
+}
+
+A_STATUS
+BMIExecute(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UINT32 *param)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
+ memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
+ device, address, *param));
+
+ cid = BMI_EXECUTE;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+ A_MEMCPY(&(pBMICmdBuf[offset]), param, sizeof(*param));
+ offset += sizeof(*param);
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), FALSE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
+ return A_ERROR;
+ }
+
+ A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
+ return A_OK;
+}
+
+A_STATUS
+BMISetAppStart(HIF_DEVICE *device,
+ A_UINT32 address)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
+ memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
+ device, address));
+
+ cid = BMI_SET_APP_START;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
+ return A_OK;
+}
+
+A_STATUS
+BMIReadSOCRegister(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UINT32 *param)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
+ memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
+ device, address));
+
+ cid = BMI_READ_SOC_REGISTER;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), TRUE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
+ return A_ERROR;
+ }
+ A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
+ return A_OK;
+}
+
+A_STATUS
+BMIWriteSOCRegister(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UINT32 param)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
+ memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
+ device, address, param));
+
+ cid = BMI_WRITE_SOC_REGISTER;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &param, sizeof(param));
+ offset += sizeof(param);
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
+ return A_OK;
+}
+
+A_STATUS
+BMIrompatchInstall(HIF_DEVICE *device,
+ A_UINT32 ROM_addr,
+ A_UINT32 RAM_addr,
+ A_UINT32 nbytes,
+ A_UINT32 do_activate,
+ A_UINT32 *rompatch_id)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
+ sizeof(nbytes) + sizeof(do_activate)));
+ memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
+ sizeof(nbytes) + sizeof(do_activate));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
+ device, ROM_addr, RAM_addr, nbytes, do_activate));
+
+ cid = BMI_ROMPATCH_INSTALL;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
+ offset += sizeof(ROM_addr);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
+ offset += sizeof(RAM_addr);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
+ offset += sizeof(nbytes);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
+ offset += sizeof(do_activate);
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), TRUE);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
+ return A_ERROR;
+ }
+ A_MEMCPY(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
+ return A_OK;
+}
+
+A_STATUS
+BMIrompatchUninstall(HIF_DEVICE *device,
+ A_UINT32 rompatch_id)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
+ memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
+ device, rompatch_id));
+
+ cid = BMI_ROMPATCH_UNINSTALL;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
+ offset += sizeof(rompatch_id);
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
+ return A_OK;
+}
+
+static A_STATUS
+_BMIrompatchChangeActivation(HIF_DEVICE *device,
+ A_UINT32 rompatch_count,
+ A_UINT32 *rompatch_list,
+ A_UINT32 do_activate)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+ A_UINT32 length;
+
+ A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
+ memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
+ device, rompatch_count));
+
+ cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
+
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
+ offset += sizeof(rompatch_count);
+ length = rompatch_count * sizeof(*rompatch_list);
+ A_MEMCPY(&(pBMICmdBuf[offset]), rompatch_list, length);
+ offset += length;
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
+
+ return A_OK;
+}
+
+A_STATUS
+BMIrompatchActivate(HIF_DEVICE *device,
+ A_UINT32 rompatch_count,
+ A_UINT32 *rompatch_list)
+{
+ return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
+}
+
+A_STATUS
+BMIrompatchDeactivate(HIF_DEVICE *device,
+ A_UINT32 rompatch_count,
+ A_UINT32 *rompatch_list)
+{
+ return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
+}
+
+A_STATUS
+BMILZData(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+ A_UINT32 remaining, txlen;
+ const A_UINT32 header = sizeof(cid) + sizeof(length);
+
+ A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
+ memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n",
+ device, length));
+
+ cid = BMI_LZ_DATA;
+
+ remaining = length;
+ while (remaining)
+ {
+ txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
+ remaining : (BMI_DATASZ_MAX - header);
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
+ offset += sizeof(txlen);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
+ offset += txlen;
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
+ return A_ERROR;
+ }
+ remaining -= txlen;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
+
+ return A_OK;
+}
+
+A_STATUS
+BMILZStreamStart(HIF_DEVICE *device,
+ A_UINT32 address)
+{
+ A_UINT32 cid;
+ A_STATUS status;
+ A_UINT32 offset;
+
+ A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
+ memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
+
+ if (bmiDone) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
+ ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n",
+ device, address));
+
+ cid = BMI_LZ_STREAM_START;
+ offset = 0;
+ A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+ offset += sizeof(cid);
+ A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+ offset += sizeof(address);
+ status = bmiBufferSend(device, pBMICmdBuf, offset);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
+ return A_ERROR;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
+
+ return A_OK;
+}
+
+/* BMI Access routines */
+A_STATUS
+bmiBufferSend(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length)
+{
+ A_STATUS status;
+ A_UINT32 timeout;
+ A_UINT32 address;
+ A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
+
+ HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
+ &mboxAddress[0], sizeof(mboxAddress));
+
+ *pBMICmdCredits = 0;
+ timeout = BMI_COMMUNICATION_TIMEOUT;
+
+ while(timeout-- && !(*pBMICmdCredits)) {
+ /* Read the counter register to get the command credits */
+ address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
+ /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
+ * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to
+ * make all HIF accesses 4-byte aligned */
+ status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, 4,
+ HIF_RD_SYNC_BYTE_INC, NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
+ return A_ERROR;
+ }
+ /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
+ (*pBMICmdCredits) &= 0xFF;
+ }
+
+ if (*pBMICmdCredits) {
+ address = mboxAddress[ENDPOINT1];
+ status = HIFReadWrite(device, address, buffer, length,
+ HIF_WR_SYNC_BYTE_INC, NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
+ return A_ERROR;
+ }
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
+ return A_ERROR;
+ }
+
+ return status;
+}
+
+A_STATUS
+bmiBufferReceive(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length,
+ A_BOOL want_timeout)
+{
+ A_STATUS status;
+ A_UINT32 address;
+ A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
+ HIF_PENDING_EVENTS_INFO hifPendingEvents;
+ static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
+
+ if (!pendingEventsFuncCheck) {
+ /* see if the HIF layer implements an alternative function to get pending events
+ * do this only once! */
+ HIFConfigureDevice(device,
+ HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
+ &getPendingEventsFunc,
+ sizeof(getPendingEventsFunc));
+ pendingEventsFuncCheck = TRUE;
+ }
+
+ HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
+ &mboxAddress[0], sizeof(mboxAddress));
+
+ /*
+ * During normal bootup, small reads may be required.
+ * Rather than issue an HIF Read and then wait as the Target
+ * adds successive bytes to the FIFO, we wait here until
+ * we know that response data is available.
+ *
+ * This allows us to cleanly timeout on an unexpected
+ * Target failure rather than risk problems at the HIF level. In
+ * particular, this avoids SDIO timeouts and possibly garbage
+ * data on some host controllers. And on an interconnect
+ * such as Compact Flash (as well as some SDIO masters) which
+ * does not provide any indication on data timeout, it avoids
+ * a potential hang or garbage response.
+ *
+ * Synchronization is more difficult for reads larger than the
+ * size of the MBOX FIFO (128B), because the Target is unable
+ * to push the 129th byte of data until AFTER the Host posts an
+ * HIF Read and removes some FIFO data. So for large reads the
+ * Host proceeds to post an HIF Read BEFORE all the data is
+ * actually available to read. Fortunately, large BMI reads do
+ * not occur in practice -- they're supported for debug/development.
+ *
+ * So Host/Target BMI synchronization is divided into these cases:
+ * CASE 1: length < 4
+ * Should not happen
+ *
+ * CASE 2: 4 <= length <= 128
+ * Wait for first 4 bytes to be in FIFO
+ * If CONSERVATIVE_BMI_READ is enabled, also wait for
+ * a BMI command credit, which indicates that the ENTIRE
+ * response is available in the the FIFO
+ *
+ * CASE 3: length > 128
+ * Wait for the first 4 bytes to be in FIFO
+ *
+ * For most uses, a small timeout should be sufficient and we will
+ * usually see a response quickly; but there may be some unusual
+ * (debug) cases of BMI_EXECUTE where we want an larger timeout.
+ * For now, we use an unbounded busy loop while waiting for
+ * BMI_EXECUTE.
+ *
+ * If BMI_EXECUTE ever needs to support longer-latency execution,
+ * especially in production, this code needs to be enhanced to sleep
+ * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
+ * a function of Host processor speed.
+ */
+ if (length >= 4) { /* NB: Currently, always true */
+ /*
+ * NB: word_available is declared static for esoteric reasons
+ * having to do with protection on some OSes.
+ */
+ static A_UINT32 word_available;
+ A_UINT32 timeout;
+
+ word_available = 0;
+ timeout = BMI_COMMUNICATION_TIMEOUT;
+ while((!want_timeout || timeout--) && !word_available) {
+
+ if (getPendingEventsFunc != NULL) {
+ status = getPendingEventsFunc(device,
+ &hifPendingEvents,
+ NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
+ break;
+ }
+
+ if (hifPendingEvents.AvailableRecvBytes >= sizeof(A_UINT32)) {
+ word_available = 1;
+ }
+ continue;
+ }
+
+ status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (A_UINT8 *)&word_available,
+ sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
+ return A_ERROR;
+ }
+ /* We did a 4-byte read to the same register; all we really want is one bit */
+ word_available &= (1 << ENDPOINT1);
+ }
+
+ if (!word_available) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
+ return A_ERROR;
+ }
+ }
+
+#define CONSERVATIVE_BMI_READ 0
+#if CONSERVATIVE_BMI_READ
+ /*
+ * This is an extra-conservative CREDIT check. It guarantees
+ * that ALL data is available in the FIFO before we start to
+ * read from the interconnect.
+ *
+ * This credit check is useless when firmware chooses to
+ * allow multiple outstanding BMI Command Credits, since the next
+ * credit will already be present. To restrict the Target to one
+ * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT.
+ *
+ * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set)
+ * we cannot wait for the next credit because the Target's FIFO
+ * will not hold the entire response. So we need the Host to
+ * start to empty the FIFO sooner. (And again, large reads are
+ * not used in practice; they are for debug/development only.)
+ *
+ * For a more conservative Host implementation (which would be
+ * safer for a Compact Flash interconnect):
+ * Set CONSERVATIVE_BMI_READ (above) to 1
+ * Set HI_OPTION_BMI_CRED_LIMIT and
+ * reduce BMI_DATASZ_MAX to 32 or 64
+ */
+ if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
+ A_UINT32 timeout;
+
+ *pBMICmdCredits = 0;
+ timeout = BMI_COMMUNICATION_TIMEOUT;
+ while((!want_timeout || timeout--) && !(*pBMICmdCredits) {
+ /* Read the counter register to get the command credits */
+ address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
+ /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing,
+ * we can read this counter multiple times using a non-incrementing address mode.
+ * The rationale here is to make all HIF accesses a multiple of 4 bytes */
+ status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
+ HIF_RD_SYNC_BYTE_FIX, NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
+ return A_ERROR;
+ }
+ /* we did a 4-byte read to the same count register so mask off upper bytes */
+ (*pBMICmdCredits) &= 0xFF;
+ }
+
+ if (!(*pBMICmdCredits)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
+ return A_ERROR;
+ }
+ }
+#endif
+
+ address = mboxAddress[ENDPOINT1];
+ status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
+ return A_ERROR;
+ }
+
+ return A_OK;
+}
+
+A_STATUS
+BMIFastDownload(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length)
+{
+ A_STATUS status = A_ERROR;
+ A_UINT32 lastWord = 0;
+ A_UINT32 lastWordOffset = length & ~0x3;
+ A_UINT32 unalignedBytes = length & 0x3;
+
+ status = BMILZStreamStart (device, address);
+ if (A_FAILED(status)) {
+ return A_ERROR;
+ }
+
+ if (unalignedBytes) {
+ /* copy the last word into a zero padded buffer */
+ A_MEMCPY(&lastWord, &buffer[lastWordOffset], unalignedBytes);
+ }
+
+ status = BMILZData(device, buffer, lastWordOffset);
+
+ if (A_FAILED(status)) {
+ return A_ERROR;
+ }
+
+ if (unalignedBytes) {
+ status = BMILZData(device, (A_UINT8 *)&lastWord, 4);
+ }
+
+ if (A_SUCCESS(status)) {
+ //
+ // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches.
+ //
+ status = BMILZStreamStart (device, 0x00);
+ if (A_FAILED(status)) {
+ return A_ERROR;
+ }
+ }
+ return status;
+}
+
+A_STATUS
+BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length)
+{
+ return bmiBufferSend(device, buffer, length);
+}
+
+A_STATUS
+BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout)
+{
+ return bmiBufferReceive(device, buffer, length, want_timeout);
+}
diff --git a/drivers/staging/ath6kl/hif/common/hif_sdio_common.h b/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
new file mode 100644
index 00000000000..0f4e913cb13
--- /dev/null
+++ b/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
@@ -0,0 +1,87 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// common header file for HIF modules designed for SDIO
+//
+// Author(s): ="Atheros"
+//==============================================================================
+
+#ifndef HIF_SDIO_COMMON_H_
+#define HIF_SDIO_COMMON_H_
+
+ /* SDIO manufacturer ID and Codes */
+#define MANUFACTURER_ID_AR6002_BASE 0x200
+#define MANUFACTURER_ID_AR6003_BASE 0x300
+#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00
+#define FUNCTION_CLASS 0x0
+#define MANUFACTURER_CODE 0x271 /* Atheros */
+
+ /* Mailbox address in SDIO address space */
+#define HIF_MBOX_BASE_ADDR 0x800
+#define HIF_MBOX_WIDTH 0x800
+#define HIF_MBOX_START_ADDR(mbox) \
+ ( HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH)
+
+#define HIF_MBOX_END_ADDR(mbox) \
+ (HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1)
+
+ /* extended MBOX address for larger MBOX writes to MBOX 0*/
+#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800
+#define HIF_MBOX0_EXTENDED_WIDTH_AR6002 (6*1024)
+#define HIF_MBOX0_EXTENDED_WIDTH_AR6003 (18*1024)
+
+ /* version 1 of the chip has only a 12K extended mbox range */
+#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1 0x4000
+#define HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1 (12*1024)
+
+ /* GMBOX addresses */
+#define HIF_GMBOX_BASE_ADDR 0x7000
+#define HIF_GMBOX_WIDTH 0x4000
+
+ /* for SDIO we recommend a 128-byte block size */
+#define HIF_DEFAULT_IO_BLOCK_SIZE 128
+
+ /* set extended MBOX window information for SDIO interconnects */
+static INLINE void SetExtendedMboxWindowInfo(A_UINT16 Manfid, HIF_DEVICE_MBOX_INFO *pInfo)
+{
+ switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) {
+ case MANUFACTURER_ID_AR6002_BASE :
+ /* MBOX 0 has an extended range */
+ pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR;
+ pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002;
+ break;
+ case MANUFACTURER_ID_AR6003_BASE :
+ /* MBOX 0 has an extended range */
+ pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
+ pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
+ pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR;
+ pInfo->GMboxSize = HIF_GMBOX_WIDTH;
+ break;
+ default:
+ A_ASSERT(FALSE);
+ break;
+ }
+}
+
+/* special CCCR (func 0) registers */
+
+#define CCCR_SDIO_IRQ_MODE_REG 0xF0 /* interrupt mode register */
+#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/
+
+#endif /*HIF_SDIO_COMMON_H_*/
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h b/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
new file mode 100644
index 00000000000..857f35f36ca
--- /dev/null
+++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
@@ -0,0 +1,134 @@
+//------------------------------------------------------------------------------
+// <copyright file="hif_internal.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// internal header file for hif layer
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _HIF_INTERNAL_H_
+#define _HIF_INTERNAL_H_
+
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "a_osapi.h"
+#include "hif.h"
+#include "../../../common/hif_sdio_common.h"
+#include <linux/scatterlist.h>
+#define HIF_LINUX_MMC_SCATTER_SUPPORT
+
+#define BUS_REQUEST_MAX_NUM 64
+
+#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000
+#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20
+#define FLAGS_CARD_ENAB 0x02
+#define FLAGS_CARD_IRQ_UNMSK 0x04
+
+#define HIF_MBOX_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE
+#define HIF_MBOX0_BLOCK_SIZE 1
+#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+
+struct _HIF_SCATTER_REQ_PRIV;
+
+typedef struct bus_request {
+ struct bus_request *next; /* link list of available requests */
+ struct bus_request *inusenext; /* link list of in use requests */
+ struct semaphore sem_req;
+ A_UINT32 address; /* request data */
+ A_UCHAR *buffer;
+ A_UINT32 length;
+ A_UINT32 request;
+ void *context;
+ A_STATUS status;
+ struct _HIF_SCATTER_REQ_PRIV *pScatterReq; /* this request is a scatter request */
+} BUS_REQUEST;
+
+struct hif_device {
+ struct sdio_func *func;
+ spinlock_t asynclock;
+ struct task_struct* async_task; /* task to handle async commands */
+ struct semaphore sem_async; /* wake up for async task */
+ int async_shutdown; /* stop the async task */
+ struct completion async_completion; /* thread completion */
+ BUS_REQUEST *asyncreq; /* request for async tasklet */
+ BUS_REQUEST *taskreq; /* async tasklet data */
+ spinlock_t lock;
+ BUS_REQUEST *s_busRequestFreeQueue; /* free list */
+ BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */
+ void *claimedContext;
+ HTC_CALLBACKS htcCallbacks;
+ A_UINT8 *dma_buffer;
+ DL_LIST ScatterReqHead; /* scatter request list head */
+ A_BOOL scatter_enabled; /* scatter enabled flag */
+ A_BOOL is_suspend;
+ A_BOOL is_disabled;
+ atomic_t irqHandling;
+ HIF_DEVICE_POWER_CHANGE_TYPE powerConfig;
+ const struct sdio_device_id *id;
+};
+
+#define HIF_DMA_BUFFER_SIZE (32 * 1024)
+#define CMD53_FIXED_ADDRESS 1
+#define CMD53_INCR_ADDRESS 2
+
+BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device);
+void hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+
+#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT
+
+#define MAX_SCATTER_REQUESTS 4
+#define MAX_SCATTER_ENTRIES_PER_REQ 16
+#define MAX_SCATTER_REQ_TRANSFER_SIZE 32*1024
+
+typedef struct _HIF_SCATTER_REQ_PRIV {
+ HIF_SCATTER_REQ *pHifScatterReq; /* HIF scatter request with allocated entries */
+ HIF_DEVICE *device; /* this device */
+ BUS_REQUEST *busrequest; /* request associated with request */
+ /* scatter list for linux */
+ struct scatterlist sgentries[MAX_SCATTER_ENTRIES_PER_REQ];
+} HIF_SCATTER_REQ_PRIV;
+
+#define ATH_DEBUG_SCATTER ATH_DEBUG_MAKE_MODULE_MASK(0)
+
+A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo);
+void CleanupHIFScatterResources(HIF_DEVICE *device);
+A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+
+#else // HIF_LINUX_MMC_SCATTER_SUPPORT
+
+static inline A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo)
+{
+ return A_ENOTSUP;
+}
+
+static inline A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+{
+ return A_ENOTSUP;
+}
+
+#define CleanupHIFScatterResources(d) { }
+
+#endif // HIF_LINUX_MMC_SCATTER_SUPPORT
+
+#endif // _HIF_INTERNAL_H_
+
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
new file mode 100644
index 00000000000..c307a555936
--- /dev/null
+++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
@@ -0,0 +1,1298 @@
+//------------------------------------------------------------------------------
+// <copyright file="hif.c" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// HIF layer reference implementation for Linux Native MMC stack
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/kthread.h>
+
+/* by default setup a bounce buffer for the data packets, if the underlying host controller driver
+ does not use DMA you may be able to skip this step and save the memory allocation and transfer time */
+#define HIF_USE_DMA_BOUNCE_BUFFER 1
+#include "hif_internal.h"
+#define ATH_MODULE_NAME hif
+#include "a_debug.h"
+#include "AR6002/hw2.0/hw/mbox_host_reg.h"
+
+#if HIF_USE_DMA_BOUNCE_BUFFER
+/* macro to check if DMA buffer is WORD-aligned and DMA-able. Most host controllers assume the
+ * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack).
+ * virt_addr_valid check fails on stack memory.
+ */
+#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer)))
+#else
+#define BUFFER_NEEDS_BOUNCE(buffer) (FALSE)
+#endif
+
+/* ATHENV */
+#if defined(CONFIG_PM)
+#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
+#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv)
+static int hifDeviceSuspend(struct device *dev);
+static int hifDeviceResume(struct device *dev);
+#endif /* CONFIG_PM */
+static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id);
+static void hifDeviceRemoved(struct sdio_func *func);
+static HIF_DEVICE *addHifDevice(struct sdio_func *func);
+static HIF_DEVICE *getHifDevice(struct sdio_func *func);
+static void delHifDevice(HIF_DEVICE * device);
+static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte);
+static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte);
+
+int reset_sdio_on_unload = 0;
+module_param(reset_sdio_on_unload, int, 0644);
+
+extern A_UINT32 nohifscattersupport;
+
+
+/* ------ Static Variables ------ */
+static const struct sdio_device_id ar6k_id_table[] = {
+ { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x0)) },
+ { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6002_BASE | 0x1)) },
+ { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0)) },
+ { SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1)) },
+ { /* null */ },
+};
+MODULE_DEVICE_TABLE(sdio, ar6k_id_table);
+
+static struct sdio_driver ar6k_driver = {
+ .name = "ar6k_wlan",
+ .id_table = ar6k_id_table,
+ .probe = hifDeviceInserted,
+ .remove = hifDeviceRemoved,
+};
+
+#if defined(CONFIG_PM)
+/* New suspend/resume based on linux-2.6.32
+ * Need to patch linux-2.6.32 with mmc2.6.32_suspend.patch
+ * Need to patch with msmsdcc2.6.29_suspend.patch for msm_sdcc host
+ */
+static struct dev_pm_ops ar6k_device_pm_ops = {
+ .suspend = hifDeviceSuspend,
+ .resume = hifDeviceResume,
+};
+#endif /* CONFIG_PM */
+
+/* make sure we only unregister when registered. */
+static int registered = 0;
+
+OSDRV_CALLBACKS osdrvCallbacks;
+extern A_UINT32 onebitmode;
+extern A_UINT32 busspeedlow;
+extern A_UINT32 debughif;
+
+static void ResetAllCards(void);
+static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func);
+static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func);
+
+#ifdef DEBUG
+
+ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif,
+ "hif",
+ "(Linux MMC) Host Interconnect Framework",
+ ATH_DEBUG_MASK_DEFAULTS,
+ 0,
+ NULL);
+
+#endif
+
+
+/* ------ Functions ------ */
+A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks)
+{
+ int status;
+ AR_DEBUG_ASSERT(callbacks != NULL);
+
+ A_REGISTER_MODULE_DEBUG_INFO(hif);
+
+ /* store the callback handlers */
+ osdrvCallbacks = *callbacks;
+
+ /* Register with bus driver core */
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n"));
+ registered = 1;
+#if defined(CONFIG_PM)
+ if (callbacks->deviceSuspendHandler && callbacks->deviceResumeHandler) {
+ ar6k_driver.drv.pm = &ar6k_device_pm_ops;
+ }
+#endif /* CONFIG_PM */
+ status = sdio_register_driver(&ar6k_driver);
+ AR_DEBUG_ASSERT(status==0);
+
+ if (status != 0) {
+ return A_ERROR;
+ }
+
+ return A_OK;
+
+}
+
+static A_STATUS
+__HIFReadWrite(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length,
+ A_UINT32 request,
+ void *context)
+{
+ A_UINT8 opcode;
+ A_STATUS status = A_OK;
+ int ret;
+ A_UINT8 *tbuffer;
+ A_BOOL bounced = FALSE;
+
+ AR_DEBUG_ASSERT(device != NULL);
+ AR_DEBUG_ASSERT(device->func != NULL);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n",
+ device, buffer, address));
+
+ do {
+ if (request & HIF_EXTENDED_IO) {
+ //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n"));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: Invalid command type: 0x%08x\n", request));
+ status = A_EINVAL;
+ break;
+ }
+
+ if (request & HIF_BLOCK_BASIS) {
+ /* round to whole block length size */
+ length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
+ ("AR6000: Block mode (BlockLen: %d)\n",
+ length));
+ } else if (request & HIF_BYTE_BASIS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
+ ("AR6000: Byte mode (BlockLen: %d)\n",
+ length));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: Invalid data mode: 0x%08x\n", request));
+ status = A_EINVAL;
+ break;
+ }
+
+#if 0
+ /* useful for checking register accesses */
+ if (length & 0x3) {
+ A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
+ request & HIF_WRITE ? "write":"read", address, length);
+ }
+#endif
+
+ if (request & HIF_WRITE) {
+ if ((address >= HIF_MBOX_START_ADDR(0)) &&
+ (address <= HIF_MBOX_END_ADDR(3)))
+ {
+
+ AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH);
+
+ /*
+ * Mailbox write. Adjust the address so that the last byte
+ * falls on the EOM address.
+ */
+ address += (HIF_MBOX_WIDTH - length);
+ }
+ }
+
+ if (request & HIF_FIXED_ADDRESS) {
+ opcode = CMD53_FIXED_ADDRESS;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address));
+ } else if (request & HIF_INCREMENTAL_ADDRESS) {
+ opcode = CMD53_INCR_ADDRESS;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: Invalid address mode: 0x%08x\n", request));
+ status = A_EINVAL;
+ break;
+ }
+
+ if (request & HIF_WRITE) {
+#if HIF_USE_DMA_BOUNCE_BUFFER
+ if (BUFFER_NEEDS_BOUNCE(buffer)) {
+ AR_DEBUG_ASSERT(device->dma_buffer != NULL);
+ tbuffer = device->dma_buffer;
+ /* copy the write data to the dma buffer */
+ AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
+ memcpy(tbuffer, buffer, length);
+ bounced = TRUE;
+ } else {
+ tbuffer = buffer;
+ }
+#else
+ tbuffer = buffer;
+#endif
+ if (opcode == CMD53_FIXED_ADDRESS) {
+ ret = sdio_writesb(device->func, address, tbuffer, length);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n",
+ ret, address, length, *(int *)tbuffer));
+ } else {
+ ret = sdio_memcpy_toio(device->func, address, tbuffer, length);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n",
+ ret, address, length, *(int *)tbuffer));
+ }
+ } else if (request & HIF_READ) {
+#if HIF_USE_DMA_BOUNCE_BUFFER
+ if (BUFFER_NEEDS_BOUNCE(buffer)) {
+ AR_DEBUG_ASSERT(device->dma_buffer != NULL);
+ AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
+ tbuffer = device->dma_buffer;
+ bounced = TRUE;
+ } else {
+ tbuffer = buffer;
+ }
+#else
+ tbuffer = buffer;
+#endif
+ if (opcode == CMD53_FIXED_ADDRESS) {
+ ret = sdio_readsb(device->func, tbuffer, address, length);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n",
+ ret, address, length, *(int *)tbuffer));
+ } else {
+ ret = sdio_memcpy_fromio(device->func, tbuffer, address, length);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n",
+ ret, address, length, *(int *)tbuffer));
+ }
+#if HIF_USE_DMA_BOUNCE_BUFFER
+ if (bounced) {
+ /* copy the read data from the dma buffer */
+ memcpy(buffer, tbuffer, length);
+ }
+#endif
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: Invalid direction: 0x%08x\n", request));
+ status = A_EINVAL;
+ break;
+ }
+
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret));
+ status = A_ERROR;
+ }
+ } while (FALSE);
+
+ return status;
+}
+
+void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+{
+ unsigned long flags;
+ BUS_REQUEST *async;
+ BUS_REQUEST *active;
+
+ spin_lock_irqsave(&device->asynclock, flags);
+ active = device->asyncreq;
+ if (active == NULL) {
+ device->asyncreq = busrequest;
+ device->asyncreq->inusenext = NULL;
+ } else {
+ for (async = device->asyncreq;
+ async != NULL;
+ async = async->inusenext) {
+ active = async;
+ }
+ active->inusenext = busrequest;
+ busrequest->inusenext = NULL;
+ }
+ spin_unlock_irqrestore(&device->asynclock, flags);
+}
+
+
+/* queue a read/write request */
+A_STATUS
+HIFReadWrite(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length,
+ A_UINT32 request,
+ void *context)
+{
+ A_STATUS status = A_OK;
+ BUS_REQUEST *busrequest;
+
+
+ AR_DEBUG_ASSERT(device != NULL);
+ AR_DEBUG_ASSERT(device->func != NULL);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,address));
+
+ do {
+ if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){
+ /* serialize all requests through the async thread */
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n",
+ (request & HIF_ASYNCHRONOUS)?"Async":"Synch"));
+ busrequest = hifAllocateBusRequest(device);
+ if (busrequest == NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n",
+ request & HIF_READ ? "READ":"WRITE", address, length));
+ return A_ERROR;
+ }
+ busrequest->address = address;
+ busrequest->buffer = buffer;
+ busrequest->length = length;
+ busrequest->request = request;
+ busrequest->context = context;
+
+ AddToAsyncList(device, busrequest);
+
+ if (request & HIF_SYNCHRONOUS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%lX\n", (unsigned long)busrequest));
+
+ /* wait for completion */
+ up(&device->sem_async);
+ if (down_interruptible(&busrequest->sem_req) != 0) {
+ /* interrupted, exit */
+ return A_ERROR;
+ } else {
+ A_STATUS status = busrequest->status;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n",
+ (unsigned long)busrequest, busrequest->status));
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request));
+ hifFreeBusRequest(device, busrequest);
+ return status;
+ }
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%lX\n", (unsigned long)busrequest));
+ up(&device->sem_async);
+ return A_PENDING;
+ }
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request));
+ status = A_EINVAL;
+ break;
+ }
+ } while(0);
+
+ return status;
+}
+/* thread to serialize all requests, both sync and async */
+static int async_task(void *param)
+ {
+ HIF_DEVICE *device;
+ BUS_REQUEST *request;
+ A_STATUS status;
+ unsigned long flags;
+
+ device = (HIF_DEVICE *)param;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n"));
+ set_current_state(TASK_INTERRUPTIBLE);
+ while(!device->async_shutdown) {
+ /* wait for work */
+ if (down_interruptible(&device->sem_async) != 0) {
+ /* interrupted, exit */
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task interrupted\n"));
+ break;
+ }
+ if (device->async_shutdown) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task stopping\n"));
+ break;
+ }
+ /* we want to hold the host over multiple cmds if possible, but holding the host blocks card interrupts */
+ sdio_claim_host(device->func);
+ spin_lock_irqsave(&device->asynclock, flags);
+ /* pull the request to work on */
+ while (device->asyncreq != NULL) {
+ request = device->asyncreq;
+ if (request->inusenext != NULL) {
+ device->asyncreq = request->inusenext;
+ } else {
+ device->asyncreq = NULL;
+ }
+ spin_unlock_irqrestore(&device->asynclock, flags);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task processing req: 0x%lX\n", (unsigned long)request));
+
+ if (request->pScatterReq != NULL) {
+ A_ASSERT(device->scatter_enabled);
+ /* this is a queued scatter request, pass the request to scatter routine which
+ * executes it synchronously, note, no need to free the request since scatter requests
+ * are maintained on a separate list */
+ status = DoHifReadWriteScatter(device,request);
+ } else {
+ /* call HIFReadWrite in sync mode to do the work */
+ status = __HIFReadWrite(device, request->address, request->buffer,
+ request->length, request->request & ~HIF_SYNCHRONOUS, NULL);
+ if (request->request & HIF_ASYNCHRONOUS) {
+ void *context = request->context;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task freeing req: 0x%lX\n", (unsigned long)request));
+ hifFreeBusRequest(device, request);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task completion routine req: 0x%lX\n", (unsigned long)request));
+ device->htcCallbacks.rwCompletionHandler(context, status);
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async_task upping req: 0x%lX\n", (unsigned long)request));
+ request->status = status;
+ up(&request->sem_req);
+ }
+ }
+ spin_lock_irqsave(&device->asynclock, flags);
+ }
+ spin_unlock_irqrestore(&device->asynclock, flags);
+ sdio_release_host(device->func);
+ }
+
+ complete_and_exit(&device->async_completion, 0);
+ return 0;
+}
+
+static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, A_UINT32 flags, A_UINT32 *resp)
+{
+ struct mmc_command cmd;
+ A_INT32 err;
+ struct mmc_host *host;
+ struct sdio_func *func;
+
+ func = device->func;
+ host = func->card->host;
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = opcode;
+ cmd.arg = arg;
+ cmd.flags = flags;
+ err = mmc_wait_for_cmd(host, &cmd, 3);
+
+ if ((!err) && (resp)) {
+ *resp = cmd.resp[0];
+ }
+
+ return err;
+}
+
+A_STATUS ReinitSDIO(HIF_DEVICE *device)
+{
+ A_INT32 err;
+ struct mmc_host *host;
+ struct mmc_card *card;
+ struct sdio_func *func;
+ A_UINT8 cmd52_resp;
+ A_UINT32 clock;
+
+ func = device->func;
+ card = func->card;
+ host = card->host;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +ReinitSDIO \n"));
+ sdio_claim_host(func);
+
+ do {
+ if (!device->is_suspend) {
+ A_UINT32 resp;
+ A_UINT16 rca;
+ A_UINT32 i;
+ int bit = fls(host->ocr_avail) - 1;
+ /* emulate the mmc_power_up(...) */
+ host->ios.vdd = bit;
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ host->ios.power_mode = MMC_POWER_UP;
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+ host->ios.timing = MMC_TIMING_LEGACY;
+ host->ops->set_ios(host, &host->ios);
+ /*
+ * This delay should be sufficient to allow the power supply
+ * to reach the minimum voltage.
+ */
+ msleep(2);
+
+ host->ios.clock = host->f_min;
+ host->ios.power_mode = MMC_POWER_ON;
+ host->ops->set_ios(host, &host->ios);
+
+ /*
+ * This delay must be at least 74 clock sizes, or 1 ms, or the
+ * time required to reach a stable voltage.
+ */
+ msleep(2);
+
+ /* Issue CMD0. Goto idle state */
+ host->ios.chip_select = MMC_CS_HIGH;
+ host->ops->set_ios(host, &host->ios);
+ msleep(1);
+ err = IssueSDCommand(device, MMC_GO_IDLE_STATE, 0, (MMC_RSP_NONE | MMC_CMD_BC), NULL);
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ops->set_ios(host, &host->ios);
+ msleep(1);
+ host->use_spi_crc = 0;
+
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD0 failed : %d \n",err));
+ break;
+ }
+
+ if (!host->ocr) {
+ /* Issue CMD5, arg = 0 */
+ err = IssueSDCommand(device, SD_IO_SEND_OP_COND, 0, (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err));
+ break;
+ }
+ host->ocr = resp;
+ }
+
+ /* Issue CMD5, arg = ocr. Wait till card is ready */
+ for (i=0;i<100;i++) {
+ err = IssueSDCommand(device, SD_IO_SEND_OP_COND, host->ocr, (MMC_RSP_R4 | MMC_CMD_BCR), &resp);
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD5 failed : %d \n",err));
+ break;
+ }
+ if (resp & MMC_CARD_BUSY) {
+ break;
+ }
+ msleep(10);
+ }
+
+ if ((i == 100) || (err)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: card in not ready : %d %d \n",i,err));
+ break;
+ }
+
+ /* Issue CMD3, get RCA */
+ err = IssueSDCommand(device, SD_SEND_RELATIVE_ADDR, 0, MMC_RSP_R6 | MMC_CMD_BCR, &resp);
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD3 failed : %d \n",err));
+ break;
+ }
+ rca = resp >> 16;
+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+ host->ops->set_ios(host, &host->ios);
+
+ /* Issue CMD7, select card */
+ err = IssueSDCommand(device, MMC_SELECT_CARD, (rca << 16), MMC_RSP_R1 | MMC_CMD_AC, NULL);
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD7 failed : %d \n",err));
+ break;
+ }
+ }
+
+ /* Enable high speed */
+ if (card->host->caps & MMC_CAP_SD_HIGHSPEED) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("ReinitSDIO: Set high speed mode\n"));
+ err = Func0_CMD52ReadByte(card, SDIO_CCCR_SPEED, &cmd52_resp);
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 read to CCCR speed register failed : %d \n",err));
+ card->state &= ~MMC_STATE_HIGHSPEED;
+ /* no need to break */
+ } else {
+ err = Func0_CMD52WriteByte(card, SDIO_CCCR_SPEED, (cmd52_resp | SDIO_SPEED_EHS));
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 write to CCCR speed register failed : %d \n",err));
+ break;
+ }
+ mmc_card_set_highspeed(card);
+ host->ios.timing = MMC_TIMING_SD_HS;
+ host->ops->set_ios(host, &host->ios);
+ }
+ }
+
+ /* Set clock */
+ if (mmc_card_highspeed(card)) {
+ clock = 50000000;
+ } else {
+ clock = card->cis.max_dtr;
+ }
+
+ if (clock > host->f_max) {
+ clock = host->f_max;
+ }
+ host->ios.clock = clock;
+ host->ops->set_ios(host, &host->ios);
+
+
+ if (card->host->caps & MMC_CAP_4_BIT_DATA) {
+ /* CMD52: Set bus width & disable card detect resistor */
+ err = Func0_CMD52WriteByte(card, SDIO_CCCR_IF, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT);
+ if (err) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("ReinitSDIO: CMD52 to set bus mode failed : %d \n",err));
+ break;
+ }
+ host->ios.bus_width = MMC_BUS_WIDTH_4;
+ host->ops->set_ios(host, &host->ios);
+ }
+ } while (0);
+
+ sdio_release_host(func);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n"));
+
+ return (err) ? A_ERROR : A_OK;
+}
+
+A_STATUS
+PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
+{
+ A_STATUS status = A_OK;
+#if defined(CONFIG_PM)
+ struct sdio_func *func = device->func;
+ int old_reset_val;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +PowerStateChangeNotify %d\n", config));
+ switch (config) {
+ case HIF_DEVICE_POWER_DOWN:
+ case HIF_DEVICE_POWER_CUT:
+ old_reset_val = reset_sdio_on_unload;
+ reset_sdio_on_unload = 1;
+ status = hifDisableFunc(device, func);
+ reset_sdio_on_unload = old_reset_val;
+ if (!device->is_suspend) {
+ struct mmc_host *host = func->card->host;
+ host->ios.clock = 0;
+ host->ios.vdd = 0;
+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ios.power_mode = MMC_POWER_OFF;
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+ host->ios.timing = MMC_TIMING_LEGACY;
+ host->ops->set_ios(host, &host->ios);
+ }
+ break;
+ case HIF_DEVICE_POWER_UP:
+ if (device->powerConfig == HIF_DEVICE_POWER_CUT) {
+ status = ReinitSDIO(device);
+ }
+ if (status == A_OK) {
+ status = hifEnableFunc(device, func);
+ }
+ break;
+ }
+ device->powerConfig = config;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -PowerStateChangeNotify\n"));
+#endif
+ return status;
+}
+
+A_STATUS
+HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
+ void *config, A_UINT32 configLen)
+{
+ A_UINT32 count;
+ A_STATUS status = A_OK;
+
+ switch(opcode) {
+ case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
+ ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
+ ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
+ ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
+ ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
+ break;
+
+ case HIF_DEVICE_GET_MBOX_ADDR:
+ for (count = 0; count < 4; count ++) {
+ ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
+ }
+
+ if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) {
+ SetExtendedMboxWindowInfo((A_UINT16)device->func->device,
+ (HIF_DEVICE_MBOX_INFO *)config);
+ }
+
+ break;
+ case HIF_DEVICE_GET_IRQ_PROC_MODE:
+ *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY;
+ break;
+ case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT:
+ if (!device->scatter_enabled) {
+ return A_ENOTSUP;
+ }
+ status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config);
+ if (A_FAILED(status)) {
+ device->scatter_enabled = FALSE;
+ }
+ break;
+ case HIF_DEVICE_GET_OS_DEVICE:
+ /* pass back a pointer to the SDIO function's "dev" struct */
+ ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev;
+ break;
+ case HIF_DEVICE_POWER_STATE_CHANGE:
+ status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config);
+ break;
+ default:
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ ("AR6000: Unsupported configuration opcode: %d\n", opcode));
+ status = A_ERROR;
+ }
+
+ return status;
+}
+
+void
+HIFShutDownDevice(HIF_DEVICE *device)
+{
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n"));
+ if (device != NULL) {
+ AR_DEBUG_ASSERT(device->func != NULL);
+ } else {
+ /* since we are unloading the driver anyways, reset all cards in case the SDIO card
+ * is externally powered and we are unloading the SDIO stack. This avoids the problem when
+ * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already
+ * enumerated */
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n"));
+ ResetAllCards();
+
+ /* Unregister with bus driver core */
+ if (registered) {
+ registered = 0;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
+ ("AR6000: Unregistering with the bus driver\n"));
+ sdio_unregister_driver(&ar6k_driver);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
+ ("AR6000: Unregistered\n"));
+ }
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n"));
+}
+
+static void
+hifIRQHandler(struct sdio_func *func)
+{
+ A_STATUS status;
+ HIF_DEVICE *device;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));
+
+ device = getHifDevice(func);
+ atomic_set(&device->irqHandling, 1);
+ /* release the host during ints so we can pick it back up when we process cmds */
+ sdio_release_host(device->func);
+ status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
+ sdio_claim_host(device->func);
+ atomic_set(&device->irqHandling, 0);
+ AR_DEBUG_ASSERT(status == A_OK || status == A_ECANCELED);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
+}
+
+/* handle HTC startup via thread*/
+static int startup_task(void *param)
+{
+ HIF_DEVICE *device;
+
+ device = (HIF_DEVICE *)param;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n"));
+ /* start up inform DRV layer */
+ if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
+ }
+ return 0;
+}
+
+#if defined(CONFIG_PM)
+static int enable_task(void *param)
+{
+ HIF_DEVICE *device;
+ device = (HIF_DEVICE *)param;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call from resume_task\n"));
+
+ /* start up inform DRV layer */
+ if (device &&
+ device->claimedContext &&
+ osdrvCallbacks.devicePowerChangeHandler &&
+ osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != A_OK)
+ {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
+ }
+
+ return 0;
+}
+#endif
+
+static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
+{
+ int ret;
+ HIF_DEVICE * device;
+ int count;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
+ ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X, Device ID: 0x%X, block size: 0x%X/0x%X\n",
+ func->num, func->vendor, func->device, func->max_blksize, func->cur_blksize));
+
+ addHifDevice(func);
+ device = getHifDevice(func);
+
+ device->id = id;
+ device->is_disabled = TRUE;
+
+ spin_lock_init(&device->lock);
+
+ spin_lock_init(&device->asynclock);
+
+ DL_LIST_INIT(&device->ScatterReqHead);
+
+ if (!nohifscattersupport) {
+ /* try to allow scatter operation on all instances,
+ * unless globally overridden */
+ device->scatter_enabled = TRUE;
+ }
+
+ /* Initialize the bus requests to be used later */
+ A_MEMZERO(device->busRequest, sizeof(device->busRequest));
+ for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
+ sema_init(&device->busRequest[count].sem_req, 0);
+ hifFreeBusRequest(device, &device->busRequest[count]);
+ }
+ sema_init(&device->sem_async, 0);
+
+ ret = hifEnableFunc(device, func);
+
+ return ret;
+}
+
+
+void
+HIFAckInterrupt(HIF_DEVICE *device)
+{
+ AR_DEBUG_ASSERT(device != NULL);
+
+ /* Acknowledge our function IRQ */
+}
+
+void
+HIFUnMaskInterrupt(HIF_DEVICE *device)
+{
+ int ret;;
+
+ AR_DEBUG_ASSERT(device != NULL);
+ AR_DEBUG_ASSERT(device->func != NULL);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n"));
+
+ /* Register the IRQ Handler */
+ sdio_claim_host(device->func);
+ ret = sdio_claim_irq(device->func, hifIRQHandler);
+ sdio_release_host(device->func);
+ AR_DEBUG_ASSERT(ret == 0);
+}
+
+void HIFMaskInterrupt(HIF_DEVICE *device)
+{
+ int ret;
+ AR_DEBUG_ASSERT(device != NULL);
+ AR_DEBUG_ASSERT(device->func != NULL);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n"));
+
+ /* Mask our function IRQ */
+ sdio_claim_host(device->func);
+ while (atomic_read(&device->irqHandling)) {
+ sdio_release_host(device->func);
+ schedule_timeout(HZ/10);
+ sdio_claim_host(device->func);
+ }
+ ret = sdio_release_irq(device->func);
+ sdio_release_host(device->func);
+ AR_DEBUG_ASSERT(ret == 0);
+}
+
+BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device)
+{
+ BUS_REQUEST *busrequest;
+ unsigned long flag;
+
+ /* Acquire lock */
+ spin_lock_irqsave(&device->lock, flag);
+
+ /* Remove first in list */
+ if((busrequest = device->s_busRequestFreeQueue) != NULL)
+ {
+ device->s_busRequestFreeQueue = busrequest->next;
+ }
+ /* Release lock */
+ spin_unlock_irqrestore(&device->lock, flag);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifAllocateBusRequest: 0x%p\n", busrequest));
+ return busrequest;
+}
+
+void
+hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+{
+ unsigned long flag;
+
+ AR_DEBUG_ASSERT(busrequest != NULL);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: hifFreeBusRequest: 0x%p\n", busrequest));
+ /* Acquire lock */
+ spin_lock_irqsave(&device->lock, flag);
+
+
+ /* Insert first in list */
+ busrequest->next = device->s_busRequestFreeQueue;
+ busrequest->inusenext = NULL;
+ device->s_busRequestFreeQueue = busrequest;
+
+ /* Release lock */
+ spin_unlock_irqrestore(&device->lock, flag);
+}
+
+static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func)
+{
+ int ret;
+ A_STATUS status = A_OK;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n"));
+ device = getHifDevice(func);
+ if (!IS_ERR(device->async_task)) {
+ init_completion(&device->async_completion);
+ device->async_shutdown = 1;
+ up(&device->sem_async);
+ wait_for_completion(&device->async_completion);
+ device->async_task = NULL;
+ }
+ /* Disable the card */
+ sdio_claim_host(device->func);
+ ret = sdio_disable_func(device->func);
+ if (ret) {
+ status = A_ERROR;
+ }
+
+ if (reset_sdio_on_unload) {
+ /* reset the SDIO interface. This is useful in automated testing where the card
+ * does not need to be removed at the end of the test. It is expected that the user will
+ * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n"));
+
+ /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows access
+ * to undefined registers in the range of: 0xF0-0xFF */
+
+ ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3));
+ if (ret) {
+ status = A_ERROR;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret));
+ }
+ }
+
+ sdio_release_host(device->func);
+
+ if (status == A_OK) {
+ device->is_disabled = TRUE;
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n"));
+
+ return status;
+}
+
+static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
+{
+ struct task_struct* pTask;
+ const char *taskName = NULL;
+ int (*taskFunc)(void *) = NULL;
+ int ret = A_OK;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n"));
+ device = getHifDevice(func);
+
+ if (device->is_disabled) {
+ /* enable the SDIO function */
+ sdio_claim_host(func);
+
+ if ((device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) {
+ /* enable 4-bit ASYNC interrupt on AR6003 or later devices */
+ ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret));
+ sdio_release_host(func);
+ return A_ERROR;
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n"));
+ }
+ /* give us some time to enable, in ms */
+ func->enable_timeout = 100;
+ ret = sdio_enable_func(func);
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
+ __FUNCTION__, ret));
+ sdio_release_host(func);
+ return A_ERROR;
+ }
+ ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+ sdio_release_host(func);
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n",
+ __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
+ return A_ERROR;
+ }
+ device->is_disabled = FALSE;
+ /* create async I/O thread */
+ if (!device->async_task) {
+ device->async_shutdown = 0;
+ device->async_task = kthread_create(async_task,
+ (void *)device,
+ "AR6K Async");
+ if (IS_ERR(device->async_task)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
+ return A_ERROR;
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
+ wake_up_process(device->async_task );
+ }
+ }
+
+ if (!device->claimedContext) {
+ taskFunc = startup_task;
+ taskName = "AR6K startup";
+ ret = A_OK;
+#if defined(CONFIG_PM)
+ } else {
+ taskFunc = enable_task;
+ taskName = "AR6K enable";
+ ret = A_PENDING;
+#endif /* CONFIG_PM */
+ }
+ /* create resume thread */
+ pTask = kthread_create(taskFunc, (void *)device, taskName);
+ if (IS_ERR(pTask)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create enabel task\n", __FUNCTION__));
+ return A_ERROR;
+ }
+ wake_up_process(pTask);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifEnableFunc\n"));
+
+ /* task will call the enable func, indicate pending */
+ return ret;
+}
+
+#if defined(CONFIG_PM)
+static int hifDeviceSuspend(struct device *dev)
+{
+ struct sdio_func *func=dev_to_sdio_func(dev);
+ A_STATUS status = A_OK;
+ HIF_DEVICE *device;
+
+ device = getHifDevice(func);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceSuspend\n"));
+ if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
+ device->is_suspend = TRUE; /* set true first for PowerStateChangeNotify(..) */
+ status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext);
+ if (status != A_OK) {
+ device->is_suspend = FALSE;
+ }
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceSuspend\n"));
+
+ switch (status) {
+ case A_OK:
+ return 0;
+ case A_EBUSY:
+ return -EBUSY; /* Hack for kernel in order to support deep sleep and wow */
+ default:
+ return -1;
+ }
+}
+
+static int hifDeviceResume(struct device *dev)
+{
+ struct sdio_func *func=dev_to_sdio_func(dev);
+ A_STATUS status = A_OK;
+ HIF_DEVICE *device;
+
+ device = getHifDevice(func);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceResume\n"));
+ if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
+ status = osdrvCallbacks.deviceResumeHandler(device->claimedContext);
+ if (status == A_OK) {
+ device->is_suspend = FALSE;
+ }
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceResume\n"));
+
+ return A_SUCCESS(status) ? 0 : status;
+}
+#endif /* CONFIG_PM */
+
+static void hifDeviceRemoved(struct sdio_func *func)
+{
+ A_STATUS status = A_OK;
+ HIF_DEVICE *device;
+ AR_DEBUG_ASSERT(func != NULL);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
+ device = getHifDevice(func);
+ if (device->claimedContext != NULL) {
+ status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device);
+ }
+
+ if (device->is_disabled) {
+ device->is_disabled = FALSE;
+ } else {
+ status = hifDisableFunc(device, func);
+ }
+ CleanupHIFScatterResources(device);
+
+ delHifDevice(device);
+ AR_DEBUG_ASSERT(status == A_OK);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
+}
+
+/*
+ * This should be moved to AR6K HTC layer.
+ */
+A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device)
+{
+ A_INT32 cnt = 10;
+ A_UINT8 host_int_status;
+ A_STATUS status = A_OK;
+
+ do {
+ while (atomic_read(&device->irqHandling)) {
+ /* wait until irq handler finished all the jobs */
+ schedule_timeout(HZ/10);
+ }
+ /* check if there is any pending irq due to force done */
+ host_int_status = 0;
+ status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS,
+ (A_UINT8 *)&host_int_status, sizeof(host_int_status),
+ HIF_RD_SYNC_BYTE_INC, NULL);
+ host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)) : 0;
+ if (host_int_status) {
+ schedule(); /* schedule for next dsrHandler */
+ }
+ } while (host_int_status && --cnt > 0);
+
+ if (host_int_status && cnt == 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__));
+ }
+
+ return A_OK;
+}
+
+
+static HIF_DEVICE *
+addHifDevice(struct sdio_func *func)
+{
+ HIF_DEVICE *hifdevice;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n"));
+ AR_DEBUG_ASSERT(func != NULL);
+ hifdevice = (HIF_DEVICE *)kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL);
+ AR_DEBUG_ASSERT(hifdevice != NULL);
+#if HIF_USE_DMA_BOUNCE_BUFFER
+ hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
+ AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL);
+#endif
+ hifdevice->func = func;
+ hifdevice->powerConfig = HIF_DEVICE_POWER_UP;
+ sdio_set_drvdata(func, hifdevice);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice; 0x%p\n", hifdevice));
+ return hifdevice;
+}
+
+static HIF_DEVICE *
+getHifDevice(struct sdio_func *func)
+{
+ AR_DEBUG_ASSERT(func != NULL);
+ return (HIF_DEVICE *)sdio_get_drvdata(func);
+}
+
+static void
+delHifDevice(HIF_DEVICE * device)
+{
+ AR_DEBUG_ASSERT(device!= NULL);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
+ if (device->dma_buffer != NULL) {
+ kfree(device->dma_buffer);
+ }
+ kfree(device);
+}
+
+static void ResetAllCards(void)
+{
+}
+
+void HIFClaimDevice(HIF_DEVICE *device, void *context)
+{
+ device->claimedContext = context;
+}
+
+void HIFReleaseDevice(HIF_DEVICE *device)
+{
+ device->claimedContext = NULL;
+}
+
+A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks)
+{
+ if (device->htcCallbacks.context != NULL) {
+ /* already in use! */
+ return A_ERROR;
+ }
+ device->htcCallbacks = *callbacks;
+ return A_OK;
+}
+
+void HIFDetachHTC(HIF_DEVICE *device)
+{
+ A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
+}
+
+#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \
+ (arg) = (((rw) & 1) << 31) | \
+ (((func) & 0x7) << 28) | \
+ (((raw) & 1) << 27) | \
+ (1 << 26) | \
+ (((address) & 0x1FFFF) << 9) | \
+ (1 << 8) | \
+ ((writedata) & 0xFF)
+
+#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \
+ SDIO_SET_CMD52_ARG(arg,0,(func),0,address,0x00)
+#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \
+ SDIO_SET_CMD52_ARG(arg,1,(func),0,address,value)
+
+static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte)
+{
+ struct mmc_command ioCmd;
+ unsigned long arg;
+
+ memset(&ioCmd,0,sizeof(ioCmd));
+ SDIO_SET_CMD52_WRITE_ARG(arg,0,address,byte);
+ ioCmd.opcode = SD_IO_RW_DIRECT;
+ ioCmd.arg = arg;
+ ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(card->host, &ioCmd, 0);
+}
+
+static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte)
+{
+ struct mmc_command ioCmd;
+ unsigned long arg;
+ A_INT32 err;
+
+ memset(&ioCmd,0,sizeof(ioCmd));
+ SDIO_SET_CMD52_READ_ARG(arg,0,address);
+ ioCmd.opcode = SD_IO_RW_DIRECT;
+ ioCmd.arg = arg;
+ ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ err = mmc_wait_for_cmd(card->host, &ioCmd, 0);
+
+ if ((!err) && (byte)) {
+ *byte = ioCmd.resp[0] & 0xFF;
+ }
+
+ return err;
+}
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
new file mode 100644
index 00000000000..22c6c6659f5
--- /dev/null
+++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
@@ -0,0 +1,393 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// HIF scatter implementation
+//
+// Author(s): ="Atheros"
+//==============================================================================
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/kthread.h>
+#include "hif_internal.h"
+#define ATH_MODULE_NAME hif
+#include "a_debug.h"
+
+#ifdef HIF_LINUX_MMC_SCATTER_SUPPORT
+
+#define _CMD53_ARG_READ 0
+#define _CMD53_ARG_WRITE 1
+#define _CMD53_ARG_BLOCK_BASIS 1
+#define _CMD53_ARG_FIXED_ADDRESS 0
+#define _CMD53_ARG_INCR_ADDRESS 1
+
+#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \
+ (arg) = (((rw) & 1) << 31) | \
+ (((func) & 0x7) << 28) | \
+ (((mode) & 1) << 27) | \
+ (((opcode) & 1) << 26) | \
+ (((address) & 0x1FFFF) << 9) | \
+ ((bytes_blocks) & 0x1FF)
+
+static void FreeScatterReq(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&device->lock, flag);
+
+ DL_ListInsertTail(&device->ScatterReqHead, &pReq->ListLink);
+
+ spin_unlock_irqrestore(&device->lock, flag);
+
+}
+
+static HIF_SCATTER_REQ *AllocScatterReq(HIF_DEVICE *device)
+{
+ DL_LIST *pItem;
+ unsigned long flag;
+
+ spin_lock_irqsave(&device->lock, flag);
+
+ pItem = DL_ListRemoveItemFromHead(&device->ScatterReqHead);
+
+ spin_unlock_irqrestore(&device->lock, flag);
+
+ if (pItem != NULL) {
+ return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
+ }
+
+ return NULL;
+}
+
+ /* called by async task to perform the operation synchronously using direct MMC APIs */
+A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+{
+ int i;
+ A_UINT8 rw;
+ A_UINT8 opcode;
+ struct mmc_request mmcreq;
+ struct mmc_command cmd;
+ struct mmc_data data;
+ HIF_SCATTER_REQ_PRIV *pReqPriv;
+ HIF_SCATTER_REQ *pReq;
+ A_STATUS status = A_OK;
+ struct scatterlist *pSg;
+
+ pReqPriv = busrequest->pScatterReq;
+
+ A_ASSERT(pReqPriv != NULL);
+
+ pReq = pReqPriv->pHifScatterReq;
+
+ memset(&mmcreq, 0, sizeof(struct mmc_request));
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ memset(&data, 0, sizeof(struct mmc_data));
+
+ data.blksz = HIF_MBOX_BLOCK_SIZE;
+ data.blocks = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: (%s) Address: 0x%X, (BlockLen: %d, BlockCount: %d) , (tot:%d,sg:%d)\n",
+ (pReq->Request & HIF_WRITE) ? "WRITE":"READ", pReq->Address, data.blksz, data.blocks,
+ pReq->TotalLength,pReq->ValidScatterEntries));
+
+ if (pReq->Request & HIF_WRITE) {
+ rw = _CMD53_ARG_WRITE;
+ data.flags = MMC_DATA_WRITE;
+ } else {
+ rw = _CMD53_ARG_READ;
+ data.flags = MMC_DATA_READ;
+ }
+
+ if (pReq->Request & HIF_FIXED_ADDRESS) {
+ opcode = _CMD53_ARG_FIXED_ADDRESS;
+ } else {
+ opcode = _CMD53_ARG_INCR_ADDRESS;
+ }
+
+ /* fill SG entries */
+ pSg = pReqPriv->sgentries;
+ sg_init_table(pSg, pReq->ValidScatterEntries);
+
+ /* assemble SG list */
+ for (i = 0 ; i < pReq->ValidScatterEntries ; i++, pSg++) {
+ /* setup each sg entry */
+ if ((unsigned long)pReq->ScatterList[i].pBuffer & 0x3) {
+ /* note some scatter engines can handle unaligned buffers, print this
+ * as informational only */
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER,
+ ("HIF: (%s) Scatter Buffer is unaligned 0x%lx\n",
+ pReq->Request & HIF_WRITE ? "WRITE":"READ",
+ (unsigned long)pReq->ScatterList[i].pBuffer));
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, (" %d: Addr:0x%lX, Len:%d \n",
+ i,(unsigned long)pReq->ScatterList[i].pBuffer,pReq->ScatterList[i].Length));
+
+ sg_set_buf(pSg, pReq->ScatterList[i].pBuffer, pReq->ScatterList[i].Length);
+ }
+ /* set scatter-gather table for request */
+ data.sg = pReqPriv->sgentries;
+ data.sg_len = pReq->ValidScatterEntries;
+ /* set command argument */
+ SDIO_SET_CMD53_ARG(cmd.arg,
+ rw,
+ device->func->num,
+ _CMD53_ARG_BLOCK_BASIS,
+ opcode,
+ pReq->Address,
+ data.blocks);
+
+ cmd.opcode = SD_IO_RW_EXTENDED;
+ cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+
+ mmcreq.cmd = &cmd;
+ mmcreq.data = &data;
+
+ mmc_set_data_timeout(&data, device->func->card);
+ /* synchronous call to process request */
+ mmc_wait_for_req(device->func->card->host, &mmcreq);
+
+ if (cmd.error) {
+ status = A_ERROR;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: cmd error: %d \n",cmd.error));
+ }
+
+ if (data.error) {
+ status = A_ERROR;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error));
+ }
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n",
+ (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks));
+ }
+
+ /* set completion status, fail or success */
+ pReq->CompletionStatus = status;
+
+ if (pReq->Request & HIF_ASYNCHRONOUS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: async_task completion routine req: 0x%lX (%d)\n",(unsigned long)busrequest, status));
+ /* complete the request */
+ A_ASSERT(pReq->CompletionRoutine != NULL);
+ pReq->CompletionRoutine(pReq);
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER async_task upping busrequest : 0x%lX (%d)\n", (unsigned long)busrequest,status));
+ /* signal wait */
+ up(&busrequest->sem_req);
+ }
+
+ return status;
+}
+
+ /* callback to issue a read-write scatter request */
+static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
+{
+ A_STATUS status = A_EINVAL;
+ A_UINT32 request = pReq->Request;
+ HIF_SCATTER_REQ_PRIV *pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0];
+
+ do {
+
+ A_ASSERT(pReqPriv != NULL);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: total len: %d Scatter Entries: %d\n",
+ pReq->TotalLength, pReq->ValidScatterEntries));
+
+ if (!(request & HIF_EXTENDED_IO)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("HIF-SCATTER: Invalid command type: 0x%08x\n", request));
+ break;
+ }
+
+ if (!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("HIF-SCATTER: Invalid execution mode: 0x%08x\n", request));
+ break;
+ }
+
+ if (!(request & HIF_BLOCK_BASIS)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("HIF-SCATTER: Invalid data mode: 0x%08x\n", request));
+ break;
+ }
+
+ if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("HIF-SCATTER: Invalid length: %d \n", pReq->TotalLength));
+ break;
+ }
+
+ if (pReq->TotalLength == 0) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* add bus request to the async list for the async I/O thread to process */
+ AddToAsyncList(device, pReqPriv->busrequest);
+
+ if (request & HIF_SYNCHRONOUS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued sync req: 0x%lX\n", (unsigned long)pReqPriv->busrequest));
+ /* signal thread and wait */
+ up(&device->sem_async);
+ if (down_interruptible(&pReqPriv->busrequest->sem_req) != 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF-SCATTER: interrupted! \n"));
+ /* interrupted, exit */
+ status = A_ERROR;
+ break;
+ } else {
+ status = pReq->CompletionStatus;
+ }
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest));
+ /* wake thread, it will process and then take care of the async callback */
+ up(&device->sem_async);
+ status = A_OK;
+ }
+
+ } while (FALSE);
+
+ if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
+ pReq->CompletionStatus = status;
+ pReq->CompletionRoutine(pReq);
+ status = A_OK;
+ }
+
+ return status;
+}
+
+ /* setup of HIF scatter resources */
+A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo)
+{
+ A_STATUS status = A_ERROR;
+ int i;
+ HIF_SCATTER_REQ_PRIV *pReqPriv;
+ BUS_REQUEST *busrequest;
+
+ do {
+
+ /* check if host supports scatter requests and it meets our requirements */
+ if (device->func->card->host->max_hw_segs < MAX_SCATTER_ENTRIES_PER_REQ) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n",
+ device->func->card->host->max_hw_segs, MAX_SCATTER_ENTRIES_PER_REQ));
+ status = A_ENOTSUP;
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HIF-SCATTER Enabled: max scatter req : %d entries: %d \n",
+ MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ));
+
+ for (i = 0; i < MAX_SCATTER_REQUESTS; i++) {
+ /* allocate the private request blob */
+ pReqPriv = (HIF_SCATTER_REQ_PRIV *)A_MALLOC(sizeof(HIF_SCATTER_REQ_PRIV));
+ if (NULL == pReqPriv) {
+ break;
+ }
+ A_MEMZERO(pReqPriv, sizeof(HIF_SCATTER_REQ_PRIV));
+ /* save the device instance*/
+ pReqPriv->device = device;
+ /* allocate the scatter request */
+ pReqPriv->pHifScatterReq = (HIF_SCATTER_REQ *)A_MALLOC(sizeof(HIF_SCATTER_REQ) +
+ (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM)));
+
+ if (NULL == pReqPriv->pHifScatterReq) {
+ A_FREE(pReqPriv);
+ break;
+ }
+ /* just zero the main part of the scatter request */
+ A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(HIF_SCATTER_REQ));
+ /* back pointer to the private struct */
+ pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv;
+ /* allocate a bus request for this scatter request */
+ busrequest = hifAllocateBusRequest(device);
+ if (NULL == busrequest) {
+ A_FREE(pReqPriv->pHifScatterReq);
+ A_FREE(pReqPriv);
+ break;
+ }
+ /* assign the scatter request to this bus request */
+ busrequest->pScatterReq = pReqPriv;
+ /* point back to the request */
+ pReqPriv->busrequest = busrequest;
+ /* add it to the scatter pool */
+ FreeScatterReq(device,pReqPriv->pHifScatterReq);
+ }
+
+ if (i != MAX_SCATTER_REQUESTS) {
+ status = A_NO_MEMORY;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : failed to alloc scatter resources !\n"));
+ break;
+ }
+
+ /* set scatter function pointers */
+ pInfo->pAllocateReqFunc = AllocScatterReq;
+ pInfo->pFreeReqFunc = FreeScatterReq;
+ pInfo->pReadWriteScatterFunc = HifReadWriteScatter;
+ pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ;
+ pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE;
+
+ status = A_OK;
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ CleanupHIFScatterResources(device);
+ }
+
+ return status;
+}
+
+ /* clean up scatter support */
+void CleanupHIFScatterResources(HIF_DEVICE *device)
+{
+ HIF_SCATTER_REQ_PRIV *pReqPriv;
+ HIF_SCATTER_REQ *pReq;
+
+ /* empty the free list */
+
+ while (1) {
+
+ pReq = AllocScatterReq(device);
+
+ if (NULL == pReq) {
+ break;
+ }
+
+ pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0];
+ A_ASSERT(pReqPriv != NULL);
+
+ if (pReqPriv->busrequest != NULL) {
+ pReqPriv->busrequest->pScatterReq = NULL;
+ /* free bus request */
+ hifFreeBusRequest(device, pReqPriv->busrequest);
+ pReqPriv->busrequest = NULL;
+ }
+
+ if (pReqPriv->pHifScatterReq != NULL) {
+ A_FREE(pReqPriv->pHifScatterReq);
+ pReqPriv->pHifScatterReq = NULL;
+ }
+
+ A_FREE(pReqPriv);
+ }
+}
+
+#endif // HIF_LINUX_MMC_SCATTER_SUPPORT
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
new file mode 100644
index 00000000000..1efc85ce02b
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
@@ -0,0 +1,1471 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6k.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// AR6K device layer that handles register level I/O
+//
+// Author(s): ="Atheros"
+//==============================================================================
+
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "AR6002/hw2.0/hw/mbox_host_reg.h"
+#include "a_osapi.h"
+#include "../htc_debug.h"
+#include "hif.h"
+#include "htc_packet.h"
+#include "ar6k.h"
+
+#define MAILBOX_FOR_BLOCK_SIZE 1
+
+A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
+A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
+
+static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev);
+
+void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket)
+{
+ LOCK_AR6K(pDev);
+ HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
+ UNLOCK_AR6K(pDev);
+}
+
+HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
+{
+ HTC_PACKET *pPacket;
+
+ LOCK_AR6K(pDev);
+ pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
+ UNLOCK_AR6K(pDev);
+
+ return pPacket;
+}
+
+void DevCleanup(AR6K_DEVICE *pDev)
+{
+ DevCleanupGMbox(pDev);
+
+ if (pDev->HifAttached) {
+ HIFDetachHTC(pDev->HIFDevice);
+ pDev->HifAttached = FALSE;
+ }
+
+ DevCleanupVirtualScatterSupport(pDev);
+
+ if (A_IS_MUTEX_VALID(&pDev->Lock)) {
+ A_MUTEX_DELETE(&pDev->Lock);
+ }
+}
+
+A_STATUS DevSetup(AR6K_DEVICE *pDev)
+{
+ A_UINT32 blocksizes[AR6K_MAILBOXES];
+ A_STATUS status = A_OK;
+ int i;
+ HTC_CALLBACKS htcCallbacks;
+
+ do {
+
+ DL_LIST_INIT(&pDev->ScatterReqHead);
+ /* initialize our free list of IO packets */
+ INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList);
+ A_MUTEX_INIT(&pDev->Lock);
+
+ A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
+ /* the device layer handles these */
+ htcCallbacks.rwCompletionHandler = DevRWCompletionHandler;
+ htcCallbacks.dsrHandler = DevDsrHandler;
+ htcCallbacks.context = pDev;
+
+ status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ pDev->HifAttached = TRUE;
+
+ /* get the addresses for all 4 mailboxes */
+ status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
+ &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo));
+
+ if (status != A_OK) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* carve up register I/O packets (these are for ASYNC register I/O ) */
+ for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) {
+ HTC_PACKET *pIOPacket;
+ pIOPacket = &pDev->RegIOBuffers[i].HtcPacket;
+ SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket,
+ pDev,
+ pDev->RegIOBuffers[i].Buffer,
+ AR6K_REG_IO_BUFFER_SIZE,
+ 0); /* don't care */
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+
+ /* get the block sizes */
+ status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
+ blocksizes, sizeof(blocksizes));
+
+ if (status != A_OK) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* note: we actually get the block size of a mailbox other than 0, for SDIO the block
+ * size on mailbox 0 is artificially set to 1. So we use the block size that is set
+ * for the other 3 mailboxes */
+ pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE];
+ /* must be a power of 2 */
+ A_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0);
+
+ /* assemble mask, used for padding to a block */
+ pDev->BlockMask = pDev->BlockSize - 1;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n",
+ pDev->BlockSize, pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]));
+
+ pDev->GetPendingEventsFunc = NULL;
+ /* see if the HIF layer implements the get pending events function */
+ HIFConfigureDevice(pDev->HIFDevice,
+ HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
+ &pDev->GetPendingEventsFunc,
+ sizeof(pDev->GetPendingEventsFunc));
+
+ /* assume we can process HIF interrupt events asynchronously */
+ pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC;
+
+ /* see if the HIF layer overrides this assumption */
+ HIFConfigureDevice(pDev->HIFDevice,
+ HIF_DEVICE_GET_IRQ_PROC_MODE,
+ &pDev->HifIRQProcessingMode,
+ sizeof(pDev->HifIRQProcessingMode));
+
+ switch (pDev->HifIRQProcessingMode) {
+ case HIF_DEVICE_IRQ_SYNC_ONLY:
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n"));
+ /* see if HIF layer wants HTC to yield */
+ HIFConfigureDevice(pDev->HIFDevice,
+ HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
+ &pDev->HifIRQYieldParams,
+ sizeof(pDev->HifIRQYieldParams));
+
+ if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ ("HIF requests that DSR yield per %d RECV packets \n",
+ pDev->HifIRQYieldParams.RecvPacketYieldCount));
+ pDev->DSRCanYield = TRUE;
+ }
+ break;
+ case HIF_DEVICE_IRQ_ASYNC_SYNC:
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
+ break;
+ default:
+ A_ASSERT(FALSE);
+ }
+
+ pDev->HifMaskUmaskRecvEvent = NULL;
+
+ /* see if the HIF layer implements the mask/unmask recv events function */
+ HIFConfigureDevice(pDev->HIFDevice,
+ HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
+ &pDev->HifMaskUmaskRecvEvent,
+ sizeof(pDev->HifMaskUmaskRecvEvent));
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n",
+ (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent));
+
+ status = DevDisableInterrupts(pDev);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ status = DevSetupGMbox(pDev);
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ if (pDev->HifAttached) {
+ HIFDetachHTC(pDev->HIFDevice);
+ pDev->HifAttached = FALSE;
+ }
+ }
+
+ return status;
+
+}
+
+A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
+{
+ A_STATUS status;
+ AR6K_IRQ_ENABLE_REGISTERS regs;
+
+ LOCK_AR6K(pDev);
+
+ /* Enable all the interrupts except for the internal AR6000 CPU interrupt */
+ pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) |
+ INT_STATUS_ENABLE_CPU_SET(0x01) |
+ INT_STATUS_ENABLE_COUNTER_SET(0x01);
+
+ if (NULL == pDev->GetPendingEventsFunc) {
+ pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
+ } else {
+ /* The HIF layer provided us with a pending events function which means that
+ * the detection of pending mbox messages is handled in the HIF layer.
+ * This is the case for the SPI2 interface.
+ * In the normal case we enable MBOX interrupts, for the case
+ * with HIFs that offer this mechanism, we keep these interrupts
+ * masked */
+ pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
+ }
+
+
+ /* Set up the CPU Interrupt Status Register */
+ pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00);
+
+ /* Set up the Error Interrupt Status Register */
+ pDev->IrqEnableRegisters.error_status_enable =
+ ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) |
+ ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01);
+
+ /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */
+ pDev->IrqEnableRegisters.counter_int_status_enable =
+ COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK);
+
+ /* copy into our temp area */
+ A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+
+ UNLOCK_AR6K(pDev);
+
+ /* always synchronous */
+ status = HIFReadWrite(pDev->HIFDevice,
+ INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_enable,
+ AR6K_IRQ_ENABLE_REGS_SIZE,
+ HIF_WR_SYNC_BYTE_INC,
+ NULL);
+
+ if (status != A_OK) {
+ /* Can't write it for some reason */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Failed to update interrupt control registers err: %d\n", status));
+
+ }
+
+ return status;
+}
+
+A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
+{
+ AR6K_IRQ_ENABLE_REGISTERS regs;
+
+ LOCK_AR6K(pDev);
+ /* Disable all interrupts */
+ pDev->IrqEnableRegisters.int_status_enable = 0;
+ pDev->IrqEnableRegisters.cpu_int_status_enable = 0;
+ pDev->IrqEnableRegisters.error_status_enable = 0;
+ pDev->IrqEnableRegisters.counter_int_status_enable = 0;
+ /* copy into our temp area */
+ A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+
+ UNLOCK_AR6K(pDev);
+
+ /* always synchronous */
+ return HIFReadWrite(pDev->HIFDevice,
+ INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_enable,
+ AR6K_IRQ_ENABLE_REGS_SIZE,
+ HIF_WR_SYNC_BYTE_INC,
+ NULL);
+}
+
+/* enable device interrupts */
+A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
+{
+ /* for good measure, make sure interrupt are disabled before unmasking at the HIF
+ * layer.
+ * The rationale here is that between device insertion (where we clear the interrupts the first time)
+ * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
+ * The AR6K interrupt enables reset back to an "enabled" state when this happens.
+ * */
+ A_STATUS IntStatus = A_OK;
+ DevDisableInterrupts(pDev);
+
+#ifdef THREAD_X
+ // Tobe verified...
+ IntStatus = DevEnableInterrupts(pDev);
+ /* Unmask the host controller interrupts */
+ HIFUnMaskInterrupt(pDev->HIFDevice);
+#else
+ /* Unmask the host controller interrupts */
+ HIFUnMaskInterrupt(pDev->HIFDevice);
+ IntStatus = DevEnableInterrupts(pDev);
+#endif
+
+ return IntStatus;
+}
+
+/* disable all device interrupts */
+A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
+{
+ /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while
+ * we zero out our shadow registers in DevDisableInterrupts()*/
+ HIFMaskInterrupt(pDev->HIFDevice);
+
+ return DevDisableInterrupts(pDev);
+}
+
+/* callback when our fetch to enable/disable completes */
+static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ if (A_FAILED(pPacket->Status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" Failed to disable receiver, status:%d \n", pPacket->Status));
+ }
+ /* free this IO packet */
+ AR6KFreeIOPacket(pDev,pPacket);
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n"));
+}
+
+/* disable packet reception (used in case the host runs out of buffers)
+ * this is the "override" method when the HIF reports another methods to
+ * disable recv events */
+static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
+{
+ A_STATUS status = A_OK;
+ HTC_PACKET *pIOPacket = NULL;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
+ EnableRecv,AsyncMode));
+
+ do {
+
+ if (AsyncMode) {
+
+ pIOPacket = AR6KAllocIOPacket(pDev);
+
+ if (NULL == pIOPacket) {
+ status = A_NO_MEMORY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
+ pIOPacket->pContext = pDev;
+
+ /* call the HIF layer override and do this asynchronously */
+ status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
+ EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
+ pIOPacket);
+ break;
+ }
+
+ /* if we get here we are doing it synchronously */
+ status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
+ EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
+ NULL);
+
+ } while (FALSE);
+
+ if (A_FAILED(status) && (pIOPacket != NULL)) {
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+
+ return status;
+}
+
+/* disable packet reception (used in case the host runs out of buffers)
+ * this is the "normal" method using the interrupt enable registers through
+ * the host I/F */
+static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
+{
+ A_STATUS status = A_OK;
+ HTC_PACKET *pIOPacket = NULL;
+ AR6K_IRQ_ENABLE_REGISTERS regs;
+
+ /* take the lock to protect interrupt enable shadows */
+ LOCK_AR6K(pDev);
+
+ if (EnableRecv) {
+ pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
+ } else {
+ pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
+ }
+
+ /* copy into our temp area */
+ A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+ UNLOCK_AR6K(pDev);
+
+ do {
+
+ if (AsyncMode) {
+
+ pIOPacket = AR6KAllocIOPacket(pDev);
+
+ if (NULL == pIOPacket) {
+ status = A_NO_MEMORY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* copy values to write to our async I/O buffer */
+ A_MEMCPY(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
+
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
+ pIOPacket->pContext = pDev;
+
+ /* write it out asynchronously */
+ HIFReadWrite(pDev->HIFDevice,
+ INT_STATUS_ENABLE_ADDRESS,
+ pIOPacket->pBuffer,
+ AR6K_IRQ_ENABLE_REGS_SIZE,
+ HIF_WR_ASYNC_BYTE_INC,
+ pIOPacket);
+ break;
+ }
+
+ /* if we get here we are doing it synchronously */
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_enable,
+ AR6K_IRQ_ENABLE_REGS_SIZE,
+ HIF_WR_SYNC_BYTE_INC,
+ NULL);
+
+ } while (FALSE);
+
+ if (A_FAILED(status) && (pIOPacket != NULL)) {
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+
+ return status;
+}
+
+
+A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
+{
+ if (NULL == pDev->HifMaskUmaskRecvEvent) {
+ return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode);
+ } else {
+ return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode);
+ }
+}
+
+A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
+{
+ if (NULL == pDev->HifMaskUmaskRecvEvent) {
+ return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode);
+ } else {
+ return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode);
+ }
+}
+
+A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending)
+{
+ A_STATUS status = A_OK;
+ A_UCHAR host_int_status = 0x0;
+ A_UINT32 counter = 0x0;
+
+ if(TimeoutInMs < 100)
+ {
+ TimeoutInMs = 100;
+ }
+
+ counter = TimeoutInMs / 100;
+
+ do
+ {
+ //Read the Host Interrupt Status Register
+ status = HIFReadWrite(pDev->HIFDevice,
+ HOST_INT_STATUS_ADDRESS,
+ &host_int_status,
+ sizeof(A_UCHAR),
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+ if(A_FAILED(status))
+ {
+ AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
+ break;
+ }
+
+ host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0;
+ if(!host_int_status)
+ {
+ status = A_OK;
+ *pbIsRecvPending = FALSE;
+ break;
+ }
+ else
+ {
+ *pbIsRecvPending = TRUE;
+ }
+
+ A_MDELAY(100);
+
+ counter--;
+
+ }while(counter);
+ return status;
+}
+
+void DevDumpRegisters(AR6K_DEVICE *pDev,
+ AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs,
+ AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
+{
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n"));
+
+ if (pIrqProcRegs != NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Host Int Status: 0x%x\n",pIrqProcRegs->host_int_status));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("CPU Int Status: 0x%x\n",pIrqProcRegs->cpu_int_status));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Error Int Status: 0x%x\n",pIrqProcRegs->error_int_status));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Counter Int Status: 0x%x\n",pIrqProcRegs->counter_int_status));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Mbox Frame: 0x%x\n",pIrqProcRegs->mbox_frame));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Rx Lookahead Valid: 0x%x\n",pIrqProcRegs->rx_lookahead_valid));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0]));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1]));
+
+ if (pDev->MailBoxInfo.GMboxAddress != 0) {
+ /* if the target supports GMBOX hardware, dump some additional state */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("GMBOX Host Int Status 2: 0x%x\n",pIrqProcRegs->host_int_status2));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("GMBOX RX Avail: 0x%x\n",pIrqProcRegs->gmbox_rx_avail));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("GMBOX lookahead alias 0: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[0]));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("GMBOX lookahead alias 1: 0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[1]));
+ }
+
+ }
+
+ if (pIrqEnableRegs != NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable));
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------->\n"));
+}
+
+
+#define DEV_GET_VIRT_DMA_INFO(p) ((DEV_SCATTER_DMA_VIRTUAL_INFO *)((p)->HIFPrivate[0]))
+
+static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
+{
+ DL_LIST *pItem;
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+ LOCK_AR6K(pDev);
+ pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead);
+ UNLOCK_AR6K(pDev);
+ if (pItem != NULL) {
+ return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
+ }
+ return NULL;
+}
+
+static void DevFreeScatterReq(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+ LOCK_AR6K(pDev);
+ DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink);
+ UNLOCK_AR6K(pDev);
+}
+
+A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA)
+{
+ A_UINT8 *pDMABuffer = NULL;
+ int i, remaining;
+ A_UINT32 length;
+
+ pDMABuffer = pReq->pScatterBounceBuffer;
+
+ if (pDMABuffer == NULL) {
+ A_ASSERT(FALSE);
+ return A_EINVAL;
+ }
+
+ remaining = (int)pReq->TotalLength;
+
+ for (i = 0; i < pReq->ValidScatterEntries; i++) {
+
+ length = min((int)pReq->ScatterList[i].Length, remaining);
+
+ if (length != (int)pReq->ScatterList[i].Length) {
+ A_ASSERT(FALSE);
+ /* there is a problem with the scatter list */
+ return A_EINVAL;
+ }
+
+ if (FromDMA) {
+ /* from DMA buffer */
+ A_MEMCPY(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
+ } else {
+ /* to DMA buffer */
+ A_MEMCPY(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
+ }
+
+ pDMABuffer += length;
+ remaining -= length;
+ }
+
+ return A_OK;
+}
+
+static void DevReadWriteScatterAsyncHandler(void *Context, HTC_PACKET *pPacket)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+ HIF_SCATTER_REQ *pReq = (HIF_SCATTER_REQ *)pPacket->pPktContext;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ pReq->CompletionStatus = pPacket->Status;
+
+ AR6KFreeIOPacket(pDev,pPacket);
+
+ pReq->CompletionRoutine(pReq);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n"));
+}
+
+static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+ A_STATUS status = A_OK;
+ HTC_PACKET *pIOPacket = NULL;
+ A_UINT32 request = pReq->Request;
+
+ do {
+
+ if (pReq->TotalLength > AR6K_MAX_TRANSFER_SIZE_PER_SCATTER) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Invalid length: %d \n", pReq->TotalLength));
+ break;
+ }
+
+ if (pReq->TotalLength == 0) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ if (request & HIF_ASYNCHRONOUS) {
+ /* use an I/O packet to carry this request */
+ pIOPacket = AR6KAllocIOPacket(pDev);
+ if (NULL == pIOPacket) {
+ status = A_NO_MEMORY;
+ break;
+ }
+
+ /* save the request */
+ pIOPacket->pPktContext = pReq;
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevReadWriteScatterAsyncHandler;
+ pIOPacket->pContext = pDev;
+ }
+
+ if (request & HIF_WRITE) {
+ /* in virtual DMA, we are issuing the requests through the legacy HIFReadWrite API
+ * this API will adjust the address automatically for the last byte to fall on the mailbox
+ * EOM. */
+
+ /* if the address is an extended address, we can adjust the address here since the extended
+ * address will bypass the normal checks in legacy HIF layers */
+ if (pReq->Address == pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress) {
+ pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength;
+ }
+ }
+
+ /* use legacy readwrite */
+ status = HIFReadWrite(pDev->HIFDevice,
+ pReq->Address,
+ DEV_GET_VIRT_DMA_INFO(pReq)->pVirtDmaBuffer,
+ pReq->TotalLength,
+ request,
+ (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL);
+
+ } while (FALSE);
+
+ if ((status != A_PENDING) && A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
+ if (pIOPacket != NULL) {
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+ pReq->CompletionStatus = status;
+ pReq->CompletionRoutine(pReq);
+ status = A_OK;
+ }
+
+ return status;
+}
+
+
+static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev)
+{
+ HIF_SCATTER_REQ *pReq;
+
+ while (1) {
+ pReq = DevAllocScatterReq((HIF_DEVICE *)pDev);
+ if (NULL == pReq) {
+ break;
+ }
+ A_FREE(pReq);
+ }
+
+}
+
+ /* function to set up virtual scatter support if HIF layer has not implemented the interface */
+static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
+{
+ A_STATUS status = A_OK;
+ int bufferSize, sgreqSize;
+ int i;
+ DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo;
+ HIF_SCATTER_REQ *pReq;
+
+ bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
+ 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
+
+ sgreqSize = sizeof(HIF_SCATTER_REQ) +
+ (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM));
+
+ for (i = 0; i < AR6K_SCATTER_REQS; i++) {
+ /* allocate the scatter request, buffer info and the actual virtual buffer itself */
+ pReq = (HIF_SCATTER_REQ *)A_MALLOC(sgreqSize + bufferSize);
+
+ if (NULL == pReq) {
+ status = A_NO_MEMORY;
+ break;
+ }
+
+ A_MEMZERO(pReq, sgreqSize);
+
+ /* the virtual DMA starts after the scatter request struct */
+ pVirtualInfo = (DEV_SCATTER_DMA_VIRTUAL_INFO *)((A_UINT8 *)pReq + sgreqSize);
+ A_MEMZERO(pVirtualInfo, sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO));
+
+ pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0];
+ /* align buffer to cache line in case host controller can actually DMA this */
+ pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer);
+ /* store the structure in the private area */
+ pReq->HIFPrivate[0] = pVirtualInfo;
+ /* we emulate a DMA bounce interface */
+ pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
+ pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer;
+ /* free request to the list */
+ DevFreeScatterReq((HIF_DEVICE *)pDev,pReq);
+ }
+
+ if (A_FAILED(status)) {
+ DevCleanupVirtualScatterSupport(pDev);
+ } else {
+ pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
+ pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq;
+ pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter;
+ if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n"));
+ pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ;
+ pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER;
+ } else {
+ pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
+ pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
+ }
+ pDev->ScatterIsVirtual = TRUE;
+ }
+
+ return status;
+}
+
+
+A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
+{
+ A_STATUS status;
+
+ if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
+ return A_ENOTSUP;
+ }
+
+ status = HIFConfigureDevice(pDev->HIFDevice,
+ HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT,
+ &pDev->HifScatterInfo,
+ sizeof(pDev->HifScatterInfo));
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status));
+
+ /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */
+ status = DevSetupVirtualScatterSupport(pDev);
+
+ if (A_SUCCESS(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n",
+ DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
+ }
+
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n",
+ DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
+ }
+
+ if (A_SUCCESS(status)) {
+ /* for the recv path, the maximum number of bytes per recv bundle is just limited
+ * by the maximum transfer size at the HIF layer */
+ pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
+
+ if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n"));
+ pDev->MaxSendBundleSize = 0;
+ } else {
+ /* for the send path, the max transfer size is limited by the existence and size of
+ * the extended mailbox address range */
+ if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) {
+ pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize;
+ } else {
+ /* legacy */
+ pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH;
+ }
+
+ if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) {
+ /* limit send bundle size to what the HIF can support for scatter requests */
+ pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
+ ("AR6K: max recv: %d max send: %d \n",
+ DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)));
+
+ }
+ return status;
+}
+
+A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async)
+{
+ A_STATUS status;
+
+ if (Read) {
+ /* read operation */
+ pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX;
+ pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
+ A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
+ } else {
+ A_UINT32 mailboxWidth;
+
+ /* write operation */
+ pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC;
+ A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
+ if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) {
+ /* for large writes use the extended address */
+ pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
+ mailboxWidth = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize;
+ } else {
+ pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
+ mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH;
+ }
+
+ if (!pDev->ScatterIsVirtual) {
+ /* we are passing this scatter list down to the HIF layer' scatter request handler, fixup the address
+ * so that the last byte falls on the EOM, we do this for those HIFs that support the
+ * scatter API */
+ pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength);
+ }
+
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV | ATH_DEBUG_SEND,
+ ("DevSubmitScatterRequest, Entries: %d, Total Length: %d Mbox:0x%X (mode: %s : %s)\n",
+ pScatterReq->ValidScatterEntries,
+ pScatterReq->TotalLength,
+ pScatterReq->Address,
+ Async ? "ASYNC" : "SYNC",
+ (Read) ? "RD" : "WR"));
+
+ status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq);
+
+ if (A_FAILED(status)) {
+ if (Async) {
+ pScatterReq->CompletionStatus = status;
+ pScatterReq->CompletionRoutine(pScatterReq);
+ return A_OK;
+ }
+ return status;
+ }
+
+ status = pDev->HifScatterInfo.pReadWriteScatterFunc(pDev->ScatterIsVirtual ? pDev : pDev->HIFDevice,
+ pScatterReq);
+ if (!Async) {
+ /* in sync mode, we can touch the scatter request */
+ pScatterReq->CompletionStatus = status;
+ DEV_FINISH_SCATTER_OPERATION(pScatterReq);
+ } else {
+ if (status == A_PENDING) {
+ status = A_OK;
+ }
+ }
+
+ return status;
+}
+
+
+#ifdef MBOXHW_UNIT_TEST
+
+
+/* This is a mailbox hardware unit test that must be called in a schedulable context
+ * This test is very simple, it will send a list of buffers with a counting pattern
+ * and the target will invert the data and send the message back
+ *
+ * the unit test has the following constraints:
+ *
+ * The target has at least 8 buffers of 256 bytes each. The host will send
+ * the following pattern of buffers in rapid succession :
+ *
+ * 1 buffer - 128 bytes
+ * 1 buffer - 256 bytes
+ * 1 buffer - 512 bytes
+ * 1 buffer - 1024 bytes
+ *
+ * The host will send the buffers to one mailbox and wait for buffers to be reflected
+ * back from the same mailbox. The target sends the buffers FIFO order.
+ * Once the final buffer has been received for a mailbox, the next mailbox is tested.
+ *
+ *
+ * Note: To simplifythe test , we assume that the chosen buffer sizes
+ * will fall on a nice block pad
+ *
+ * It is expected that higher-order tests will be written to stress the mailboxes using
+ * a message-based protocol (with some performance timming) that can create more
+ * randomness in the packets sent over mailboxes.
+ *
+ * */
+
+#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1))
+
+#define BUFFER_BLOCK_PAD 128
+
+#if 0
+#define BUFFER1 128
+#define BUFFER2 256
+#define BUFFER3 512
+#define BUFFER4 1024
+#endif
+
+#if 1
+#define BUFFER1 80
+#define BUFFER2 200
+#define BUFFER3 444
+#define BUFFER4 800
+#endif
+
+#define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \
+ A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \
+ A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \
+ A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) )
+
+#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4)
+
+#define TEST_CREDITS_RECV_TIMEOUT 100
+
+static A_UINT8 g_Buffer[TOTAL_BYTES];
+static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES];
+static A_UINT32 g_BlockSizes[AR6K_MAILBOXES];
+
+#define BUFFER_PROC_LIST_DEPTH 4
+
+typedef struct _BUFFER_PROC_LIST{
+ A_UINT8 *pBuffer;
+ A_UINT32 length;
+}BUFFER_PROC_LIST;
+
+
+#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
+{ \
+ (pList)->pBuffer = (pCurrpos); \
+ (pList)->length = (len); \
+ (pCurrpos) += (len); \
+ (pList)++; \
+}
+
+/* a simple and crude way to send different "message" sizes */
+static void AssembleBufferList(BUFFER_PROC_LIST *pList)
+{
+ A_UINT8 *pBuffer = g_Buffer;
+
+#if BUFFER_PROC_LIST_DEPTH < 4
+#error "Buffer processing list depth is not deep enough!!"
+#endif
+
+ PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer);
+ PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer);
+ PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer);
+ PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer);
+
+}
+
+#define FILL_ZERO TRUE
+#define FILL_COUNTING FALSE
+static void InitBuffers(A_BOOL Zero)
+{
+ A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer;
+ int i;
+
+ /* fill buffer with 16 bit counting pattern or zeros */
+ for (i = 0; i < (TOTAL_BYTES / 2) ; i++) {
+ if (!Zero) {
+ pBuffer16[i] = (A_UINT16)i;
+ } else {
+ pBuffer16[i] = 0;
+ }
+ }
+}
+
+
+static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
+{
+ int i;
+ A_UINT16 startCount;
+ A_BOOL success = TRUE;
+
+ /* get the starting count */
+ startCount = pBuffer16[0];
+ /* invert it, this is the expected value */
+ startCount = ~startCount;
+ /* scan the buffer and verify */
+ for (i = 0; i < (Length / 2) ; i++,startCount++) {
+ /* target will invert all the data */
+ if ((A_UINT16)pBuffer16[i] != (A_UINT16)~startCount) {
+ success = FALSE;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n",
+ pBuffer16[i], ((A_UINT16)~startCount), i, Length));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n",
+ pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3]));
+ break;
+ }
+ }
+
+ return success;
+}
+
+static A_BOOL CheckBuffers(void)
+{
+ int i;
+ A_BOOL success = TRUE;
+ BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
+
+ /* assemble the list */
+ AssembleBufferList(checkList);
+
+ /* scan the buffers and verify */
+ for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) {
+ success = CheckOneBuffer((A_UINT16 *)checkList[i].pBuffer, checkList[i].length);
+ if (!success) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
+ (A_UINT32)checkList[i].pBuffer, checkList[i].length));
+ break;
+ }
+ }
+
+ return success;
+}
+
+ /* find the end marker for the last buffer we will be sending */
+static A_UINT16 GetEndMarker(void)
+{
+ A_UINT8 *pBuffer;
+ BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
+
+ /* fill up buffers with the normal counting pattern */
+ InitBuffers(FILL_COUNTING);
+
+ /* assemble the list we will be sending down */
+ AssembleBufferList(checkList);
+ /* point to the last 2 bytes of the last buffer */
+ pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]);
+
+ /* the last count in the last buffer is the marker */
+ return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8);
+}
+
+#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
+
+/* send the ordered buffers to the target */
+static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
+{
+ A_STATUS status = A_OK;
+ A_UINT32 request = HIF_WR_SYNC_BLOCK_INC;
+ BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH];
+ int i;
+ int totalBytes = 0;
+ int paddedLength;
+ int totalwPadding = 0;
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox));
+
+ /* fill buffer with counting pattern */
+ InitBuffers(FILL_COUNTING);
+
+ /* assemble the order in which we send */
+ AssembleBufferList(sendList);
+
+ for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) {
+
+ /* we are doing block transfers, so we need to pad everything to a block size */
+ paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) &
+ (~(g_BlockSizes[mbox] - 1));
+
+ /* send each buffer synchronously */
+ status = HIFReadWrite(pDev->HIFDevice,
+ g_MailboxAddrs[mbox],
+ sendList[i].pBuffer,
+ paddedLength,
+ request,
+ NULL);
+ if (status != A_OK) {
+ break;
+ }
+ totalBytes += sendList[i].length;
+ totalwPadding += paddedLength;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox));
+
+ return status;
+}
+
+/* poll the mailbox credit counter until we get a credit or timeout */
+static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
+{
+ A_STATUS status = A_OK;
+ int timeout = TEST_CREDITS_RECV_TIMEOUT;
+ A_UINT8 credits = 0;
+ A_UINT32 address;
+
+ while (TRUE) {
+
+ /* Read the counter register to get credits, this auto-decrements */
+ address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
+ status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
+ HIF_RD_SYNC_BYTE_FIX, NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
+ status = A_ERROR;
+ break;
+ }
+
+ if (credits) {
+ break;
+ }
+
+ timeout--;
+
+ if (timeout <= 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address));
+ status = A_ERROR;
+ break;
+ }
+
+ /* delay a little, target may not be ready */
+ A_MDELAY(1000);
+
+ }
+
+ if (status == A_OK) {
+ *pCredits = credits;
+ }
+
+ return status;
+}
+
+
+/* wait for the buffers to come back */
+static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
+{
+ A_STATUS status = A_OK;
+ A_UINT32 request = HIF_RD_SYNC_BLOCK_INC;
+ BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH];
+ int curBuffer;
+ int credits;
+ int i;
+ int totalBytes = 0;
+ int paddedLength;
+ int totalwPadding = 0;
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox));
+
+ /* zero the buffers */
+ InitBuffers(FILL_ZERO);
+
+ /* assemble the order in which we should receive */
+ AssembleBufferList(recvList);
+
+ curBuffer = 0;
+
+ while (curBuffer < BUFFER_PROC_LIST_DEPTH) {
+
+ /* get number of buffers that have been completed, this blocks
+ * until we get at least 1 credit or it times out */
+ status = GetCredits(pDev, mbox, &credits);
+
+ if (status != A_OK) {
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox));
+
+ /* get all the buffers that are sitting on the queue */
+ for (i = 0; i < credits; i++) {
+ A_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH);
+ /* recv the current buffer synchronously, the buffers should come back in
+ * order... with padding applied by the target */
+ paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) &
+ (~(g_BlockSizes[mbox] - 1));
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ g_MailboxAddrs[mbox],
+ recvList[curBuffer].pBuffer,
+ paddedLength,
+ request,
+ NULL);
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n",
+ recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox]));
+ break;
+ }
+
+ totalwPadding += paddedLength;
+ totalBytes += recvList[curBuffer].length;
+ curBuffer++;
+ }
+
+ if (status != A_OK) {
+ break;
+ }
+ /* go back and get some more */
+ credits = 0;
+ }
+
+ if (totalBytes != TEST_BYTES) {
+ A_ASSERT(FALSE);
+ } else {
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n",
+ mbox, totalBytes, totalwPadding));
+ }
+
+ return status;
+
+
+}
+
+static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
+{
+ A_STATUS status;
+
+ do {
+ /* send out buffers */
+ status = SendBuffers(pDev,mbox);
+
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
+ break;
+ }
+
+ /* go get them, this will block */
+ status = RecvBuffers(pDev, mbox);
+
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
+ break;
+ }
+
+ /* check the returned data patterns */
+ if (!CheckBuffers()) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox));
+ status = A_ERROR;
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
+
+ } while (FALSE);
+
+ return status;
+}
+
+/* here is where the test starts */
+A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
+{
+ int i;
+ A_STATUS status;
+ int credits = 0;
+ A_UINT8 params[4];
+ int numBufs;
+ int bufferSize;
+ A_UINT16 temp;
+
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n"));
+
+ do {
+ /* get the addresses for all 4 mailboxes */
+ status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
+ g_MailboxAddrs, sizeof(g_MailboxAddrs));
+
+ if (status != A_OK) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* get the block sizes */
+ status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
+ g_BlockSizes, sizeof(g_BlockSizes));
+
+ if (status != A_OK) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* note, the HIF layer usually reports mbox 0 to have a block size of
+ * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes
+ * the same. */
+ g_BlockSizes[0] = g_BlockSizes[1];
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0]));
+
+ if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) {
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n",
+ g_BlockSizes[1], BUFFER_BLOCK_PAD));
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n"));
+
+ /* the target lets us know it is ready by giving us 1 credit on
+ * mailbox 0 */
+ status = GetCredits(pDev, 0, &credits);
+
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n"));
+
+ /* read the first 4 scratch registers */
+ status = HIFReadWrite(pDev->HIFDevice,
+ SCRATCH_ADDRESS,
+ params,
+ 4,
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
+ break;
+ }
+
+ numBufs = params[0];
+ bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]);
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE,
+ ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n",
+ numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES));
+
+ if ((numBufs * bufferSize) < TOTAL_BYTES) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n",
+ TOTAL_BYTES, (numBufs*bufferSize)));
+ status = A_ERROR;
+ break;
+ }
+
+ temp = GetEndMarker();
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ SCRATCH_ADDRESS + 4,
+ (A_UINT8 *)&temp,
+ 2,
+ HIF_WR_SYNC_BYTE_INC,
+ NULL);
+
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
+
+ temp = (A_UINT16)g_BlockSizes[1];
+ /* convert to a mask */
+ temp = temp - 1;
+ status = HIFReadWrite(pDev->HIFDevice,
+ SCRATCH_ADDRESS + 6,
+ (A_UINT8 *)&temp,
+ 2,
+ HIF_WR_SYNC_BYTE_INC,
+ NULL);
+
+ if (status != A_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp));
+
+ /* execute the test on each mailbox */
+ for (i = 0; i < AR6K_MAILBOXES; i++) {
+ status = DoOneMboxHWTest(pDev, i);
+ if (status != A_OK) {
+ break;
+ }
+ }
+
+ } while (FALSE);
+
+ if (status == A_OK) {
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n"));
+ } else {
+ AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n"));
+ }
+ /* don't let HTC_Start continue, the target is actually not running any HTC code */
+ return A_ERROR;
+}
+#endif
+
+
+
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k.h b/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
new file mode 100644
index 00000000000..b30fd877aeb
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
@@ -0,0 +1,398 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6k.h" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// AR6K device layer that handles register level I/O
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef AR6K_H_
+#define AR6K_H_
+
+#include "hci_transport_api.h"
+#include "../htc_debug.h"
+
+#define AR6K_MAILBOXES 4
+
+/* HTC runs over mailbox 0 */
+#define HTC_MAILBOX 0
+
+#define AR6K_TARGET_DEBUG_INTR_MASK 0x01
+
+#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
+ INT_STATUS_ENABLE_CPU_MASK | \
+ INT_STATUS_ENABLE_COUNTER_MASK)
+
+
+//#define MBOXHW_UNIT_TEST 1
+
+#include "athstartpack.h"
+typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS {
+ A_UINT8 host_int_status;
+ A_UINT8 cpu_int_status;
+ A_UINT8 error_int_status;
+ A_UINT8 counter_int_status;
+ A_UINT8 mbox_frame;
+ A_UINT8 rx_lookahead_valid;
+ A_UINT8 host_int_status2;
+ A_UINT8 gmbox_rx_avail;
+ A_UINT32 rx_lookahead[2];
+ A_UINT32 rx_gmbox_lookahead_alias[2];
+} POSTPACK AR6K_IRQ_PROC_REGISTERS;
+
+#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
+
+typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS {
+ A_UINT8 int_status_enable;
+ A_UINT8 cpu_int_status_enable;
+ A_UINT8 error_status_enable;
+ A_UINT8 counter_int_status_enable;
+} POSTPACK AR6K_IRQ_ENABLE_REGISTERS;
+
+typedef PREPACK struct _AR6K_GMBOX_CTRL_REGISTERS {
+ A_UINT8 int_status_enable;
+} POSTPACK AR6K_GMBOX_CTRL_REGISTERS;
+
+#include "athendpack.h"
+
+#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS)
+
+#define AR6K_REG_IO_BUFFER_SIZE 32
+#define AR6K_MAX_REG_IO_BUFFERS 8
+#define FROM_DMA_BUFFER TRUE
+#define TO_DMA_BUFFER FALSE
+#define AR6K_SCATTER_ENTRIES_PER_REQ 16
+#define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER 16*1024
+#define AR6K_SCATTER_REQS 4
+#define AR6K_LEGACY_MAX_WRITE_LENGTH 2048
+
+#ifndef A_CACHE_LINE_PAD
+#define A_CACHE_LINE_PAD 128
+#endif
+#define AR6K_MIN_SCATTER_ENTRIES_PER_REQ 2
+#define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER 4*1024
+
+/* buffers for ASYNC I/O */
+typedef struct AR6K_ASYNC_REG_IO_BUFFER {
+ HTC_PACKET HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */
+ A_UINT8 _Pad1[A_CACHE_LINE_PAD];
+ A_UINT8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; /* cache-line safe with pads around */
+ A_UINT8 _Pad2[A_CACHE_LINE_PAD];
+} AR6K_ASYNC_REG_IO_BUFFER;
+
+typedef struct _AR6K_GMBOX_INFO {
+ void *pProtocolContext;
+ A_STATUS (*pMessagePendingCallBack)(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes);
+ A_STATUS (*pCreditsPendingCallback)(void *pContext, int NumCredits, A_BOOL CreditIRQEnabled);
+ void (*pTargetFailureCallback)(void *pContext, A_STATUS Status);
+ void (*pStateDumpCallback)(void *pContext);
+ A_BOOL CreditCountIRQEnabled;
+} AR6K_GMBOX_INFO;
+
+typedef struct _AR6K_DEVICE {
+ A_MUTEX_T Lock;
+ A_UINT8 _Pad1[A_CACHE_LINE_PAD];
+ AR6K_IRQ_PROC_REGISTERS IrqProcRegisters; /* cache-line safe with pads around */
+ A_UINT8 _Pad2[A_CACHE_LINE_PAD];
+ AR6K_IRQ_ENABLE_REGISTERS IrqEnableRegisters; /* cache-line safe with pads around */
+ A_UINT8 _Pad3[A_CACHE_LINE_PAD];
+ void *HIFDevice;
+ A_UINT32 BlockSize;
+ A_UINT32 BlockMask;
+ HIF_DEVICE_MBOX_INFO MailBoxInfo;
+ HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc;
+ void *HTCContext;
+ HTC_PACKET_QUEUE RegisterIOList;
+ AR6K_ASYNC_REG_IO_BUFFER RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
+ void (*TargetFailureCallback)(void *Context);
+ A_STATUS (*MessagePendingCallback)(void *Context,
+ A_UINT32 LookAheads[],
+ int NumLookAheads,
+ A_BOOL *pAsyncProc,
+ int *pNumPktsFetched);
+ HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode;
+ HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent;
+ A_BOOL HifAttached;
+ HIF_DEVICE_IRQ_YIELD_PARAMS HifIRQYieldParams;
+ A_BOOL DSRCanYield;
+ int CurrentDSRRecvCount;
+ HIF_DEVICE_SCATTER_SUPPORT_INFO HifScatterInfo;
+ DL_LIST ScatterReqHead;
+ A_BOOL ScatterIsVirtual;
+ int MaxRecvBundleSize;
+ int MaxSendBundleSize;
+ AR6K_GMBOX_INFO GMboxInfo;
+ A_BOOL GMboxEnabled;
+ AR6K_GMBOX_CTRL_REGISTERS GMboxControlRegisters;
+ int RecheckIRQStatusCnt;
+} AR6K_DEVICE;
+
+#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock);
+#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock);
+#define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1 /* note: no need to lock this, it only gets set */
+
+A_STATUS DevSetup(AR6K_DEVICE *pDev);
+void DevCleanup(AR6K_DEVICE *pDev);
+A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev);
+A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev);
+A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
+ A_UINT32 *pLookAhead,
+ int TimeoutMS);
+A_STATUS DevRWCompletionHandler(void *context, A_STATUS status);
+A_STATUS DevDsrHandler(void *context);
+A_STATUS DevCheckPendingRecvMsgsAsync(void *context);
+void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev);
+void DevDumpRegisters(AR6K_DEVICE *pDev,
+ AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs,
+ AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs);
+
+#define DEV_STOP_RECV_ASYNC TRUE
+#define DEV_STOP_RECV_SYNC FALSE
+#define DEV_ENABLE_RECV_ASYNC TRUE
+#define DEV_ENABLE_RECV_SYNC FALSE
+A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
+A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
+A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
+A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
+A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending);
+
+#define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask)))
+#define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length)
+#define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0)
+
+static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) {
+ A_UINT32 paddedLength;
+ A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+ A_STATUS status;
+
+ /* adjust the length to be a multiple of block size if appropriate */
+ paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength);
+
+#if 0
+ if (paddedLength > pPacket->BufferLength) {
+ A_ASSERT(FALSE);
+ if (pPacket->Completion != NULL) {
+ COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
+ return A_OK;
+ }
+ return A_EINVAL;
+ }
+#endif
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
+ paddedLength,
+ pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
+ sync ? "SYNC" : "ASYNC"));
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
+ pPacket->pBuffer,
+ paddedLength, /* the padded length */
+ sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
+ sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
+
+ if (sync) {
+ pPacket->Status = status;
+ } else {
+ if (status == A_PENDING) {
+ status = A_OK;
+ }
+ }
+
+ return status;
+}
+
+static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) {
+ A_UINT32 paddedLength;
+ A_STATUS status;
+ A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+
+ /* adjust the length to be a multiple of block size if appropriate */
+ paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength);
+
+ if (paddedLength > pPacket->BufferLength) {
+ A_ASSERT(FALSE);
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
+ paddedLength,RecvLength,pPacket->BufferLength));
+ if (pPacket->Completion != NULL) {
+ COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
+ return A_OK;
+ }
+ return A_EINVAL;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("DevRecvPacket (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
+ (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
+ paddedLength,
+ pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
+ sync ? "SYNC" : "ASYNC"));
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX],
+ pPacket->pBuffer,
+ paddedLength,
+ sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
+ sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
+
+ if (sync) {
+ pPacket->Status = status;
+ }
+
+ return status;
+}
+
+#define DEV_CHECK_RECV_YIELD(pDev) \
+ ((pDev)->CurrentDSRRecvCount >= (pDev)->HifIRQYieldParams.RecvPacketYieldCount)
+
+#define IS_DEV_IRQ_PROC_SYNC_MODE(pDev) (HIF_DEVICE_IRQ_SYNC_ONLY == (pDev)->HifIRQProcessingMode)
+#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY)
+
+/**************************************************/
+/****** Scatter Function and Definitions
+ *
+ *
+ */
+
+A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA);
+
+ /* copy any READ data back into scatter list */
+#define DEV_FINISH_SCATTER_OPERATION(pR) \
+ if (A_SUCCESS((pR)->CompletionStatus) && \
+ !((pR)->Request & HIF_WRITE) && \
+ ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) { \
+ (pR)->CompletionStatus = DevCopyScatterListToFromDMABuffer((pR),FROM_DMA_BUFFER); \
+ }
+
+ /* copy any WRITE data to bounce buffer */
+static INLINE A_STATUS DEV_PREPARE_SCATTER_OPERATION(HIF_SCATTER_REQ *pReq) {
+ if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
+ return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);
+ } else {
+ return A_OK;
+ }
+}
+
+
+A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer);
+
+#define DEV_GET_MAX_MSG_PER_BUNDLE(pDev) (pDev)->HifScatterInfo.MaxScatterEntries
+#define DEV_GET_MAX_BUNDLE_LENGTH(pDev) (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
+#define DEV_ALLOC_SCATTER_REQ(pDev) \
+ (pDev)->HifScatterInfo.pAllocateReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice)
+
+#define DEV_FREE_SCATTER_REQ(pDev,pR) \
+ (pDev)->HifScatterInfo.pFreeReqFunc((pDev)->ScatterIsVirtual ? (pDev) : (pDev)->HIFDevice,(pR))
+
+#define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev) (pDev)->MaxRecvBundleSize
+#define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev) (pDev)->MaxSendBundleSize
+
+#define DEV_SCATTER_READ TRUE
+#define DEV_SCATTER_WRITE FALSE
+#define DEV_SCATTER_ASYNC TRUE
+#define DEV_SCATTER_SYNC FALSE
+A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async);
+
+#ifdef MBOXHW_UNIT_TEST
+A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev);
+#endif
+
+ /* completely virtual */
+typedef struct _DEV_SCATTER_DMA_VIRTUAL_INFO {
+ A_UINT8 *pVirtDmaBuffer; /* dma-able buffer - CPU accessible address */
+ A_UINT8 DataArea[1]; /* start of data area */
+} DEV_SCATTER_DMA_VIRTUAL_INFO;
+
+
+
+void DumpAR6KDevState(AR6K_DEVICE *pDev);
+
+/**************************************************/
+/****** GMBOX functions and definitions
+ *
+ *
+ */
+
+#ifdef ATH_AR6K_ENABLE_GMBOX
+
+void DevCleanupGMbox(AR6K_DEVICE *pDev);
+A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev);
+A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev);
+void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev);
+
+#else
+
+ /* compiled out */
+#define DevCleanupGMbox(p)
+#define DevCheckGMboxInterrupts(p) A_OK
+#define DevNotifyGMboxTargetFailure(p)
+
+static INLINE A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) {
+ pDev->GMboxEnabled = FALSE;
+ return A_OK;
+}
+
+#endif
+
+#ifdef ATH_AR6K_ENABLE_GMBOX
+
+ /* GMBOX protocol modules must expose each of these internal APIs */
+HCI_TRANSPORT_HANDLE GMboxAttachProtocol(AR6K_DEVICE *pDev, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev);
+void GMboxProtocolUninstall(AR6K_DEVICE *pDev);
+
+ /* API used by GMBOX protocol modules */
+AR6K_DEVICE *HTCGetAR6KDevice(void *HTCHandle);
+#define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
+{ \
+ (pDev)->GMboxInfo.pProtocolContext = (context); \
+ (pDev)->GMboxInfo.pMessagePendingCallBack = (recv_callback); \
+ (pDev)->GMboxInfo.pCreditsPendingCallback = (credits_pending); \
+ (pDev)->GMboxInfo.pTargetFailureCallback = (failure); \
+ (pDev)->GMboxInfo.pStateDumpCallback = (statedump); \
+}
+
+#define DEV_GMBOX_GET_PROTOCOL(pDev) (pDev)->GMboxInfo.pProtocolContext
+
+A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength);
+A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength);
+
+#define PROC_IO_ASYNC TRUE
+#define PROC_IO_SYNC FALSE
+typedef enum GMBOX_IRQ_ACTION_TYPE {
+ GMBOX_ACTION_NONE = 0,
+ GMBOX_DISABLE_ALL,
+ GMBOX_ERRORS_IRQ_ENABLE,
+ GMBOX_RECV_IRQ_ENABLE,
+ GMBOX_RECV_IRQ_DISABLE,
+ GMBOX_CREDIT_IRQ_ENABLE,
+ GMBOX_CREDIT_IRQ_DISABLE,
+} GMBOX_IRQ_ACTION_TYPE;
+
+A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE, A_BOOL AsyncMode);
+A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits);
+A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize);
+A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes);
+A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int SignalNumber, int AckTimeoutMS);
+
+#endif
+
+#endif /*AR6K_H_*/
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
new file mode 100644
index 00000000000..920123b9ba1
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
@@ -0,0 +1,784 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6k_events.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// AR6K Driver layer event handling (i.e. interrupts, message polling)
+//
+// Author(s): ="Atheros"
+//==============================================================================
+
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "AR6002/hw2.0/hw/mbox_host_reg.h"
+#include "a_osapi.h"
+#include "../htc_debug.h"
+#include "hif.h"
+#include "htc_packet.h"
+#include "ar6k.h"
+
+extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
+extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
+
+static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev);
+
+#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */
+
+/* completion routine for ALL HIF layer async I/O */
+A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
+{
+ HTC_PACKET *pPacket = (HTC_PACKET *)context;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n",
+ (unsigned long)pPacket,
+ status));
+
+ COMPLETE_HTC_PACKET(pPacket,status);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("-DevRWCompletionHandler\n"));
+
+ return A_OK;
+}
+
+/* mailbox recv message polling */
+A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
+ A_UINT32 *pLookAhead,
+ int TimeoutMS)
+{
+ A_STATUS status = A_OK;
+ int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
+
+ A_ASSERT(timeout > 0);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
+
+ while (TRUE) {
+
+ if (pDev->GetPendingEventsFunc != NULL) {
+
+ HIF_PENDING_EVENTS_INFO events;
+
+#ifdef THREAD_X
+ events.Polling =1;
+#endif
+
+ /* the HIF layer uses a special mechanism to get events, do this
+ * synchronously */
+ status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
+ &events,
+ NULL);
+ if (A_FAILED(status))
+ {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
+ break;
+ }
+
+ if (events.Events & HIF_RECV_MSG_AVAIL)
+ {
+ /* there is a message available, the lookahead should be valid now */
+ *pLookAhead = events.LookAhead;
+
+ break;
+ }
+ } else {
+
+ /* this is the standard HIF way.... */
+ /* load the register table */
+ status = HIFReadWrite(pDev->HIFDevice,
+ HOST_INT_STATUS_ADDRESS,
+ (A_UINT8 *)&pDev->IrqProcRegisters,
+ AR6K_IRQ_PROC_REGS_SIZE,
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+
+ if (A_FAILED(status)){
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
+ break;
+ }
+
+ /* check for MBOX data and valid lookahead */
+ if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) {
+ if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX))
+ {
+ /* mailbox has a message and the look ahead is valid */
+ *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
+ break;
+ }
+ }
+
+ }
+
+ timeout--;
+
+ if (timeout <= 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n"));
+ status = A_ERROR;
+
+ /* check if the target asserted */
+ if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
+ /* target signaled an assert, process this pending interrupt
+ * this will call the target failure handler */
+ DevServiceDebugInterrupt(pDev);
+ }
+
+ break;
+ }
+
+ /* delay a little */
+ A_MDELAY(DELAY_PER_INTERVAL_MS);
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout));
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n"));
+
+ return status;
+}
+
+static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
+{
+ A_STATUS status;
+ A_UINT8 cpu_int_status;
+ A_UINT8 regBuffer[4];
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
+ cpu_int_status = pDev->IrqProcRegisters.cpu_int_status &
+ pDev->IrqEnableRegisters.cpu_int_status_enable;
+ A_ASSERT(cpu_int_status);
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
+ cpu_int_status));
+
+ /* Clear the interrupt */
+ pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */
+
+ /* set up the register transfer buffer to hit the register 4 times , this is done
+ * to make the access 4-byte aligned to mitigate issues with host bus interconnects that
+ * restrict bus transfer lengths to be a multiple of 4-bytes */
+
+ /* set W1C value to clear the interrupt, this hits the register first */
+ regBuffer[0] = cpu_int_status;
+ /* the remaining 4 values are set to zero which have no-effect */
+ regBuffer[1] = 0;
+ regBuffer[2] = 0;
+ regBuffer[3] = 0;
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ CPU_INT_STATUS_ADDRESS,
+ regBuffer,
+ 4,
+ HIF_WR_SYNC_BYTE_FIX,
+ NULL);
+
+ A_ASSERT(status == A_OK);
+ return status;
+}
+
+
+static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
+{
+ A_STATUS status;
+ A_UINT8 error_int_status;
+ A_UINT8 regBuffer[4];
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
+ error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F;
+ A_ASSERT(error_int_status);
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n",
+ error_int_status));
+
+ if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) {
+ /* Wakeup */
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n"));
+ }
+
+ if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) {
+ /* Rx Underflow */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n"));
+ }
+
+ if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) {
+ /* Tx Overflow */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n"));
+ }
+
+ /* Clear the interrupt */
+ pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */
+
+ /* set up the register transfer buffer to hit the register 4 times , this is done
+ * to make the access 4-byte aligned to mitigate issues with host bus interconnects that
+ * restrict bus transfer lengths to be a multiple of 4-bytes */
+
+ /* set W1C value to clear the interrupt, this hits the register first */
+ regBuffer[0] = error_int_status;
+ /* the remaining 4 values are set to zero which have no-effect */
+ regBuffer[1] = 0;
+ regBuffer[2] = 0;
+ regBuffer[3] = 0;
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ ERROR_INT_STATUS_ADDRESS,
+ regBuffer,
+ 4,
+ HIF_WR_SYNC_BYTE_FIX,
+ NULL);
+
+ A_ASSERT(status == A_OK);
+ return status;
+}
+
+static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
+{
+ A_UINT32 dummy;
+ A_STATUS status;
+
+ /* Send a target failure event to the application */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
+
+ if (pDev->TargetFailureCallback != NULL) {
+ pDev->TargetFailureCallback(pDev->HTCContext);
+ }
+
+ if (pDev->GMboxEnabled) {
+ DevNotifyGMboxTargetFailure(pDev);
+ }
+
+ /* clear the interrupt , the debug error interrupt is
+ * counter 0 */
+ /* read counter to clear interrupt */
+ status = HIFReadWrite(pDev->HIFDevice,
+ COUNT_DEC_ADDRESS,
+ (A_UINT8 *)&dummy,
+ 4,
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+
+ A_ASSERT(status == A_OK);
+ return status;
+}
+
+static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
+{
+ A_UINT8 counter_int_status;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
+
+ counter_int_status = pDev->IrqProcRegisters.counter_int_status &
+ pDev->IrqEnableRegisters.counter_int_status_enable;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
+ counter_int_status));
+
+ /* Check if the debug interrupt is pending
+ * NOTE: other modules like GMBOX may use the counter interrupt for
+ * credit flow control on other counters, we only need to check for the debug assertion
+ * counter interrupt */
+ if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
+ return DevServiceDebugInterrupt(pDev);
+ }
+
+ return A_OK;
+}
+
+/* callback when our fetch to get interrupt status registers completes */
+static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+ A_UINT32 lookAhead = 0;
+ A_BOOL otherInts = FALSE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ do {
+
+ if (A_FAILED(pPacket->Status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" GetEvents I/O request failed, status:%d \n", pPacket->Status));
+ /* bail out, don't unmask HIF interrupt */
+ break;
+ }
+
+ if (pDev->GetPendingEventsFunc != NULL) {
+ /* the HIF layer collected the information for us */
+ HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacket->pBuffer;
+ if (pEvents->Events & HIF_RECV_MSG_AVAIL) {
+ lookAhead = pEvents->LookAhead;
+ if (0 == lookAhead) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n"));
+ }
+ }
+ if (pEvents->Events & HIF_OTHER_EVENTS) {
+ otherInts = TRUE;
+ }
+ } else {
+ /* standard interrupt table handling.... */
+ AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer;
+ A_UINT8 host_int_status;
+
+ host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable;
+
+ if (host_int_status & (1 << HTC_MAILBOX)) {
+ host_int_status &= ~(1 << HTC_MAILBOX);
+ if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) {
+ /* mailbox has a message and the look ahead is valid */
+ lookAhead = pReg->rx_lookahead[HTC_MAILBOX];
+ if (0 == lookAhead) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n"));
+ }
+ }
+ }
+
+ if (host_int_status) {
+ /* there are other interrupts to handle */
+ otherInts = TRUE;
+ }
+ }
+
+ if (otherInts || (lookAhead == 0)) {
+ /* if there are other interrupts to process, we cannot do this in the async handler so
+ * ack the interrupt which will cause our sync handler to run again
+ * if however there are no more messages, we can now ack the interrupt */
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n",
+ otherInts, lookAhead));
+ HIFAckInterrupt(pDev->HIFDevice);
+ } else {
+ int fetched = 0;
+ A_STATUS status;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n",
+ lookAhead));
+ /* lookahead is non-zero and there are no other interrupts to service,
+ * go get the next message */
+ status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched);
+
+ if (A_SUCCESS(status) && !fetched) {
+ /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n"));
+ DevAsyncIrqProcessComplete(pDev);
+ }
+ }
+
+ } while (FALSE);
+
+ /* free this IO packet */
+ AR6KFreeIOPacket(pDev,pPacket);
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n"));
+}
+
+/* called by the HTC layer when it wants us to check if the device has any more pending
+ * recv messages, this starts off a series of async requests to read interrupt registers */
+A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
+ A_STATUS status = A_OK;
+ HTC_PACKET *pIOPacket;
+
+ /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can
+ * cause us to switch contexts */
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ do {
+
+ if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
+ /* break the async processing chain right here, no need to continue.
+ * The DevDsrHandler() will handle things in a loop when things are driven
+ * synchronously */
+ break;
+ }
+
+ /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake
+ * the target, if upper layers determine that we are in a low-throughput mode, we can
+ * rely on taking another interrupt rather than re-checking the status registers which can
+ * re-wake the target */
+ if (pDev->RecheckIRQStatusCnt == 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, re-acking HIF interrupts\n"));
+ /* ack interrupt */
+ HIFAckInterrupt(pDev->HIFDevice);
+ break;
+ }
+
+ /* first allocate one of our HTC packets we created for async I/O
+ * we reuse HTC packet definitions so that we can use the completion mechanism
+ * in DevRWCompletionHandler() */
+ pIOPacket = AR6KAllocIOPacket(pDev);
+
+ if (NULL == pIOPacket) {
+ /* there should be only 1 asynchronous request out at a time to read these registers
+ * so this should actually never happen */
+ status = A_NO_MEMORY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevGetEventAsyncHandler;
+ pIOPacket->pContext = pDev;
+
+ if (pDev->GetPendingEventsFunc) {
+ /* HIF layer has it's own mechanism, pass the IO to it.. */
+ status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
+ (HIF_PENDING_EVENTS_INFO *)pIOPacket->pBuffer,
+ pIOPacket);
+
+ } else {
+ /* standard way, read the interrupt register table asynchronously again */
+ status = HIFReadWrite(pDev->HIFDevice,
+ HOST_INT_STATUS_ADDRESS,
+ pIOPacket->pBuffer,
+ AR6K_IRQ_PROC_REGS_SIZE,
+ HIF_RD_ASYNC_BYTE_INC,
+ pIOPacket);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n"));
+ } while (FALSE);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
+
+ return status;
+}
+
+void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev)
+{
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n"));
+ HIFAckInterrupt(pDev->HIFDevice);
+}
+
+/* process pending interrupts synchronously */
+static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pASyncProcessing)
+{
+ A_STATUS status = A_OK;
+ A_UINT8 host_int_status = 0;
+ A_UINT32 lookAhead = 0;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ /*** NOTE: the HIF implementation guarantees that the context of this call allows
+ * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that
+ * can block or switch thread/task ontexts.
+ * This is a fully schedulable context.
+ * */
+ do {
+
+ if (pDev->IrqEnableRegisters.int_status_enable == 0) {
+ /* interrupt enables have been cleared, do not try to process any pending interrupts that
+ * may result in more bus transactions. The target may be unresponsive at this
+ * point. */
+ break;
+ }
+
+ if (pDev->GetPendingEventsFunc != NULL) {
+ HIF_PENDING_EVENTS_INFO events;
+
+#ifdef THREAD_X
+ events.Polling= 0;
+#endif
+ /* the HIF layer uses a special mechanism to get events
+ * get this synchronously */
+ status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
+ &events,
+ NULL);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (events.Events & HIF_RECV_MSG_AVAIL) {
+ lookAhead = events.LookAhead;
+ if (0 == lookAhead) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhead is zero! \n"));
+ }
+ }
+
+ if (!(events.Events & HIF_OTHER_EVENTS) ||
+ !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLED)) {
+ /* no need to read the register table, no other interesting interrupts.
+ * Some interfaces (like SPI) can shadow interrupt sources without
+ * requiring the host to do a full table read */
+ break;
+ }
+
+ /* otherwise fall through and read the register table */
+ }
+
+ /*
+ * Read the first 28 bytes of the HTC register table. This will yield us
+ * the value of different int status registers and the lookahead
+ * registers.
+ * length = sizeof(int_status) + sizeof(cpu_int_status) +
+ * sizeof(error_int_status) + sizeof(counter_int_status) +
+ * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) +
+ * sizeof(hole) + sizeof(rx_lookahead) +
+ * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) +
+ * sizeof(error_status_enable) +
+ * sizeof(counter_int_status_enable);
+ *
+ */
+#ifdef CONFIG_MMC_SDHCI_S3C
+ pDev->IrqProcRegisters.host_int_status = 0;
+ pDev->IrqProcRegisters.rx_lookahead_valid = 0;
+ pDev->IrqProcRegisters.host_int_status2 = 0;
+ pDev->IrqProcRegisters.rx_lookahead[0] = 0;
+ pDev->IrqProcRegisters.rx_lookahead[1] = 0xaaa5555;
+#endif /* CONFIG_MMC_SDHCI_S3C */
+ status = HIFReadWrite(pDev->HIFDevice,
+ HOST_INT_STATUS_ADDRESS,
+ (A_UINT8 *)&pDev->IrqProcRegisters,
+ AR6K_IRQ_PROC_REGS_SIZE,
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+#ifdef ATH_DEBUG_MODULE
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
+ DevDumpRegisters(pDev,
+ &pDev->IrqProcRegisters,
+ &pDev->IrqEnableRegisters);
+ }
+#endif
+
+ /* Update only those registers that are enabled */
+ host_int_status = pDev->IrqProcRegisters.host_int_status &
+ pDev->IrqEnableRegisters.int_status_enable;
+
+ if (NULL == pDev->GetPendingEventsFunc) {
+ /* only look at mailbox status if the HIF layer did not provide this function,
+ * on some HIF interfaces reading the RX lookahead is not valid to do */
+ if (host_int_status & (1 << HTC_MAILBOX)) {
+ /* mask out pending mailbox value, we use "lookAhead" as the real flag for
+ * mailbox processing below */
+ host_int_status &= ~(1 << HTC_MAILBOX);
+ if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) {
+ /* mailbox has a message and the look ahead is valid */
+ lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
+ if (0 == lookAhead) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lookAhead is zero! \n"));
+ }
+ }
+ }
+ } else {
+ /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/
+ host_int_status &= ~(1 << HTC_MAILBOX);
+ }
+
+ if (pDev->GMboxEnabled) {
+ /*call GMBOX layer to process any interrupts of interest */
+ status = DevCheckGMboxInterrupts(pDev);
+ }
+
+ } while (FALSE);
+
+
+ do {
+
+ /* did the interrupt status fetches succeed? */
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if ((0 == host_int_status) && (0 == lookAhead)) {
+ /* nothing to process, the caller can use this to break out of a loop */
+ *pDone = TRUE;
+ break;
+ }
+
+ if (lookAhead != 0) {
+ int fetched = 0;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead));
+ /* Mailbox Interrupt, the HTC layer may issue async requests to empty the
+ * mailbox...
+ * When emptying the recv mailbox we use the async handler above called from the
+ * completion routine of the callers read request. This can improve performance
+ * by reducing context switching when we rapidly pull packets */
+ status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (!fetched) {
+ /* HTC could not pull any messages out due to lack of resources */
+ /* force DSR handler to ack the interrupt */
+ *pASyncProcessing = FALSE;
+ pDev->RecheckIRQStatusCnt = 0;
+ }
+ }
+
+ /* now handle the rest of them */
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n",
+ host_int_status));
+
+ if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
+ /* CPU Interrupt */
+ status = DevServiceCPUInterrupt(pDev);
+ if (A_FAILED(status)){
+ break;
+ }
+ }
+
+ if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
+ /* Error Interrupt */
+ status = DevServiceErrorInterrupt(pDev);
+ if (A_FAILED(status)){
+ break;
+ }
+ }
+
+ if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
+ /* Counter Interrupt */
+ status = DevServiceCounterInterrupt(pDev);
+ if (A_FAILED(status)){
+ break;
+ }
+ }
+
+ } while (FALSE);
+
+ /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake
+ * the target, if upper layers determine that we are in a low-throughput mode, we can
+ * rely on taking another interrupt rather than re-checking the status registers which can
+ * re-wake the target.
+ *
+ * NOTE : for host interfaces that use the special GetPendingEventsFunc, this optimization cannot
+ * be used due to possible side-effects. For example, SPI requires the host to drain all
+ * messages from the mailbox before exiting the ISR routine. */
+ if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPendingEventsFunc == NULL)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing done \n"));
+ *pDone = TRUE;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n",
+ *pDone, *pASyncProcessing, status));
+
+ return status;
+}
+
+
+/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/
+A_STATUS DevDsrHandler(void *context)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
+ A_STATUS status = A_OK;
+ A_BOOL done = FALSE;
+ A_BOOL asyncProc = FALSE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ /* reset the recv counter that tracks when we need to yield from the DSR */
+ pDev->CurrentDSRRecvCount = 0;
+ /* reset counter used to flag a re-scan of IRQ status registers on the target */
+ pDev->RecheckIRQStatusCnt = 0;
+
+ while (!done) {
+ status = ProcessPendingIRQs(pDev, &done, &asyncProc);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
+ /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */
+ asyncProc = FALSE;
+ /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers.
+ * this has a nice side effect of blocking us until all async read requests are completed.
+ * This behavior is required on some HIF implementations that do not allow ASYNC
+ * processing in interrupt handlers (like Windows CE) */
+
+ if (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) {
+ /* ProcessPendingIRQs() pulled enough recv messages to satisfy the yield count, stop
+ * checking for more messages and return */
+ break;
+ }
+ }
+
+ if (asyncProc) {
+ /* the function performed some async I/O for performance, we
+ need to exit the ISR immediately, the check below will prevent the interrupt from being
+ Ack'd while we handle it asynchronously */
+ break;
+ }
+
+ }
+
+ if (A_SUCCESS(status) && !asyncProc) {
+ /* Ack the interrupt only if :
+ * 1. we did not get any errors in processing interrupts
+ * 2. there are no outstanding async processing requests */
+ if (pDev->DSRCanYield) {
+ /* if the DSR can yield do not ACK the interrupt, there could be more pending messages.
+ * The HIF layer must ACK the interrupt on behalf of HTC */
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n"));
+ HIFAckInterrupt(pDev->HIFDevice);
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n"));
+ return status;
+}
+
+#ifdef ATH_DEBUG_MODULE
+void DumpAR6KDevState(AR6K_DEVICE *pDev)
+{
+ A_STATUS status;
+ AR6K_IRQ_ENABLE_REGISTERS regs;
+ AR6K_IRQ_PROC_REGISTERS procRegs;
+
+ LOCK_AR6K(pDev);
+ /* copy into our temp area */
+ A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+ UNLOCK_AR6K(pDev);
+
+ /* load the register table from the device */
+ status = HIFReadWrite(pDev->HIFDevice,
+ HOST_INT_STATUS_ADDRESS,
+ (A_UINT8 *)&procRegs,
+ AR6K_IRQ_PROC_REGS_SIZE,
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("DumpAR6KDevState : Failed to read register table (%d) \n",status));
+ return;
+ }
+
+ DevDumpRegisters(pDev,&procRegs,&regs);
+
+ if (pDev->GMboxInfo.pStateDumpCallback != NULL) {
+ pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext);
+ }
+
+ /* dump any bus state at the HIF layer */
+ HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0);
+
+}
+#endif
+
+
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
new file mode 100644
index 00000000000..e3d270d1d62
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
@@ -0,0 +1,756 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6k_gmbox.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Generic MBOX API implementation
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "a_osapi.h"
+#include "../htc_debug.h"
+#include "hif.h"
+#include "htc_packet.h"
+#include "ar6k.h"
+#include "hw/mbox_host_reg.h"
+#include "gmboxif.h"
+
+/*
+ * This file provides management functions and a toolbox for GMBOX protocol modules.
+ * Only one protocol module can be installed at a time. The determination of which protocol
+ * module is installed is determined at compile time.
+ *
+ */
+#ifdef ATH_AR6K_ENABLE_GMBOX
+ /* GMBOX definitions */
+#define GMBOX_INT_STATUS_ENABLE_REG 0x488
+#define GMBOX_INT_STATUS_RX_DATA (1 << 0)
+#define GMBOX_INT_STATUS_TX_OVERFLOW (1 << 1)
+#define GMBOX_INT_STATUS_RX_OVERFLOW (1 << 2)
+
+#define GMBOX_LOOKAHEAD_MUX_REG 0x498
+#define GMBOX_LA_MUX_OVERRIDE_2_3 (1 << 0)
+
+#define AR6K_GMBOX_CREDIT_DEC_ADDRESS (COUNT_DEC_ADDRESS + 4 * AR6K_GMBOX_CREDIT_COUNTER)
+#define AR6K_GMBOX_CREDIT_SIZE_ADDRESS (COUNT_ADDRESS + AR6K_GMBOX_CREDIT_SIZE_COUNTER)
+
+
+ /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */
+extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
+extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
+
+
+/* callback when our fetch to enable/disable completes */
+static void DevGMboxIRQActionAsyncHandler(void *Context, HTC_PACKET *pPacket)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ if (A_FAILED(pPacket->Status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status));
+ }
+ /* free this IO packet */
+ AR6KFreeIOPacket(pDev,pPacket);
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n"));
+}
+
+static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
+{
+ A_STATUS status = A_OK;
+ AR6K_IRQ_ENABLE_REGISTERS regs;
+ HTC_PACKET *pIOPacket = NULL;
+
+ LOCK_AR6K(pDev);
+
+ if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
+ pDev->GMboxInfo.CreditCountIRQEnabled = TRUE;
+ pDev->IrqEnableRegisters.counter_int_status_enable |=
+ COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER);
+ pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01);
+ } else {
+ pDev->GMboxInfo.CreditCountIRQEnabled = FALSE;
+ pDev->IrqEnableRegisters.counter_int_status_enable &=
+ ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER));
+ }
+ /* copy into our temp area */
+ A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+
+ UNLOCK_AR6K(pDev);
+
+ do {
+
+ if (AsyncMode) {
+
+ pIOPacket = AR6KAllocIOPacket(pDev);
+
+ if (NULL == pIOPacket) {
+ status = A_NO_MEMORY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* copy values to write to our async I/O buffer */
+ A_MEMCPY(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
+ pIOPacket->pContext = pDev;
+ pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction;
+ /* write it out asynchronously */
+ HIFReadWrite(pDev->HIFDevice,
+ INT_STATUS_ENABLE_ADDRESS,
+ pIOPacket->pBuffer,
+ AR6K_IRQ_ENABLE_REGS_SIZE,
+ HIF_WR_ASYNC_BYTE_INC,
+ pIOPacket);
+
+ pIOPacket = NULL;
+ break;
+ }
+
+ /* if we get here we are doing it synchronously */
+ status = HIFReadWrite(pDev->HIFDevice,
+ INT_STATUS_ENABLE_ADDRESS,
+ &regs.int_status_enable,
+ AR6K_IRQ_ENABLE_REGS_SIZE,
+ HIF_WR_SYNC_BYTE_INC,
+ NULL);
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));
+ } else {
+ if (!AsyncMode) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ (" IRQAction Operation (%d) success \n", IrqAction));
+ }
+ }
+
+ if (pIOPacket != NULL) {
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+
+ return status;
+}
+
+
+A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
+{
+ A_STATUS status = A_OK;
+ HTC_PACKET *pIOPacket = NULL;
+ A_UINT8 GMboxIntControl[4];
+
+ if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
+ return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode);
+ } else if(GMBOX_CREDIT_IRQ_DISABLE == IrqAction) {
+ return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode);
+ }
+
+ if (GMBOX_DISABLE_ALL == IrqAction) {
+ /* disable credit IRQ, those are on a different set of registers */
+ DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_DISABLE, AsyncMode);
+ }
+
+ /* take the lock to protect interrupt enable shadows */
+ LOCK_AR6K(pDev);
+
+ switch (IrqAction) {
+
+ case GMBOX_DISABLE_ALL:
+ pDev->GMboxControlRegisters.int_status_enable = 0;
+ break;
+ case GMBOX_ERRORS_IRQ_ENABLE:
+ pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_TX_OVERFLOW |
+ GMBOX_INT_STATUS_RX_OVERFLOW;
+ break;
+ case GMBOX_RECV_IRQ_ENABLE:
+ pDev->GMboxControlRegisters.int_status_enable |= GMBOX_INT_STATUS_RX_DATA;
+ break;
+ case GMBOX_RECV_IRQ_DISABLE:
+ pDev->GMboxControlRegisters.int_status_enable &= ~GMBOX_INT_STATUS_RX_DATA;
+ break;
+ case GMBOX_ACTION_NONE:
+ default:
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ GMboxIntControl[0] = pDev->GMboxControlRegisters.int_status_enable;
+ GMboxIntControl[1] = GMboxIntControl[0];
+ GMboxIntControl[2] = GMboxIntControl[0];
+ GMboxIntControl[3] = GMboxIntControl[0];
+
+ UNLOCK_AR6K(pDev);
+
+ do {
+
+ if (AsyncMode) {
+
+ pIOPacket = AR6KAllocIOPacket(pDev);
+
+ if (NULL == pIOPacket) {
+ status = A_NO_MEMORY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* copy values to write to our async I/O buffer */
+ A_MEMCPY(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
+
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
+ pIOPacket->pContext = pDev;
+ pIOPacket->PktInfo.AsRx.HTCRxFlags = IrqAction;
+ /* write it out asynchronously */
+ HIFReadWrite(pDev->HIFDevice,
+ GMBOX_INT_STATUS_ENABLE_REG,
+ pIOPacket->pBuffer,
+ sizeof(GMboxIntControl),
+ HIF_WR_ASYNC_BYTE_FIX,
+ pIOPacket);
+ pIOPacket = NULL;
+ break;
+ }
+
+ /* if we get here we are doing it synchronously */
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ GMBOX_INT_STATUS_ENABLE_REG,
+ GMboxIntControl,
+ sizeof(GMboxIntControl),
+ HIF_WR_SYNC_BYTE_FIX,
+ NULL);
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));
+ } else {
+ if (!AsyncMode) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+ (" IRQAction Operation (%d) success \n", IrqAction));
+ }
+ }
+
+ if (pIOPacket != NULL) {
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+
+ return status;
+}
+
+void DevCleanupGMbox(AR6K_DEVICE *pDev)
+{
+ if (pDev->GMboxEnabled) {
+ pDev->GMboxEnabled = FALSE;
+ GMboxProtocolUninstall(pDev);
+ }
+}
+
+A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev)
+{
+ A_STATUS status = A_OK;
+ A_UINT8 muxControl[4];
+
+ do {
+
+ if (0 == pDev->MailBoxInfo.GMboxAddress) {
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" GMBOX Advertised: Address:0x%X , size:%d \n",
+ pDev->MailBoxInfo.GMboxAddress, pDev->MailBoxInfo.GMboxSize));
+
+ status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ /* write to mailbox look ahead mux control register, we want the
+ * GMBOX lookaheads to appear on lookaheads 2 and 3
+ * the register is 1-byte wide so we need to hit it 4 times to align the operation
+ * to 4-bytes */
+ muxControl[0] = GMBOX_LA_MUX_OVERRIDE_2_3;
+ muxControl[1] = GMBOX_LA_MUX_OVERRIDE_2_3;
+ muxControl[2] = GMBOX_LA_MUX_OVERRIDE_2_3;
+ muxControl[3] = GMBOX_LA_MUX_OVERRIDE_2_3;
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ GMBOX_LOOKAHEAD_MUX_REG,
+ muxControl,
+ sizeof(muxControl),
+ HIF_WR_SYNC_BYTE_FIX, /* hit this register 4 times */
+ NULL);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ status = GMboxProtocolInstall(pDev);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ pDev->GMboxEnabled = TRUE;
+
+ } while (FALSE);
+
+ return status;
+}
+
+A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
+{
+ A_STATUS status = A_OK;
+ A_UINT8 counter_int_status;
+ int credits;
+ A_UINT8 host_int_status2;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n"));
+
+ /* the caller guarantees that this is a context that allows for blocking I/O */
+
+ do {
+
+ host_int_status2 = pDev->IrqProcRegisters.host_int_status2 &
+ pDev->GMboxControlRegisters.int_status_enable;
+
+ if (host_int_status2 & GMBOX_INT_STATUS_TX_OVERFLOW) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : TX Overflow \n"));
+ status = A_ECOMM;
+ }
+
+ if (host_int_status2 & GMBOX_INT_STATUS_RX_OVERFLOW) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("GMBOX : RX Overflow \n"));
+ status = A_ECOMM;
+ }
+
+ if (A_FAILED(status)) {
+ if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
+ pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status);
+ }
+ break;
+ }
+
+ if (host_int_status2 & GMBOX_INT_STATUS_RX_DATA) {
+ if (pDev->IrqProcRegisters.gmbox_rx_avail > 0) {
+ A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL);
+ status = pDev->GMboxInfo.pMessagePendingCallBack(
+ pDev->GMboxInfo.pProtocolContext,
+ (A_UINT8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
+ pDev->IrqProcRegisters.gmbox_rx_avail);
+ }
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ counter_int_status = pDev->IrqProcRegisters.counter_int_status &
+ pDev->IrqEnableRegisters.counter_int_status_enable;
+
+ /* check if credit interrupt is pending */
+ if (counter_int_status & (COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER))) {
+
+ /* do synchronous read */
+ status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ A_ASSERT(pDev->GMboxInfo.pCreditsPendingCallback != NULL);
+ status = pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext,
+ credits,
+ pDev->GMboxInfo.CreditCountIRQEnabled);
+ }
+
+ } while (FALSE);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status));
+
+ return status;
+}
+
+
+A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength)
+{
+ A_UINT32 paddedLength;
+ A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+ A_STATUS status;
+ A_UINT32 address;
+
+ /* adjust the length to be a multiple of block size if appropriate */
+ paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ ("DevGMboxWrite, Padded Length: %d Mbox:0x%X (mode:%s)\n",
+ WriteLength,
+ pDev->MailBoxInfo.GMboxAddress,
+ sync ? "SYNC" : "ASYNC"));
+
+ /* last byte of packet has to hit the EOM marker */
+ address = pDev->MailBoxInfo.GMboxAddress + pDev->MailBoxInfo.GMboxSize - paddedLength;
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ address,
+ pPacket->pBuffer,
+ paddedLength, /* the padded length */
+ sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
+ sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
+
+ if (sync) {
+ pPacket->Status = status;
+ } else {
+ if (status == A_PENDING) {
+ status = A_OK;
+ }
+ }
+
+ return status;
+}
+
+A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength)
+{
+
+ A_UINT32 paddedLength;
+ A_STATUS status;
+ A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+
+ /* adjust the length to be a multiple of block size if appropriate */
+ paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength);
+
+ if (paddedLength > pPacket->BufferLength) {
+ A_ASSERT(FALSE);
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
+ paddedLength,ReadLength,pPacket->BufferLength));
+ if (pPacket->Completion != NULL) {
+ COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
+ return A_OK;
+ }
+ return A_EINVAL;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("DevGMboxRead (0x%lX : hdr:0x%X) Padded Length: %d Mbox:0x%X (mode:%s)\n",
+ (unsigned long)pPacket, pPacket->PktInfo.AsRx.ExpectedHdr,
+ paddedLength,
+ pDev->MailBoxInfo.GMboxAddress,
+ sync ? "SYNC" : "ASYNC"));
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ pDev->MailBoxInfo.GMboxAddress,
+ pPacket->pBuffer,
+ paddedLength,
+ sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX,
+ sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
+
+ if (sync) {
+ pPacket->Status = status;
+ }
+
+ return status;
+}
+
+
+static int ProcessCreditCounterReadBuffer(A_UINT8 *pBuffer, int Length)
+{
+ int credits = 0;
+
+ /* theory of how this works:
+ * We read the credit decrement register multiple times on a byte-wide basis.
+ * The number of times (32) aligns the I/O operation to be a multiple of 4 bytes and provides a
+ * reasonable chance to acquire "all" pending credits in a single I/O operation.
+ *
+ * Once we obtain the filled buffer, we can walk through it looking for credit decrement transitions.
+ * Each non-zero byte represents a single credit decrement (which is a credit given back to the host)
+ * For example if the target provides 3 credits and added 4 more during the 32-byte read operation the following
+ * pattern "could" appear:
+ *
+ * 0x3 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 ......rest zeros
+ * <---------> <----------------------------->
+ * \_ credits aleady there \_ target adding 4 more credits
+ *
+ * The total available credits would be 7, since there are 7 non-zero bytes in the buffer.
+ *
+ * */
+
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+ DebugDumpBytes(pBuffer, Length, "GMBOX Credit read buffer");
+ }
+
+ while (Length) {
+ if (*pBuffer != 0) {
+ credits++;
+ }
+ Length--;
+ pBuffer++;
+ }
+
+ return credits;
+}
+
+
+/* callback when our fetch to enable/disable completes */
+static void DevGMboxReadCreditsAsyncHandler(void *Context, HTC_PACKET *pPacket)
+{
+ AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
+
+ if (A_FAILED(pPacket->Status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Read Credit Operation failed! status:%d \n", pPacket->Status));
+ } else {
+ int credits = 0;
+ credits = ProcessCreditCounterReadBuffer(pPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);
+ pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext,
+ credits,
+ pDev->GMboxInfo.CreditCountIRQEnabled);
+
+
+ }
+ /* free this IO packet */
+ AR6KFreeIOPacket(pDev,pPacket);
+ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n"));
+}
+
+A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits)
+{
+ A_STATUS status = A_OK;
+ HTC_PACKET *pIOPacket = NULL;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC"));
+
+ do {
+
+ pIOPacket = AR6KAllocIOPacket(pDev);
+
+ if (NULL == pIOPacket) {
+ status = A_NO_MEMORY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ A_MEMZERO(pIOPacket->pBuffer,AR6K_REG_IO_BUFFER_SIZE);
+
+ if (AsyncMode) {
+ /* stick in our completion routine when the I/O operation completes */
+ pIOPacket->Completion = DevGMboxReadCreditsAsyncHandler;
+ pIOPacket->pContext = pDev;
+ /* read registers asynchronously */
+ HIFReadWrite(pDev->HIFDevice,
+ AR6K_GMBOX_CREDIT_DEC_ADDRESS,
+ pIOPacket->pBuffer,
+ AR6K_REG_IO_BUFFER_SIZE, /* hit the register multiple times */
+ HIF_RD_ASYNC_BYTE_FIX,
+ pIOPacket);
+ pIOPacket = NULL;
+ break;
+ }
+
+ pIOPacket->Completion = NULL;
+ /* if we get here we are doing it synchronously */
+ status = HIFReadWrite(pDev->HIFDevice,
+ AR6K_GMBOX_CREDIT_DEC_ADDRESS,
+ pIOPacket->pBuffer,
+ AR6K_REG_IO_BUFFER_SIZE,
+ HIF_RD_SYNC_BYTE_FIX,
+ NULL);
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" DevGMboxReadCreditCounter failed! status:%d \n", status));
+ }
+
+ if (pIOPacket != NULL) {
+ if (A_SUCCESS(status)) {
+ /* sync mode processing */
+ *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);
+ }
+ AR6KFreeIOPacket(pDev,pIOPacket);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-DevGMboxReadCreditCounter (%s) (%d) \n",
+ AsyncMode ? "ASYNC" : "SYNC", status));
+
+ return status;
+}
+
+A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize)
+{
+ A_STATUS status;
+ A_UINT8 buffer[4];
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ AR6K_GMBOX_CREDIT_SIZE_ADDRESS,
+ buffer,
+ sizeof(buffer),
+ HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
+ NULL);
+
+ if (A_SUCCESS(status)) {
+ if (buffer[0] == 0) {
+ *pCreditSize = 256;
+ } else {
+ *pCreditSize = buffer[0];
+ }
+
+ }
+
+ return status;
+}
+
+void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev)
+{
+ /* Target ASSERTED!!! */
+ if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
+ pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, A_HARDWARE);
+ }
+}
+
+A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes)
+{
+
+ A_STATUS status = A_OK;
+ AR6K_IRQ_PROC_REGISTERS procRegs;
+ int maxCopy;
+
+ do {
+ /* on entry the caller provides the length of the lookahead buffer */
+ if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) {
+ A_ASSERT(FALSE);
+ status = A_EINVAL;
+ break;
+ }
+
+ maxCopy = *pLookAheadBytes;
+ *pLookAheadBytes = 0;
+ /* load the register table from the device */
+ status = HIFReadWrite(pDev->HIFDevice,
+ HOST_INT_STATUS_ADDRESS,
+ (A_UINT8 *)&procRegs,
+ AR6K_IRQ_PROC_REGS_SIZE,
+ HIF_RD_SYNC_BYTE_INC,
+ NULL);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status));
+ break;
+ }
+
+ if (procRegs.gmbox_rx_avail > 0) {
+ int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail;
+ A_MEMCPY(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
+ *pLookAheadBytes = bytes;
+ }
+
+ } while (FALSE);
+
+ return status;
+}
+
+A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeoutMS)
+{
+ A_STATUS status = A_OK;
+ int i;
+ A_UINT8 buffer[4];
+
+ A_MEMZERO(buffer, sizeof(buffer));
+
+ do {
+
+ if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) {
+ status = A_EINVAL;
+ break;
+ }
+
+ /* set the last buffer to do the actual signal trigger */
+ buffer[3] = (1 << Signal);
+
+ status = HIFReadWrite(pDev->HIFDevice,
+ INT_WLAN_ADDRESS,
+ buffer,
+ sizeof(buffer),
+ HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
+ NULL);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ } while (FALSE);
+
+
+ if (A_SUCCESS(status)) {
+ /* now read back the register to see if the bit cleared */
+ while (AckTimeoutMS) {
+ status = HIFReadWrite(pDev->HIFDevice,
+ INT_WLAN_ADDRESS,
+ buffer,
+ sizeof(buffer),
+ HIF_RD_SYNC_BYTE_FIX,
+ NULL);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ for (i = 0; i < sizeof(buffer); i++) {
+ if (buffer[i] & (1 << Signal)) {
+ /* bit is still set */
+ break;
+ }
+ }
+
+ if (i >= sizeof(buffer)) {
+ /* done */
+ break;
+ }
+
+ AckTimeoutMS--;
+ A_MDELAY(1);
+ }
+
+ if (0 == AckTimeoutMS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal));
+ status = A_ERROR;
+ }
+ }
+
+ return status;
+
+}
+
+#endif //ATH_AR6K_ENABLE_GMBOX
+
+
+
+
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
new file mode 100644
index 00000000000..db6d30c113b
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
@@ -0,0 +1,1280 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6k_prot_hciUart.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Protocol module for use in bridging HCI-UART packets over the GMBOX interface
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "a_osapi.h"
+#include "../htc_debug.h"
+#include "hif.h"
+#include "htc_packet.h"
+#include "ar6k.h"
+#include "hci_transport_api.h"
+#include "gmboxif.h"
+#include "ar6000_diag.h"
+#include "hw/apb_map.h"
+#include "hw/mbox_reg.h"
+
+#ifdef ATH_AR6K_ENABLE_GMBOX
+#define HCI_UART_COMMAND_PKT 0x01
+#define HCI_UART_ACL_PKT 0x02
+#define HCI_UART_SCO_PKT 0x03
+#define HCI_UART_EVENT_PKT 0x04
+
+#define HCI_RECV_WAIT_BUFFERS (1 << 0)
+
+#define HCI_SEND_WAIT_CREDITS (1 << 0)
+
+#define HCI_UART_BRIDGE_CREDIT_SIZE 128
+
+#define CREDIT_POLL_COUNT 256
+
+#define HCI_DELAY_PER_INTERVAL_MS 10
+#define BTON_TIMEOUT_MS 500
+#define BTOFF_TIMEOUT_MS 500
+#define BAUD_TIMEOUT_MS 1
+#define BTPWRSAV_TIMEOUT_MS 1
+
+typedef struct {
+ HCI_TRANSPORT_CONFIG_INFO HCIConfig;
+ A_BOOL HCIAttached;
+ A_BOOL HCIStopped;
+ A_UINT32 RecvStateFlags;
+ A_UINT32 SendStateFlags;
+ HCI_TRANSPORT_PACKET_TYPE WaitBufferType;
+ HTC_PACKET_QUEUE SendQueue; /* write queue holding HCI Command and ACL packets */
+ HTC_PACKET_QUEUE HCIACLRecvBuffers; /* recv queue holding buffers for incomming ACL packets */
+ HTC_PACKET_QUEUE HCIEventBuffers; /* recv queue holding buffers for incomming event packets */
+ AR6K_DEVICE *pDev;
+ A_MUTEX_T HCIRxLock;
+ A_MUTEX_T HCITxLock;
+ int CreditsMax;
+ int CreditsConsumed;
+ int CreditsAvailable;
+ int CreditSize;
+ int CreditsCurrentSeek;
+ int SendProcessCount;
+} GMBOX_PROTO_HCI_UART;
+
+#define LOCK_HCI_RX(t) A_MUTEX_LOCK(&(t)->HCIRxLock);
+#define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock);
+#define LOCK_HCI_TX(t) A_MUTEX_LOCK(&(t)->HCITxLock);
+#define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock);
+
+#define DO_HCI_RECV_INDICATION(p,pt) \
+{ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \
+ (unsigned long)(pt),(pt)->Status, A_SUCCESS((pt)->Status) ? (pt)->ActualLength : 0, HCI_GET_PACKET_TYPE(pt))); \
+ (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt)); \
+}
+
+#define DO_HCI_SEND_INDICATION(p,pt) \
+{ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n", \
+ (unsigned long)(pt),(pt)->Status,HCI_GET_PACKET_TYPE(pt))); \
+ (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt)); \
+}
+
+static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous);
+
+static void HCIUartCleanup(GMBOX_PROTO_HCI_UART *pProtocol)
+{
+ A_ASSERT(pProtocol != NULL);
+
+ A_MUTEX_DELETE(&pProtocol->HCIRxLock);
+ A_MUTEX_DELETE(&pProtocol->HCITxLock);
+
+ A_FREE(pProtocol);
+}
+
+static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
+{
+ A_STATUS status;
+ int credits;
+ int creditPollCount = CREDIT_POLL_COUNT;
+ A_BOOL gotCredits = FALSE;
+
+ pProt->CreditsConsumed = 0;
+
+ do {
+
+ if (pProt->CreditsMax != 0) {
+ /* we can only call this only once per target reset */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called! \n"));
+ A_ASSERT(FALSE);
+ status = A_EINVAL;
+ break;
+ }
+
+ /* read the credit counter. At startup the target will set the credit counter
+ * to the max available, we read this in a loop because it may take
+ * multiple credit counter reads to get all credits */
+
+ while (creditPollCount) {
+
+ credits = 0;
+
+ status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (!gotCredits && (0 == credits)) {
+ creditPollCount--;
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: credit is 0, retrying (%d) \n",creditPollCount));
+ A_MDELAY(HCI_DELAY_PER_INTERVAL_MS);
+ continue;
+ } else {
+ gotCredits = TRUE;
+ }
+
+ if (0 == credits) {
+ break;
+ }
+
+ pProt->CreditsMax += credits;
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (0 == creditPollCount) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("** HCI : Failed to get credits! GMBOX Target was not available \n"));
+ status = A_ERROR;
+ break;
+ }
+
+ /* now get the size */
+ status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ } while (FALSE);
+
+ if (A_SUCCESS(status)) {
+ pProt->CreditsAvailable = pProt->CreditsMax;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n",
+ pProt->CreditsAvailable, pProt->CreditSize));
+ }
+
+ return status;
+}
+
+static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL CreditIRQEnabled)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
+ A_BOOL enableCreditIrq = FALSE;
+ A_BOOL disableCreditIrq = FALSE;
+ A_BOOL doPendingSends = FALSE;
+ A_STATUS status = A_OK;
+
+ /** this callback is called under 2 conditions:
+ * 1. The credit IRQ interrupt was enabled and signaled.
+ * 2. A credit counter read completed.
+ *
+ * The function must not assume that the calling context can block !
+ */
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback (Credits:%d, IRQ:%s) \n",
+ Credits, CreditIRQEnabled ? "ON" : "OFF"));
+
+ LOCK_HCI_TX(pProt);
+
+ do {
+
+ if (0 == Credits) {
+ if (!CreditIRQEnabled) {
+ /* enable credit IRQ */
+ enableCreditIrq = TRUE;
+ }
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: current credit state, consumed:%d available:%d max:%d seek:%d\n",
+ pProt->CreditsConsumed,
+ pProt->CreditsAvailable,
+ pProt->CreditsMax,
+ pProt->CreditsCurrentSeek));
+
+ pProt->CreditsAvailable += Credits;
+ A_ASSERT(pProt->CreditsAvailable <= pProt->CreditsMax);
+ pProt->CreditsConsumed -= Credits;
+ A_ASSERT(pProt->CreditsConsumed >= 0);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state, consumed:%d available:%d max:%d seek:%d\n",
+ pProt->CreditsConsumed,
+ pProt->CreditsAvailable,
+ pProt->CreditsMax,
+ pProt->CreditsCurrentSeek));
+
+ if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
+ /* we have enough credits to fullfill at least 1 packet waiting in the queue */
+ pProt->CreditsCurrentSeek = 0;
+ pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS;
+ doPendingSends = TRUE;
+ if (CreditIRQEnabled) {
+ /* credit IRQ was enabled, we shouldn't need it anymore */
+ disableCreditIrq = TRUE;
+ }
+ } else {
+ /* not enough credits yet, enable credit IRQ if we haven't already */
+ if (!CreditIRQEnabled) {
+ enableCreditIrq = TRUE;
+ }
+ }
+
+ } while (FALSE);
+
+ UNLOCK_HCI_TX(pProt);
+
+ if (enableCreditIrq) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Enabling credit count IRQ...\n"));
+ /* must use async only */
+ status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_ENABLE, PROC_IO_ASYNC);
+ } else if (disableCreditIrq) {
+ /* must use async only */
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Disabling credit count IRQ...\n"));
+ status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_DISABLE, PROC_IO_ASYNC);
+ }
+
+ if (doPendingSends) {
+ HCITrySend(pProt, NULL, FALSE);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n"));
+ return status;
+}
+
+static INLINE void NotifyTransportFailure(GMBOX_PROTO_HCI_UART *pProt, A_STATUS status)
+{
+ if (pProt->HCIConfig.TransportFailure != NULL) {
+ pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status);
+ }
+}
+
+static void FailureCallback(void *pContext, A_STATUS Status)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
+
+ /* target assertion occured */
+ NotifyTransportFailure(pProt, Status);
+}
+
+static void StateDumpCallback(void *pContext)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n"));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags : 0x%X \n",pProt->RecvStateFlags));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendStateFlags : 0x%X \n",pProt->SendStateFlags));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("WaitBufferType : %d \n",pProt->WaitBufferType));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendQueue Depth : %d \n",HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsMax : %d \n",pProt->CreditsMax));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsConsumed : %d \n",pProt->CreditsConsumed));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsAvailable : %d \n",pProt->CreditsAvailable));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n"));
+}
+
+static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
+ A_STATUS status = A_OK;
+ int totalRecvLength = 0;
+ HCI_TRANSPORT_PACKET_TYPE pktType = HCI_PACKET_INVALID;
+ A_BOOL recvRefillCalled = FALSE;
+ A_BOOL blockRecv = FALSE;
+ HTC_PACKET *pPacket = NULL;
+
+ /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCIUartMessagePending Lookahead Bytes:%d \n",ValidBytes));
+
+ LOCK_HCI_RX(pProt);
+
+ do {
+
+ if (ValidBytes < 3) {
+ /* not enough for ACL or event header */
+ break;
+ }
+
+ if ((LookAheadBytes[0] == HCI_UART_ACL_PKT) && (ValidBytes < 5)) {
+ /* not enough for ACL data header */
+ break;
+ }
+
+ switch (LookAheadBytes[0]) {
+ case HCI_UART_EVENT_PKT:
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
+ LookAheadBytes[1], LookAheadBytes[2]));
+ totalRecvLength = LookAheadBytes[2];
+ totalRecvLength += 3; /* add type + event code + length field */
+ pktType = HCI_EVENT_TYPE;
+ break;
+ case HCI_UART_ACL_PKT:
+ totalRecvLength = (LookAheadBytes[4] << 8) | LookAheadBytes[3];
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI ACL: conn:0x%X length: %d \n",
+ ((LookAheadBytes[2] & 0xF0) << 8) | LookAheadBytes[1], totalRecvLength));
+ totalRecvLength += 5; /* add type + connection handle + length field */
+ pktType = HCI_ACL_TYPE;
+ break;
+ default:
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",LookAheadBytes[0]));
+ status = A_EPROTO;
+ break;
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (pProt->HCIConfig.pHCIPktRecvAlloc != NULL) {
+ UNLOCK_HCI_RX(pProt);
+ /* user is using a per-packet allocation callback */
+ pPacket = pProt->HCIConfig.pHCIPktRecvAlloc(pProt->HCIConfig.pContext,
+ pktType,
+ totalRecvLength);
+ LOCK_HCI_RX(pProt);
+
+ } else {
+ HTC_PACKET_QUEUE *pQueue;
+ /* user is using a refill handler that can refill multiple HTC buffers */
+
+ /* select buffer queue */
+ if (pktType == HCI_ACL_TYPE) {
+ pQueue = &pProt->HCIACLRecvBuffers;
+ } else {
+ pQueue = &pProt->HCIEventBuffers;
+ }
+
+ if (HTC_QUEUE_EMPTY(pQueue)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("** HCI pkt type: %d has no buffers available calling allocation handler \n",
+ pktType));
+ /* check for refill handler */
+ if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) {
+ recvRefillCalled = TRUE;
+ UNLOCK_HCI_RX(pProt);
+ /* call the re-fill handler */
+ pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
+ pktType,
+ 0);
+ LOCK_HCI_RX(pProt);
+ /* check if we have more buffers */
+ pPacket = HTC_PACKET_DEQUEUE(pQueue);
+ /* fall through */
+ }
+ } else {
+ pPacket = HTC_PACKET_DEQUEUE(pQueue);
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("HCI pkt type: %d now has %d recv buffers left \n",
+ pktType, HTC_PACKET_QUEUE_DEPTH(pQueue)));
+ }
+ }
+
+ if (NULL == pPacket) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("** HCI pkt type: %d has no buffers available stopping recv...\n", pktType));
+ /* this is not an error, we simply need to mark that we are waiting for buffers.*/
+ pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS;
+ pProt->WaitBufferType = pktType;
+ blockRecv = TRUE;
+ break;
+ }
+
+ if (totalRecvLength > (int)pPacket->BufferLength) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI-UART pkt: %d requires %d bytes (%d buffer bytes avail) ! \n",
+ LookAheadBytes[0], totalRecvLength, pPacket->BufferLength));
+ status = A_EINVAL;
+ break;
+ }
+
+ } while (FALSE);
+
+ UNLOCK_HCI_RX(pProt);
+
+ /* locks are released, we can go fetch the packet */
+
+ do {
+
+ if (A_FAILED(status) || (NULL == pPacket)) {
+ break;
+ }
+
+ /* do this synchronously, we don't need to be fast here */
+ pPacket->Completion = NULL;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI : getting recv packet len:%d hci-uart-type: %s \n",
+ totalRecvLength, (LookAheadBytes[0] == HCI_UART_EVENT_PKT) ? "EVENT" : "ACL"));
+
+ status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (pPacket->pBuffer[0] != LookAheadBytes[0]) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not contain expected packet type: %d ! \n",
+ pPacket->pBuffer[0]));
+ status = A_EPROTO;
+ break;
+ }
+
+ if (pPacket->pBuffer[0] == HCI_UART_EVENT_PKT) {
+ /* validate event header fields */
+ if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
+ (pPacket->pBuffer[2] != LookAheadBytes[2])) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n"));
+ DebugDumpBytes(LookAheadBytes, 3, "Expected HCI-UART Header");
+ DebugDumpBytes(pPacket->pBuffer, 3, "** Bad HCI-UART Header");
+ status = A_EPROTO;
+ break;
+ }
+ } else if (pPacket->pBuffer[0] == HCI_UART_ACL_PKT) {
+ /* validate acl header fields */
+ if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
+ (pPacket->pBuffer[2] != LookAheadBytes[2]) ||
+ (pPacket->pBuffer[3] != LookAheadBytes[3]) ||
+ (pPacket->pBuffer[4] != LookAheadBytes[4])) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n"));
+ DebugDumpBytes(LookAheadBytes, 5, "Expected HCI-UART Header");
+ DebugDumpBytes(pPacket->pBuffer, 5, "** Bad HCI-UART Header");
+ status = A_EPROTO;
+ break;
+ }
+ }
+
+ /* adjust buffer to move past packet ID */
+ pPacket->pBuffer++;
+ pPacket->ActualLength = totalRecvLength - 1;
+ pPacket->Status = A_OK;
+ /* indicate packet */
+ DO_HCI_RECV_INDICATION(pProt,pPacket);
+ pPacket = NULL;
+
+ /* check if we need to refill recv buffers */
+ if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) {
+ HTC_PACKET_QUEUE *pQueue;
+ int watermark;
+
+ if (pktType == HCI_ACL_TYPE) {
+ watermark = pProt->HCIConfig.ACLRecvBufferWaterMark;
+ pQueue = &pProt->HCIACLRecvBuffers;
+ } else {
+ watermark = pProt->HCIConfig.EventRecvBufferWaterMark;
+ pQueue = &pProt->HCIEventBuffers;
+ }
+
+ if (HTC_PACKET_QUEUE_DEPTH(pQueue) < watermark) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("** HCI pkt type: %d watermark hit (%d) current:%d \n",
+ pktType, watermark, HTC_PACKET_QUEUE_DEPTH(pQueue)));
+ /* call the re-fill handler */
+ pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
+ pktType,
+ HTC_PACKET_QUEUE_DEPTH(pQueue));
+ }
+ }
+
+ } while (FALSE);
+
+ /* check if we need to disable the reciever */
+ if (A_FAILED(status) || blockRecv) {
+ DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC);
+ }
+
+ /* see if we need to recycle the recv buffer */
+ if (A_FAILED(status) && (pPacket != NULL)) {
+ HTC_PACKET_QUEUE queue;
+
+ if (A_EPROTO == status) {
+ DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet");
+ }
+ /* recycle packet */
+ HTC_PACKET_RESET_RX(pPacket);
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
+ HCI_TransportAddReceivePkts(pProt,&queue);
+ NotifyTransportFailure(pProt,status);
+ }
+
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCIUartMessagePending \n"));
+
+ return status;
+}
+
+static void HCISendPacketCompletion(void *Context, HTC_PACKET *pPacket)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)Context;
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket));
+
+ if (A_FAILED(pPacket->Status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n",
+ (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength));
+ }
+
+ DO_HCI_SEND_INDICATION(pProt,pPacket);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n"));
+}
+
+static A_STATUS SeekCreditsSynch(GMBOX_PROTO_HCI_UART *pProt)
+{
+ A_STATUS status = A_OK;
+ int credits;
+ int retry = 100;
+
+ while (TRUE) {
+ credits = 0;
+ status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
+ if (A_FAILED(status)) {
+ break;
+ }
+ LOCK_HCI_TX(pProt);
+ pProt->CreditsAvailable += credits;
+ pProt->CreditsConsumed -= credits;
+ if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
+ pProt->CreditsCurrentSeek = 0;
+ UNLOCK_HCI_TX(pProt);
+ break;
+ }
+ UNLOCK_HCI_TX(pProt);
+ retry--;
+ if (0 == retry) {
+ status = A_EBUSY;
+ break;
+ }
+ A_MDELAY(20);
+ }
+
+ return status;
+}
+
+static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous)
+{
+ A_STATUS status = A_OK;
+ int transferLength;
+ int creditsRequired, remainder;
+ A_UINT8 hciUartType;
+ A_BOOL synchSendComplete = FALSE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket,
+ Synchronous ? "SYNC" :"ASYNC"));
+
+ LOCK_HCI_TX(pProt);
+
+ /* increment write processing count on entry */
+ pProt->SendProcessCount++;
+
+ do {
+
+ if (pProt->HCIStopped) {
+ status = A_ECANCELED;
+ break;
+ }
+
+ if (pPacket != NULL) {
+ /* packet was supplied */
+ if (Synchronous) {
+ /* in synchronous mode, the send queue can only hold 1 packet */
+ if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
+ status = A_EBUSY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ if (pProt->SendProcessCount > 1) {
+ /* another thread or task is draining the TX queues */
+ status = A_EBUSY;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
+
+ } else {
+ /* see if adding this packet hits the max depth (asynchronous mode only) */
+ if ((pProt->HCIConfig.MaxSendQueueDepth > 0) &&
+ ((HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue) + 1) >= pProt->HCIConfig.MaxSendQueueDepth)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HCI Send queue is full, Depth:%d, Max:%d \n",
+ HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue),
+ pProt->HCIConfig.MaxSendQueueDepth));
+ /* queue will be full, invoke any callbacks to determine what action to take */
+ if (pProt->HCIConfig.pHCISendFull != NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ ("HCI : Calling driver's send full callback.... \n"));
+ if (pProt->HCIConfig.pHCISendFull(pProt->HCIConfig.pContext,
+ pPacket) == HCI_SEND_FULL_DROP) {
+ /* drop it */
+ status = A_NO_RESOURCE;
+ break;
+ }
+ }
+ }
+
+ HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
+ }
+
+ }
+
+ if (pProt->SendStateFlags & HCI_SEND_WAIT_CREDITS) {
+ break;
+ }
+
+ if (pProt->SendProcessCount > 1) {
+ /* another thread or task is draining the TX queues */
+ break;
+ }
+
+ /***** beyond this point only 1 thread may enter ******/
+
+ /* now drain the send queue for transmission as long as we have enough
+ * credits */
+ while (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
+
+ pPacket = HTC_PACKET_DEQUEUE(&pProt->SendQueue);
+
+ switch (HCI_GET_PACKET_TYPE(pPacket)) {
+ case HCI_COMMAND_TYPE:
+ hciUartType = HCI_UART_COMMAND_PKT;
+ break;
+ case HCI_ACL_TYPE:
+ hciUartType = HCI_UART_ACL_PKT;
+ break;
+ default:
+ status = A_EINVAL;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Got head packet:0x%lX , Type:%d Length: %d Remaining Queue Depth: %d\n",
+ (unsigned long)pPacket, HCI_GET_PACKET_TYPE(pPacket), pPacket->ActualLength,
+ HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
+
+ transferLength = 1; /* UART type header is 1 byte */
+ transferLength += pPacket->ActualLength;
+ transferLength = DEV_CALC_SEND_PADDED_LEN(pProt->pDev, transferLength);
+
+ /* figure out how many credits this message requires */
+ creditsRequired = transferLength / pProt->CreditSize;
+ remainder = transferLength % pProt->CreditSize;
+
+ if (remainder) {
+ creditsRequired++;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Creds Required:%d Got:%d\n",
+ creditsRequired, pProt->CreditsAvailable));
+
+ if (creditsRequired > pProt->CreditsAvailable) {
+ if (Synchronous) {
+ /* in synchronous mode we need to seek credits in synchronously */
+ pProt->CreditsCurrentSeek = creditsRequired;
+ UNLOCK_HCI_TX(pProt);
+ status = SeekCreditsSynch(pProt);
+ LOCK_HCI_TX(pProt);
+ if (A_FAILED(status)) {
+ break;
+ }
+ /* fall through and continue processing this send op */
+ } else {
+ /* not enough credits, queue back to the head */
+ HTC_PACKET_ENQUEUE_TO_HEAD(&pProt->SendQueue,pPacket);
+ /* waiting for credits */
+ pProt->SendStateFlags |= HCI_SEND_WAIT_CREDITS;
+ /* provide a hint to reduce attempts to re-send if credits are dribbling back
+ * this hint is the short fall of credits */
+ pProt->CreditsCurrentSeek = creditsRequired;
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: packet:0x%lX placed back in queue. head packet needs: %d credits \n",
+ (unsigned long)pPacket, pProt->CreditsCurrentSeek));
+ pPacket = NULL;
+ UNLOCK_HCI_TX(pProt);
+
+ /* schedule a credit counter read, our CreditsAvailableCallback callback will be called
+ * with the result */
+ DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_ASYNC, NULL);
+
+ LOCK_HCI_TX(pProt);
+ break;
+ }
+ }
+
+ /* caller guarantees some head room */
+ pPacket->pBuffer--;
+ pPacket->pBuffer[0] = hciUartType;
+
+ pProt->CreditsAvailable -= creditsRequired;
+ pProt->CreditsConsumed += creditsRequired;
+ A_ASSERT(pProt->CreditsConsumed <= pProt->CreditsMax);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state: consumed:%d available:%d max:%d\n",
+ pProt->CreditsConsumed, pProt->CreditsAvailable, pProt->CreditsMax));
+
+ UNLOCK_HCI_TX(pProt);
+
+ /* write it out */
+ if (Synchronous) {
+ pPacket->Completion = NULL;
+ pPacket->pContext = NULL;
+ } else {
+ pPacket->Completion = HCISendPacketCompletion;
+ pPacket->pContext = pProt;
+ }
+
+ status = DevGMboxWrite(pProt->pDev,pPacket,transferLength);
+ if (Synchronous) {
+ synchSendComplete = TRUE;
+ } else {
+ pPacket = NULL;
+ }
+
+ LOCK_HCI_TX(pProt);
+
+ }
+
+ } while (FALSE);
+
+ pProt->SendProcessCount--;
+ A_ASSERT(pProt->SendProcessCount >= 0);
+ UNLOCK_HCI_TX(pProt);
+
+ if (Synchronous) {
+ A_ASSERT(pPacket != NULL);
+ if (A_SUCCESS(status) && (!synchSendComplete)) {
+ status = A_EBUSY;
+ A_ASSERT(FALSE);
+ LOCK_HCI_TX(pProt);
+ if (pPacket->ListLink.pNext != NULL) {
+ /* remove from the queue */
+ HTC_PACKET_REMOVE(&pProt->SendQueue,pPacket);
+ }
+ UNLOCK_HCI_TX(pProt);
+ }
+ } else {
+ if (A_FAILED(status) && (pPacket != NULL)) {
+ pPacket->Status = status;
+ DO_HCI_SEND_INDICATION(pProt,pPacket);
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HCITrySend: \n"));
+ return status;
+}
+
+static void FlushSendQueue(GMBOX_PROTO_HCI_UART *pProt)
+{
+ HTC_PACKET *pPacket;
+ HTC_PACKET_QUEUE discardQueue;
+
+ INIT_HTC_PACKET_QUEUE(&discardQueue);
+
+ LOCK_HCI_TX(pProt);
+
+ if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->SendQueue);
+ }
+
+ UNLOCK_HCI_TX(pProt);
+
+ /* discard packets */
+ while (!HTC_QUEUE_EMPTY(&discardQueue)) {
+ pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
+ pPacket->Status = A_ECANCELED;
+ DO_HCI_SEND_INDICATION(pProt,pPacket);
+ }
+
+}
+
+static void FlushRecvBuffers(GMBOX_PROTO_HCI_UART *pProt)
+{
+ HTC_PACKET_QUEUE discardQueue;
+ HTC_PACKET *pPacket;
+
+ INIT_HTC_PACKET_QUEUE(&discardQueue);
+
+ LOCK_HCI_RX(pProt);
+ /*transfer list items from ACL and event buffer queues to the discard queue */
+ if (!HTC_QUEUE_EMPTY(&pProt->HCIACLRecvBuffers)) {
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIACLRecvBuffers);
+ }
+ if (!HTC_QUEUE_EMPTY(&pProt->HCIEventBuffers)) {
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIEventBuffers);
+ }
+ UNLOCK_HCI_RX(pProt);
+
+ /* now empty the discard queue */
+ while (!HTC_QUEUE_EMPTY(&discardQueue)) {
+ pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
+ pPacket->Status = A_ECANCELED;
+ DO_HCI_RECV_INDICATION(pProt,pPacket);
+ }
+
+}
+
+/*** protocol module install entry point ***/
+
+A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
+{
+ A_STATUS status = A_OK;
+ GMBOX_PROTO_HCI_UART *pProtocol = NULL;
+
+ do {
+
+ pProtocol = A_MALLOC(sizeof(GMBOX_PROTO_HCI_UART));
+
+ if (NULL == pProtocol) {
+ status = A_NO_MEMORY;
+ break;
+ }
+
+ A_MEMZERO(pProtocol, sizeof(*pProtocol));
+ pProtocol->pDev = pDev;
+ INIT_HTC_PACKET_QUEUE(&pProtocol->SendQueue);
+ INIT_HTC_PACKET_QUEUE(&pProtocol->HCIACLRecvBuffers);
+ INIT_HTC_PACKET_QUEUE(&pProtocol->HCIEventBuffers);
+ A_MUTEX_INIT(&pProtocol->HCIRxLock);
+ A_MUTEX_INIT(&pProtocol->HCITxLock);
+
+ } while (FALSE);
+
+ if (A_SUCCESS(status)) {
+ LOCK_AR6K(pDev);
+ DEV_GMBOX_SET_PROTOCOL(pDev,
+ HCIUartMessagePending,
+ CreditsAvailableCallback,
+ FailureCallback,
+ StateDumpCallback,
+ pProtocol);
+ UNLOCK_AR6K(pDev);
+ } else {
+ if (pProtocol != NULL) {
+ HCIUartCleanup(pProtocol);
+ }
+ }
+
+ return status;
+}
+
+/*** protocol module uninstall entry point ***/
+void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
+{
+ GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
+
+ if (pProtocol != NULL) {
+
+ /* notify anyone attached */
+ if (pProtocol->HCIAttached) {
+ A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL);
+ pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext);
+ pProtocol->HCIAttached = FALSE;
+ }
+
+ HCIUartCleanup(pProtocol);
+ DEV_GMBOX_SET_PROTOCOL(pDev,NULL,NULL,NULL,NULL,NULL);
+ }
+
+}
+
+static A_STATUS NotifyTransportReady(GMBOX_PROTO_HCI_UART *pProt)
+{
+ HCI_TRANSPORT_PROPERTIES props;
+ A_STATUS status = A_OK;
+
+ do {
+
+ A_MEMZERO(&props,sizeof(props));
+
+ /* HCI UART only needs one extra byte at the head to indicate the packet TYPE */
+ props.HeadRoom = 1;
+ props.TailRoom = 0;
+ props.IOBlockPad = pProt->pDev->BlockSize;
+ if (pProt->HCIAttached) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI: notifying attached client to transport... \n"));
+ A_ASSERT(pProt->HCIConfig.TransportReady != NULL);
+ status = pProt->HCIConfig.TransportReady(pProt,
+ &props,
+ pProt->HCIConfig.pContext);
+ }
+
+ } while (FALSE);
+
+ return status;
+}
+
+/*********** HCI UART protocol implementation ************************************************/
+
+HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo)
+{
+ GMBOX_PROTO_HCI_UART *pProtocol = NULL;
+ AR6K_DEVICE *pDev;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n"));
+
+ pDev = HTCGetAR6KDevice(HTCHandle);
+
+ LOCK_AR6K(pDev);
+
+ do {
+
+ pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
+
+ if (NULL == pProtocol) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n"));
+ break;
+ }
+
+ if (pProtocol->HCIAttached) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol already attached! \n"));
+ break;
+ }
+
+ A_MEMCPY(&pProtocol->HCIConfig, pInfo, sizeof(HCI_TRANSPORT_CONFIG_INFO));
+
+ A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL);
+ A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL);
+
+ pProtocol->HCIAttached = TRUE;
+
+ } while (FALSE);
+
+ UNLOCK_AR6K(pDev);
+
+ if (pProtocol != NULL) {
+ /* TODO ... should we use a worker? */
+ NotifyTransportReady(pProtocol);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach (0x%lX) \n",(unsigned long)pProtocol));
+ return (HCI_TRANSPORT_HANDLE)pProtocol;
+}
+
+void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
+{
+ GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)HciTrans;
+ AR6K_DEVICE *pDev = pProtocol->pDev;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n"));
+
+ LOCK_AR6K(pDev);
+ if (!pProtocol->HCIAttached) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not attached! \n"));
+ UNLOCK_AR6K(pDev);
+ return;
+ }
+ pProtocol->HCIAttached = FALSE;
+ UNLOCK_AR6K(pDev);
+
+ HCI_TransportStop(HciTrans);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n"));
+}
+
+A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+ A_STATUS status = A_OK;
+ A_BOOL unblockRecv = FALSE;
+ HTC_PACKET *pPacket;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n"));
+
+ LOCK_HCI_RX(pProt);
+
+ do {
+
+ if (pProt->HCIStopped) {
+ status = A_ECANCELED;
+ break;
+ }
+
+ pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
+
+ if (NULL == pPacket) {
+ status = A_EINVAL;
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv packet added, type :%d, len:%d num:%d \n",
+ HCI_GET_PACKET_TYPE(pPacket), pPacket->BufferLength, HTC_PACKET_QUEUE_DEPTH(pQueue)));
+
+ if (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) {
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIEventBuffers, pQueue);
+ } else if (HCI_GET_PACKET_TYPE(pPacket) == HCI_ACL_TYPE) {
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIACLRecvBuffers, pQueue);
+ } else {
+ status = A_EINVAL;
+ break;
+ }
+
+ if (pProt->RecvStateFlags & HCI_RECV_WAIT_BUFFERS) {
+ if (pProt->WaitBufferType == HCI_GET_PACKET_TYPE(pPacket)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv was blocked on packet type :%d, unblocking.. \n",
+ pProt->WaitBufferType));
+ pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS;
+ pProt->WaitBufferType = HCI_PACKET_INVALID;
+ unblockRecv = TRUE;
+ }
+ }
+
+ } while (FALSE);
+
+ UNLOCK_HCI_RX(pProt);
+
+ if (A_FAILED(status)) {
+ while (!HTC_QUEUE_EMPTY(pQueue)) {
+ pPacket = HTC_PACKET_DEQUEUE(pQueue);
+ pPacket->Status = A_ECANCELED;
+ DO_HCI_RECV_INDICATION(pProt,pPacket);
+ }
+ }
+
+ if (unblockRecv) {
+ DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_ASYNC);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n"));
+
+ return A_OK;
+}
+
+A_STATUS HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+
+ return HCITrySend(pProt,pPacket,Synchronous);
+}
+
+void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n"));
+
+ LOCK_AR6K(pProt->pDev);
+ if (pProt->HCIStopped) {
+ UNLOCK_AR6K(pProt->pDev);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
+ return;
+ }
+ pProt->HCIStopped = TRUE;
+ UNLOCK_AR6K(pProt->pDev);
+
+ /* disable interrupts */
+ DevGMboxIRQAction(pProt->pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
+ FlushSendQueue(pProt);
+ FlushRecvBuffers(pProt);
+
+ /* signal bridge side to power down BT */
+ DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_OFF, BTOFF_TIMEOUT_MS);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
+}
+
+A_STATUS HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
+{
+ A_STATUS status;
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n"));
+
+ /* set stopped in case we have a problem in starting */
+ pProt->HCIStopped = TRUE;
+
+ do {
+
+ status = InitTxCreditState(pProt);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+ /* enable recv */
+ status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+ /* signal bridge side to power up BT */
+ status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n"));
+ break;
+ }
+
+ /* we made it */
+ pProt->HCIStopped = FALSE;
+
+ } while (FALSE);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n"));
+
+ return status;
+}
+
+A_STATUS HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+ return DevGMboxIRQAction(pProt->pDev,
+ Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE,
+ PROC_IO_SYNC);
+
+}
+
+A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
+ HTC_PACKET *pPacket,
+ int MaxPollMS)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+ A_STATUS status = A_OK;
+ A_UINT8 lookAhead[8];
+ int bytes;
+ int totalRecvLength;
+
+ MaxPollMS = MaxPollMS / 16;
+
+ if (MaxPollMS < 2) {
+ MaxPollMS = 2;
+ }
+
+ while (MaxPollMS) {
+
+ bytes = sizeof(lookAhead);
+ status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (bytes < 3) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI recv poll got bytes: %d, retry : %d \n",
+ bytes, MaxPollMS));
+ A_MDELAY(16);
+ MaxPollMS--;
+ continue;
+ }
+
+ totalRecvLength = 0;
+ switch (lookAhead[0]) {
+ case HCI_UART_EVENT_PKT:
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
+ lookAhead[1], lookAhead[2]));
+ totalRecvLength = lookAhead[2];
+ totalRecvLength += 3; /* add type + event code + length field */
+ break;
+ default:
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",lookAhead[0]));
+ status = A_EPROTO;
+ break;
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ pPacket->Completion = NULL;
+ status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ pPacket->pBuffer++;
+ pPacket->ActualLength = totalRecvLength - 1;
+ pPacket->Status = A_OK;
+ break;
+ }
+
+ if (MaxPollMS == 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI recv poll timeout! \n"));
+ status = A_ERROR;
+ }
+
+ return status;
+}
+
+#define LSB_SCRATCH_IDX 4
+#define MSB_SCRATCH_IDX 5
+A_STATUS HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud)
+{
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+ HIF_DEVICE *pHIFDevice = (HIF_DEVICE *)(pProt->pDev->HIFDevice);
+ A_UINT32 scaledBaud, scratchAddr;
+ A_STATUS status = A_OK;
+
+ /* Divide the desired baud rate by 100
+ * Store the LSB in the local scratch register 4 and the MSB in the local
+ * scratch register 5 for the target to read
+ */
+ scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * LSB_SCRATCH_IDX);
+ scaledBaud = (Baud / 100) & LOCAL_SCRATCH_VALUE_MASK;
+ status = ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);
+ scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX);
+ scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK;
+ status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);
+ if (A_OK != status) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!"));
+ return status;
+ }
+
+ /* Now interrupt the target to tell it about the baud rate */
+ status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS);
+ if (A_OK != status) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!"));
+ }
+
+ return status;
+}
+
+A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
+{
+ A_STATUS status;
+ GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+
+ if (Enable) {
+ status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS);
+ } else {
+ status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS);
+ }
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n"));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n"));
+ }
+
+ return status;
+}
+
+#endif //ATH_AR6K_ENABLE_GMBOX
+
diff --git a/drivers/staging/ath6kl/htc2/htc.c b/drivers/staging/ath6kl/htc2/htc.c
new file mode 100644
index 00000000000..7df62a20d48
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/htc.c
@@ -0,0 +1,579 @@
+//------------------------------------------------------------------------------
+// <copyright file="htc.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#include "htc_internal.h"
+
+#ifdef ATH_DEBUG_MODULE
+static ATH_DEBUG_MASK_DESCRIPTION g_HTCDebugDescription[] = {
+ { ATH_DEBUG_SEND , "Send"},
+ { ATH_DEBUG_RECV , "Recv"},
+ { ATH_DEBUG_SYNC , "Sync"},
+ { ATH_DEBUG_DUMP , "Dump Data (RX or TX)"},
+ { ATH_DEBUG_IRQ , "Interrupt Processing"}
+};
+
+ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
+ "htc",
+ "Host Target Communications",
+ ATH_DEBUG_MASK_DEFAULTS,
+ ATH_DEBUG_DESCRIPTION_COUNT(g_HTCDebugDescription),
+ g_HTCDebugDescription);
+
+#endif
+
+static void HTCReportFailure(void *Context);
+static void ResetEndpointStates(HTC_TARGET *target);
+
+void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList)
+{
+ LOCK_HTC(target);
+ HTC_PACKET_ENQUEUE(pList,pPacket);
+ UNLOCK_HTC(target);
+}
+
+HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList)
+{
+ HTC_PACKET *pPacket;
+
+ LOCK_HTC(target);
+ pPacket = HTC_PACKET_DEQUEUE(pList);
+ UNLOCK_HTC(target);
+
+ return pPacket;
+}
+
+/* cleanup the HTC instance */
+static void HTCCleanup(HTC_TARGET *target)
+{
+ A_INT32 i;
+
+ DevCleanup(&target->Device);
+
+ for (i = 0;i < NUM_CONTROL_BUFFERS;i++) {
+ if (target->HTCControlBuffers[i].Buffer) {
+ A_FREE(target->HTCControlBuffers[i].Buffer);
+ }
+ }
+
+ if (A_IS_MUTEX_VALID(&target->HTCLock)) {
+ A_MUTEX_DELETE(&target->HTCLock);
+ }
+
+ if (A_IS_MUTEX_VALID(&target->HTCRxLock)) {
+ A_MUTEX_DELETE(&target->HTCRxLock);
+ }
+
+ if (A_IS_MUTEX_VALID(&target->HTCTxLock)) {
+ A_MUTEX_DELETE(&target->HTCTxLock);
+ }
+ /* free our instance */
+ A_FREE(target);
+}
+
+/* registered target arrival callback from the HIF layer */
+HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
+{
+ HTC_TARGET *target = NULL;
+ A_STATUS status = A_OK;
+ int i;
+ A_UINT32 ctrl_bufsz;
+ A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n"));
+
+ A_REGISTER_MODULE_DEBUG_INFO(htc);
+
+ do {
+
+ /* allocate target memory */
+ if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
+ status = A_ERROR;
+ break;
+ }
+
+ A_MEMZERO(target, sizeof(HTC_TARGET));
+ A_MUTEX_INIT(&target->HTCLock);
+ A_MUTEX_INIT(&target->HTCRxLock);
+ A_MUTEX_INIT(&target->HTCTxLock);
+ INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
+ INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList);
+
+ /* give device layer the hif device handle */
+ target->Device.HIFDevice = hif_handle;
+ /* give the device layer our context (for event processing)
+ * the device layer will register it's own context with HIF
+ * so we need to set this so we can fetch it in the target remove handler */
+ target->Device.HTCContext = target;
+ /* set device layer target failure callback */
+ target->Device.TargetFailureCallback = HTCReportFailure;
+ /* set device layer recv message pending callback */
+ target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;
+ target->EpWaitingForBuffers = ENDPOINT_MAX;
+
+ A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO));
+
+ ResetEndpointStates(target);
+
+ /* setup device layer */
+ status = DevSetup(&target->Device);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+
+ /* get the block sizes */
+ status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
+ blocksizes, sizeof(blocksizes));
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n"));
+ break;
+ }
+
+ /* Set the control buffer size based on the block size */
+ if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) {
+ ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH;
+ } else {
+ ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH;
+ }
+ for (i = 0;i < NUM_CONTROL_BUFFERS;i++) {
+ target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz);
+ if (target->HTCControlBuffers[i].Buffer == NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
+ status = A_ERROR;
+ break;
+ }
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ /* carve up buffers/packets for control messages */
+ for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) {
+ HTC_PACKET *pControlPacket;
+ pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
+ SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket,
+ target,
+ target->HTCControlBuffers[i].Buffer,
+ ctrl_bufsz,
+ ENDPOINT_0);
+ HTC_FREE_CONTROL_RX(target,pControlPacket);
+ }
+
+ for (;i < NUM_CONTROL_BUFFERS;i++) {
+ HTC_PACKET *pControlPacket;
+ pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
+ INIT_HTC_PACKET_INFO(pControlPacket,
+ target->HTCControlBuffers[i].Buffer,
+ ctrl_bufsz);
+ HTC_FREE_CONTROL_TX(target,pControlPacket);
+ }
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ if (target != NULL) {
+ HTCCleanup(target);
+ target = NULL;
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n"));
+
+ return target;
+}
+
+void HTCDestroy(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%lX \n",(unsigned long)target));
+ HTCCleanup(target);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n"));
+}
+
+/* get the low level HIF device for the caller , the caller may wish to do low level
+ * HIF requests */
+void *HTCGetHifDevice(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ return target->Device.HIFDevice;
+}
+
+/* wait for the target to arrive (sends HTC Ready message)
+ * this operation is fully synchronous and the message is polled for */
+A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ A_STATUS status;
+ HTC_PACKET *pPacket = NULL;
+ HTC_READY_EX_MSG *pRdyMsg;
+
+ HTC_SERVICE_CONNECT_REQ connect;
+ HTC_SERVICE_CONNECT_RESP resp;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target));
+
+ do {
+
+#ifdef MBOXHW_UNIT_TEST
+
+ status = DoMboxHWTest(&target->Device);
+
+ if (status != A_OK) {
+ break;
+ }
+
+#endif
+
+ /* we should be getting 1 control message that the target is ready */
+ status = HTCWaitforControlMessage(target, &pPacket);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
+ break;
+ }
+
+ /* we controlled the buffer creation so it has to be properly aligned */
+ pRdyMsg = (HTC_READY_EX_MSG *)pPacket->pBuffer;
+
+ if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) ||
+ (pPacket->ActualLength < sizeof(HTC_READY_MSG))) {
+ /* this message is not valid */
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+
+ if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) {
+ /* this message is not valid */
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+ target->TargetCredits = pRdyMsg->Version2_0_Info.CreditCount;
+ target->TargetCreditSize = pRdyMsg->Version2_0_Info.CreditSize;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN, (" Target Ready: credits: %d credit size: %d\n",
+ target->TargetCredits, target->TargetCreditSize));
+
+ /* check if this is an extended ready message */
+ if (pPacket->ActualLength >= sizeof(HTC_READY_EX_MSG)) {
+ /* this is an extended message */
+ target->HTCTargetVersion = pRdyMsg->HTCVersion;
+ target->MaxMsgPerBundle = pRdyMsg->MaxMsgsPerHTCBundle;
+ } else {
+ /* legacy */
+ target->HTCTargetVersion = HTC_VERSION_2P0;
+ target->MaxMsgPerBundle = 0;
+ }
+
+#ifdef HTC_FORCE_LEGACY_2P0
+ /* for testing and comparison...*/
+ target->HTCTargetVersion = HTC_VERSION_2P0;
+ target->MaxMsgPerBundle = 0;
+#endif
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
+ ("Using HTC Protocol Version : %s (%d)\n ",
+ (target->HTCTargetVersion == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
+ target->HTCTargetVersion));
+
+ if (target->MaxMsgPerBundle > 0) {
+ /* limit what HTC can handle */
+ target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle);
+ /* target supports message bundling, setup device layer */
+ if (A_FAILED(DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle))) {
+ /* device layer can't handle bundling */
+ target->MaxMsgPerBundle = 0;
+ } else {
+ /* limit bundle what the device layer can handle */
+ target->MaxMsgPerBundle = min(DEV_GET_MAX_MSG_PER_BUNDLE(&target->Device),
+ target->MaxMsgPerBundle);
+ }
+ }
+
+ if (target->MaxMsgPerBundle > 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
+ (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle));
+
+ if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) {
+ target->SendBundlingEnabled = TRUE;
+ }
+ if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) {
+ target->RecvBundlingEnabled = TRUE;
+ }
+
+ if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("*** Credit size: %d is not block aligned! Disabling send bundling \n",
+ target->TargetCreditSize));
+ /* disallow send bundling since the credit size is not aligned to a block size
+ * the I/O block padding will spill into the next credit buffer which is fatal */
+ target->SendBundlingEnabled = FALSE;
+ }
+ }
+
+ /* setup our pseudo HTC control endpoint connection */
+ A_MEMZERO(&connect,sizeof(connect));
+ A_MEMZERO(&resp,sizeof(resp));
+ connect.EpCallbacks.pContext = target;
+ connect.EpCallbacks.EpTxComplete = HTCControlTxComplete;
+ connect.EpCallbacks.EpRecv = HTCControlRecv;
+ connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */
+ connect.EpCallbacks.EpSendFull = NULL; /* not nedded */
+ connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS;
+ connect.ServiceID = HTC_CTRL_RSVD_SVC;
+
+ /* connect fake service */
+ status = HTCConnectService((HTC_HANDLE)target,
+ &connect,
+ &resp);
+
+ if (!A_FAILED(status)) {
+ break;
+ }
+
+ } while (FALSE);
+
+ if (pPacket != NULL) {
+ HTC_FREE_CONTROL_RX(target,pPacket);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n"));
+
+ return status;
+}
+
+
+
+/* Start HTC, enable interrupts and let the target know host has finished setup */
+A_STATUS HTCStart(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ HTC_PACKET *pPacket;
+ A_STATUS status;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
+
+ /* make sure interrupts are disabled at the chip level,
+ * this function can be called again from a reboot of the target without shutting down HTC */
+ DevDisableInterrupts(&target->Device);
+ /* make sure state is cleared again */
+ target->OpStateFlags = 0;
+ target->RecvStateFlags = 0;
+
+ /* now that we are starting, push control receive buffers into the
+ * HTC control endpoint */
+
+ while (1) {
+ pPacket = HTC_ALLOC_CONTROL_RX(target);
+ if (NULL == pPacket) {
+ break;
+ }
+ HTCAddReceivePkt((HTC_HANDLE)target,pPacket);
+ }
+
+ do {
+
+ AR_DEBUG_ASSERT(target->InitCredits != NULL);
+ AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL);
+ AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL);
+
+ /* call init credits callback to do the distribution ,
+ * NOTE: the first entry in the distribution list is ENDPOINT_0, so
+ * we pass the start of the list after this one. */
+ target->InitCredits(target->pCredDistContext,
+ target->EpCreditDistributionListHead->pNext,
+ target->TargetCredits);
+
+#ifdef ATH_DEBUG_MODULE
+
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
+ DumpCreditDistStates(target);
+ }
+#endif
+
+ /* the caller is done connecting to services, so we can indicate to the
+ * target that the setup phase is complete */
+ status = HTCSendSetupComplete(target);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ /* unmask interrupts */
+ status = DevUnmaskInterrupts(&target->Device);
+
+ if (A_FAILED(status)) {
+ HTCStop(target);
+ }
+
+ } while (FALSE);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
+ return status;
+}
+
+static void ResetEndpointStates(HTC_TARGET *target)
+{
+ HTC_ENDPOINT *pEndpoint;
+ int i;
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ pEndpoint = &target->EndPoint[i];
+
+ A_MEMZERO(&pEndpoint->CreditDist, sizeof(pEndpoint->CreditDist));
+ pEndpoint->ServiceID = 0;
+ pEndpoint->MaxMsgLength = 0;
+ pEndpoint->MaxTxQueueDepth = 0;
+#ifdef HTC_EP_STAT_PROFILING
+ A_MEMZERO(&pEndpoint->EndPointStats,sizeof(pEndpoint->EndPointStats));
+#endif
+ INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers);
+ INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
+ INIT_HTC_PACKET_QUEUE(&pEndpoint->RecvIndicationQueue);
+ pEndpoint->target = target;
+ }
+ /* reset distribution list */
+ target->EpCreditDistributionListHead = NULL;
+}
+
+/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
+void HTCStop(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
+
+ LOCK_HTC(target);
+ /* mark that we are shutting down .. */
+ target->OpStateFlags |= HTC_OP_STATE_STOPPING;
+ UNLOCK_HTC(target);
+
+ /* Masking interrupts is a synchronous operation, when this function returns
+ * all pending HIF I/O has completed, we can safely flush the queues */
+ DevMaskInterrupts(&target->Device);
+
+#ifdef THREAD_X
+ //
+ // Is this delay required
+ //
+ A_MDELAY(200); // wait for IRQ process done
+#endif
+ /* flush all send packets */
+ HTCFlushSendPkts(target);
+ /* flush all recv buffers */
+ HTCFlushRecvBuffers(target);
+
+ ResetEndpointStates(target);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
+}
+
+#ifdef ATH_DEBUG_MODULE
+void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+
+ LOCK_HTC_TX(target);
+
+ DumpCreditDistStates(target);
+
+ UNLOCK_HTC_TX(target);
+
+ DumpAR6KDevState(&target->Device);
+}
+#endif
+/* report a target failure from the device, this is a callback from the device layer
+ * which uses a mechanism to report errors from the target (i.e. special interrupts) */
+static void HTCReportFailure(void *Context)
+{
+ HTC_TARGET *target = (HTC_TARGET *)Context;
+
+ target->TargetFailure = TRUE;
+
+ if (target->HTCInitInfo.TargetFailure != NULL) {
+ /* let upper layer know, it needs to call HTCStop() */
+ target->HTCInitInfo.TargetFailure(target->HTCInitInfo.pContext, A_ERROR);
+ }
+}
+
+A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
+ HTC_ENDPOINT_ID Endpoint,
+ HTC_ENDPOINT_STAT_ACTION Action,
+ HTC_ENDPOINT_STATS *pStats)
+{
+
+#ifdef HTC_EP_STAT_PROFILING
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ A_BOOL clearStats = FALSE;
+ A_BOOL sample = FALSE;
+
+ switch (Action) {
+ case HTC_EP_STAT_SAMPLE :
+ sample = TRUE;
+ break;
+ case HTC_EP_STAT_SAMPLE_AND_CLEAR :
+ sample = TRUE;
+ clearStats = TRUE;
+ break;
+ case HTC_EP_STAT_CLEAR :
+ clearStats = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ A_ASSERT(Endpoint < ENDPOINT_MAX);
+
+ /* lock out TX and RX while we sample and/or clear */
+ LOCK_HTC_TX(target);
+ LOCK_HTC_RX(target);
+
+ if (sample) {
+ A_ASSERT(pStats != NULL);
+ /* return the stats to the caller */
+ A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
+ }
+
+ if (clearStats) {
+ /* reset stats */
+ A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
+ }
+
+ UNLOCK_HTC_RX(target);
+ UNLOCK_HTC_TX(target);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+AR6K_DEVICE *HTCGetAR6KDevice(void *HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ return &target->Device;
+}
+
diff --git a/drivers/staging/ath6kl/htc2/htc_debug.h b/drivers/staging/ath6kl/htc2/htc_debug.h
new file mode 100644
index 00000000000..8455703e221
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/htc_debug.h
@@ -0,0 +1,38 @@
+//------------------------------------------------------------------------------
+// <copyright file="htc_debug.h" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef HTC_DEBUG_H_
+#define HTC_DEBUG_H_
+
+#define ATH_MODULE_NAME htc
+#include "a_debug.h"
+
+/* ------- Debug related stuff ------- */
+
+#define ATH_DEBUG_SEND ATH_DEBUG_MAKE_MODULE_MASK(0)
+#define ATH_DEBUG_RECV ATH_DEBUG_MAKE_MODULE_MASK(1)
+#define ATH_DEBUG_SYNC ATH_DEBUG_MAKE_MODULE_MASK(2)
+#define ATH_DEBUG_DUMP ATH_DEBUG_MAKE_MODULE_MASK(3)
+#define ATH_DEBUG_IRQ ATH_DEBUG_MAKE_MODULE_MASK(4)
+
+
+#endif /*HTC_DEBUG_H_*/
diff --git a/drivers/staging/ath6kl/htc2/htc_internal.h b/drivers/staging/ath6kl/htc2/htc_internal.h
new file mode 100644
index 00000000000..bd6754beb22
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/htc_internal.h
@@ -0,0 +1,220 @@
+//------------------------------------------------------------------------------
+// <copyright file="htc_internal.h" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _HTC_INTERNAL_H_
+#define _HTC_INTERNAL_H_
+
+/* for debugging, uncomment this to capture the last frame header, on frame header
+ * processing errors, the last frame header is dump for comparison */
+//#define HTC_CAPTURE_LAST_FRAME
+
+//#define HTC_EP_STAT_PROFILING
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Header files */
+
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "a_osapi.h"
+#include "htc_debug.h"
+#include "htc.h"
+#include "htc_api.h"
+#include "bmi_msg.h"
+#include "hif.h"
+#include "AR6000/ar6k.h"
+
+/* HTC operational parameters */
+#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */
+#define HTC_TARGET_DEBUG_INTR_MASK 0x01
+#define HTC_TARGET_CREDIT_INTR_MASK 0xF0
+
+#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
+#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2
+
+/* packet flags */
+
+#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0)
+#define HTC_RX_PKT_REFRESH_HDR (1 << 1)
+#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2)
+#define HTC_RX_PKT_NO_RECYCLE (1 << 3)
+
+/* scatter request flags */
+
+#define HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE (1 << 0)
+
+typedef struct _HTC_ENDPOINT {
+ HTC_ENDPOINT_ID Id;
+ HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to
+ non-zero value means this endpoint is in use */
+ HTC_PACKET_QUEUE TxQueue; /* HTC frame buffer TX queue */
+ HTC_PACKET_QUEUE RxBuffers; /* HTC frame buffer RX list */
+ HTC_ENDPOINT_CREDIT_DIST CreditDist; /* credit distribution structure (exposed to driver layer) */
+ HTC_EP_CALLBACKS EpCallBacks; /* callbacks associated with this endpoint */
+ int MaxTxQueueDepth; /* max depth of the TX queue before we need to
+ call driver's full handler */
+ int MaxMsgLength; /* max length of endpoint message */
+ int TxProcessCount; /* reference count to continue tx processing */
+ HTC_PACKET_QUEUE RecvIndicationQueue; /* recv packets ready to be indicated */
+ int RxProcessCount; /* reference count to allow single processing context */
+ struct _HTC_TARGET *target; /* back pointer to target */
+ A_UINT8 SeqNo; /* TX seq no (helpful) for debugging */
+ A_UINT32 LocalConnectionFlags; /* local connection flags */
+#ifdef HTC_EP_STAT_PROFILING
+ HTC_ENDPOINT_STATS EndPointStats; /* endpoint statistics */
+#endif
+} HTC_ENDPOINT;
+
+#ifdef HTC_EP_STAT_PROFILING
+#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count);
+#else
+#define INC_HTC_EP_STAT(p,stat,count)
+#endif
+
+#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL
+
+#define NUM_CONTROL_BUFFERS 8
+#define NUM_CONTROL_TX_BUFFERS 2
+#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
+
+typedef struct HTC_CONTROL_BUFFER {
+ HTC_PACKET HtcPacket;
+ A_UINT8 *Buffer;
+} HTC_CONTROL_BUFFER;
+
+#define HTC_RECV_WAIT_BUFFERS (1 << 0)
+#define HTC_OP_STATE_STOPPING (1 << 0)
+
+/* our HTC target state */
+typedef struct _HTC_TARGET {
+ HTC_ENDPOINT EndPoint[ENDPOINT_MAX];
+ HTC_CONTROL_BUFFER HTCControlBuffers[NUM_CONTROL_BUFFERS];
+ HTC_ENDPOINT_CREDIT_DIST *EpCreditDistributionListHead;
+ HTC_PACKET_QUEUE ControlBufferTXFreeList;
+ HTC_PACKET_QUEUE ControlBufferRXFreeList;
+ HTC_CREDIT_DIST_CALLBACK DistributeCredits;
+ HTC_CREDIT_INIT_CALLBACK InitCredits;
+ void *pCredDistContext;
+ int TargetCredits;
+ unsigned int TargetCreditSize;
+ A_MUTEX_T HTCLock;
+ A_MUTEX_T HTCRxLock;
+ A_MUTEX_T HTCTxLock;
+ AR6K_DEVICE Device; /* AR6K - specific state */
+ A_UINT32 OpStateFlags;
+ A_UINT32 RecvStateFlags;
+ HTC_ENDPOINT_ID EpWaitingForBuffers;
+ A_BOOL TargetFailure;
+#ifdef HTC_CAPTURE_LAST_FRAME
+ HTC_FRAME_HDR LastFrameHdr; /* useful for debugging */
+ A_UINT8 LastTrailer[256];
+ A_UINT8 LastTrailerLength;
+#endif
+ HTC_INIT_INFO HTCInitInfo;
+ A_UINT8 HTCTargetVersion;
+ int MaxMsgPerBundle; /* max messages per bundle for HTC */
+ A_BOOL SendBundlingEnabled; /* run time enable for send bundling (dynamic) */
+ int RecvBundlingEnabled; /* run time enable for recv bundling (dynamic) */
+} HTC_TARGET;
+
+#define HTC_STOPPING(t) ((t)->OpStateFlags & HTC_OP_STATE_STOPPING)
+#define LOCK_HTC(t) A_MUTEX_LOCK(&(t)->HTCLock);
+#define UNLOCK_HTC(t) A_MUTEX_UNLOCK(&(t)->HTCLock);
+#define LOCK_HTC_RX(t) A_MUTEX_LOCK(&(t)->HTCRxLock);
+#define UNLOCK_HTC_RX(t) A_MUTEX_UNLOCK(&(t)->HTCRxLock);
+#define LOCK_HTC_TX(t) A_MUTEX_LOCK(&(t)->HTCTxLock);
+#define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock);
+
+#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))
+#define HTC_RECYCLE_RX_PKT(target,p,e) \
+{ \
+ if ((p)->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_NO_RECYCLE) { \
+ HTC_PACKET_RESET_RX(pPacket); \
+ pPacket->Status = A_ECANCELED; \
+ (e)->EpCallBacks.EpRecv((e)->EpCallBacks.pContext, \
+ (p)); \
+ } else { \
+ HTC_PACKET_RESET_RX(pPacket); \
+ HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \
+ } \
+}
+
+/* internal HTC functions */
+void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket);
+void HTCControlRecv(void *Context, HTC_PACKET *pPacket);
+A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket);
+HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList);
+void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList);
+A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket);
+void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket);
+A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], int NumLookAheads, A_BOOL *pAsyncProc, int *pNumPktsFetched);
+void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
+A_STATUS HTCSendSetupComplete(HTC_TARGET *target);
+void HTCFlushRecvBuffers(HTC_TARGET *target);
+void HTCFlushSendPkts(HTC_TARGET *target);
+
+#ifdef ATH_DEBUG_MODULE
+void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist);
+void DumpCreditDistStates(HTC_TARGET *target);
+void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
+#endif
+
+static INLINE HTC_PACKET *HTC_ALLOC_CONTROL_TX(HTC_TARGET *target) {
+ HTC_PACKET *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
+ if (pPacket != NULL) {
+ /* set payload pointer area with some headroom */
+ pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH;
+ }
+ return pPacket;
+}
+
+#define HTC_FREE_CONTROL_TX(t,p) HTCFreeControlBuffer((t),(p),&(t)->ControlBufferTXFreeList)
+#define HTC_ALLOC_CONTROL_RX(t) HTCAllocControlBuffer((t),&(t)->ControlBufferRXFreeList)
+#define HTC_FREE_CONTROL_RX(t,p) \
+{ \
+ HTC_PACKET_RESET_RX(p); \
+ HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \
+}
+
+#define HTC_PREPARE_SEND_PKT(pP,sendflags,ctrl0,ctrl1) \
+{ \
+ A_UINT8 *pHdrBuf; \
+ (pP)->pBuffer -= HTC_HDR_LENGTH; \
+ pHdrBuf = (pP)->pBuffer; \
+ A_SET_UINT16_FIELD(pHdrBuf,HTC_FRAME_HDR,PayloadLen,(A_UINT16)(pP)->ActualLength); \
+ A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,Flags,(sendflags)); \
+ A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,EndpointID, (A_UINT8)(pP)->Endpoint); \
+ A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,ControlBytes[0], (A_UINT8)(ctrl0)); \
+ A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,ControlBytes[1], (A_UINT8)(ctrl1)); \
+}
+
+#define HTC_UNPREPARE_SEND_PKT(pP) \
+ (pP)->pBuffer += HTC_HDR_LENGTH; \
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTC_INTERNAL_H_ */
diff --git a/drivers/staging/ath6kl/htc2/htc_recv.c b/drivers/staging/ath6kl/htc2/htc_recv.c
new file mode 100644
index 00000000000..3503657fe7d
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/htc_recv.c
@@ -0,0 +1,1578 @@
+//------------------------------------------------------------------------------
+// <copyright file="htc_recv.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#include "htc_internal.h"
+
+#define HTCIssueRecv(t, p) \
+ DevRecvPacket(&(t)->Device, \
+ (p), \
+ (p)->ActualLength)
+
+#define DO_RCV_COMPLETION(e,q) DoRecvCompletion(e,q)
+
+#define DUMP_RECV_PKT_INFO(pP) \
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC RECV packet 0x%lX (%d bytes) (hdr:0x%X) on ep : %d \n", \
+ (unsigned long)(pP), \
+ (pP)->ActualLength, \
+ (pP)->PktInfo.AsRx.ExpectedHdr, \
+ (pP)->Endpoint))
+
+#ifdef HTC_EP_STAT_PROFILING
+#define HTC_RX_STAT_PROFILE(t,ep,numLookAheads) \
+{ \
+ INC_HTC_EP_STAT((ep), RxReceived, 1); \
+ if ((numLookAheads) == 1) { \
+ INC_HTC_EP_STAT((ep), RxLookAheads, 1); \
+ } else if ((numLookAheads) > 1) { \
+ INC_HTC_EP_STAT((ep), RxBundleLookAheads, 1); \
+ } \
+}
+#else
+#define HTC_RX_STAT_PROFILE(t,ep,lookAhead)
+#endif
+
+static void DoRecvCompletion(HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET_QUEUE *pQueueToIndicate)
+{
+
+ do {
+
+ if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
+ /* nothing to indicate */
+ break;
+ }
+
+ if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d, recv multiple callback (%d pkts) \n",
+ pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate)));
+ /* a recv multiple handler is being used, pass the queue to the handler */
+ pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint->EpCallBacks.pContext,
+ pQueueToIndicate);
+ INIT_HTC_PACKET_QUEUE(pQueueToIndicate);
+ } else {
+ HTC_PACKET *pPacket;
+ /* using legacy EpRecv */
+ do {
+ pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d recv callback on packet 0x%lX \n", \
+ pEndpoint->Id, (unsigned long)(pPacket)));
+ pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket);
+ } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
+ }
+
+ } while (FALSE);
+
+}
+
+static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
+ A_UINT8 *pBuffer,
+ int Length,
+ A_UINT32 *pNextLookAheads,
+ int *pNumLookAheads,
+ HTC_ENDPOINT_ID FromEndpoint)
+{
+ HTC_RECORD_HDR *pRecord;
+ A_UINT8 *pRecordBuf;
+ HTC_LOOKAHEAD_REPORT *pLookAhead;
+ A_UINT8 *pOrigBuffer;
+ int origLength;
+ A_STATUS status;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
+
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+ AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer");
+ }
+
+ pOrigBuffer = pBuffer;
+ origLength = Length;
+ status = A_OK;
+
+ while (Length > 0) {
+
+ if (Length < sizeof(HTC_RECORD_HDR)) {
+ status = A_EPROTO;
+ break;
+ }
+ /* these are byte aligned structs */
+ pRecord = (HTC_RECORD_HDR *)pBuffer;
+ Length -= sizeof(HTC_RECORD_HDR);
+ pBuffer += sizeof(HTC_RECORD_HDR);
+
+ if (pRecord->Length > Length) {
+ /* no room left in buffer for record */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" invalid record length: %d (id:%d) buffer has: %d bytes left \n",
+ pRecord->Length, pRecord->RecordID, Length));
+ status = A_EPROTO;
+ break;
+ }
+ /* start of record follows the header */
+ pRecordBuf = pBuffer;
+
+ switch (pRecord->RecordID) {
+ case HTC_RECORD_CREDITS:
+ AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT));
+ HTCProcessCreditRpt(target,
+ (HTC_CREDIT_REPORT *)pRecordBuf,
+ pRecord->Length / (sizeof(HTC_CREDIT_REPORT)),
+ FromEndpoint);
+ break;
+ case HTC_RECORD_LOOKAHEAD:
+ AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT));
+ pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf;
+ if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) &&
+ (pNextLookAheads != NULL)) {
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n",
+ pLookAhead->PreValid,
+ pLookAhead->PostValid));
+
+ /* look ahead bytes are valid, copy them over */
+ ((A_UINT8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
+ ((A_UINT8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
+ ((A_UINT8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
+ ((A_UINT8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
+
+#ifdef ATH_DEBUG_MODULE
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+ DebugDumpBytes((A_UINT8 *)pNextLookAheads,4,"Next Look Ahead");
+ }
+#endif
+ /* just one normal lookahead */
+ *pNumLookAheads = 1;
+ }
+ break;
+ case HTC_RECORD_LOOKAHEAD_BUNDLE:
+ AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT));
+ if (pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT) &&
+ (pNextLookAheads != NULL)) {
+ HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt;
+ int i;
+
+ pBundledLookAheadRpt = (HTC_BUNDLED_LOOKAHEAD_REPORT *)pRecordBuf;
+
+#ifdef ATH_DEBUG_MODULE
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+ DebugDumpBytes(pRecordBuf,pRecord->Length,"Bundle LookAhead");
+ }
+#endif
+
+ if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) >
+ HTC_HOST_MAX_MSG_PER_BUNDLE) {
+ /* this should never happen, the target restricts the number
+ * of messages per bundle configured by the host */
+ A_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+ for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) {
+ ((A_UINT8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
+ ((A_UINT8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
+ ((A_UINT8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
+ ((A_UINT8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
+ pBundledLookAheadRpt++;
+ }
+
+ *pNumLookAheads = i;
+ }
+ break;
+ default:
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
+ pRecord->RecordID, pRecord->Length));
+ break;
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ /* advance buffer past this record for next time around */
+ pBuffer += pRecord->Length;
+ Length -= pRecord->Length;
+ }
+
+#ifdef ATH_DEBUG_MODULE
+ if (A_FAILED(status)) {
+ DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
+ }
+#endif
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
+ return status;
+
+}
+
+/* process a received message (i.e. strip off header, process any trailer data)
+ * note : locks must be released when this function is called */
+static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
+ HTC_PACKET *pPacket,
+ A_UINT32 *pNextLookAheads,
+ int *pNumLookAheads)
+{
+ A_UINT8 temp;
+ A_UINT8 *pBuf;
+ A_STATUS status = A_OK;
+ A_UINT16 payloadLen;
+ A_UINT32 lookAhead;
+
+ pBuf = pPacket->pBuffer;
+
+ if (pNumLookAheads != NULL) {
+ *pNumLookAheads = 0;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n"));
+
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+ AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT");
+ }
+
+ do {
+ /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to
+ * retrieve 16 bit fields */
+ payloadLen = A_GET_UINT16_FIELD(pBuf, HTC_FRAME_HDR, PayloadLen);
+
+ ((A_UINT8 *)&lookAhead)[0] = pBuf[0];
+ ((A_UINT8 *)&lookAhead)[1] = pBuf[1];
+ ((A_UINT8 *)&lookAhead)[2] = pBuf[2];
+ ((A_UINT8 *)&lookAhead)[3] = pBuf[3];
+
+ if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
+ /* refresh expected hdr, since this was unknown at the time we grabbed the packets
+ * as part of a bundle */
+ pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead;
+ /* refresh actual length since we now have the real header */
+ pPacket->ActualLength = payloadLen + HTC_HDR_LENGTH;
+
+ /* validate the actual header that was refreshed */
+ if (pPacket->ActualLength > pPacket->BufferLength) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Refreshed HDR payload length (%d) in bundled RECV is invalid (hdr: 0x%X) \n",
+ payloadLen, lookAhead));
+ /* limit this to max buffer just to print out some of the buffer */
+ pPacket->ActualLength = min(pPacket->ActualLength, pPacket->BufferLength);
+ status = A_EPROTO;
+ break;
+ }
+
+ if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, EndpointID)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n",
+ A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, EndpointID), pPacket->Endpoint));
+ status = A_EPROTO;
+ break;
+ }
+ }
+
+ if (lookAhead != pPacket->PktInfo.AsRx.ExpectedHdr) {
+ /* somehow the lookahead that gave us the full read length did not
+ * reflect the actual header in the pending message */
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n",
+ (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags));
+#ifdef ATH_DEBUG_MODULE
+ DebugDumpBytes((A_UINT8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
+ DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header");
+#ifdef HTC_CAPTURE_LAST_FRAME
+ DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header");
+ if (target->LastTrailerLength != 0) {
+ DebugDumpBytes(target->LastTrailer,
+ target->LastTrailerLength,
+ "Last trailer");
+ }
+#endif
+#endif
+ status = A_EPROTO;
+ break;
+ }
+
+ /* get flags */
+ temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, Flags);
+
+ if (temp & HTC_FLAGS_RECV_TRAILER) {
+ /* this packet has a trailer */
+
+ /* extract the trailer length in control byte 0 */
+ temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, ControlBytes[0]);
+
+ if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n",
+ payloadLen, temp));
+ status = A_EPROTO;
+ break;
+ }
+
+ if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
+ /* this packet was fetched as part of an HTC bundle, the embedded lookahead is
+ * not valid since the next packet may have already been fetched as part of the
+ * bundle */
+ pNextLookAheads = NULL;
+ pNumLookAheads = NULL;
+ }
+
+ /* process trailer data that follows HDR + application payload */
+ status = HTCProcessTrailer(target,
+ (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
+ temp,
+ pNextLookAheads,
+ pNumLookAheads,
+ pPacket->Endpoint);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+#ifdef HTC_CAPTURE_LAST_FRAME
+ A_MEMCPY(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
+ target->LastTrailerLength = temp;
+#endif
+ /* trim length by trailer bytes */
+ pPacket->ActualLength -= temp;
+ }
+#ifdef HTC_CAPTURE_LAST_FRAME
+ else {
+ target->LastTrailerLength = 0;
+ }
+#endif
+
+ /* if we get to this point, the packet is good */
+ /* remove header and adjust length */
+ pPacket->pBuffer += HTC_HDR_LENGTH;
+ pPacket->ActualLength -= HTC_HDR_LENGTH;
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ /* dump the whole packet */
+#ifdef ATH_DEBUG_MODULE
+ DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT");
+#endif
+ } else {
+#ifdef HTC_CAPTURE_LAST_FRAME
+ A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(HTC_FRAME_HDR));
+#endif
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+ if (pPacket->ActualLength > 0) {
+ AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg");
+ }
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n"));
+ return status;
+}
+
+static INLINE void HTCAsyncRecvCheckMorePackets(HTC_TARGET *target,
+ A_UINT32 NextLookAheads[],
+ int NumLookAheads,
+ A_BOOL CheckMoreMsgs)
+{
+ /* was there a lookahead for the next packet? */
+ if (NumLookAheads > 0) {
+ A_STATUS nextStatus;
+ int fetched = 0;
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n",
+ NumLookAheads));
+ /* force status re-check */
+ REF_IRQ_STATUS_RECHECK(&target->Device);
+ /* we have more packets, get the next packet fetch started */
+ nextStatus = HTCRecvMessagePendingHandler(target, NextLookAheads, NumLookAheads, NULL, &fetched);
+ if (A_EPROTO == nextStatus) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Next look ahead from recv header was INVALID\n"));
+#ifdef ATH_DEBUG_MODULE
+ DebugDumpBytes((A_UINT8 *)NextLookAheads,
+ NumLookAheads * (sizeof(A_UINT32)),
+ "BAD lookaheads from lookahead report");
+#endif
+ }
+ if (A_SUCCESS(nextStatus) && !fetched) {
+ /* we could not fetch any more packets due to resources */
+ DevAsyncIrqProcessComplete(&target->Device);
+ }
+ } else {
+ if (CheckMoreMsgs) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("HTCAsyncRecvCheckMorePackets - rechecking for more messages...\n"));
+ /* if we did not get anything on the look-ahead,
+ * call device layer to asynchronously re-check for messages. If we can keep the async
+ * processing going we get better performance. If there is a pending message we will keep processing
+ * messages asynchronously which should pipeline things nicely */
+ DevCheckPendingRecvMsgsAsync(&target->Device);
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTCAsyncRecvCheckMorePackets - no check \n"));
+ }
+ }
+
+
+}
+
+ /* unload the recv completion queue */
+static INLINE void DrainRecvIndicationQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
+{
+ HTC_PACKET_QUEUE recvCompletions;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n"));
+
+ INIT_HTC_PACKET_QUEUE(&recvCompletions);
+
+ LOCK_HTC_RX(target);
+
+ /* increment rx processing count on entry */
+ pEndpoint->RxProcessCount++;
+ if (pEndpoint->RxProcessCount > 1) {
+ pEndpoint->RxProcessCount--;
+ /* another thread or task is draining the RX completion queue on this endpoint
+ * that thread will reset the rx processing count when the queue is drained */
+ UNLOCK_HTC_RX(target);
+ return;
+ }
+
+ /******* at this point only 1 thread may enter ******/
+
+ while (TRUE) {
+
+ /* transfer items from main recv queue to the local one so we can release the lock */
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue);
+
+ if (HTC_QUEUE_EMPTY(&recvCompletions)) {
+ /* all drained */
+ break;
+ }
+
+ /* release lock while we do the recv completions
+ * other threads can now queue more recv completions */
+ UNLOCK_HTC_RX(target);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("DrainRecvIndicationQueue : completing %d RECV packets \n",
+ HTC_PACKET_QUEUE_DEPTH(&recvCompletions)));
+ /* do completion */
+ DO_RCV_COMPLETION(pEndpoint,&recvCompletions);
+
+ /* re-acquire lock to grab some more completions */
+ LOCK_HTC_RX(target);
+ }
+
+ /* reset count */
+ pEndpoint->RxProcessCount = 0;
+ UNLOCK_HTC_RX(target);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-DrainRecvIndicationQueue \n"));
+
+}
+
+ /* optimization for recv packets, we can indicate a "hint" that there are more
+ * single-packets to fetch on this endpoint */
+#define SET_MORE_RX_PACKET_INDICATION_FLAG(L,N,E,P) \
+ if ((N) > 0) { SetRxPacketIndicationFlags((L)[0],(E),(P)); }
+
+ /* for bundled frames, we can force the flag to indicate there are more packets */
+#define FORCE_MORE_RX_PACKET_INDICATION_FLAG(P) \
+ (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS;
+
+ /* note: this function can be called with the RX lock held */
+static INLINE void SetRxPacketIndicationFlags(A_UINT32 LookAhead,
+ HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET *pPacket)
+{
+ HTC_FRAME_HDR *pHdr = (HTC_FRAME_HDR *)&LookAhead;
+ /* check to see if the "next" packet is from the same endpoint of the
+ completing packet */
+ if (pHdr->EndpointID == pPacket->Endpoint) {
+ /* check that there is a buffer available to actually fetch it */
+ if (!HTC_QUEUE_EMPTY(&pEndpoint->RxBuffers)) {
+ /* provide a hint that there are more RX packets to fetch */
+ FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
+ }
+ }
+}
+
+
+/* asynchronous completion handler for recv packet fetching, when the device layer
+ * completes a read request, it will call this completion handler */
+void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
+{
+ HTC_TARGET *target = (HTC_TARGET *)Context;
+ HTC_ENDPOINT *pEndpoint;
+ A_UINT32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+ int numLookAheads = 0;
+ A_STATUS status;
+ A_BOOL checkMorePkts = TRUE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n",
+ (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint));
+
+ A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
+ AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
+ pEndpoint = &target->EndPoint[pPacket->Endpoint];
+ pPacket->Completion = NULL;
+
+ /* get completion status */
+ status = pPacket->Status;
+
+ do {
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n",
+ pPacket->Status, pPacket->Endpoint));
+ break;
+ }
+ /* process the header for any trailer data */
+ status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
+ /* this packet was part of a bundle that had to be broken up.
+ * It was fetched one message at a time. There may be other asynchronous reads queued behind this one.
+ * Do no issue another check for more packets since the last one in the series of requests
+ * will handle it */
+ checkMorePkts = FALSE;
+ }
+
+ DUMP_RECV_PKT_INFO(pPacket);
+ LOCK_HTC_RX(target);
+ SET_MORE_RX_PACKET_INDICATION_FLAG(nextLookAheads,numLookAheads,pEndpoint,pPacket);
+ /* we have a good packet, queue it to the completion queue */
+ HTC_PACKET_ENQUEUE(&pEndpoint->RecvIndicationQueue,pPacket);
+ HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
+ UNLOCK_HTC_RX(target);
+
+ /* check for more recv packets before indicating */
+ HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts);
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
+ status));
+ /* recycle this packet */
+ HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
+ } else {
+ /* a good packet was queued, drain the queue */
+ DrainRecvIndicationQueue(target,pEndpoint);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n"));
+}
+
+/* synchronously wait for a control message from the target,
+ * This function is used at initialization time ONLY. At init messages
+ * on ENDPOINT 0 are expected. */
+A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket)
+{
+ A_STATUS status;
+ A_UINT32 lookAhead;
+ HTC_PACKET *pPacket = NULL;
+ HTC_FRAME_HDR *pHdr;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
+
+ do {
+
+ *ppControlPacket = NULL;
+
+ /* call the polling function to see if we have a message */
+ status = DevPollMboxMsgRecv(&target->Device,
+ &lookAhead,
+ HTC_TARGET_RESPONSE_TIMEOUT);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
+
+ /* check the lookahead */
+ pHdr = (HTC_FRAME_HDR *)&lookAhead;
+
+ if (pHdr->EndpointID != ENDPOINT_0) {
+ /* unexpected endpoint number, should be zero */
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+ if (A_FAILED(status)) {
+ /* bad message */
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+ pPacket = HTC_ALLOC_CONTROL_RX(target);
+
+ if (pPacket == NULL) {
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_NO_MEMORY;
+ break;
+ }
+
+ pPacket->PktInfo.AsRx.HTCRxFlags = 0;
+ pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead;
+ pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
+
+ if (pPacket->ActualLength > pPacket->BufferLength) {
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+ /* we want synchronous operation */
+ pPacket->Completion = NULL;
+
+ /* get the message from the device, this will block */
+ status = HTCIssueRecv(target, pPacket);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ /* process receive header */
+ status = HTCProcessRecvHeader(target,pPacket,NULL,NULL);
+
+ pPacket->Status = status;
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
+ status));
+ break;
+ }
+
+ /* give the caller this control message packet, they are responsible to free */
+ *ppControlPacket = pPacket;
+
+ } while (FALSE);
+
+ if (A_FAILED(status)) {
+ if (pPacket != NULL) {
+ /* cleanup buffer on error */
+ HTC_FREE_CONTROL_RX(target,pPacket);
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n"));
+
+ return status;
+}
+
+static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET *target,
+ A_UINT32 LookAheads[],
+ int Messages,
+ HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET_QUEUE *pQueue)
+{
+ A_STATUS status = A_OK;
+ HTC_PACKET *pPacket;
+ HTC_FRAME_HDR *pHdr;
+ int i,j;
+ int numMessages;
+ int fullLength;
+ A_BOOL noRecycle;
+
+ /* lock RX while we assemble the packet buffers */
+ LOCK_HTC_RX(target);
+
+ for (i = 0; i < Messages; i++) {
+
+ pHdr = (HTC_FRAME_HDR *)&LookAheads[i];
+
+ if (pHdr->EndpointID >= ENDPOINT_MAX) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID));
+ /* invalid endpoint */
+ status = A_EPROTO;
+ break;
+ }
+
+ if (pHdr->EndpointID != pEndpoint->Id) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d should be : %d (index:%d)\n",
+ pHdr->EndpointID, pEndpoint->Id, i));
+ /* invalid endpoint */
+ status = A_EPROTO;
+ break;
+ }
+
+ if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
+ pHdr->PayloadLen, (A_UINT32)HTC_MAX_PAYLOAD_LENGTH));
+ status = A_EPROTO;
+ break;
+ }
+
+ if (0 == pEndpoint->ServiceID) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID));
+ /* endpoint isn't even connected */
+ status = A_EPROTO;
+ break;
+ }
+
+ if ((pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) {
+ /* HTC header only indicates 1 message to fetch */
+ numMessages = 1;
+ } else {
+ /* HTC header indicates that every packet to follow has the same padded length so that it can
+ * be optimally fetched as a full bundle */
+ numMessages = (pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) >> HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT;
+ /* the count doesn't include the starter frame, just a count of frames to follow */
+ numMessages++;
+ A_ASSERT(numMessages <= target->MaxMsgPerBundle);
+ INC_HTC_EP_STAT(pEndpoint, RxBundleIndFromHdr, 1);
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages));
+ }
+
+ fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR));
+
+ /* get packet buffers for each message, if there was a bundle detected in the header,
+ * use pHdr as a template to fetch all packets in the bundle */
+ for (j = 0; j < numMessages; j++) {
+
+ /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup,
+ * they must be explicitly returned */
+ noRecycle = FALSE;
+
+ if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) {
+ UNLOCK_HTC_RX(target);
+ noRecycle = TRUE;
+ /* user is using a per-packet allocation callback */
+ pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext,
+ pEndpoint->Id,
+ fullLength);
+ LOCK_HTC_RX(target);
+
+ } else if ((pEndpoint->EpCallBacks.EpRecvAllocThresh != NULL) &&
+ (fullLength > pEndpoint->EpCallBacks.RecvAllocThreshold)) {
+ INC_HTC_EP_STAT(pEndpoint,RxAllocThreshHit,1);
+ INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen);
+ /* threshold was hit, call the special recv allocation callback */
+ UNLOCK_HTC_RX(target);
+ noRecycle = TRUE;
+ /* user wants to allocate packets above a certain threshold */
+ pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext,
+ pEndpoint->Id,
+ fullLength);
+ LOCK_HTC_RX(target);
+
+ } else {
+ /* user is using a refill handler that can refill multiple HTC buffers */
+
+ /* get a packet from the endpoint recv queue */
+ pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
+
+ if (NULL == pPacket) {
+ /* check for refill handler */
+ if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) {
+ UNLOCK_HTC_RX(target);
+ /* call the re-fill handler */
+ pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
+ pEndpoint->Id);
+ LOCK_HTC_RX(target);
+ /* check if we have more buffers */
+ pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
+ /* fall through */
+ }
+ }
+ }
+
+ if (NULL == pPacket) {
+ /* this is not an error, we simply need to mark that we are waiting for buffers.*/
+ target->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS;
+ target->EpWaitingForBuffers = pEndpoint->Id;
+ status = A_NO_RESOURCE;
+ break;
+ }
+
+ AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id);
+ /* clear flags */
+ pPacket->PktInfo.AsRx.HTCRxFlags = 0;
+ pPacket->PktInfo.AsRx.IndicationFlags = 0;
+ pPacket->Status = A_OK;
+
+ if (noRecycle) {
+ /* flag that these packets cannot be recycled, they have to be returned to the
+ * user */
+ pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_NO_RECYCLE;
+ }
+ /* add packet to queue (also incase we need to cleanup down below) */
+ HTC_PACKET_ENQUEUE(pQueue,pPacket);
+
+ if (HTC_STOPPING(target)) {
+ status = A_ECANCELED;
+ break;
+ }
+
+ /* make sure this message can fit in the endpoint buffer */
+ if ((A_UINT32)fullLength > pPacket->BufferLength) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n",
+ pHdr->PayloadLen, fullLength, pPacket->BufferLength));
+ status = A_EPROTO;
+ break;
+ }
+
+ if (j > 0) {
+ /* for messages fetched in a bundle the expected lookahead is unknown since we
+ * are only using the lookahead of the first packet as a template of what to
+ * expect for lengths */
+ /* flag that once we get the real HTC header we need to refesh the information */
+ pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_REFRESH_HDR;
+ /* set it to something invalid */
+ pPacket->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF;
+ } else {
+
+ pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */
+ }
+ /* set the amount of data to fetch */
+ pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
+ }
+
+ if (A_FAILED(status)) {
+ if (A_NO_RESOURCE == status) {
+ /* this is actually okay */
+ status = A_OK;
+ }
+ break;
+ }
+
+ }
+
+ UNLOCK_HTC_RX(target);
+
+ if (A_FAILED(status)) {
+ while (!HTC_QUEUE_EMPTY(pQueue)) {
+ pPacket = HTC_PACKET_DEQUEUE(pQueue);
+ /* recycle all allocated packets */
+ HTC_RECYCLE_RX_PKT(target,pPacket,&target->EndPoint[pPacket->Endpoint]);
+ }
+ }
+
+ return status;
+}
+
+static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
+{
+ int i;
+ HTC_PACKET *pPacket;
+ HTC_ENDPOINT *pEndpoint;
+ A_UINT32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+ int numLookAheads = 0;
+ HTC_TARGET *target = (HTC_TARGET *)pScatterReq->Context;
+ A_STATUS status;
+ A_BOOL partialBundle = FALSE;
+ HTC_PACKET_QUEUE localRecvQueue;
+ A_BOOL procError = FALSE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion TotLen: %d Entries: %d\n",
+ pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
+
+ A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
+
+ if (A_FAILED(pScatterReq->CompletionStatus)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));
+ }
+
+ if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) {
+ partialBundle = TRUE;
+ }
+
+ DEV_FINISH_SCATTER_OPERATION(pScatterReq);
+
+ INIT_HTC_PACKET_QUEUE(&localRecvQueue);
+
+ pPacket = (HTC_PACKET *)pScatterReq->ScatterList[0].pCallerContexts[0];
+ /* note: all packets in a scatter req are for the same endpoint ! */
+ pEndpoint = &target->EndPoint[pPacket->Endpoint];
+
+ /* walk through the scatter list and process */
+ /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock
+ * as it processes credit reports */
+ for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
+ pPacket = (HTC_PACKET *)pScatterReq->ScatterList[i].pCallerContexts[0];
+ A_ASSERT(pPacket != NULL);
+ /* reset count, we are only interested in the look ahead in the last packet when we
+ * break out of this loop */
+ numLookAheads = 0;
+
+ if (A_SUCCESS(pScatterReq->CompletionStatus)) {
+ /* process header for each of the recv packets */
+ status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads);
+ } else {
+ status = A_ERROR;
+ }
+
+ if (A_SUCCESS(status)) {
+#ifdef HTC_EP_STAT_PROFILING
+ LOCK_HTC_RX(target);
+ HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
+ INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1);
+ UNLOCK_HTC_RX(target);
+#endif
+ if (i == (pScatterReq->ValidScatterEntries - 1)) {
+ /* last packet's more packets flag is set based on the lookahead */
+ SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,numLookAheads,pEndpoint,pPacket);
+ } else {
+ /* packets in a bundle automatically have this flag set */
+ FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
+ }
+
+ DUMP_RECV_PKT_INFO(pPacket);
+ /* since we can't hold a lock in this loop, we insert into our local recv queue for
+ * storage until we can transfer them to the recv completion queue */
+ HTC_PACKET_ENQUEUE(&localRecvQueue,pPacket);
+
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Recv packet scatter entry %d failed (out of %d) \n",
+ i, pScatterReq->ValidScatterEntries));
+ /* recycle failed recv */
+ HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
+ /* set flag and continue processing the remaining scatter entries */
+ procError = TRUE;
+ }
+
+ }
+
+ /* free scatter request */
+ DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
+
+ LOCK_HTC_RX(target);
+ /* transfer the packets in the local recv queue to the recv completion queue */
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RecvIndicationQueue, &localRecvQueue);
+
+ UNLOCK_HTC_RX(target);
+
+ if (!procError) {
+ /* pipeline the next check (asynchronously) for more packets */
+ HTCAsyncRecvCheckMorePackets(target,
+ lookAheads,
+ numLookAheads,
+ partialBundle ? FALSE : TRUE);
+ }
+
+ /* now drain the indication queue */
+ DrainRecvIndicationQueue(target,pEndpoint);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n"));
+}
+
+static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET *target,
+ HTC_PACKET_QUEUE *pRecvPktQueue,
+ HTC_PACKET_QUEUE *pSyncCompletionQueue,
+ int *pNumPacketsFetched,
+ A_BOOL PartialBundle)
+{
+ A_STATUS status = A_OK;
+ HIF_SCATTER_REQ *pScatterReq;
+ int i, totalLength;
+ int pktsToScatter;
+ HTC_PACKET *pPacket;
+ A_BOOL asyncMode = (pSyncCompletionQueue == NULL) ? TRUE : FALSE;
+ int scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device);
+
+ pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue);
+ pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
+
+ if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) {
+ /* we were forced to split this bundle receive operation
+ * all packets in this partial bundle must have their lookaheads ignored */
+ PartialBundle = TRUE;
+ /* this would only happen if the target ignored our max bundle limit */
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n",
+ HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter));
+ }
+
+ totalLength = 0;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCIssueRecvPacketBundle (Numpackets: %d , actual : %d) \n",
+ HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter));
+
+ do {
+
+ pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
+
+ if (pScatterReq == NULL) {
+ /* no scatter resources left, just let caller handle it the legacy way */
+ break;
+ }
+
+ pScatterReq->CallerFlags = 0;
+
+ if (PartialBundle) {
+ /* mark that this is a partial bundle, this has special ramifications to the
+ * scatter completion routine */
+ pScatterReq->CallerFlags |= HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE;
+ }
+
+ /* convert HTC packets to scatter list */
+ for (i = 0; i < pktsToScatter; i++) {
+ int paddedLength;
+
+ pPacket = HTC_PACKET_DEQUEUE(pRecvPktQueue);
+ A_ASSERT(pPacket != NULL);
+
+ paddedLength = DEV_CALC_RECV_PADDED_LEN(&target->Device, pPacket->ActualLength);
+
+ if ((scatterSpaceRemaining - paddedLength) < 0) {
+ /* exceeds what we can transfer, put the packet back */
+ HTC_PACKET_ENQUEUE_TO_HEAD(pRecvPktQueue,pPacket);
+ break;
+ }
+
+ scatterSpaceRemaining -= paddedLength;
+
+ if (PartialBundle || (i < (pktsToScatter - 1))) {
+ /* packet 0..n-1 cannot be checked for look-aheads since we are fetching a bundle
+ * the last packet however can have it's lookahead used */
+ pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD;
+ }
+
+ /* note: 1 HTC packet per scatter entry */
+ /* setup packet into */
+ pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
+ pScatterReq->ScatterList[i].Length = paddedLength;
+
+ pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE;
+
+ if (asyncMode) {
+ /* save HTC packet for async completion routine */
+ pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
+ } else {
+ /* queue to caller's sync completion queue, caller will unload this when we return */
+ HTC_PACKET_ENQUEUE(pSyncCompletionQueue,pPacket);
+ }
+
+ A_ASSERT(pScatterReq->ScatterList[i].Length);
+ totalLength += pScatterReq->ScatterList[i].Length;
+ }
+
+ pScatterReq->TotalLength = totalLength;
+ pScatterReq->ValidScatterEntries = i;
+
+ if (asyncMode) {
+ pScatterReq->CompletionRoutine = HTCAsyncRecvScatterCompletion;
+ pScatterReq->Context = target;
+ }
+
+ status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode);
+
+ if (A_SUCCESS(status)) {
+ *pNumPacketsFetched = i;
+ }
+
+ if (!asyncMode) {
+ /* free scatter request */
+ DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq);
+ }
+
+ } while (FALSE);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n",
+ status,*pNumPacketsFetched));
+
+ return status;
+}
+
+static INLINE void CheckRecvWaterMark(HTC_ENDPOINT *pEndpoint)
+{
+ /* see if endpoint is using a refill watermark
+ * ** no need to use a lock here, since we are only inspecting...
+ * caller may must not hold locks when calling this function */
+ if (pEndpoint->EpCallBacks.RecvRefillWaterMark > 0) {
+ if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBuffers) < pEndpoint->EpCallBacks.RecvRefillWaterMark) {
+ /* call the re-fill handler before we continue */
+ pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
+ pEndpoint->Id);
+ }
+ }
+}
+
+/* callback when device layer or lookahead report parsing detects a pending message */
+A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], int NumLookAheads, A_BOOL *pAsyncProc, int *pNumPktsFetched)
+{
+ HTC_TARGET *target = (HTC_TARGET *)Context;
+ A_STATUS status = A_OK;
+ HTC_PACKET *pPacket;
+ HTC_ENDPOINT *pEndpoint;
+ A_BOOL asyncProc = FALSE;
+ A_UINT32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+ int pktsFetched;
+ HTC_PACKET_QUEUE recvPktQueue, syncCompletedPktsQueue;
+ A_BOOL partialBundle;
+ HTC_ENDPOINT_ID id;
+ int totalFetched = 0;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler NumLookAheads: %d \n",NumLookAheads));
+
+ if (pNumPktsFetched != NULL) {
+ *pNumPktsFetched = 0;
+ }
+
+ if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) {
+ /* We use async mode to get the packets if the device layer supports it.
+ * The device layer interfaces with HIF in which HIF may have restrictions on
+ * how interrupts are processed */
+ asyncProc = TRUE;
+ }
+
+ if (pAsyncProc != NULL) {
+ /* indicate to caller how we decided to process this */
+ *pAsyncProc = asyncProc;
+ }
+
+ if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
+ A_ASSERT(FALSE);
+ return A_EPROTO;
+ }
+
+ /* on first entry copy the lookaheads into our temp array for processing */
+ A_MEMCPY(lookAheads, MsgLookAheads, (sizeof(A_UINT32)) * NumLookAheads);
+
+ while (TRUE) {
+
+ /* reset packets queues */
+ INIT_HTC_PACKET_QUEUE(&recvPktQueue);
+ INIT_HTC_PACKET_QUEUE(&syncCompletedPktsQueue);
+
+ if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
+ status = A_EPROTO;
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ /* first lookahead sets the expected endpoint IDs for all packets in a bundle */
+ id = ((HTC_FRAME_HDR *)&lookAheads[0])->EndpointID;
+ pEndpoint = &target->EndPoint[id];
+
+ if (id >= ENDPOINT_MAX) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MsgPend, Invalid Endpoint in look-ahead: %d \n",id));
+ status = A_EPROTO;
+ break;
+ }
+
+ /* try to allocate as many HTC RX packets indicated by the lookaheads
+ * these packets are stored in the recvPkt queue */
+ status = AllocAndPrepareRxPackets(target,
+ lookAheads,
+ NumLookAheads,
+ pEndpoint,
+ &recvPktQueue);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) >= 2) {
+ /* a recv bundle was detected, force IRQ status re-check again */
+ REF_IRQ_STATUS_RECHECK(&target->Device);
+ }
+
+ totalFetched += HTC_PACKET_QUEUE_DEPTH(&recvPktQueue);
+
+ /* we've got packet buffers for all we can currently fetch,
+ * this count is not valid anymore */
+ NumLookAheads = 0;
+ partialBundle = FALSE;
+
+ /* now go fetch the list of HTC packets */
+ while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
+
+ pktsFetched = 0;
+
+ if (target->RecvBundlingEnabled && (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) {
+ /* there are enough packets to attempt a bundle transfer and recv bundling is allowed */
+ status = HTCIssueRecvPacketBundle(target,
+ &recvPktQueue,
+ asyncProc ? NULL : &syncCompletedPktsQueue,
+ &pktsFetched,
+ partialBundle);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) {
+ /* we couldn't fetch all packets at one time, this creates a broken
+ * bundle */
+ partialBundle = TRUE;
+ }
+ }
+
+ /* see if the previous operation fetched any packets using bundling */
+ if (0 == pktsFetched) {
+ /* dequeue one packet */
+ pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue);
+ A_ASSERT(pPacket != NULL);
+
+ if (asyncProc) {
+ /* we use async mode to get the packet if the device layer supports it
+ * set our callback and context */
+ pPacket->Completion = HTCRecvCompleteHandler;
+ pPacket->pContext = target;
+ } else {
+ /* fully synchronous */
+ pPacket->Completion = NULL;
+ }
+
+ if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 0) {
+ /* lookaheads in all packets except the last one in the bundle must be ignored */
+ pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD;
+ }
+
+ /* go fetch the packet */
+ status = HTCIssueRecv(target, pPacket);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (!asyncProc) {
+ /* sent synchronously, queue this packet for synchronous completion */
+ HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue,pPacket);
+ }
+
+ }
+
+ }
+
+ if (A_SUCCESS(status)) {
+ CheckRecvWaterMark(pEndpoint);
+ }
+
+ if (asyncProc) {
+ /* we did this asynchronously so we can get out of the loop, the asynch processing
+ * creates a chain of requests to continue processing pending messages in the
+ * context of callbacks */
+ break;
+ }
+
+ /* synchronous handling */
+ if (target->Device.DSRCanYield) {
+ /* for the SYNC case, increment count that tracks when the DSR should yield */
+ target->Device.CurrentDSRRecvCount++;
+ }
+
+ /* in the sync case, all packet buffers are now filled,
+ * we can process each packet, check lookaheads and then repeat */
+
+ /* unload sync completion queue */
+ while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
+ HTC_PACKET_QUEUE container;
+
+ pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
+ A_ASSERT(pPacket != NULL);
+
+ pEndpoint = &target->EndPoint[pPacket->Endpoint];
+ /* reset count on each iteration, we are only interested in the last packet's lookahead
+ * information when we break out of this loop */
+ NumLookAheads = 0;
+ /* process header for each of the recv packets
+ * note: the lookahead of the last packet is useful for us to continue in this loop */
+ status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads);
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
+ /* last packet's more packets flag is set based on the lookahead */
+ SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,NumLookAheads,pEndpoint,pPacket);
+ } else {
+ /* packets in a bundle automatically have this flag set */
+ FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
+ }
+ /* good packet, indicate it */
+ HTC_RX_STAT_PROFILE(target,pEndpoint,NumLookAheads);
+
+ if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_PART_OF_BUNDLE) {
+ INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1);
+ }
+
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
+ DO_RCV_COMPLETION(pEndpoint,&container);
+ }
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ if (NumLookAheads == 0) {
+ /* no more look aheads */
+ break;
+ }
+
+ /* when we process recv synchronously we need to check if we should yield and stop
+ * fetching more packets indicated by the embedded lookaheads */
+ if (target->Device.DSRCanYield) {
+ if (DEV_CHECK_RECV_YIELD(&target->Device)) {
+ /* break out, don't fetch any more packets */
+ break;
+ }
+ }
+
+
+ /* check whether other OS contexts have queued any WMI command/data for WLAN.
+ * This check is needed only if WLAN Tx and Rx happens in same thread context */
+ A_CHECK_DRV_TX();
+
+ /* for SYNCH processing, if we get here, we are running through the loop again due to a detected lookahead.
+ * Set flag that we should re-check IRQ status registers again before leaving IRQ processing,
+ * this can net better performance in high throughput situations */
+ REF_IRQ_STATUS_RECHECK(&target->Device);
+ }
+
+ if (A_FAILED(status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("Failed to get pending recv messages (%d) \n",status));
+ /* cleanup any packets we allocated but didn't use to actually fetch any packets */
+ while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
+ pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue);
+ /* clean up packets */
+ HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]);
+ }
+ /* cleanup any packets in sync completion queue */
+ while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
+ pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
+ /* clean up packets */
+ HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]);
+ }
+ if (HTC_STOPPING(target)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ (" Host is going to stop. blocking receiver for HTCStop.. \n"));
+ DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
+ }
+ }
+ /* before leaving, check to see if host ran out of buffers and needs to stop the
+ * receiver */
+ if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ (" Host has no RX buffers, blocking receiver to prevent overrun.. \n"));
+ /* try to stop receive at the device layer */
+ DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
+ }
+
+ if (pNumPktsFetched != NULL) {
+ *pNumPktsFetched = totalFetched;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n"));
+
+ return status;
+}
+
+A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ HTC_ENDPOINT *pEndpoint;
+ A_BOOL unblockRecv = FALSE;
+ A_STATUS status = A_OK;
+ HTC_PACKET *pFirstPacket;
+
+ pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
+
+ if (NULL == pFirstPacket) {
+ A_ASSERT(FALSE);
+ return A_EINVAL;
+ }
+
+ AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+ ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n",
+ pFirstPacket->Endpoint,
+ HTC_PACKET_QUEUE_DEPTH(pPktQueue),
+ pFirstPacket->BufferLength));
+
+ do {
+
+ pEndpoint = &target->EndPoint[pFirstPacket->Endpoint];
+
+ LOCK_HTC_RX(target);
+
+ if (HTC_STOPPING(target)) {
+ HTC_PACKET *pPacket;
+
+ UNLOCK_HTC_RX(target);
+
+ /* walk through queue and mark each one canceled */
+ HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) {
+ pPacket->Status = A_ECANCELED;
+ } HTC_PACKET_QUEUE_ITERATE_END;
+
+ DO_RCV_COMPLETION(pEndpoint,pPktQueue);
+ break;
+ }
+
+ /* store receive packets */
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBuffers, pPktQueue);
+
+ /* check if we are blocked waiting for a new buffer */
+ if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
+ if (target->EpWaitingForBuffers == pFirstPacket->Endpoint) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n",
+ target->EpWaitingForBuffers));
+ target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
+ target->EpWaitingForBuffers = ENDPOINT_MAX;
+ unblockRecv = TRUE;
+ }
+ }
+
+ UNLOCK_HTC_RX(target);
+
+ if (unblockRecv && !HTC_STOPPING(target)) {
+ /* TODO : implement a buffer threshold count? */
+ DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
+ }
+
+ } while (FALSE);
+
+ return status;
+}
+
+/* Makes a buffer available to the HTC module */
+A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
+{
+ HTC_PACKET_QUEUE queue;
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
+ return HTCAddReceivePktMultiple(HTCHandle, &queue);
+}
+
+void HTCUnblockRecv(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ A_BOOL unblockRecv = FALSE;
+
+ LOCK_HTC_RX(target);
+
+ /* check if we are blocked waiting for a new buffer */
+ if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n",
+ target->EpWaitingForBuffers));
+ target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
+ target->EpWaitingForBuffers = ENDPOINT_MAX;
+ unblockRecv = TRUE;
+ }
+
+ UNLOCK_HTC_RX(target);
+
+ if (unblockRecv && !HTC_STOPPING(target)) {
+ /* re-enable */
+ DevEnableRecv(&target->Device,DEV_ENABLE_RECV_ASYNC);
+ }
+}
+
+static void HTCFlushRxQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET_QUEUE *pQueue)
+{
+ HTC_PACKET *pPacket;
+ HTC_PACKET_QUEUE container;
+
+ LOCK_HTC_RX(target);
+
+ while (1) {
+ pPacket = HTC_PACKET_DEQUEUE(pQueue);
+ if (NULL == pPacket) {
+ break;
+ }
+ UNLOCK_HTC_RX(target);
+ pPacket->Status = A_ECANCELED;
+ pPacket->ActualLength = 0;
+ AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%lX, length:%d, ep:%d \n",
+ (unsigned long)pPacket, pPacket->BufferLength, pPacket->Endpoint));
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
+ /* give the packet back */
+ DO_RCV_COMPLETION(pEndpoint,&container);
+ LOCK_HTC_RX(target);
+ }
+
+ UNLOCK_HTC_RX(target);
+}
+
+static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
+{
+ /* flush any recv indications not already made */
+ HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue);
+ /* flush any rx buffers */
+ HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers);
+}
+
+void HTCFlushRecvBuffers(HTC_TARGET *target)
+{
+ HTC_ENDPOINT *pEndpoint;
+ int i;
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ pEndpoint = &target->EndPoint[i];
+ if (pEndpoint->ServiceID == 0) {
+ /* not in use.. */
+ continue;
+ }
+ HTCFlushEndpointRX(target,pEndpoint);
+ }
+}
+
+
+void HTCEnableRecv(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+
+ if (!HTC_STOPPING(target)) {
+ /* re-enable */
+ DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
+ }
+}
+
+void HTCDisableRecv(HTC_HANDLE HTCHandle)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+
+ if (!HTC_STOPPING(target)) {
+ /* disable */
+ DevStopRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
+ }
+}
+
+int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle,
+ HTC_ENDPOINT_ID Endpoint)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers));
+}
+
+A_STATUS HTCWaitForPendingRecv(HTC_HANDLE HTCHandle,
+ A_UINT32 TimeoutInMs,
+ A_BOOL *pbIsRecvPending)
+{
+ A_STATUS status = A_OK;
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+
+ status = DevWaitForPendingRecv(&target->Device,
+ TimeoutInMs,
+ pbIsRecvPending);
+
+ return status;
+}
diff --git a/drivers/staging/ath6kl/htc2/htc_send.c b/drivers/staging/ath6kl/htc2/htc_send.c
new file mode 100644
index 00000000000..bc7ee784826
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/htc_send.c
@@ -0,0 +1,1023 @@
+//------------------------------------------------------------------------------
+// <copyright file="htc_send.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#include "htc_internal.h"
+
+typedef enum _HTC_SEND_QUEUE_RESULT {
+ HTC_SEND_QUEUE_OK = 0, /* packet was queued */
+ HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */
+} HTC_SEND_QUEUE_RESULT;
+
+#define DO_EP_TX_COMPLETION(ep,q) DoSendCompletion(ep,q)
+
+/* call the distribute credits callback with the distribution */
+#define DO_DISTRIBUTION(t,reason,description,pList) \
+{ \
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
+ (" calling distribute function (%s) (dfn:0x%lX, ctxt:0x%lX, dist:0x%lX) \n", \
+ (description), \
+ (unsigned long)(t)->DistributeCredits, \
+ (unsigned long)(t)->pCredDistContext, \
+ (unsigned long)pList)); \
+ (t)->DistributeCredits((t)->pCredDistContext, \
+ (pList), \
+ (reason)); \
+}
+
+static void DoSendCompletion(HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET_QUEUE *pQueueToIndicate)
+{
+ do {
+
+ if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
+ /* nothing to indicate */
+ break;
+ }
+
+ if (pEndpoint->EpCallBacks.EpTxCompleteMultiple != NULL) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d, send complete multiple callback (%d pkts) \n",
+ pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate)));
+ /* a multiple send complete handler is being used, pass the queue to the handler */
+ pEndpoint->EpCallBacks.EpTxCompleteMultiple(pEndpoint->EpCallBacks.pContext,
+ pQueueToIndicate);
+ /* all packets are now owned by the callback, reset queue to be safe */
+ INIT_HTC_PACKET_QUEUE(pQueueToIndicate);
+ } else {
+ HTC_PACKET *pPacket;
+ /* using legacy EpTxComplete */
+ do {
+ pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" HTC calling ep %d send complete callback on packet 0x%lX \n", \
+ pEndpoint->Id, (unsigned long)(pPacket)));
+ pEndpoint->EpCallBacks.EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket);
+ } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
+ }
+
+ } while (FALSE);
+
+}
+
+/* do final completion on sent packet */
+static INLINE void CompleteSentPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET *pPacket)
+{
+ pPacket->Completion = NULL;
+
+ if (A_FAILED(pPacket->Status)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n",
+ pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed));
+ /* on failure to submit, reclaim credits for this packet */
+ LOCK_HTC_TX(target);
+ pEndpoint->CreditDist.TxCreditsToDist += pPacket->PktInfo.AsTx.CreditsUsed;
+ pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
+ DO_DISTRIBUTION(target,
+ HTC_CREDIT_DIST_SEND_COMPLETE,
+ "Send Complete",
+ target->EpCreditDistributionListHead->pNext);
+ UNLOCK_HTC_TX(target);
+ }
+ /* first, fixup the head room we allocated */
+ pPacket->pBuffer += HTC_HDR_LENGTH;
+}
+
+/* our internal send packet completion handler when packets are submited to the AR6K device
+ * layer */
+static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
+{
+ HTC_TARGET *target = (HTC_TARGET *)Context;
+ HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint];
+ HTC_PACKET_QUEUE container;
+
+ CompleteSentPacket(target,pEndpoint,pPacket);
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
+ /* do completion */
+ DO_EP_TX_COMPLETION(pEndpoint,&container);
+}
+
+A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket)
+{
+ A_STATUS status;
+ A_BOOL sync = FALSE;
+
+ if (pPacket->Completion == NULL) {
+ /* mark that this request was synchronously issued */
+ sync = TRUE;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ ("+-HTCIssueSend: transmit length : %d (%s) \n",
+ pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH,
+ sync ? "SYNC" : "ASYNC" ));
+
+ /* send message to device */
+ status = DevSendPacket(&target->Device,
+ pPacket,
+ pPacket->ActualLength + HTC_HDR_LENGTH);
+
+ if (sync) {
+ /* use local sync variable. If this was issued asynchronously, pPacket is no longer
+ * safe to access. */
+ pPacket->pBuffer += HTC_HDR_LENGTH;
+ }
+
+ /* if this request was asynchronous, the packet completion routine will be invoked by
+ * the device layer when the HIF layer completes the request */
+
+ return status;
+}
+
+ /* get HTC send packets from the TX queue on an endpoint */
+static INLINE void GetHTCSendPackets(HTC_TARGET *target,
+ HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET_QUEUE *pQueue)
+{
+ int creditsRequired;
+ int remainder;
+ A_UINT8 sendFlags;
+ HTC_PACKET *pPacket;
+ unsigned int transferLength;
+
+ /****** NOTE : the TX lock is held when this function is called *****************/
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n"));
+
+ /* loop until we can grab as many packets out of the queue as we can */
+ while (TRUE) {
+
+ sendFlags = 0;
+ /* get packet at head, but don't remove it */
+ pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue);
+ if (pPacket == NULL) {
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%lX , Queue Depth: %d\n",
+ (unsigned long)pPacket, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
+
+ transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device, pPacket->ActualLength + HTC_HDR_LENGTH);
+
+ if (transferLength <= target->TargetCreditSize) {
+ creditsRequired = 1;
+ } else {
+ /* figure out how many credits this message requires */
+ creditsRequired = transferLength / target->TargetCreditSize;
+ remainder = transferLength % target->TargetCreditSize;
+
+ if (remainder) {
+ creditsRequired++;
+ }
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
+ creditsRequired, pEndpoint->CreditDist.TxCredits));
+
+ if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
+
+ /* not enough credits */
+ if (pPacket->Endpoint == ENDPOINT_0) {
+ /* leave it in the queue */
+ break;
+ }
+ /* invoke the registered distribution function only if this is not
+ * endpoint 0, we let the driver layer provide more credits if it can.
+ * We pass the credit distribution list starting at the endpoint in question
+ * */
+
+ /* set how many credits we need */
+ pEndpoint->CreditDist.TxCreditsSeek =
+ creditsRequired - pEndpoint->CreditDist.TxCredits;
+ DO_DISTRIBUTION(target,
+ HTC_CREDIT_DIST_SEEK_CREDITS,
+ "Seek Credits",
+ &pEndpoint->CreditDist);
+ pEndpoint->CreditDist.TxCreditsSeek = 0;
+
+ if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
+ /* still not enough credits to send, leave packet in the queue */
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ (" Not enough credits for ep %d leaving packet in queue..\n",
+ pPacket->Endpoint));
+ break;
+ }
+
+ }
+
+ pEndpoint->CreditDist.TxCredits -= creditsRequired;
+ INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
+
+ /* check if we need credits back from the target */
+ if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
+ /* we are getting low on credits, see if we can ask for more from the distribution function */
+ pEndpoint->CreditDist.TxCreditsSeek =
+ pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits;
+
+ DO_DISTRIBUTION(target,
+ HTC_CREDIT_DIST_SEEK_CREDITS,
+ "Seek Credits",
+ &pEndpoint->CreditDist);
+
+ pEndpoint->CreditDist.TxCreditsSeek = 0;
+ /* see if we were successful in getting more */
+ if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
+ /* tell the target we need credits ASAP! */
+ sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
+ INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1);
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n"));
+ }
+ }
+
+ /* now we can fully dequeue */
+ pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
+ /* save the number of credits this packet consumed */
+ pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
+ /* all TX packets are handled asynchronously */
+ pPacket->Completion = HTCSendPktCompletionHandler;
+ pPacket->pContext = target;
+ INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
+ /* save send flags */
+ pPacket->PktInfo.AsTx.SendFlags = sendFlags;
+ pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo;
+ pEndpoint->SeqNo++;
+ /* queue this packet into the caller's queue */
+ HTC_PACKET_ENQUEUE(pQueue,pPacket);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-GetHTCSendPackets \n"));
+
+}
+
+static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
+{
+ int i;
+ HTC_PACKET *pPacket;
+ HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *)pScatterReq->Context;
+ HTC_TARGET *target = (HTC_TARGET *)pEndpoint->target;
+ A_STATUS status = A_OK;
+ HTC_PACKET_QUEUE sendCompletes;
+
+ INIT_HTC_PACKET_QUEUE(&sendCompletes);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCAsyncSendScatterCompletion TotLen: %d Entries: %d\n",
+ pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
+
+ DEV_FINISH_SCATTER_OPERATION(pScatterReq);
+
+ if (A_FAILED(pScatterReq->CompletionStatus)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));
+ status = A_ERROR;
+ }
+
+ /* walk through the scatter list and process */
+ for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
+ pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
+ A_ASSERT(pPacket != NULL);
+ pPacket->Status = status;
+ CompleteSentPacket(target,pEndpoint,pPacket);
+ /* add it to the completion queue */
+ HTC_PACKET_ENQUEUE(&sendCompletes, pPacket);
+ }
+
+ /* free scatter request */
+ DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
+ /* complete all packets */
+ DO_EP_TX_COMPLETION(pEndpoint,&sendCompletes);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCAsyncSendScatterCompletion \n"));
+}
+
+ /* drain a queue and send as bundles
+ * this function may return without fully draining the queue under the following conditions :
+ * - scatter resources are exhausted
+ * - a message that will consume a partial credit will stop the bundling process early
+ * - we drop below the minimum number of messages for a bundle
+ * */
+static void HTCIssueSendBundle(HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET_QUEUE *pQueue,
+ int *pBundlesSent,
+ int *pTotalBundlesPkts)
+{
+ int pktsToScatter;
+ unsigned int scatterSpaceRemaining;
+ HIF_SCATTER_REQ *pScatterReq = NULL;
+ int i, packetsInScatterReq;
+ unsigned int transferLength;
+ HTC_PACKET *pPacket;
+ A_BOOL done = FALSE;
+ int bundlesSent = 0;
+ int totalPktsInBundle = 0;
+ HTC_TARGET *target = pEndpoint->target;
+ int creditRemainder = 0;
+ int creditPad;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCIssueSendBundle \n"));
+
+ while (!done) {
+
+ pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pQueue);
+ pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
+
+ if (pktsToScatter < HTC_MIN_HTC_MSGS_TO_BUNDLE) {
+ /* not enough to bundle */
+ break;
+ }
+
+ pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
+
+ if (pScatterReq == NULL) {
+ /* no scatter resources */
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" No more scatter resources \n"));
+ break;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" pkts to scatter: %d \n", pktsToScatter));
+
+ pScatterReq->TotalLength = 0;
+ pScatterReq->ValidScatterEntries = 0;
+
+ packetsInScatterReq = 0;
+ scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device);
+
+ for (i = 0; i < pktsToScatter; i++) {
+
+ pScatterReq->ScatterList[i].pCallerContexts[0] = NULL;
+
+ pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
+ if (pPacket == NULL) {
+ A_ASSERT(FALSE);
+ break;
+ }
+
+ creditPad = 0;
+ transferLength = DEV_CALC_SEND_PADDED_LEN(&target->Device,
+ pPacket->ActualLength + HTC_HDR_LENGTH);
+ /* see if the padded transfer length falls on a credit boundary */
+ creditRemainder = transferLength % target->TargetCreditSize;
+
+ if (creditRemainder != 0) {
+ /* the transfer consumes a "partial" credit, this packet cannot be bundled unless
+ * we add additional "dummy" padding (max 255 bytes) to consume the entire credit
+ *** NOTE: only allow the send padding if the endpoint is allowed to */
+ if (pEndpoint->LocalConnectionFlags & HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING) {
+ if (transferLength < target->TargetCreditSize) {
+ /* special case where the transfer is less than a credit */
+ creditPad = target->TargetCreditSize - transferLength;
+ } else {
+ creditPad = creditRemainder;
+ }
+
+ /* now check to see if we can indicate padding in the HTC header */
+ if ((creditPad > 0) && (creditPad <= 255)) {
+ /* adjust the transferlength of this packet with the new credit padding */
+ transferLength += creditPad;
+ } else {
+ /* the amount to pad is too large, bail on this packet, we have to
+ * send it using the non-bundled method */
+ pPacket = NULL;
+ }
+ } else {
+ /* bail on this packet, user does not want padding applied */
+ pPacket = NULL;
+ }
+ }
+
+ if (NULL == pPacket) {
+ /* can't bundle */
+ done = TRUE;
+ break;
+ }
+
+ if (scatterSpaceRemaining < transferLength) {
+ /* exceeds what we can transfer */
+ break;
+ }
+
+ scatterSpaceRemaining -= transferLength;
+ /* now remove it from the queue */
+ pPacket = HTC_PACKET_DEQUEUE(pQueue);
+ /* save it in the scatter list */
+ pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
+ /* prepare packet and flag message as part of a send bundle */
+ HTC_PREPARE_SEND_PKT(pPacket,
+ pPacket->PktInfo.AsTx.SendFlags | HTC_FLAGS_SEND_BUNDLE,
+ creditPad,
+ pPacket->PktInfo.AsTx.SeqNo);
+ pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
+ pScatterReq->ScatterList[i].Length = transferLength;
+ A_ASSERT(transferLength);
+ pScatterReq->TotalLength += transferLength;
+ pScatterReq->ValidScatterEntries++;
+ packetsInScatterReq++;
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" %d, Adding packet : 0x%lX, len:%d (remaining space:%d) \n",
+ i, (unsigned long)pPacket,transferLength,scatterSpaceRemaining));
+ }
+
+ if (packetsInScatterReq >= HTC_MIN_HTC_MSGS_TO_BUNDLE) {
+ /* send path is always asynchronous */
+ pScatterReq->CompletionRoutine = HTCAsyncSendScatterCompletion;
+ pScatterReq->Context = pEndpoint;
+ bundlesSent++;
+ totalPktsInBundle += packetsInScatterReq;
+ packetsInScatterReq = 0;
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Send Scatter total bytes: %d , entries: %d\n",
+ pScatterReq->TotalLength,pScatterReq->ValidScatterEntries));
+ DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_WRITE, DEV_SCATTER_ASYNC);
+ /* we don't own this anymore */
+ pScatterReq = NULL;
+ /* try to send some more */
+ continue;
+ }
+
+ /* not enough packets to use the scatter request, cleanup */
+ if (pScatterReq != NULL) {
+ if (packetsInScatterReq > 0) {
+ /* work backwards to requeue requests */
+ for (i = (packetsInScatterReq - 1); i >= 0; i--) {
+ pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
+ if (pPacket != NULL) {
+ /* undo any prep */
+ HTC_UNPREPARE_SEND_PKT(pPacket);
+ /* queue back to the head */
+ HTC_PACKET_ENQUEUE_TO_HEAD(pQueue,pPacket);
+ }
+ }
+ }
+ DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
+ }
+
+ /* if we get here, we sent all that we could, get out */
+ break;
+
+ }
+
+ *pBundlesSent = bundlesSent;
+ *pTotalBundlesPkts = totalPktsInBundle;
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCIssueSendBundle (sent:%d) \n",bundlesSent));
+
+ return;
+}
+
+/*
+ * if there are no credits, the packet(s) remains in the queue.
+ * this function returns the result of the attempt to send a queue of HTC packets */
+static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET *target,
+ HTC_ENDPOINT *pEndpoint,
+ HTC_PACKET_QUEUE *pCallersSendQueue)
+{
+ HTC_PACKET_QUEUE sendQueue; /* temp queue to hold packets at various stages */
+ HTC_PACKET *pPacket;
+ int bundlesSent;
+ int pktsInBundles;
+ int overflow;
+ HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (Queue:0x%lX Depth:%d)\n",
+ (unsigned long)pCallersSendQueue,
+ (pCallersSendQueue == NULL) ? 0 : HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue)));
+
+ /* init the local send queue */
+ INIT_HTC_PACKET_QUEUE(&sendQueue);
+
+ do {
+
+ if (NULL == pCallersSendQueue) {
+ /* caller didn't provide a queue, just wants us to check queues and send */
+ break;
+ }
+
+ if (HTC_QUEUE_EMPTY(pCallersSendQueue)) {
+ /* empty queue */
+ result = HTC_SEND_QUEUE_DROP;
+ break;
+ }
+
+ if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= pEndpoint->MaxTxQueueDepth) {
+ /* we've already overflowed */
+ overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
+ } else {
+ /* figure out how much we will overflow by */
+ overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
+ overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue);
+ /* figure out how much we will overflow the TX queue by */
+ overflow -= pEndpoint->MaxTxQueueDepth;
+ }
+
+ /* if overflow is negative or zero, we are okay */
+ if (overflow > 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ (" Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d \n",
+ pEndpoint->Id, overflow, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue), pEndpoint->MaxTxQueueDepth));
+ }
+ if ((overflow <= 0) || (pEndpoint->EpCallBacks.EpSendFull == NULL)) {
+ /* all packets will fit or caller did not provide send full indication handler
+ * -- just move all of them to the local sendQueue object */
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, pCallersSendQueue);
+ } else {
+ int i;
+ int goodPkts = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - overflow;
+
+ A_ASSERT(goodPkts >= 0);
+ /* we have overflowed, and a callback is provided */
+ /* dequeue all non-overflow packets into the sendqueue */
+ for (i = 0; i < goodPkts; i++) {
+ /* pop off caller's queue*/
+ pPacket = HTC_PACKET_DEQUEUE(pCallersSendQueue);
+ A_ASSERT(pPacket != NULL);
+ /* insert into local queue */
+ HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
+ }
+
+ /* the caller's queue has all the packets that won't fit*/
+ /* walk through the caller's queue and indicate each one to the send full handler */
+ ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, HTC_PACKET, ListLink) {
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n",
+ (unsigned long)pPacket));
+ if (pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext,
+ pPacket) == HTC_SEND_FULL_DROP) {
+ /* callback wants the packet dropped */
+ INC_HTC_EP_STAT(pEndpoint, TxDropped, 1);
+ /* leave this one in the caller's queue for cleanup */
+ } else {
+ /* callback wants to keep this packet, remove from caller's queue */
+ HTC_PACKET_REMOVE(pCallersSendQueue, pPacket);
+ /* put it in the send queue */
+ HTC_PACKET_ENQUEUE(&sendQueue,pPacket);
+ }
+
+ } ITERATE_END;
+
+ if (HTC_QUEUE_EMPTY(&sendQueue)) {
+ /* no packets made it in, caller will cleanup */
+ result = HTC_SEND_QUEUE_DROP;
+ break;
+ }
+ }
+
+ } while (FALSE);
+
+ if (result != HTC_SEND_QUEUE_OK) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
+ return result;
+ }
+
+ LOCK_HTC_TX(target);
+
+ if (!HTC_QUEUE_EMPTY(&sendQueue)) {
+ /* transfer packets */
+ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue,&sendQueue);
+ A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue));
+ INIT_HTC_PACKET_QUEUE(&sendQueue);
+ }
+
+ /* increment tx processing count on entry */
+ pEndpoint->TxProcessCount++;
+ if (pEndpoint->TxProcessCount > 1) {
+ /* another thread or task is draining the TX queues on this endpoint
+ * that thread will reset the tx processing count when the queue is drained */
+ pEndpoint->TxProcessCount--;
+ UNLOCK_HTC_TX(target);
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend (busy) \n"));
+ return HTC_SEND_QUEUE_OK;
+ }
+
+ /***** beyond this point only 1 thread may enter ******/
+
+ /* now drain the endpoint TX queue for transmission as long as we have enough
+ * credits */
+ while (TRUE) {
+
+ if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) {
+ break;
+ }
+
+ /* get all the packets for this endpoint that we can for this pass */
+ GetHTCSendPackets(target, pEndpoint, &sendQueue);
+
+ if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) {
+ /* didn't get any packets due to a lack of credits */
+ break;
+ }
+
+ UNLOCK_HTC_TX(target);
+
+ /* any packets to send are now in our local send queue */
+
+ bundlesSent = 0;
+ pktsInBundles = 0;
+
+ while (TRUE) {
+
+ /* try to send a bundle on each pass */
+ if ((target->SendBundlingEnabled) &&
+ (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
+ int temp1,temp2;
+ /* bundling is enabled and there is at least a minimum number of packets in the send queue
+ * send what we can in this pass */
+ HTCIssueSendBundle(pEndpoint, &sendQueue, &temp1, &temp2);
+ bundlesSent += temp1;
+ pktsInBundles += temp2;
+ }
+
+ /* if not bundling or there was a packet that could not be placed in a bundle, pull it out
+ * and send it the normal way */
+ pPacket = HTC_PACKET_DEQUEUE(&sendQueue);
+ if (NULL == pPacket) {
+ /* local queue is fully drained */
+ break;
+ }
+ HTC_PREPARE_SEND_PKT(pPacket,
+ pPacket->PktInfo.AsTx.SendFlags,
+ 0,
+ pPacket->PktInfo.AsTx.SeqNo);
+ HTCIssueSend(target, pPacket);
+
+ /* go back and see if we can bundle some more */
+ }
+
+ LOCK_HTC_TX(target);
+
+ INC_HTC_EP_STAT(pEndpoint, TxBundles, bundlesSent);
+ INC_HTC_EP_STAT(pEndpoint, TxPacketsBundled, pktsInBundles);
+
+ }
+
+ /* done with this endpoint, we can clear the count */
+ pEndpoint->TxProcessCount = 0;
+ UNLOCK_HTC_TX(target);
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
+
+ return HTC_SEND_QUEUE_OK;
+}
+
+A_STATUS HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ HTC_ENDPOINT *pEndpoint;
+ HTC_PACKET *pPacket;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n",
+ (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
+
+ /* get packet at head to figure out which endpoint these packets will go into */
+ pPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
+ if (NULL == pPacket) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
+ return A_EINVAL;
+ }
+
+ AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
+ pEndpoint = &target->EndPoint[pPacket->Endpoint];
+
+ HTCTrySend(target, pEndpoint, pPktQueue);
+
+ /* do completion on any packets that couldn't get in */
+ if (!HTC_QUEUE_EMPTY(pPktQueue)) {
+
+ HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) {
+ if (HTC_STOPPING(target)) {
+ pPacket->Status = A_ECANCELED;
+ } else {
+ pPacket->Status = A_NO_RESOURCE;
+ }
+ } HTC_PACKET_QUEUE_ITERATE_END;
+
+ DO_EP_TX_COMPLETION(pEndpoint,pPktQueue);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
+
+ return A_OK;
+}
+
+/* HTC API - HTCSendPkt */
+A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
+{
+ HTC_PACKET_QUEUE queue;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
+ ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n",
+ pPacket->Endpoint, (unsigned long)pPacket->pBuffer, pPacket->ActualLength));
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
+ return HTCSendPktsMultiple(HTCHandle, &queue);
+}
+
+/* check TX queues to drain because of credit distribution update */
+static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
+{
+ HTC_ENDPOINT *pEndpoint;
+ HTC_ENDPOINT_CREDIT_DIST *pDistItem;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
+ pDistItem = target->EpCreditDistributionListHead;
+
+ /* run through the credit distribution list to see
+ * if there are packets queued
+ * NOTE: no locks need to be taken since the distribution list
+ * is not dynamic (cannot be re-ordered) and we are not modifying any state */
+ while (pDistItem != NULL) {
+ pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
+
+ if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
+ pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
+ /* try to start the stalled queue, this list is ordered by priority.
+ * Highest priority queue get's processed first, if there are credits available the
+ * highest priority queue will get a chance to reclaim credits from lower priority
+ * ones */
+ HTCTrySend(target, pEndpoint, NULL);
+ }
+
+ pDistItem = pDistItem->pNext;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
+}
+
+/* process credit reports and call distribution function */
+void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
+{
+ int i;
+ HTC_ENDPOINT *pEndpoint;
+ int totalCredits = 0;
+ A_BOOL doDist = FALSE;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
+
+ /* lock out TX while we update credits */
+ LOCK_HTC_TX(target);
+
+ for (i = 0; i < NumEntries; i++, pRpt++) {
+ if (pRpt->EndpointID >= ENDPOINT_MAX) {
+ AR_DEBUG_ASSERT(FALSE);
+ break;
+ }
+
+ pEndpoint = &target->EndPoint[pRpt->EndpointID];
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
+ pRpt->EndpointID, pRpt->Credits));
+
+
+#ifdef HTC_EP_STAT_PROFILING
+
+ INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
+ INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
+
+ if (FromEndpoint == pRpt->EndpointID) {
+ /* this credit report arrived on the same endpoint indicating it arrived in an RX
+ * packet */
+ INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits);
+ INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
+ } else if (FromEndpoint == ENDPOINT_0) {
+ /* this credit arrived on endpoint 0 as a NULL message */
+ INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits);
+ INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
+ } else {
+ /* arrived on another endpoint */
+ INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
+ INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
+ }
+
+#endif
+
+ if (ENDPOINT_0 == pRpt->EndpointID) {
+ /* always give endpoint 0 credits back */
+ pEndpoint->CreditDist.TxCredits += pRpt->Credits;
+ } else {
+ /* for all other endpoints, update credits to distribute, the distribution function
+ * will handle giving out credits back to the endpoints */
+ pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
+ /* flag that we have to do the distribution */
+ doDist = TRUE;
+ }
+
+ /* refresh tx depth for distribution function that will recover these credits
+ * NOTE: this is only valid when there are credits to recover! */
+ pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
+
+ totalCredits += pRpt->Credits;
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits));
+
+ if (doDist) {
+ /* this was a credit return based on a completed send operations
+ * note, this is done with the lock held */
+ DO_DISTRIBUTION(target,
+ HTC_CREDIT_DIST_SEND_COMPLETE,
+ "Send Complete",
+ target->EpCreditDistributionListHead->pNext);
+ }
+
+ UNLOCK_HTC_TX(target);
+
+ if (totalCredits) {
+ HTCCheckEndpointTxQueues(target);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
+}
+
+/* flush endpoint TX queue */
+static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
+{
+ HTC_PACKET *pPacket;
+ HTC_PACKET_QUEUE discardQueue;
+ HTC_PACKET_QUEUE container;
+
+ /* initialize the discard queue */
+ INIT_HTC_PACKET_QUEUE(&discardQueue);
+
+ LOCK_HTC_TX(target);
+
+ /* interate from the front of the TX queue and flush out packets */
+ ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, HTC_PACKET, ListLink) {
+
+ /* check for removal */
+ if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
+ /* remove from queue */
+ HTC_PACKET_REMOVE(&pEndpoint->TxQueue, pPacket);
+ /* add it to the discard pile */
+ HTC_PACKET_ENQUEUE(&discardQueue, pPacket);
+ }
+
+ } ITERATE_END;
+
+ UNLOCK_HTC_TX(target);
+
+ /* empty the discard queue */
+ while (1) {
+ pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
+ if (NULL == pPacket) {
+ break;
+ }
+ pPacket->Status = A_ECANCELED;
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%lX, length:%d, ep:%d tag:0x%X \n",
+ (unsigned long)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag));
+ INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
+ DO_EP_TX_COMPLETION(pEndpoint,&container);
+ }
+
+}
+
+void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
+{
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n",
+ pEPDist->Endpoint, pEPDist->ServiceID));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%lX next:0x%lX prev:0x%lX\n",
+ (unsigned long)pEPDist, (unsigned long)pEPDist->pNext, (unsigned long)pEPDist->pPrev));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n",
+ HTC_PACKET_QUEUE_DEPTH(&((HTC_ENDPOINT *)pEPDist->pHTCReserved)->TxQueue)));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
+}
+
+void DumpCreditDistStates(HTC_TARGET *target)
+{
+ HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
+
+ while (pEPList != NULL) {
+ DumpCreditDist(pEPList);
+ pEPList = pEPList->pNext;
+ }
+
+ if (target->DistributeCredits != NULL) {
+ DO_DISTRIBUTION(target,
+ HTC_DUMP_CREDIT_STATE,
+ "Dump State",
+ NULL);
+ }
+}
+
+/* flush all send packets from all endpoint queues */
+void HTCFlushSendPkts(HTC_TARGET *target)
+{
+ HTC_ENDPOINT *pEndpoint;
+ int i;
+
+ if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
+ DumpCreditDistStates(target);
+ }
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ pEndpoint = &target->EndPoint[i];
+ if (pEndpoint->ServiceID == 0) {
+ /* not in use.. */
+ continue;
+ }
+ HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
+ }
+
+
+}
+
+/* HTC API to flush an endpoint's TX queue*/
+void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
+
+ if (pEndpoint->ServiceID == 0) {
+ AR_DEBUG_ASSERT(FALSE);
+ /* not in use.. */
+ return;
+ }
+
+ HTCFlushEndpointTX(target, pEndpoint, Tag);
+}
+
+/* HTC API to indicate activity to the credit distribution function */
+void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
+ HTC_ENDPOINT_ID Endpoint,
+ A_BOOL Active)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
+ A_BOOL doDist = FALSE;
+
+ if (pEndpoint->ServiceID == 0) {
+ AR_DEBUG_ASSERT(FALSE);
+ /* not in use.. */
+ return;
+ }
+
+ LOCK_HTC_TX(target);
+
+ if (Active) {
+ if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
+ /* mark active now */
+ pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
+ doDist = TRUE;
+ }
+ } else {
+ if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
+ /* mark inactive now */
+ pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
+ doDist = TRUE;
+ }
+ }
+
+ if (doDist) {
+ /* indicate current Tx Queue depth to the credit distribution function */
+ pEndpoint->CreditDist.TxQueueDepth = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue);
+ /* do distribution again based on activity change
+ * note, this is done with the lock held */
+ DO_DISTRIBUTION(target,
+ HTC_CREDIT_DIST_ACTIVITY_CHANGE,
+ "Activity Change",
+ target->EpCreditDistributionListHead->pNext);
+ }
+
+ UNLOCK_HTC_TX(target);
+
+ if (doDist && !Active) {
+ /* if a stream went inactive and this resulted in a credit distribution change,
+ * some credits may now be available for HTC packets that are stuck in
+ * HTC queues */
+ HTCCheckEndpointTxQueues(target);
+ }
+}
+
+A_BOOL HTCIsEndpointActive(HTC_HANDLE HTCHandle,
+ HTC_ENDPOINT_ID Endpoint)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
+
+ if (pEndpoint->ServiceID == 0) {
+ return FALSE;
+ }
+
+ if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/drivers/staging/ath6kl/htc2/htc_services.c b/drivers/staging/ath6kl/htc2/htc_services.c
new file mode 100644
index 00000000000..64fddc0ee37
--- /dev/null
+++ b/drivers/staging/ath6kl/htc2/htc_services.c
@@ -0,0 +1,450 @@
+//------------------------------------------------------------------------------
+// <copyright file="htc_services.c" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#include "htc_internal.h"
+
+void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket)
+{
+ /* not implemented
+ * we do not send control TX frames during normal runtime, only during setup */
+ AR_DEBUG_ASSERT(FALSE);
+}
+
+ /* callback when a control message arrives on this endpoint */
+void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
+{
+ AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);
+
+ if (pPacket->Status == A_ECANCELED) {
+ /* this is a flush operation, return the control packet back to the pool */
+ HTC_FREE_CONTROL_RX((HTC_TARGET*)Context,pPacket);
+ return;
+ }
+
+ /* the only control messages we are expecting are NULL messages (credit resports) */
+ if (pPacket->ActualLength > 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("HTCControlRecv, got message with length:%d \n",
+ pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH));
+
+#ifdef ATH_DEBUG_MODULE
+ /* dump header and message */
+ DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH,
+ pPacket->ActualLength + HTC_HDR_LENGTH,
+ "Unexpected ENDPOINT 0 Message");
+#endif
+ }
+
+ HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket,&((HTC_TARGET*)Context)->EndPoint[0]);
+}
+
+A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
+{
+ HTC_PACKET *pSendPacket = NULL;
+ A_STATUS status;
+
+ do {
+ /* allocate a packet to send to the target */
+ pSendPacket = HTC_ALLOC_CONTROL_TX(target);
+
+ if (NULL == pSendPacket) {
+ status = A_NO_MEMORY;
+ break;
+ }
+
+ if (target->HTCTargetVersion >= HTC_VERSION_2P1) {
+ HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx;
+ A_UINT32 setupFlags = 0;
+
+ pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer;
+ A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
+ pSetupCompleteEx->MessageID = HTC_MSG_SETUP_COMPLETE_EX_ID;
+ if (target->MaxMsgPerBundle > 0) {
+ /* host can do HTC bundling, indicate this to the target */
+ setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
+ pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle;
+ }
+ A_MEMCPY(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags));
+ SET_HTC_PACKET_INFO_TX(pSendPacket,
+ NULL,
+ (A_UINT8 *)pSetupCompleteEx,
+ sizeof(HTC_SETUP_COMPLETE_EX_MSG),
+ ENDPOINT_0,
+ HTC_SERVICE_TX_PACKET_TAG);
+
+ } else {
+ HTC_SETUP_COMPLETE_MSG *pSetupComplete;
+ /* assemble setup complete message */
+ pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer;
+ A_MEMZERO(pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG));
+ pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID;
+ SET_HTC_PACKET_INFO_TX(pSendPacket,
+ NULL,
+ (A_UINT8 *)pSetupComplete,
+ sizeof(HTC_SETUP_COMPLETE_MSG),
+ ENDPOINT_0,
+ HTC_SERVICE_TX_PACKET_TAG);
+ }
+
+ /* we want synchronous operation */
+ pSendPacket->Completion = NULL;
+ HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0);
+ /* send the message */
+ status = HTCIssueSend(target,pSendPacket);
+
+ } while (FALSE);
+
+ if (pSendPacket != NULL) {
+ HTC_FREE_CONTROL_TX(target,pSendPacket);
+ }
+
+ return status;
+}
+
+
+A_STATUS HTCConnectService(HTC_HANDLE HTCHandle,
+ HTC_SERVICE_CONNECT_REQ *pConnectReq,
+ HTC_SERVICE_CONNECT_RESP *pConnectResp)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ A_STATUS status = A_OK;
+ HTC_PACKET *pRecvPacket = NULL;
+ HTC_PACKET *pSendPacket = NULL;
+ HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg;
+ HTC_CONNECT_SERVICE_MSG *pConnectMsg;
+ HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX;
+ HTC_ENDPOINT *pEndpoint;
+ unsigned int maxMsgSize = 0;
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%lX SvcID:0x%X \n",
+ (unsigned long)target, pConnectReq->ServiceID));
+
+ do {
+
+ AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0);
+
+ if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) {
+ /* special case for pseudo control service */
+ assignedEndpoint = ENDPOINT_0;
+ maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH;
+ } else {
+ /* allocate a packet to send to the target */
+ pSendPacket = HTC_ALLOC_CONTROL_TX(target);
+
+ if (NULL == pSendPacket) {
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_NO_MEMORY;
+ break;
+ }
+ /* assemble connect service message */
+ pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer;
+ AR_DEBUG_ASSERT(pConnectMsg != NULL);
+ A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG));
+ pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID;
+ pConnectMsg->ServiceID = pConnectReq->ServiceID;
+ pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags;
+ /* check caller if it wants to transfer meta data */
+ if ((pConnectReq->pMetaData != NULL) &&
+ (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
+ /* copy meta data into message buffer (after header ) */
+ A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
+ pConnectReq->pMetaData,
+ pConnectReq->MetaDataLength);
+ pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength;
+ }
+
+ SET_HTC_PACKET_INFO_TX(pSendPacket,
+ NULL,
+ (A_UINT8 *)pConnectMsg,
+ sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength,
+ ENDPOINT_0,
+ HTC_SERVICE_TX_PACKET_TAG);
+
+ /* we want synchronous operation */
+ pSendPacket->Completion = NULL;
+ HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0);
+ status = HTCIssueSend(target,pSendPacket);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+
+ /* wait for response */
+ status = HTCWaitforControlMessage(target, &pRecvPacket);
+
+ if (A_FAILED(status)) {
+ break;
+ }
+ /* we controlled the buffer creation so it has to be properly aligned */
+ pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer;
+
+ if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) ||
+ (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) {
+ /* this message is not valid */
+ AR_DEBUG_ASSERT(FALSE);
+ status = A_EPROTO;
+ break;
+ }
+
+ pConnectResp->ConnectRespCode = pResponseMsg->Status;
+ /* check response status */
+ if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ (" Target failed service 0x%X connect request (status:%d)\n",
+ pResponseMsg->ServiceID, pResponseMsg->Status));
+ status = A_EPROTO;
+ break;
+ }
+
+ assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID;
+ maxMsgSize = pResponseMsg->MaxMsgSize;
+
+ if ((pConnectResp->pMetaData != NULL) &&
+ (pResponseMsg->ServiceMetaLength > 0) &&
+ (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
+ /* caller supplied a buffer and the target responded with data */
+ int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength);
+ /* copy the meta data */
+ A_MEMCPY(pConnectResp->pMetaData,
+ ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
+ copyLength);
+ pConnectResp->ActualLength = copyLength;
+ }
+
+ }
+
+ /* the rest of these are parameter checks so set the error status */
+ status = A_EPROTO;
+
+ if (assignedEndpoint >= ENDPOINT_MAX) {
+ AR_DEBUG_ASSERT(FALSE);
+ break;
+ }
+
+ if (0 == maxMsgSize) {
+ AR_DEBUG_ASSERT(FALSE);
+ break;
+ }
+
+ pEndpoint = &target->EndPoint[assignedEndpoint];
+ pEndpoint->Id = assignedEndpoint;
+ if (pEndpoint->ServiceID != 0) {
+ /* endpoint already in use! */
+ AR_DEBUG_ASSERT(FALSE);
+ break;
+ }
+
+ /* return assigned endpoint to caller */
+ pConnectResp->Endpoint = assignedEndpoint;
+ pConnectResp->MaxMsgLength = maxMsgSize;
+
+ /* setup the endpoint */
+ pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */
+ pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth;
+ pEndpoint->MaxMsgLength = maxMsgSize;
+ /* copy all the callbacks */
+ pEndpoint->EpCallBacks = pConnectReq->EpCallbacks;
+ /* set the credit distribution info for this endpoint, this information is
+ * passed back to the credit distribution callback function */
+ pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID;
+ pEndpoint->CreditDist.pHTCReserved = pEndpoint;
+ pEndpoint->CreditDist.Endpoint = assignedEndpoint;
+ pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize;
+
+ if (pConnectReq->MaxSendMsgSize != 0) {
+ /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications
+ * since the host will actually issue smaller messages in the Send path */
+ if (pConnectReq->MaxSendMsgSize > maxMsgSize) {
+ /* can't be larger than the maximum the target can support */
+ AR_DEBUG_ASSERT(FALSE);
+ break;
+ }
+ pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize;
+ } else {
+ pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize;
+ }
+
+ if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
+ pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1;
+ }
+
+ /* save local connection flags */
+ pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags;
+
+ status = A_OK;
+
+ } while (FALSE);
+
+ if (pSendPacket != NULL) {
+ HTC_FREE_CONTROL_TX(target,pSendPacket);
+ }
+
+ if (pRecvPacket != NULL) {
+ HTC_FREE_CONTROL_RX(target,pRecvPacket);
+ }
+
+ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n"));
+
+ return status;
+}
+
+static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *pEpDist)
+{
+ HTC_ENDPOINT_CREDIT_DIST *pCurEntry,*pLastEntry;
+
+ if (NULL == target->EpCreditDistributionListHead) {
+ target->EpCreditDistributionListHead = pEpDist;
+ pEpDist->pNext = NULL;
+ pEpDist->pPrev = NULL;
+ return;
+ }
+
+ /* queue to the end of the list, this does not have to be very
+ * fast since this list is built at startup time */
+ pCurEntry = target->EpCreditDistributionListHead;
+
+ while (pCurEntry) {
+ pLastEntry = pCurEntry;
+ pCurEntry = pCurEntry->pNext;
+ }
+
+ pLastEntry->pNext = pEpDist;
+ pEpDist->pPrev = pLastEntry;
+ pEpDist->pNext = NULL;
+}
+
+
+
+/* default credit init callback */
+static void HTCDefaultCreditInit(void *Context,
+ HTC_ENDPOINT_CREDIT_DIST *pEPList,
+ int TotalCredits)
+{
+ HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+ int totalEps = 0;
+ int creditsPerEndpoint;
+
+ pCurEpDist = pEPList;
+ /* first run through the list and figure out how many endpoints we are dealing with */
+ while (pCurEpDist != NULL) {
+ pCurEpDist = pCurEpDist->pNext;
+ totalEps++;
+ }
+
+ /* even distribution */
+ creditsPerEndpoint = TotalCredits/totalEps;
+
+ pCurEpDist = pEPList;
+ /* run through the list and set minimum and normal credits and
+ * provide the endpoint with some credits to start */
+ while (pCurEpDist != NULL) {
+
+ if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) {
+ /* too many endpoints and not enough credits */
+ AR_DEBUG_ASSERT(FALSE);
+ break;
+ }
+ /* our minimum is set for at least 1 max message */
+ pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
+ /* this value is ignored by our credit alg, since we do
+ * not dynamically adjust credits, this is the policy of
+ * the "default" credit distribution, something simple and easy */
+ pCurEpDist->TxCreditsNorm = 0xFFFF;
+ /* give the endpoint minimum credits */
+ pCurEpDist->TxCredits = creditsPerEndpoint;
+ pCurEpDist->TxCreditsAssigned = creditsPerEndpoint;
+ pCurEpDist = pCurEpDist->pNext;
+ }
+
+}
+
+/* default credit distribution callback, NOTE, this callback holds the TX lock */
+void HTCDefaultCreditDist(void *Context,
+ HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
+ HTC_CREDIT_DIST_REASON Reason)
+{
+ HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+
+ if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) {
+ pCurEpDist = pEPDistList;
+ /* simple distribution */
+ while (pCurEpDist != NULL) {
+ if (pCurEpDist->TxCreditsToDist > 0) {
+ /* just give the endpoint back the credits */
+ pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
+ pCurEpDist->TxCreditsToDist = 0;
+ }
+ pCurEpDist = pCurEpDist->pNext;
+ }
+ }
+
+ /* note we do not need to handle the other reason codes as this is a very
+ * simple distribution scheme, no need to seek for more credits or handle inactivity */
+}
+
+void HTCSetCreditDistribution(HTC_HANDLE HTCHandle,
+ void *pCreditDistContext,
+ HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
+ HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
+ HTC_SERVICE_ID ServicePriorityOrder[],
+ int ListLength)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+ int i;
+ int ep;
+
+ if (CreditInitFunc != NULL) {
+ /* caller has supplied their own distribution functions */
+ target->InitCredits = CreditInitFunc;
+ AR_DEBUG_ASSERT(CreditDistFunc != NULL);
+ target->DistributeCredits = CreditDistFunc;
+ target->pCredDistContext = pCreditDistContext;
+ } else {
+ /* caller wants HTC to do distribution */
+ /* if caller wants service to handle distributions then
+ * it must set both of these to NULL! */
+ AR_DEBUG_ASSERT(CreditDistFunc == NULL);
+ target->InitCredits = HTCDefaultCreditInit;
+ target->DistributeCredits = HTCDefaultCreditDist;
+ target->pCredDistContext = target;
+ }
+
+ /* always add HTC control endpoint first, we only expose the list after the
+ * first one, this is added for TX queue checking */
+ AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist);
+
+ /* build the list of credit distribution structures in priority order
+ * supplied by the caller, these will follow endpoint 0 */
+ for (i = 0; i < ListLength; i++) {
+ /* match services with endpoints and add the endpoints to the distribution list
+ * in FIFO order */
+ for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) {
+ if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) {
+ /* queue this one to the list */
+ AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist);
+ break;
+ }
+ }
+ AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
+ }
+
+}
diff --git a/drivers/staging/ath6kl/include/a_config.h b/drivers/staging/ath6kl/include/a_config.h
new file mode 100644
index 00000000000..4a0083c6511
--- /dev/null
+++ b/drivers/staging/ath6kl/include/a_config.h
@@ -0,0 +1,53 @@
+//------------------------------------------------------------------------------
+// <copyright file="a_config.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// This file contains software configuration options that enables
+// specific software "features"
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _A_CONFIG_H_
+#define _A_CONFIG_H_
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/config.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/config.h"
+#endif
+
+#if defined(__linux__) && !defined(LINUX_EMULATION)
+#include "../os/linux/include/config_linux.h"
+#endif
+
+#ifdef REXOS
+#include "../os/rexos/include/common/config_rexos.h"
+#endif
+
+#ifdef WIN_NWF
+#include "../os/windows/include/win/config_win.h"
+#endif
+
+#ifdef THREADX
+#include "../os/threadx/include/common/config_threadx.h"
+#endif
+
+#endif
diff --git a/drivers/staging/ath6kl/include/a_debug.h b/drivers/staging/ath6kl/include/a_debug.h
new file mode 100644
index 00000000000..5a1b01fbb93
--- /dev/null
+++ b/drivers/staging/ath6kl/include/a_debug.h
@@ -0,0 +1,224 @@
+//------------------------------------------------------------------------------
+// <copyright file="a_debug.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _A_DEBUG_H_
+#define _A_DEBUG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <a_types.h>
+#include <a_osapi.h>
+
+ /* standard debug print masks bits 0..7 */
+#define ATH_DEBUG_ERR (1 << 0) /* errors */
+#define ATH_DEBUG_WARN (1 << 1) /* warnings */
+#define ATH_DEBUG_INFO (1 << 2) /* informational (module startup info) */
+#define ATH_DEBUG_TRC (1 << 3) /* generic function call tracing */
+#define ATH_DEBUG_RSVD1 (1 << 4)
+#define ATH_DEBUG_RSVD2 (1 << 5)
+#define ATH_DEBUG_RSVD3 (1 << 6)
+#define ATH_DEBUG_RSVD4 (1 << 7)
+
+#define ATH_DEBUG_MASK_DEFAULTS (ATH_DEBUG_ERR | ATH_DEBUG_WARN)
+#define ATH_DEBUG_ANY 0xFFFF
+
+ /* other aliases used throughout */
+#define ATH_DEBUG_ERROR ATH_DEBUG_ERR
+#define ATH_LOG_ERR ATH_DEBUG_ERR
+#define ATH_LOG_INF ATH_DEBUG_INFO
+#define ATH_LOG_TRC ATH_DEBUG_TRC
+#define ATH_DEBUG_TRACE ATH_DEBUG_TRC
+#define ATH_DEBUG_INIT ATH_DEBUG_INFO
+
+ /* bits 8..31 are module-specific masks */
+#define ATH_DEBUG_MODULE_MASK_SHIFT 8
+
+ /* macro to make a module-specific masks */
+#define ATH_DEBUG_MAKE_MODULE_MASK(index) (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index)))
+
+void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
+
+/* Debug support on a per-module basis
+ *
+ * Usage:
+ *
+ * Each module can utilize it's own debug mask variable. A set of commonly used
+ * masks are provided (ERRORS, WARNINGS, TRACE etc..). It is up to each module
+ * to define module-specific masks using the macros above.
+ *
+ * Each module defines a single debug mask variable debug_XXX where the "name" of the module is
+ * common to all C-files within that module. This requires every C-file that includes a_debug.h
+ * to define the module name in that file.
+ *
+ * Example:
+ *
+ * #define ATH_MODULE_NAME htc
+ * #include "a_debug.h"
+ *
+ * This will define a debug mask structure called debug_htc and all debug macros will reference this
+ * variable.
+ *
+ * A module can define module-specific bit masks using the ATH_DEBUG_MAKE_MODULE_MASK() macro:
+ *
+ * #define ATH_DEBUG_MY_MASK1 ATH_DEBUG_MAKE_MODULE_MASK(0)
+ * #define ATH_DEBUG_MY_MASK2 ATH_DEBUG_MAKE_MODULE_MASK(1)
+ *
+ * The instantiation of the debug structure should be made by the module. When a module is
+ * instantiated, the module can set a description string, a default mask and an array of description
+ * entries containing information on each module-defined debug mask.
+ * NOTE: The instantiation is statically allocated, only one instance can exist per module.
+ *
+ * Example:
+ *
+ *
+ * #define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
+ *
+ * #ifdef DEBUG
+ * static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
+ * { ATH_DEBUG_BMI , "BMI Tracing"}, <== description of the module specific mask
+ * };
+ *
+ * ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
+ * "bmi" <== module name
+ * "Boot Manager Interface", <== description of module
+ * ATH_DEBUG_MASK_DEFAULTS, <== defaults
+ * ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
+ * bmi_debug_desc);
+ *
+ * #endif
+ *
+ * A module can optionally register it's debug module information in order for other tools to change the
+ * bit mask at runtime. A module can call A_REGISTER_MODULE_DEBUG_INFO() in it's module
+ * init code. This macro can be called multiple times without consequence. The debug info maintains
+ * state to indicate whether the information was previously registered.
+ *
+ * */
+
+#define ATH_DEBUG_MAX_MASK_DESC_LENGTH 32
+#define ATH_DEBUG_MAX_MOD_DESC_LENGTH 64
+
+typedef struct {
+ A_UINT32 Mask;
+ A_CHAR Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH];
+} ATH_DEBUG_MASK_DESCRIPTION;
+
+#define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0)
+
+typedef struct _ATH_DEBUG_MODULE_DBG_INFO{
+ struct _ATH_DEBUG_MODULE_DBG_INFO *pNext;
+ A_CHAR ModuleName[16];
+ A_CHAR ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH];
+ A_UINT32 Flags;
+ A_UINT32 CurrentMask;
+ int MaxDescriptions;
+ ATH_DEBUG_MASK_DESCRIPTION *pMaskDescriptions; /* pointer to array of descriptions */
+} ATH_DEBUG_MODULE_DBG_INFO;
+
+#define ATH_DEBUG_DESCRIPTION_COUNT(d) (int)((sizeof((d))) / (sizeof(ATH_DEBUG_MASK_DESCRIPTION)))
+
+#define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s)
+#define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask
+#define _XGET_ATH_MODULE_NAME_DEBUG_(s) debug_ ## s
+
+#ifdef ATH_DEBUG_MODULE
+
+ /* for source files that will instantiate the debug variables */
+#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions) \
+ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s) = \
+ {NULL,(name),(moddesc),0,(initmask),count,(descriptions)}
+
+#ifdef ATH_MODULE_NAME
+extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(ATH_MODULE_NAME);
+#define AR_DEBUG_LVL_CHECK(lvl) (GET_ATH_MODULE_DEBUG_VAR_MASK(ATH_MODULE_NAME) & (lvl))
+#endif /* ATH_MODULE_NAME */
+
+#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl) GET_ATH_MODULE_DEBUG_VAR_MASK(s) = (lvl)
+
+#define ATH_DEBUG_DECLARE_EXTERN(s) \
+ extern ATH_DEBUG_MODULE_DBG_INFO GET_ATH_MODULE_DEBUG_VAR_NAME(s)
+
+#define AR_DEBUG_PRINTBUF(buffer, length, desc) DebugDumpBytes(buffer,length,desc)
+
+
+#define AR_DEBUG_ASSERT A_ASSERT
+
+void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo);
+void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo);
+#define A_DUMP_MODULE_DEBUG_INFO(s) a_dump_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s)))
+#define A_REGISTER_MODULE_DEBUG_INFO(s) a_register_module_debug_info(&(GET_ATH_MODULE_DEBUG_VAR_NAME(s)))
+
+#else /* !ATH_DEBUG_MODULE */
+ /* NON ATH_DEBUG_MODULE */
+#define ATH_DEBUG_INSTANTIATE_MODULE_VAR(s,name,moddesc,initmask,count,descriptions)
+#define AR_DEBUG_LVL_CHECK(lvl) 0
+#define AR_DEBUG_PRINTBUF(buffer, length, desc)
+#define AR_DEBUG_ASSERT(test)
+#define ATH_DEBUG_DECLARE_EXTERN(s)
+#define ATH_DEBUG_SET_DEBUG_MASK(s,lvl)
+#define A_DUMP_MODULE_DEBUG_INFO(s)
+#define A_REGISTER_MODULE_DEBUG_INFO(s)
+
+#endif
+
+A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask);
+A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask);
+void a_dump_module_debug_info_by_name(A_CHAR *module_name);
+void a_module_debug_support_init(void);
+void a_module_debug_support_cleanup(void);
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/debug.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/debug.h"
+#endif
+
+#if defined(__linux__) && !defined(LINUX_EMULATION)
+#include "../os/linux/include/debug_linux.h"
+#endif
+
+#ifdef REXOS
+#include "../os/rexos/include/common/debug_rexos.h"
+#endif
+
+#if defined ART_WIN
+#include "../os/win_art/include/debug_win.h"
+#endif
+
+#ifdef WIN_NWF
+#include <debug_win.h>
+#endif
+
+#ifdef THREADX
+#define ATH_DEBUG_MAKE_MODULE_MASK(index) (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index)))
+#include "../os/threadx/include/common/debug_threadx.h"
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/drivers/staging/ath6kl/include/a_drv.h b/drivers/staging/ath6kl/include/a_drv.h
new file mode 100644
index 00000000000..6db10f0f2d1
--- /dev/null
+++ b/drivers/staging/ath6kl/include/a_drv.h
@@ -0,0 +1,54 @@
+//------------------------------------------------------------------------------
+// <copyright file="a_drv.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// This file contains the definitions of the basic atheros data types.
+// It is used to map the data types in atheros files to a platform specific
+// type.
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _A_DRV_H_
+#define _A_DRV_H_
+
+#if defined(__linux__) && !defined(LINUX_EMULATION)
+#include "../os/linux/include/athdrv_linux.h"
+#endif
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/athdrv.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/athdrv.h"
+#endif
+
+#ifdef REXOS
+#include "../os/rexos/include/common/athdrv_rexos.h"
+#endif
+
+#ifdef WIN_NWF
+#include "../os/windows/include/athdrv.h"
+#endif
+
+#ifdef THREADX
+#include "../os/threadx/include/common/athdrv_threadx.h"
+#endif
+
+#endif /* _ADRV_H_ */
diff --git a/drivers/staging/ath6kl/include/a_drv_api.h b/drivers/staging/ath6kl/include/a_drv_api.h
new file mode 100644
index 00000000000..7d077c62ad7
--- /dev/null
+++ b/drivers/staging/ath6kl/include/a_drv_api.h
@@ -0,0 +1,232 @@
+//------------------------------------------------------------------------------
+// <copyright file="a_drv_api.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _A_DRV_API_H_
+#define _A_DRV_API_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************/
+/****************************************************************************/
+/** **/
+/** WMI related hooks **/
+/** **/
+/****************************************************************************/
+/****************************************************************************/
+
+#include <ar6000_api.h>
+
+#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \
+ ar6000_channelList_rx((devt), (numChan), (chanList))
+
+#define A_WMI_SET_NUMDATAENDPTS(devt, num) \
+ ar6000_set_numdataendpts((devt), (num))
+
+#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \
+ ar6000_control_tx((devt), (osbuf), (streamID))
+
+#define A_WMI_TARGETSTATS_EVENT(devt, pStats, len) \
+ ar6000_targetStats_event((devt), (pStats), (len))
+
+#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \
+ ar6000_scanComplete_event((devt), (status))
+
+#ifdef CONFIG_HOST_DSET_SUPPORT
+
+#define A_WMI_DSET_DATA_REQ(devt, access_cookie, offset, length, targ_buf, targ_reply_fn, targ_reply_arg) \
+ ar6000_dset_data_req((devt), (access_cookie), (offset), (length), (targ_buf), (targ_reply_fn), (targ_reply_arg))
+
+#define A_WMI_DSET_CLOSE(devt, access_cookie) \
+ ar6000_dset_close((devt), (access_cookie))
+
+#endif
+
+#define A_WMI_DSET_OPEN_REQ(devt, id, targ_handle, targ_reply_fn, targ_reply_arg) \
+ ar6000_dset_open_req((devt), (id), (targ_handle), (targ_reply_fn), (targ_reply_arg))
+
+#define A_WMI_CONNECT_EVENT(devt, channel, bssid, listenInterval, beaconInterval, networkType, beaconIeLen, assocReqLen, assocRespLen, assocInfo) \
+ ar6000_connect_event((devt), (channel), (bssid), (listenInterval), (beaconInterval), (networkType), (beaconIeLen), (assocReqLen), (assocRespLen), (assocInfo))
+
+#define A_WMI_PSPOLL_EVENT(devt, aid)\
+ ar6000_pspoll_event((devt),(aid))
+
+#define A_WMI_DTIMEXPIRY_EVENT(devt)\
+ ar6000_dtimexpiry_event((devt))
+
+#ifdef WAPI_ENABLE
+#define A_WMI_WAPI_REKEY_EVENT(devt, type, mac)\
+ ap_wapi_rekey_event((devt),(type),(mac))
+#endif
+
+#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \
+ ar6000_regDomain_event((devt), (regCode))
+
+#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \
+ ar6000_neighborReport_event((devt), (numAps), (info))
+
+#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \
+ ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus))
+
+#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \
+ ar6000_tkip_micerr_event((devt), (keyid), (ismcast))
+
+#define A_WMI_BITRATE_RX(devt, rateKbps) \
+ ar6000_bitrate_rx((devt), (rateKbps))
+
+#define A_WMI_TXPWR_RX(devt, txPwr) \
+ ar6000_txPwr_rx((devt), (txPwr))
+
+#define A_WMI_READY_EVENT(devt, datap, phyCap, sw_ver, abi_ver) \
+ ar6000_ready_event((devt), (datap), (phyCap), (sw_ver), (abi_ver))
+
+#define A_WMI_DBGLOG_INIT_DONE(ar) \
+ ar6000_dbglog_init_done(ar);
+
+#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \
+ ar6000_rssiThreshold_event((devt), (newThreshold), (rssi))
+
+#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \
+ ar6000_reportError_event((devt), (errorVal))
+
+#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \
+ ar6000_roam_tbl_event((devt), (pTbl))
+
+#define A_WMI_ROAM_DATA_EVENT(devt, p) \
+ ar6000_roam_data_event((devt), (p))
+
+#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \
+ ar6000_wow_list_event((devt), (num_filters), (wow_filters))
+
+#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \
+ ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion))
+
+#define A_WMI_CHANNEL_CHANGE_EVENT(devt, oldChannel, newChannel) \
+ ar6000_channel_change_event((devt), (oldChannel), (newChannel))
+
+#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list, bssid_list) \
+ ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list), (bssid_list))
+
+#define A_WMI_PEER_EVENT(devt, eventCode, bssid) \
+ ar6000_peer_event ((devt), (eventCode), (bssid))
+
+#ifdef CONFIG_HOST_GPIO_SUPPORT
+
+#define A_WMI_GPIO_INTR_RX(intr_mask, input_values) \
+ ar6000_gpio_intr_rx((intr_mask), (input_values))
+
+#define A_WMI_GPIO_DATA_RX(reg_id, value) \
+ ar6000_gpio_data_rx((reg_id), (value))
+
+#define A_WMI_GPIO_ACK_RX() \
+ ar6000_gpio_ack_rx()
+
+#endif
+
+#ifdef SEND_EVENT_TO_APP
+
+#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len) \
+ ar6000_send_event_to_app((ar), (eventId), (datap), (len))
+
+#define A_WMI_SEND_GENERIC_EVENT_TO_APP(ar, eventId, datap, len) \
+ ar6000_send_generic_event_to_app((ar), (eventId), (datap), (len))
+
+#else
+
+#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len)
+#define A_WMI_SEND_GENERIC_EVENT_TO_APP(ar, eventId, datap, len)
+
+#endif
+
+#ifdef CONFIG_HOST_TCMD_SUPPORT
+#define A_WMI_TCMD_RX_REPORT_EVENT(devt, results, len) \
+ ar6000_tcmd_rx_report_event((devt), (results), (len))
+#endif
+
+#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \
+ ar6000_hbChallengeResp_event((devt), (cookie), (source))
+
+#define A_WMI_TX_RETRY_ERR_EVENT(devt) \
+ ar6000_tx_retry_err_event((devt))
+
+#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \
+ ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr))
+
+#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \
+ ar6000_lqThresholdEvent_rx((devt), (range), (lqVal))
+
+#define A_WMI_RATEMASK_RX(devt, ratemask) \
+ ar6000_ratemask_rx((devt), (ratemask))
+
+#define A_WMI_KEEPALIVE_RX(devt, configured) \
+ ar6000_keepalive_rx((devt), (configured))
+
+#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \
+ ar6000_bssInfo_event_rx((ar), (datap), (len))
+
+#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \
+ ar6000_dbglog_event((ar), (dropped), (buffer), (length));
+
+#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \
+ ar6000_indicate_tx_activity((devt),(trafficClass), TRUE)
+
+#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \
+ ar6000_indicate_tx_activity((devt),(trafficClass), FALSE)
+#define A_WMI_Ac2EndpointID(devht, ac)\
+ ar6000_ac2_endpoint_id((devht), (ac))
+
+#define A_WMI_AGGR_RECV_ADDBA_REQ_EVT(devt, cmd)\
+ ar6000_aggr_rcv_addba_req_evt((devt), (cmd))
+#define A_WMI_AGGR_RECV_ADDBA_RESP_EVT(devt, cmd)\
+ ar6000_aggr_rcv_addba_resp_evt((devt), (cmd))
+#define A_WMI_AGGR_RECV_DELBA_REQ_EVT(devt, cmd)\
+ ar6000_aggr_rcv_delba_req_evt((devt), (cmd))
+#define A_WMI_HCI_EVENT_EVT(devt, cmd)\
+ ar6000_hci_event_rcv_evt((devt), (cmd))
+
+#define A_WMI_Endpoint2Ac(devt, ep) \
+ ar6000_endpoint_id2_ac((devt), (ep))
+
+#define A_WMI_BTCOEX_CONFIG_EVENT(devt, evt, len)\
+ ar6000_btcoex_config_event((devt), (evt), (len))
+
+#define A_WMI_BTCOEX_STATS_EVENT(devt, datap, len)\
+ ar6000_btcoex_stats_event((devt), (datap), (len))
+
+/****************************************************************************/
+/****************************************************************************/
+/** **/
+/** HTC related hooks **/
+/** **/
+/****************************************************************************/
+/****************************************************************************/
+
+#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
+#define A_WMI_PROF_COUNT_RX(addr, count) prof_count_rx((addr), (count))
+#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/staging/ath6kl/include/a_osapi.h b/drivers/staging/ath6kl/include/a_osapi.h
new file mode 100644
index 00000000000..7bdeeea2150
--- /dev/null
+++ b/drivers/staging/ath6kl/include/a_osapi.h
@@ -0,0 +1,61 @@
+//------------------------------------------------------------------------------
+// <copyright file="a_osapi.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// This file contains the definitions of the basic atheros data types.
+// It is used to map the data types in atheros files to a platform specific
+// type.
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _A_OSAPI_H_
+#define _A_OSAPI_H_
+
+#if defined(__linux__) && !defined(LINUX_EMULATION)
+#include "../os/linux/include/osapi_linux.h"
+#endif
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/osapi.h"
+#include "../os/windows/include/netbuf.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/osapi.h"
+#include "../os/windows/include/netbuf.h"
+#endif
+
+#ifdef REXOS
+#include "../os/rexos/include/common/osapi_rexos.h"
+#endif
+
+#if defined ART_WIN
+#include "../os/win_art/include/osapi_win.h"
+#include "../os/win_art/include/netbuf.h"
+#endif
+
+#ifdef WIN_NWF
+#include <osapi_win.h>
+#endif
+
+#if defined(THREADX)
+#include "../os/threadx/include/common/osapi_threadx.h"
+#endif
+
+#endif /* _OSAPI_H_ */
diff --git a/drivers/staging/ath6kl/include/a_types.h b/drivers/staging/ath6kl/include/a_types.h
new file mode 100644
index 00000000000..18f4cfe4f97
--- /dev/null
+++ b/drivers/staging/ath6kl/include/a_types.h
@@ -0,0 +1,58 @@
+//------------------------------------------------------------------------------
+// <copyright file="a_types.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// This file contains the definitions of the basic atheros data types.
+// It is used to map the data types in atheros files to a platform specific
+// type.
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _A_TYPES_H_
+#define _A_TYPES_H_
+
+#if defined(__linux__) && !defined(LINUX_EMULATION)
+#include "../os/linux/include/athtypes_linux.h"
+#endif
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/athtypes.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/athtypes.h"
+#endif
+
+#ifdef REXOS
+#include "../os/rexos/include/common/athtypes_rexos.h"
+#endif
+
+#if defined ART_WIN
+#include "../os/win_art/include/athtypes_win.h"
+#endif
+
+#ifdef WIN_NWF
+#include <athtypes_win.h>
+#endif
+
+#ifdef THREADX
+#include "../os/threadx/include/common/athtypes_threadx.h"
+#endif
+
+#endif /* _ATHTYPES_H_ */
diff --git a/drivers/staging/ath6kl/include/aggr_recv_api.h b/drivers/staging/ath6kl/include/aggr_recv_api.h
new file mode 100644
index 00000000000..0682bb4edcf
--- /dev/null
+++ b/drivers/staging/ath6kl/include/aggr_recv_api.h
@@ -0,0 +1,140 @@
+/*
+ *
+ * Copyright (c) 2004-2010 Atheros Communications Inc.
+ * All rights reserved.
+ *
+ *
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+ *
+ */
+
+#ifndef __AGGR_RECV_API_H__
+#define __AGGR_RECV_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (* RX_CALLBACK)(void * dev, void *osbuf);
+
+typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, A_UINT16 num);
+
+/*
+ * aggr_init:
+ * Initialises the data structures, allocates data queues and
+ * os buffers. Netbuf allocator is the input param, used by the
+ * aggr module for allocation of NETBUFs from driver context.
+ * These NETBUFs are used for AMSDU processing.
+ * Returns the context for the aggr module.
+ */
+void *
+aggr_init(ALLOC_NETBUFS netbuf_allocator);
+
+
+/*
+ * aggr_register_rx_dispatcher:
+ * Registers OS call back function to deliver the
+ * frames to OS. This is generally the topmost layer of
+ * the driver context, after which the frames go to
+ * IP stack via the call back function.
+ * This dispatcher is active only when aggregation is ON.
+ */
+void
+aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn);
+
+
+/*
+ * aggr_process_bar:
+ * When target receives BAR, it communicates to host driver
+ * for modifying window parameters. Target indicates this via the
+ * event: WMI_ADDBA_REQ_EVENTID. Host will dequeue all frames
+ * up to the indicated sequence number.
+ */
+void
+aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no);
+
+
+/*
+ * aggr_recv_addba_req_evt:
+ * This event is to initiate/modify the receive side window.
+ * Target will send WMI_ADDBA_REQ_EVENTID event to host - to setup
+ * recv re-ordering queues. Target will negotiate ADDBA with peer,
+ * and indicate via this event after succesfully completing the
+ * negotiation. This happens in two situations:
+ * 1. Initial setup of aggregation
+ * 2. Renegotiation of current recv window.
+ * Window size for re-ordering is limited by target buffer
+ * space, which is reflected in win_sz.
+ * (Re)Start the periodic timer to deliver long standing frames,
+ * in hold_q to OS.
+ */
+void
+aggr_recv_addba_req_evt(void * cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_sz);
+
+
+/*
+ * aggr_recv_delba_req_evt:
+ * Target indicates deletion of a BA window for a tid via the
+ * WMI_DELBA_EVENTID. Host would deliver all the frames in the
+ * hold_q, reset tid config and disable the periodic timer, if
+ * aggr is not enabled on any tid.
+ */
+void
+aggr_recv_delba_req_evt(void * cntxt, A_UINT8 tid);
+
+
+
+/*
+ * aggr_process_recv_frm:
+ * Called only for data frames. When aggr is ON for a tid, the buffer
+ * is always consumed, and osbuf would be NULL. For a non-aggr case,
+ * osbuf is not modified.
+ * AMSDU frames are consumed and are later freed. They are sliced and
+ * diced to individual frames and dispatched to stack.
+ * After consuming a osbuf(when aggr is ON), a previously registered
+ * callback may be called to deliver frames in order.
+ */
+void
+aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu, void **osbuf);
+
+
+/*
+ * aggr_module_destroy:
+ * Frees up all the queues and frames in them. Releases the cntxt to OS.
+ */
+void
+aggr_module_destroy(void *cntxt);
+
+/*
+ * Dumps the aggregation stats
+ */
+void
+aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf);
+
+/*
+ * aggr_reset_state -- Called when it is deemed necessary to clear the aggregate
+ * hold Q state. Examples include when a Connect event or disconnect event is
+ * received.
+ */
+void
+aggr_reset_state(void *cntxt);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__AGGR_RECV_API_H__ */
diff --git a/drivers/staging/ath6kl/include/ar3kconfig.h b/drivers/staging/ath6kl/include/ar3kconfig.h
new file mode 100644
index 00000000000..a10788cee46
--- /dev/null
+++ b/drivers/staging/ath6kl/include/ar3kconfig.h
@@ -0,0 +1,65 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+
+/* AR3K module configuration APIs for HCI-bridge operation */
+
+#ifndef AR3KCONFIG_H_
+#define AR3KCONFIG_H_
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT (1 << 0)
+#define AR3K_CONFIG_FLAG_SET_AR3K_BAUD (1 << 1)
+#define AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY (1 << 2)
+#define AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP (1 << 3)
+
+
+typedef struct {
+ A_UINT32 Flags; /* config flags */
+ void *pHCIDev; /* HCI bridge device */
+ HCI_TRANSPORT_PROPERTIES *pHCIProps; /* HCI bridge props */
+ HIF_DEVICE *pHIFDevice; /* HIF layer device */
+
+ A_UINT32 AR3KBaudRate; /* AR3K operational baud rate */
+ A_UINT16 AR6KScale; /* AR6K UART scale value */
+ A_UINT16 AR6KStep; /* AR6K UART step value */
+ struct hci_dev *pBtStackHCIDev; /* BT Stack HCI dev */
+ A_UINT32 PwrMgmtEnabled; /* TLPM enabled? */
+ A_UINT16 IdleTimeout; /* TLPM idle timeout */
+ A_UINT16 WakeupTimeout; /* TLPM wakeup timeout */
+ A_UINT8 bdaddr[6]; /* Bluetooth device address */
+} AR3K_CONFIG_INFO;
+
+A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfigInfo);
+
+A_STATUS AR3KConfigureExit(void *config);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*AR3KCONFIG_H_*/
diff --git a/drivers/staging/ath6kl/include/ar6000_api.h b/drivers/staging/ath6kl/include/ar6000_api.h
new file mode 100644
index 00000000000..1e1d92a507e
--- /dev/null
+++ b/drivers/staging/ath6kl/include/ar6000_api.h
@@ -0,0 +1,54 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6000_api.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// This file contains the API to access the OS dependent atheros host driver
+// by the WMI or WLAN generic modules.
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _AR6000_API_H_
+#define _AR6000_API_H_
+
+#if defined(__linux__) && !defined(LINUX_EMULATION)
+#include "../os/linux/include/ar6xapi_linux.h"
+#endif
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/ar6xapi.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/ar6xapi.h"
+#endif
+
+#ifdef REXOS
+#include "../os/rexos/include/common/ar6xapi_rexos.h"
+#endif
+
+#if defined ART_WIN
+#include "../os/win_art/include/ar6xapi_win.h"
+#endif
+
+#ifdef WIN_NWF
+#include "../os/windows/include/ar6xapi.h"
+#endif
+
+#endif /* _AR6000_API_H */
+
diff --git a/drivers/staging/ath6kl/include/ar6000_diag.h b/drivers/staging/ath6kl/include/ar6000_diag.h
new file mode 100644
index 00000000000..b53512e23d3
--- /dev/null
+++ b/drivers/staging/ath6kl/include/ar6000_diag.h
@@ -0,0 +1,48 @@
+//------------------------------------------------------------------------------
+// <copyright file="ar6000_diag.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+
+#ifndef AR6000_DIAG_H_
+#define AR6000_DIAG_H_
+
+
+A_STATUS
+ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+
+A_STATUS
+ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+
+A_STATUS
+ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
+ A_UCHAR *data, A_UINT32 length);
+
+A_STATUS
+ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
+ A_UCHAR *data, A_UINT32 length);
+
+A_STATUS
+ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval);
+
+void
+ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs);
+
+#endif /*AR6000_DIAG_H_*/
diff --git a/drivers/staging/ath6kl/include/ar6kap_common.h b/drivers/staging/ath6kl/include/ar6kap_common.h
new file mode 100644
index 00000000000..9b1b8bfae67
--- /dev/null
+++ b/drivers/staging/ath6kl/include/ar6kap_common.h
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+
+// <copyright file="ar6kap_common.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+
+//==============================================================================
+
+// This file contains the definitions of common AP mode data structures.
+//
+// Author(s): ="Atheros"
+//==============================================================================
+
+#ifndef _AR6KAP_COMMON_H_
+#define _AR6KAP_COMMON_H_
+/*
+ * Used with AR6000_XIOCTL_AP_GET_STA_LIST
+ */
+typedef struct {
+ A_UINT8 mac[ATH_MAC_LEN];
+ A_UINT8 aid;
+ A_UINT8 keymgmt;
+ A_UINT8 ucipher;
+ A_UINT8 auth;
+} station_t;
+typedef struct {
+ station_t sta[AP_MAX_NUM_STA];
+} ap_get_sta_t;
+#endif /* _AR6KAP_COMMON_H_ */
diff --git a/drivers/staging/ath6kl/include/athbtfilter.h b/drivers/staging/ath6kl/include/athbtfilter.h
new file mode 100644
index 00000000000..dbe68bbb727
--- /dev/null
+++ b/drivers/staging/ath6kl/include/athbtfilter.h
@@ -0,0 +1,135 @@
+//------------------------------------------------------------------------------
+// <copyright file="athbtfilter.h" company="Atheros">
+// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Public Bluetooth filter APIs
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef ATHBTFILTER_H_
+#define ATHBTFILTER_H_
+
+#define ATH_DEBUG_INFO (1 << 2)
+#define ATH_DEBUG_INF ATH_DEBUG_INFO
+
+typedef enum _ATHBT_HCI_CTRL_TYPE {
+ ATHBT_HCI_COMMAND = 0,
+ ATHBT_HCI_EVENT = 1,
+} ATHBT_HCI_CTRL_TYPE;
+
+typedef enum _ATHBT_STATE_INDICATION {
+ ATH_BT_NOOP = 0,
+ ATH_BT_INQUIRY = 1,
+ ATH_BT_CONNECT = 2,
+ ATH_BT_SCO = 3,
+ ATH_BT_ACL = 4,
+ ATH_BT_A2DP = 5,
+ ATH_BT_ESCO = 6,
+ /* new states go here.. */
+
+ ATH_BT_MAX_STATE_INDICATION
+} ATHBT_STATE_INDICATION;
+
+ /* filter function for OUTGOING commands and INCOMMING events */
+typedef void (*ATHBT_FILTER_CMD_EVENTS_FN)(void *pContext, ATHBT_HCI_CTRL_TYPE Type, unsigned char *pBuffer, int Length);
+
+ /* filter function for OUTGOING data HCI packets */
+typedef void (*ATHBT_FILTER_DATA_FN)(void *pContext, unsigned char *pBuffer, int Length);
+
+typedef enum _ATHBT_STATE {
+ STATE_OFF = 0,
+ STATE_ON = 1,
+ STATE_MAX
+} ATHBT_STATE;
+
+ /* BT state indication (when filter functions are not used) */
+
+typedef void (*ATHBT_INDICATE_STATE_FN)(void *pContext, ATHBT_STATE_INDICATION Indication, ATHBT_STATE State, unsigned char LMPVersion);
+
+typedef struct _ATHBT_FILTER_INSTANCE {
+#ifdef UNDER_CE
+ WCHAR *pWlanAdapterName; /* filled in by user */
+#else
+ char *pWlanAdapterName; /* filled in by user */
+#endif /* UNDER_CE */
+ int FilterEnabled; /* filtering is enabled */
+ int Attached; /* filter library is attached */
+ void *pContext; /* private context for filter library */
+ ATHBT_FILTER_CMD_EVENTS_FN pFilterCmdEvents; /* function ptr to filter a command or event */
+ ATHBT_FILTER_DATA_FN pFilterAclDataOut; /* function ptr to filter ACL data out (to radio) */
+ ATHBT_FILTER_DATA_FN pFilterAclDataIn; /* function ptr to filter ACL data in (from radio) */
+ ATHBT_INDICATE_STATE_FN pIndicateState; /* function ptr to indicate a state */
+} ATH_BT_FILTER_INSTANCE;
+
+
+/* API MACROS */
+
+#define AthBtFilterHciCommand(instance,packet,length) \
+ if ((instance)->FilterEnabled) { \
+ (instance)->pFilterCmdEvents((instance)->pContext, \
+ ATHBT_HCI_COMMAND, \
+ (unsigned char *)(packet), \
+ (length)); \
+ }
+
+#define AthBtFilterHciEvent(instance,packet,length) \
+ if ((instance)->FilterEnabled) { \
+ (instance)->pFilterCmdEvents((instance)->pContext, \
+ ATHBT_HCI_EVENT, \
+ (unsigned char *)(packet), \
+ (length)); \
+ }
+
+#define AthBtFilterHciAclDataOut(instance,packet,length) \
+ if ((instance)->FilterEnabled) { \
+ (instance)->pFilterAclDataOut((instance)->pContext, \
+ (unsigned char *)(packet), \
+ (length)); \
+ }
+
+#define AthBtFilterHciAclDataIn(instance,packet,length) \
+ if ((instance)->FilterEnabled) { \
+ (instance)->pFilterAclDataIn((instance)->pContext, \
+ (unsigned char *)(packet), \
+ (length)); \
+ }
+
+/* if filtering is not desired, the application can indicate the state directly using this
+ * macro:
+ */
+#define AthBtIndicateState(instance,indication,state) \
+ if ((instance)->FilterEnabled) { \
+ (instance)->pIndicateState((instance)->pContext, \
+ (indication), \
+ (state), \
+ 0); \
+ }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* API prototypes */
+int AthBtFilter_Attach(ATH_BT_FILTER_INSTANCE *pInstance, unsigned int flags);
+void AthBtFilter_Detach(ATH_BT_FILTER_INSTANCE *pInstance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ATHBTFILTER_H_*/
diff --git a/drivers/staging/ath6kl/include/athendpack.h b/drivers/staging/ath6kl/include/athendpack.h
new file mode 100644
index 00000000000..1b940503bb2
--- /dev/null
+++ b/drivers/staging/ath6kl/include/athendpack.h
@@ -0,0 +1,52 @@
+//------------------------------------------------------------------------------
+// <copyright file="athendpack.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// end compiler-specific structure packing
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifdef VXWORKS
+#endif /* VXWORKS */
+
+#if defined(LINUX) || defined(__linux__)
+#endif /* LINUX */
+
+#ifdef QNX
+#endif /* QNX */
+
+#ifdef INTEGRITY
+#include "integrity/athendpack_integrity.h"
+#endif /* INTEGRITY */
+
+#ifdef NUCLEUS
+#endif /* NUCLEUS */
+
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/athendpack.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/athendpack.h"
+#endif /* WINCE */
+
+#ifdef WIN_NWF
+#include <athendpack_win.h>
+#endif
diff --git a/drivers/staging/ath6kl/include/athstartpack.h b/drivers/staging/ath6kl/include/athstartpack.h
new file mode 100644
index 00000000000..1c45f666d8a
--- /dev/null
+++ b/drivers/staging/ath6kl/include/athstartpack.h
@@ -0,0 +1,55 @@
+//------------------------------------------------------------------------------
+// <copyright file="athstartpack.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// start compiler-specific structure packing
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifdef VXWORKS
+#endif /* VXWORKS */
+
+#if defined(LINUX) || defined(__linux__)
+#endif /* LINUX */
+
+#ifdef QNX
+#endif /* QNX */
+
+#ifdef INTEGRITY
+#include "integrity/athstartpack_integrity.h"
+#endif /* INTEGRITY */
+
+#ifdef NUCLEUS
+#endif /* NUCLEUS */
+
+#ifdef UNDER_NWIFI
+#include "../os/windows/include/athstartpack.h"
+#endif
+
+#ifdef ATHR_CE_LEGACY
+#include "../os/windows/include/athstartpack.h"
+#endif /* WINCE */
+
+#ifdef WIN_NWF
+#include <athstartpack_win.h>
+#endif
+
+#ifdef THREADX
+#include "../os/threadx/include/common/osapi_threadx.h"
+#endif
diff --git a/drivers/staging/ath6kl/include/bmi.h b/drivers/staging/ath6kl/include/bmi.h
new file mode 100644
index 00000000000..27aa98df9c0
--- /dev/null
+++ b/drivers/staging/ath6kl/include/bmi.h
@@ -0,0 +1,135 @@
+//------------------------------------------------------------------------------
+// <copyright file="bmi.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// BMI declarations and prototypes
+//
+// Author(s): ="Atheros"
+//==============================================================================
+#ifndef _BMI_H_
+#define _BMI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Header files */
+#include "a_config.h"
+#include "athdefs.h"
+#include "a_types.h"
+#include "hif.h"
+#include "a_osapi.h"
+#include "bmi_msg.h"
+
+void
+BMIInit(void);
+
+void
+BMICleanup(void);
+
+A_STATUS
+BMIDone(HIF_DEVICE *device);
+
+A_STATUS
+BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info);
+
+A_STATUS
+BMIReadMemory(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length);
+
+A_STATUS
+BMIWriteMemory(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length);
+
+A_STATUS
+BMIExecute(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UINT32 *param);
+
+A_STATUS
+BMISetAppStart(HIF_DEVICE *device,
+ A_UINT32 address);
+
+A_STATUS
+BMIReadSOCRegister(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UINT32 *param);
+
+A_STATUS
+BMIWriteSOCRegister(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UINT32 param);
+
+A_STATUS
+BMIrompatchInstall(HIF_DEVICE *device,
+ A_UINT32 ROM_addr,
+ A_UINT32 RAM_addr,
+ A_UINT32 nbytes,
+ A_UINT32 do_activate,
+ A_UINT32 *patch_id);
+
+A_STATUS
+BMIrompatchUninstall(HIF_DEVICE *device,
+ A_UINT32 rompatch_id);
+
+A_STATUS
+BMIrompatchActivate(HIF_DEVICE *device,
+ A_UINT32 rompatch_count,
+ A_UINT32 *rompatch_list);
+
+A_STATUS
+BMIrompatchDeactivate(HIF_DEVICE *device,
+ A_UINT32 rompatch_count,
+ A_UINT32 *rompatch_list);
+
+A_STATUS
+BMILZStreamStart(HIF_DEVICE *device,
+ A_UINT32 address);
+
+A_STATUS
+BMILZData(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length);
+
+A_STATUS
+BMIFastDownload(HIF_DEVICE *device,
+ A_UINT32 address,
+ A_UCHAR *buffer,
+ A_UINT32 length);
+
+A_STATUS
+BMIRawWrite(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length);
+
+A_STATUS
+BMIRawRead(HIF_DEVICE *device,
+ A_UCHAR *buffer,
+ A_UINT32 length,
+ A_BOOL want_timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BMI_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h b/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h
new file mode 100644
index 00000000000..e3291cf4dbd
--- /dev/null
+++ b/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h
@@ -0,0 +1,60 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2006-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+
+#ifndef __AR6002_REGDUMP_H__
+#define __AR6002_REGDUMP_H__
+
+#if !defined(__ASSEMBLER__)
+/*
+ * XTensa CPU state
+ * This must match the state saved by the target exception handler.
+ */
+struct XTensa_exception_frame_s {
+ A_UINT32 xt_pc;
+ A_UINT32 xt_ps;
+ A_UINT32 xt_sar;
+ A_UINT32 xt_vpri;
+ A_UINT32 xt_a2;
+ A_UINT32 xt_a3;
+ A_UINT32 xt_a4;
+ A_UINT32 xt_a5;
+ A_UINT32 xt_exccause;
+ A_UINT32 xt_lcount;
+ A_UINT32 xt_lbeg;
+ A_UINT32 xt_lend;
+
+ A_UINT32 epc1, epc2, epc3, epc4;
+
+ /* Extra info to simplify post-mortem stack walkback */
+#define AR6002_REGDUMP_FRAMES 10
+ struct {
+ A_UINT32 a0; /* pc */
+ A_UINT32 a1; /* sp */
+ A_UINT32 a2;
+ A_UINT32 a3;
+ } wb[AR6002_REGDUMP_FRAMES];
+};
+typedef struct XTensa_exception_frame_s CPU_exception_frame_t;
+#define RD_SIZE sizeof(CPU_exception_frame_t)
+
+#endif
+#endif /* __AR6002_REGDUMP_H__ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h b/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h
new file mode 100644
index 00000000000..5407e05d9b0
--- /dev/null
+++ b/drivers/staging/ath6kl/include/common/AR6002/AR6K_version.h
@@ -0,0 +1,52 @@
+//------------------------------------------------------------------------------
+// <copyright file="AR6K_version.h" company="Atheros">
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//------------------------------------------------------------------------------
+//==============================================================================
+// Author(s): ="Atheros"
+//==============================================================================
+
+#define __VER_MAJOR_ 3
+#define __VER_MINOR_ 0
+#define __VER_PATCH_ 0
+
+/* The makear6ksdk script (used for release builds) modifies the following line. */
+#define __BUILD_NUMBER_ 233
+
+
+/* Format of the version number. */
+#define VER_MAJOR_BIT_OFFSET 28
+#define VER_MINOR_BIT_OFFSET 24
+#define VER_PATCH_BIT_OFFSET 16
+#define VER_BUILD_NUM_BIT_OFFSET 0
+
+
+/*
+ * The version has the following format:
+ * Bits 28-31: Major version
+ * Bits 24-27: Minor version
+ * Bits 16-23: Patch version
+ * Bits 0-15: Build number (automatically generated during build process )
+ * E.g. Build 1.1.3.7 would be represented as 0x11030007.
+ *
+ * DO NOT split the following macro into multiple lines as this may confuse the build scripts.
+ */
+#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) )
+
+/* ABI Version. Reflects the version of binary interface exposed by AR6K target firmware. Needs to be incremented by 1 for any change in the firmware that requires upgrade of the driver on the host side for the change to work correctly */
+#define AR6K_ABI_VERSION 1
diff --git a/drivers/staging/ath6kl/include/common/AR6002/addrs.h b/drivers/staging/ath6kl/include/common/AR6002/addrs.h
new file mode 100644
index 00000000000..eaaccf4cad7
--- /dev/null
+++ b/drivers/staging/ath6kl/include/common/AR6002/addrs.h
@@ -0,0 +1,90 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
+//
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//
+//
+// Author(s): ="Atheros"
+//------------------------------------------------------------------------------
+
+#ifndef __ADDRS_H__
+#define __ADDRS_H__
+
+/*
+ * Special AR6002 Addresses that may be needed by special
+ * applications (e.g. ART) on the Host as well as Target.
+ */
+
+#if defined(AR6002_REV2)
+#define AR6K_RAM_START 0x00500000
+#define TARG_RAM_OFFSET(vaddr) ((A_UINT32)(vaddr) & 0xfffff)
+#define TARG_RAM_SZ (184*1024)
+#define TARG_ROM_SZ (80*1024)
+#endif
+#if defined(AR6002_REV4) || defined(AR6003)
+#define AR6K_RAM_START 0x00540000
+#define TARG_RAM_OFFSET(vaddr) (((A_UINT32)(vaddr) & 0xfffff) - 0x40000)
+#define TARG_RAM_SZ (256*1024)
+#define TARG_ROM_SZ (256*1024)
+#endif
+
+#define AR6002_BOARD_DATA_SZ 768
+#define AR6002_BOARD_EXT_DATA_SZ 0
+#define AR6003_BOARD_DATA_SZ 1024
+#define AR6003_BOARD_EXT_DATA_SZ 768
+
+#define AR6K_RAM_ADDR(byte_offset) (AR6K_RAM_START+(byte_offset))
+#define TARG_RAM_ADDRS(byte_offset) AR6K_RAM_ADDR(byte_offset)
+
+#define AR6K_ROM_START 0x004e0000
+#define TARG_ROM_OFFSET(vaddr) (((A_UINT32)(vaddr) & 0x1fffff) - 0xe0000)
+#define AR6K_ROM_ADDR(byte_offset) (AR6K_ROM_START+(byte_offset))
+#define TARG_ROM_ADDRS(byte_offset) AR6K_ROM_ADDR(byte_offset)
+
+/*
+ * At this ROM address is a pointer to the start of the ROM DataSet Index.
+ * If there are no ROM DataSets, there's a 0 at this address.
+ */
+#define ROM_DATASET_INDEX_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-8)
+#define ROM_MBIST_CKSUM_ADDR (TARG_ROM_ADDRS(TARG_ROM_SZ)-4)
+
+/*
+ * The API A_BOARD_DATA_ADDR() is the proper way to get a read pointer to
+ * board data.
+ */
+
+/* Size of Board Data, in bytes */
+#if defined(AR6002_REV4) || defined(AR6003)
+#define BOARD_DATA_SZ AR6003_BOARD_DATA_SZ
+#else
+#define BOARD_DATA_SZ AR6002_BOARD_DATA_SZ
+#endif
+
+
+/*
+ * Constants used by ASM code to access fields of host_interest_s,
+ * which is at a fixed location in RAM.
+ */
+#if defined(AR6002_REV4) || defined(AR6003)
+#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x60c)
+#else
+#define HOST_INTEREST_FLASH_IS_PRESENT_ADDR (AR6K_RAM_START + 0x40c)
+#endif
+#define FLASH_IS_PRESENT_TARGADDR HOST_INTEREST_FLASH_IS_PRESENT_ADDR
+
+#endif /* __ADDRS_H__ */
+
+
+
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_intf_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_intf_reg.h
new file mode 100644
index 00000000000..9c82767b6ef
--- /dev/null
+++ b/drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_intf_reg.h
@@ -0,0 +1,64 @@
+#ifndef _ANALOG_INTF_REG_REG_H_
+#define _ANALOG_INTF_REG_REG_H_
+
+#define SW_OVERRIDE_ADDRESS 0x00000080
+#define SW_OVERRIDE_OFFSET 0x00000080
+#define SW_OVERRIDE_SUPDATE_DELAY_MSB 1
+#define SW_OVERRIDE_SUPDATE_DELAY_LSB 1
+#define SW_OVERRIDE_SUPDATE_DELAY_MASK 0x00000002
+#define SW_OVERRIDE_SUPDATE_DELAY_GET(x) (((x) & SW_OVERRIDE_SUPDATE_DELAY_MASK) >> SW_OVERRIDE_SUPDATE_DELAY_LSB)
+#define SW_OVERRIDE_SUPDATE_DELAY_SET(x) (((x) << SW_OVERRIDE_SUPDATE_DELAY_LSB) & SW_OVERRIDE_SUPDATE_DELAY_MASK)
+#define SW_OVERRIDE_ENABLE_MSB 0
+#define SW_OVERRIDE_ENABLE_LSB 0
+#define SW_OVERRIDE_ENABLE_MASK 0x00000001
+#define SW_OVERRIDE_ENABLE_GET(x) (((x) & SW_OVERRIDE_ENABLE_MASK) >> SW_OVERRIDE_ENABLE_LSB)
+#define SW_OVERRIDE_ENABLE_SET(x) (((x) << SW_OVERRIDE_ENABLE_LSB) & SW_OVERRIDE_ENABLE_MASK)
+
+#define SIN_VAL_ADDRESS 0x00000084
+#define SIN_VAL_OFFSET 0x00000084
+#define SIN_VAL_SIN_MSB 0
+#define SIN_VAL_SIN_LSB 0
+#define SIN_VAL_SIN_MASK 0x00000001
+#define SIN_VAL_SIN_GET(x) (((x) & SIN_VAL_SIN_MASK) >> SIN_VAL_SIN_LSB)
+#define SIN_VAL_SIN_SET(x) (((x) << SIN_VAL_SIN_LSB) & SIN_VAL_SIN_MASK)
+
+#define SW_SCLK_ADDRESS 0x00000088
+#define SW_SCLK_OFFSET 0x00000088
+#define SW_SCLK_SW_SCLK_MSB 0
+#define SW_SCLK_SW_SCLK_LSB 0
+#define SW_SCLK_SW_SCLK_MASK 0x00000001
+#define SW_SCLK_SW_SCLK_GET(x) (((x) & SW_SCLK_SW_SCLK_MASK) >> SW_SCLK_SW_SCLK_LSB)
+#define SW_SCLK_SW_SCLK_SET(x) (((x) << SW_SCLK_SW_SCLK_LSB) & SW_SCLK_SW_SCLK_MASK)
+
+#define SW_CNTL_ADDRESS 0x0000008c
+#define SW_CNTL_OFFSET 0x0000008c
+#define SW_CNTL_SW_SCAPTURE_MSB 2
+#define SW_CNTL_SW_SCAPTURE_LSB 2
+#define SW_CNTL_SW_SCAPTURE_MASK 0x00000004
+#define SW_CNTL_SW_SCAPTURE_GET(x) (((x) & SW_CNTL_SW_SCAPTURE_MASK) >> SW_CNTL_SW_SCAPTURE_LSB)
+#define SW_CNTL_SW_SCAPTURE_SET(x) (((x) << SW_CNTL_SW_SCAPTURE_LSB) & SW_CNTL_SW_SCAPTURE_MASK)
+#define SW_CNTL_SW_SUPDATE_MSB 1
+#define SW_CNTL_SW_SUPDATE_LSB 1
+#define SW_CNTL_SW_SUPDATE_MASK 0x00000002
+#define SW_CNTL_SW_SUPDATE_GET(x) (((x) & SW_CNTL_SW_SUPDATE_MASK) >> SW_CNTL_SW_SUPDATE_LSB)
+#define SW_CNTL_SW_SUPDATE_SET(x) (((x) << SW_CNTL_SW_SUPDATE_LSB) & SW_CNTL_SW_SUPDATE_MASK)
+#define SW_CNTL_SW_SOUT_MSB 0
+#define SW_CNTL_SW_SOUT_LSB 0
+#define SW_CNTL_SW_SOUT_MASK 0x00000001
+#define SW_CNTL_SW_SOUT_GET(x) (((x) & SW_CNTL_SW_SOUT_MASK) >> SW_CNTL_SW_SOUT_LSB)
+#define SW_CNTL_SW_SOUT_SET(x) (((x) << SW_CNTL_SW_SOUT_LSB) & SW_CNTL_SW_SOUT_MASK)
+
+
+#ifndef __ASSEMBLER__
+
+typedef struct analog_intf_reg_reg_s {
+ unsigned char pad0[128]; /* pad to 0x80 */
+ volatile unsigned int sw_override;
+ volatile unsigned int sin_val;
+ volatile unsigned int sw_sclk;
+ volatile unsigned int sw_cntl;
+} analog_intf_reg_reg_t;
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* _ANALOG_INTF_REG_H_ */
diff --git a/drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_reg.h b/drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_reg.h
new file mode 100644
index 00000000000..cf562b86f65
--- /dev/null
+++ b/drivers/staging/ath6kl/include/common/AR6002/hw.0/analog_reg.h
@@ -0,0 +1,1932 @@
+#ifndef _ANALOG_REG_REG_H_
+#define _ANALOG_REG_REG_H_
+
+#define SYNTH_SYNTH1_ADDRESS 0x00000000
+#define SYNTH_SYNTH1_OFFSET 0x00000000
+#define SYNTH_SYNTH1_PWD_BIAS_MSB 31
+#define SYNTH_SYNTH1_PWD_BIAS_LSB 31
+#define SYNTH_SYNTH1_PWD_BIAS_MASK 0x80000000
+#define SYNTH_SYNTH1_PWD_BIAS_GET(x) (((x) & SYNTH_SYNTH1_PWD_BIAS_MASK) >> SYNTH_SYNTH1_PWD_BIAS_LSB)
+#define SYNTH_SYNTH1_PWD_BIAS_SET(x) (((x) << SYNTH_SYNTH1_PWD_BIAS_LSB) & SYNTH_SYNTH1_PWD_BIAS_MASK)
+#define SYNTH_SYNTH1_PWD_CP_MSB 30
+#define SYNTH_SYNTH1_PWD_CP_LSB 30
+#define SYNTH_SYNTH1_PWD_CP_MASK 0x40000000
+#define SYNTH_SYNTH1_PWD_CP_GET(x) (((x) & SYNTH_SYNTH1_PWD_CP_MASK) >> SYNTH_SYNTH1_PWD_CP_LSB)
+#define SYNTH_SYNTH1_PWD_CP_SET(x) (((x) << SYNTH_SYNTH1_PWD_CP_LSB) & SYNTH_SYNTH1_PWD_CP_MASK)
+#define SYNTH_SYNTH1_PWD_VCMON_MSB 29
+#define SYNTH_SYNTH1_PWD_VCMON_LSB 29
+#define SYNTH_SYNTH1_PWD_VCMON_MASK 0x20000000
+#define SYNTH_SYNTH1_PWD_VCMON_GET(x) (((x) & SYNTH_SYNTH1_PWD_VCMON_MASK) >> SYNTH_SYNTH1_PWD_VCMON_LSB)
+#define SYNTH_SYNTH1_PWD_VCMON_SET(x) (((x) << SYNTH_SYNTH1_PWD_VCMON_LSB) & SYNTH_SYNTH1_PWD_VCMON_MASK)
+#define SYNTH_SYNTH1_PWD_VCO_MSB 28
+#define SYNTH_SYNTH1_PWD_VCO_LSB 28
+#define SYNTH_SYNTH1_PWD_VCO_MASK 0x10000000
+#define SYNTH_SYNTH1_PWD_VCO_GET(x) (((x) & SYNTH_SYNTH1_PWD_VCO_MASK) >> SYNTH_SYNTH1_PWD_VCO_LSB)
+#define SYNTH_SYNTH1_PWD_VCO_SET(x) (((x) << SYNTH_SYNTH1_PWD_VCO_LSB) & SYNTH_SYNTH1_PWD_VCO_MASK)
+#define SYNTH_SYNTH1_PWD_PRESC_MSB 27
+#define SYNTH_SYNTH1_PWD_PRESC_LSB 27
+#define SYNTH_SYNTH1_PWD_PRESC_MASK 0x08000000
+#define SYNTH_SYNTH1_PWD_PRESC_GET(x) (((x) & SYNTH_SYNTH1_PWD_PRESC_MASK) >> SYNTH_SYNTH1_PWD_PRESC_LSB)
+#define SYNTH_SYNTH1_PWD_PRESC_SET(x) (((x) << SYNTH_SYNTH1_PWD_PRESC_LSB) & SYNTH_SYNTH1_PWD_PRESC_MASK)
+#define SYNTH_SYNTH1_PWD_LODIV_MSB 26
+#define SYNTH_SYNTH1_PWD_LODIV_LSB 26
+#define SYNTH_SYNTH1_PWD_LODIV_MASK 0x04000000
+#define SYNTH_SYNTH1_PWD_LODIV_GET(x) (((x) & SYNTH_SYNTH1_PWD_LODIV_MASK) >> SYNTH_SYNTH1_PWD_LODIV_LSB)
+#define SYNTH_SYNTH1_PWD_LODIV_SET(x) (((x) << SYNTH_SYNTH1_PWD_LODIV_LSB) & SYNTH_SYNTH1_PWD_LODIV_MASK)
+#define SYNTH_SYNTH1_PWD_LOMIX_MSB 25
+#define SYNTH_SYNTH1_PWD_LOMIX_LSB 25
+#define SYNTH_SYNTH1_PWD_LOMIX_MASK 0x02000000
+#define SYNTH_SYNTH1_PWD_LOMIX_GET(x) (((x) & SYNTH_SYNTH1_PWD_LOMIX_MASK) >> SYNTH_SYNTH1_PWD_LOMIX_LSB)
+#define SYNTH_SYNTH1_PWD_LOMIX_SET(x) (((x) << SYNTH_SYNTH1_PWD_LOMIX_LSB) & SYNTH_SYNTH1_PWD_LOMIX_MASK)
+#define SYNTH_SYNTH1_FORCE_LO_ON_MSB 24
+#define SYNTH_SYNTH1_FORCE_LO_ON_LSB 24
+#define SYNTH_SYNTH1_FORCE_LO_ON_MASK 0x01000000
+#define SYNTH_SYNTH1_FORCE_LO_ON_GET(x) (((x) & SYNTH_SYNTH1_FORCE_LO_ON_MASK) >> SYNTH_SYNTH1_FORCE_LO_ON_LSB)
+#define SYNTH_SYNTH1_FORCE_LO_ON_SET(x) (((x) << SYNTH_SYNTH1_FORCE_LO_ON_LSB) & SYNTH_SYNTH1_FORCE_LO_ON_MASK)
+#define SYNTH_SYNTH1_PWD_LOBUF5G_MSB 23
+#define SYNTH_SYNTH1_PWD_LOBUF5G_LSB 23
+#define SYNTH_SYNTH1_PWD_LOBUF5G_MASK 0x00800000
+#define SYNTH_SYNTH1_PWD_LOBUF5G_GET(x) (((x) & SYNTH_SYNTH1_PWD_LOBUF5G_MASK) >> SYNTH_SYNTH1_PWD_LOBUF5G_LSB)
+#define SYNTH_SYNTH1_PWD_LOBUF5G_SET(x) (((x) << SYNTH_SYNTH1_PWD_LOBUF5G_LSB) & SYNTH_SYNTH1_PWD_LOBUF5G_MASK)
+#define SYNTH_SYNTH1_VCOREGBYPASS_MSB 22
+#define SYNTH_SYNTH1_VCOREGBYPASS_LSB 22
+#define SYNTH_SYNTH1_VCOREGBYPASS_MASK 0x00400000
+#define SYNTH_SYNTH1_VCOREGBYPASS_GET(x) (((x) & SYNTH_SYNTH1_VCOREGBYPASS_MASK) >> SYNTH_SYNTH1_VCOREGBYPASS_LSB)
+#define SYNTH_SYNTH1_VCOREGBYPASS_SET(x) (((x) << SYNTH_SYNTH1_VCOREGBYPASS_LSB) & SYNTH_SYNTH1_VCOREGBYPASS_MASK)
+#define SYNTH_SYNTH1_VCOREGLEVEL_MSB 21
+#define SYNTH_SYNTH1_VCOREGLEVEL_LSB 20
+#define SYNTH_SYNTH1_VCOREGLEVEL_MASK 0x00300000
+#define SYNTH_SYNTH1_VCOREGLEVEL_GET(x) (((x) & SYNTH_SYNTH1_VCOREGLEVEL_MASK) >> SYNTH_SYNTH1_VCOREGLEVEL_LSB)
+#define SYNTH_SYNTH1_VCOREGLEVEL_SET(x) (((x) << SYNTH_SYNTH1_VCOREGLEVEL_LSB) & SYNTH_SYNTH1_VCOREGLEVEL_MASK)
+#define SYNTH_SYNTH1_VCOREGBIAS_MSB 19
+#define SYNTH_SYNTH1_VCOREGBIAS_LSB 18
+#define SYNTH_SYNTH1_VCOREGBIAS_MASK 0x000c0000
+#define SYNTH_SYNTH1_VCOREGBIAS_GET(x) (((x) & SYNTH_SYNTH1_VCOREGBIAS_MASK) >> SYNTH_SYNTH1_VCOREGBIAS_LSB)
+#define SYNTH_SYNTH1_VCOREGBIAS_SET(x) (((x) << SYNTH_SYNTH1_VCOREGBIAS_LSB) & SYNTH_SYNTH1_VCOREGBIAS_MASK)
+#define SYNTH_SYNTH1_SLIDINGIF_MSB 17
+#define SYNTH_SYNTH1_SLIDINGIF_LSB 17
+#define SYNTH_SYNTH1_SLIDINGIF_MASK 0x00020000
+#define SYNTH_SYNTH1_SLIDINGIF_GET(x) (((x) & SYNTH_SYNTH1_SLIDINGIF_MASK) >> SYNTH_SYNTH1_SLIDINGIF_LSB)
+#define SYNTH_SYNTH1_SLIDINGIF_SET(x) (((x) << SYNTH_SYNTH1_SLIDINGIF_LSB) & SYNTH_SYNTH1_SLIDINGIF_MASK)
+#define SYNTH_SYNTH1_SPARE_PWD_MSB 16
+#define SYNTH_SYNTH1_SPARE_PWD_LSB 16
+#define SYNTH_SYNTH1_SPARE_PWD_MASK 0x00010000
+#define SYNTH_SYNTH1_SPARE_PWD_GET(x) (((x) & SYNTH_SYNTH1_SPARE_PWD_MASK) >> SYNTH_SYNTH1_SPARE_PWD_LSB)
+#define SYNTH_SYNTH1_SPARE_PWD_SET(x) (((x) << SYNTH_SYNTH1_SPARE_PWD_LSB) & SYNTH_SYNTH1_SPARE_PWD_MASK)
+#define SYNTH_SYNTH1_CON_VDDVCOREG_MSB 15
+#define SYNTH_SYNTH1_CON_VDDVCOREG_LSB 15
+#define SYNTH_SYNTH1_CON_VDDVCOREG_MASK 0x00008000
+#define SYNTH_SYNTH1_CON_VDDVCOREG_GET(x) (((x) & SYNTH_SYNTH1_CON_VDDVCOREG_MASK) >> SYNTH_SYNTH1_CON_VDDVCOREG_LSB)
+#define SYNTH_SYNTH1_CON_VDDVCOREG_SET(x) (((x) << SYNTH_SYNTH1_CON_VDDVCOREG_LSB) & SYNTH_SYNTH1_CON_VDDVCOREG_MASK)
+#define SYNTH_SYNTH1_CON_IVCOREG_MSB 14
+#define SYNTH_SYNTH1_CON_IVCOREG_LSB 14
+#define SYNTH_SYNTH1_CON_IVCOREG_MASK 0x00004000
+#define SYNTH_SYNTH1_CON_IVCOREG_GET(x) (((x) & SYNTH_SYNTH1_CON_IVCOREG_MASK) >> SYNTH_SYNTH1_CON_IVCOREG_LSB)
+#define SYNTH_SYNTH1_CON_IVCOREG_SET(x) (((x) << SYNTH_SYNTH1_CON_IVCOREG_LSB) & SYNTH_SYNTH1_CON_IVCOREG_MASK)
+#define SYNTH_SYNTH1_CON_IVCOBUF_MSB 13
+#define SYNTH_SYNTH1_CON_IVCOBUF_LSB 13
+#define SYNTH_SYNTH1_CON_IVCOBUF_MASK 0x00002000
+#define SYNTH_SYNTH1_CON_IVCOBUF_GET(x) (((x) & SYNTH_SYNTH1_CON_IVCOBUF_MASK) >> SYNTH_SYNTH1_CON_IVCOBUF_LSB)
+#define SYNTH_SYNTH1_CON_IVCOBUF_SET(x) (((x) << SYNTH_SYNTH1_CON_IVCOBUF_LSB) & SYNTH_SYNTH1_CON_IVCOBUF_MASK)
+#define SYNTH_SYNTH1_SEL_VCMONABUS_MSB 12
+#define SYNTH_SYNTH1_SEL_VCMONABUS_LSB 10
+#define SYNTH_SYNTH1_SEL_VCMONABUS_MASK 0x00001c00
+#define SYNTH_SYNTH1_SEL_VCMONABUS_GET(x) (((x) & SYNTH_SYNTH1_SEL_VCMONABUS_MASK) >> SYNTH_SYNTH1_SEL_VCMONABUS_LSB)
+#define SYNTH_SYNTH1_SEL_VCMONABUS_SET(x) (((x) << SYNTH_SYNTH1_SEL_VCMONABUS_LSB) & SYNTH_SYNTH1_SEL_VCMONABUS_MASK)
+#define SYNTH_SYNTH1_PWUP_VCOBUF_PD_MSB 9
+#define SYNTH_SYNTH1_PWUP_VCOBUF_PD_LSB 9
+#define SYNTH_SYNTH1_PWUP_VCOBUF_PD_MASK 0x00000200
+#define SYNTH_SYNTH1_PWUP_VCOBUF_PD_GET(x) (((x) & SYNTH_SYNTH1_PWUP_VCOBUF_PD_MASK) >> SYNTH_SYNTH1_PWUP_VCOBUF_PD_LSB)
+#define SYNTH_SYNTH1_PWUP_VCOBUF_PD_SET(x) (((x) << SYNTH_SYNTH1_PWUP_VCOBUF_PD_LSB) & SYNTH_SYNTH1_PWUP_VCOBUF_PD_MASK)
+#define SYNTH_SYNTH1_PWUP_LODIV_PD_MSB 8
+#define SYNTH_SYNTH1_PWUP_LODIV_PD_LSB 8
+#define SYNTH_SYNTH1_PWUP_LODIV_PD_MASK 0x00000100
+#define SYNTH_SYNTH1_PWUP_LODIV_PD_GET(x) (((x) & SYNTH_SYNTH1_PWUP_LODIV_PD_MASK) >> SYNTH_SYNTH1_PWUP_LODIV_PD_LSB)
+#define SYNTH_SYNTH1_PWUP_LODIV_PD_SET(x) (((x) << SYNTH_SYNTH1_PWUP_LODIV_PD_LSB) & SYNTH_SYNTH1_PWUP_LODIV_PD_MASK)
+#define SYNTH_SYNTH1_PWUP_LOMIX_PD_MSB 7
+#define SYNTH_SYNTH1_PWUP_LOMIX_PD_LSB 7
+#define SYNTH_SYNTH1_PWUP_LOMIX_PD_MASK 0x00000080
+#define SYNTH_SYNTH1_PWUP_LOMIX_PD_GET(x) (((x) & SYNTH_SYNTH1_PWUP_LOMIX_PD_MASK) >> SYNTH_SYNTH1_PWUP_LOMIX_PD_LSB)
+#define SYNTH_SYNTH1_PWUP_LOMIX_PD_SET(x) (((x) << SYNTH_SYNTH1_PWUP_LOMIX_PD_LSB) & SYNTH_SYNTH1_PWUP_LOMIX_PD_MASK)
+#define SYNTH_SYNTH1_PWUP_LOBUF5G_PD_MSB 6
+#define SYNTH_SYNTH1_PWUP_LOBUF5G_PD_LSB 6
+#define SYNTH_SYNTH1_PWUP_LOBUF5G_PD_MASK 0x00000040
+#define SYNTH_SYNTH1_PWUP_LOBUF5G_PD_GET(x) (((x) & SYNTH_SYNTH1_PWUP_LOBUF5G_PD_MASK) >> SYNTH_SYNTH1_PWUP_LOBUF5G_PD_LSB)
+#define SYNTH_SYNTH1_PWUP_LOBUF5G_PD_SET(x) (((x) << SYNTH_SYNTH1_PWUP_LOBUF5G_PD_LSB) & SYNTH_SYNTH1_PWUP_LOBUF5G_PD_MASK)
+#define SYNTH_SYNTH1_MONITOR_FB_MSB 5
+#define SYNTH_SYNTH1_MONITOR_FB_LSB 5
+#define SYNTH_SYNTH1_MONITOR_FB_MASK 0x00000020
+#define SYNTH_SYNTH1_MONITOR_FB_GET(x) (((x) & SYNTH_SYNTH1_MONITOR_FB_MASK) >> SYNTH_SYNTH1_MONITOR_FB_LSB)
+#define SYNTH_SYNTH1_MONITOR_FB_SET(x) (((x) << SYNTH_SYNTH1_MONITOR_FB_LSB) & SYNTH_SYNTH1_MONITOR_FB_MASK)
+#define SYNTH_SYNTH1_MONITOR_REF_MSB 4
+#define SYNTH_SYNTH1_MONITOR_REF_LSB 4
+#define SYNTH_SYNTH1_MONITOR_REF_MASK 0x00000010
+#define SYNTH_SYNTH1_MONITOR_REF_GET(x) (((x) & SYNTH_SYNTH1_MONITOR_REF_MASK) >> SYNTH_SYNTH1_MONITOR_REF_LSB)
+#define SYNTH_SYNTH1_MONITOR_REF_SET(x) (((x) << SYNTH_SYNTH1_MONITOR_REF_LSB) & SYNTH_SYNTH1_MONITOR_REF_MASK)
+#define SYNTH_SYNTH1_MONITOR_FB_DIV2_MSB 3
+#define SYNTH_SYNTH1_MONITOR_FB_DIV2_LSB 3
+#define SYNTH_SYNTH1_MONITOR_FB_DIV2_MASK 0x00000008
+#define SYNTH_SYNTH1_MONITOR_FB_DIV2_GET(x) (((x) & SYNTH_SYNTH1_MONITOR_FB_DIV2_MASK) >> SYNTH_SYNTH1_MONITOR_FB_DIV2_LSB)
+#define SYNTH_SYNTH1_MONITOR_FB_DIV2_SET(x) (((x) << SYNTH_SYNTH1_MONITOR_FB_DIV2_LSB) & SYNTH_SYNTH1_MONITOR_FB_DIV2_MASK)
+#define SYNTH_SYNTH1_MONITOR_VC2HIGH_MSB 2
+#define SYNTH_SYNTH1_MONITOR_VC2HIGH_LSB 2
+#define SYNTH_SYNTH1_MONITOR_VC2HIGH_MASK 0x00000004
+#define SYNTH_SYNTH1_MONITOR_VC2HIGH_GET(x) (((x) & SYNTH_SYNTH1_MONITOR_VC2HIGH_MASK) >> SYNTH_SYNTH1_MONITOR_VC2HIGH_LSB)
+#define SYNTH_SYNTH1_MONITOR_VC2HIGH_SET(x) (((x) << SYNTH_SYNTH1_MONITOR_VC2HIGH_LSB) & SYNTH_SYNTH1_MONITOR_VC2HIGH_MASK)
+#define SYNTH_SYNTH1_MONITOR_VC2LOW_MSB 1
+#define SYNTH_SYNTH1_MONITOR_VC2LOW_LSB 1
+#define SYNTH_SYNTH1_MONITOR_VC2LOW_MASK 0x00000002
+#define SYNTH_SYNTH1_MONITOR_VC2LOW_GET(x) (((x) & SYNTH_SYNTH1_MONITOR_VC2LOW_MASK) >> SYNTH_SYNTH1_MONITOR_VC2LOW_LSB)
+#define SYNTH_SYNTH1_MONITOR_VC2LOW_SET(x) (((x) << SYNTH_SYNTH1_MONITOR_VC2LOW_LSB) & SYNTH_SYNTH1_MONITOR_VC2LOW_MASK)
+#define SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_MSB 0
+#define SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_LSB 0
+#define SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_MASK 0x00000001
+#define SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_GET(x) (((x) & SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_MASK) >> SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_LSB)
+#define SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_SET(x) (((x) << SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_LSB) & SYNTH_SYNTH1_MONITOR_SYNTHLOCKVCOK_MASK)
+
+#define SYNTH_SYNTH2_ADDRESS 0x00000004
+#define SYNTH_SYNTH2_OFFSET 0x00000004
+#define SYNTH_SYNTH2_VC_CAL_REF_MSB 31
+#define SYNTH_SYNTH2_VC_CAL_REF_LSB 29
+#define SYNTH_SYNTH2_VC_CAL_REF_MASK 0xe0000000
+#define SYNTH_SYNTH2_VC_CAL_REF_GET(x) (((x) & SYNTH_SYNTH2_VC_CAL_REF_MASK) >> SYNTH_SYNTH2_VC_CAL_REF_LSB)
+#define SYNTH_SYNTH2_VC_CAL_REF_SET(x) (((x) << SYNTH_SYNTH2_VC_CAL_REF_LSB) & SYNTH_SYNTH2_VC_CAL_REF_MASK)
+#define SYNTH_SYNTH2_VC_HI_REF_MSB 28
+#define SYNTH_SYNTH2_VC_HI_REF_LSB 26
+#define SYNTH_SYNTH2_VC_HI_REF_MASK 0x1c000000
+#define SYNTH_SYNTH2_VC_HI_REF_GET(x) (((x) & SYNTH_SYNTH2_VC_HI_REF_MASK) >> SYNTH_SYNTH2_VC_HI_REF_LSB)
+#define SYNTH_SYNTH2_VC_HI_REF_SET(x) (((x) << SYNTH_SYNTH2_VC_HI_REF_LSB) & SYNTH_SYNTH2_VC_HI_REF_MASK)
+#define SYNTH_SYNTH2_VC_MID_REF_MSB 25
+#define SYNTH_SYNTH2_VC_MID_REF_LSB 23
+#define SYNTH_SYNTH2_VC_MID_REF_MASK 0x03800000
+#define SYNTH_SYNTH2_VC_MID_REF_GET(x) (((x) & SYNTH_SYNTH2_VC_MID_REF_MASK) >> SYNTH_SYNTH2_VC_MID_REF_LSB)
+#define SYNTH_SYNTH2_VC_MID_REF_SET(x) (((x) << SYNTH_SYNTH2_VC_MID_REF_LSB) & SYNTH_SYNTH2_VC_MID_REF_MASK)
+#define SYNTH_SYNTH2_VC_LOW_REF_MSB 22
+#define SYNTH_SYNTH2_VC_LOW_REF_LSB 20
+#define SYNTH_SYNTH2_VC_LOW_REF_MASK 0x00700000
+#define SYNTH_SYNTH2_VC_LOW_REF_GET(x) (((x) & SYNTH_SYNTH2_VC_LOW_REF_MASK) >> SYNTH_SYNTH2_VC_LOW_REF_LSB)
+#define SYNTH_SYNTH2_VC_LOW_REF_SET(x) (((x) << SYNTH_SYNTH2_VC_LOW_REF_LSB) & SYNTH_SYNTH2_VC_LOW_REF_MASK)
+#define SYNTH_SYNTH2_LOOP_3RD_ORDER_R_MSB 19
+#define SYNTH_SYNTH2_LOOP_3RD_ORDER_R_LSB 15
+#define SYNTH_SYNTH2_LOOP_3RD_ORDER_R_MASK 0x000f8000
+#define SYNTH_SYNTH2_LOOP_3RD_ORDER_R_GET(x) (((x) & SYNTH_SYNTH2_LOOP_3RD_ORDER_R_MASK) >> SYNTH_SYNTH2_LOOP_3RD_ORDER_R_LSB)
+#define SYNTH_SYNTH2_LOOP_3RD_ORDER_R_SET(x) (((x) << SYNTH_SYNTH2_LOOP_3RD_ORDER_R_LSB) & SYNTH_SYNTH2_LOOP_3RD_ORDER_R_MASK)
+#define SYNTH_SYNTH2_LOOP_CP_MSB 14
+#define SYNTH_SYNTH2_LOOP_CP_LSB 10
+#define SYNTH_SYNTH2_LOOP_CP_MASK 0x00007c00
+#define SYNTH_SYNTH2_LOOP_CP_GET(x) (((x) & SYNTH_SYNTH2_LOOP_CP_MASK) >> SYNTH_SYNTH2_LOOP_CP_LSB)
+#define SYNTH_SYNTH2_LOOP_CP_SET(x) (((x) << SYNTH_SYNTH2_LOOP_CP_LSB) & SYNTH_SYNTH2_LOOP_CP_MASK)
+#define SYNTH_SYNTH2_LOOP_RS_MSB 9
+#define SYNTH_SYNTH2_LOOP_RS_LSB 5
+#define SYNTH_SYNTH2_LOOP_RS_MASK 0x000003e0
+#define SYNTH_SYNTH2_LOOP_RS_GET(x) (((x) & SYNTH_SYNTH2_LOOP_RS_MASK) >> SYNTH_SYNTH2_LOOP_RS_LSB)
+#define SYNTH_SYNTH2_LOOP_RS_SET(x) (((x) << SYNTH_SYNTH2_LOOP_RS_LSB) & SYNTH_SYNTH2_LOOP_RS_MASK)
+#define SYNTH_SYNTH2_LOOP_CS_MSB 4
+#define SYNTH_SYNTH2_LOOP_CS_LSB 3
+#define SYNTH_SYNTH2_LOOP_CS_MASK 0x00000018
+#define SYNTH_SYNTH2_LOOP_CS_GET(x) (((x) & SYNTH_SYNTH2_LOOP_CS_MASK) >> SYNTH_SYNTH2_LOOP_CS_LSB)
+#define SYNTH_SYNTH2_LOOP_CS_SET(x) (((x) << SYNTH_SYNTH2_LOOP_CS_LSB) & SYNTH_SYNTH2_LOOP_CS_MASK)
+#define SYNTH_SYNTH2_SPARE_BITS_MSB 2
+#define SYNTH_SYNTH2_SPARE_BITS_LSB 0
+#define SYNTH_SYNTH2_SPARE_BITS_MASK 0x00000007
+#define SYNTH_SYNTH2_SPARE_BITS_GET(x) (((x) & SYNTH_SYNTH2_SPARE_BITS_MASK) >> SYNTH_SYNTH2_SPARE_BITS_LSB)
+#define SYNTH_SYNTH2_SPARE_BITS_SET(x) (((x) << SYNTH_SYNTH2_SPARE_BITS_LSB) & SYNTH_SYNTH2_SPARE_BITS_MASK)
+
+#define SYNTH_SYNTH3_ADDRESS 0x00000008
+#define SYNTH_SYNTH3_OFFSET 0x00000008
+#define SYNTH_SYNTH3_DIS_CLK_XTAL_MSB 31
+#define SYNTH_SYNTH3_DIS_CLK_XTAL_LSB 31
+#define SYNTH_SYNTH3_DIS_CLK_XTAL_MASK 0x80000000
+#define SYNTH_SYNTH3_DIS_CLK_XTAL_GET(x) (((x) & SYNTH_SYNTH3_DIS_CLK_XTAL_MASK) >> SYNTH_SYNTH3_DIS_CLK_XTAL_LSB)
+#define SYNTH_SYNTH3_DIS_CLK_XTAL_SET(x) (((x) << SYNTH_SYNTH3_DIS_CLK_XTAL_LSB) & SYNTH_SYNTH3_DIS_CLK_XTAL_MASK)
+#define SYNTH_SYNTH3_SEL_CLK_DIV2_MSB 30
+#define SYNTH_SYNTH3_SEL_CLK_DIV2_LSB 30
+#define SYNTH_SYNTH3_SEL_CLK_DIV2_MASK 0x40000000
+#define SYNTH_SYNTH3_SEL_CLK_DIV2_GET(x) (((x) & SYNTH_SYNTH3_SEL_CLK_DIV2_MASK) >> SYNTH_SYNTH3_SEL_CLK_DIV2_LSB)
+#define SYNTH_SYNTH3_SEL_CLK_DIV2_SET(x) (((x) << SYNTH_SYNTH3_SEL_CLK_DIV2_LSB) & SYNTH_SYNTH3_SEL_CLK_DIV2_MASK)
+#define SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_MSB 29
+#define SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_LSB 24
+#define SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_MASK 0x3f000000
+#define SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_GET(x) (((x) & SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_MASK) >> SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_LSB)
+#define SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_SET(x) (((x) << SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_LSB) & SYNTH_SYNTH3_WAIT_SHORTR_PWRUP_MASK)
+#define SYNTH_SYNTH3_WAIT_PWRUP_MSB 23
+#define SYNTH_SYNTH3_WAIT_PWRUP_LSB 18
+#define SYNTH_SYNTH3_WAIT_PWRUP_MASK 0x00fc0000
+#define SYNTH_SYNTH3_WAIT_PWRUP_GET(x) (((x) & SYNTH_SYNTH3_WAIT_PWRUP_MASK) >> SYNTH_SYNTH3_WAIT_PWRUP_LSB)
+#define SYNTH_SYNTH3_WAIT_PWRUP_SET(x) (((x) << SYNTH_SYNTH3_WAIT_PWRUP_LSB) & SYNTH_SYNTH3_WAIT_PWRUP_MASK)
+#define SYNTH_SYNTH3_WAIT_CAL_BIN_MSB 17
+#define SYNTH_SYNTH3_WAIT_CAL_BIN_LSB 12
+#define SYNTH_SYNTH3_WAIT_CAL_BIN_MASK 0x0003f000
+#define SYNTH_SYNTH3_WAIT_CAL_BIN_GET(x) (((x) & SYNTH_SYNTH3_WAIT_CAL_BIN_MASK) >> SYNTH_SYNTH3_WAIT_CAL_BIN_LSB)
+#define SYNTH_SYNTH3_WAIT_CAL_BIN_SET(x) (((x) << SYNTH_SYNTH3_WAIT_CAL_BIN_LSB) & SYNTH_SYNTH3_WAIT_CAL_BIN_MASK)
+#define SYNTH_SYNTH3_WAIT_CAL_LIN_MSB 11
+#define SYNTH_SYNTH3_WAIT_CAL_LIN_LSB 6
+#define SYNTH_SYNTH3_WAIT_CAL_LIN_MASK 0x00000fc0
+#define SYNTH_SYNTH3_WAIT_CAL_LIN_GET(x) (((x) & SYNTH_SYNTH3_WAIT_CAL_LIN_MASK) >> SYNTH_SYNTH3_WAIT_CAL_LIN_LSB)
+#define SYNTH_SYNTH3_WAIT_CAL_LIN_SET(x) (((x) << SYNTH_SYNTH3_WAIT_CAL_LIN_LSB) & SYNTH_SYNTH3_WAIT_CAL_LIN_MASK)
+#define SYNTH_SYNTH3_WAIT_VC_CHECK_MSB 5
+#define SYNTH_SYNTH3_WAIT_VC_CHECK_LSB 0
+#define SYNTH_SYNTH3_WAIT_VC_CHECK_MASK 0x0000003f
+#define SYNTH_SYNTH3_WAIT_VC_CHECK_GET(x) (((x) & SYNTH_SYNTH3_WAIT_VC_CHECK_MASK) >> SYNTH_SYNTH3_WAIT_VC_CHECK_LSB)
+#define SYNTH_SYNTH3_WAIT_VC_CHECK_SET(x) (((x) << SYNTH_SYNTH3_WAIT_VC_CHECK_LSB) & SYNTH_SYNTH3_WAIT_VC_CHECK_MASK)
+
+#define SYNTH_SYNTH4_ADDRESS 0x0000000c
+#define SYNTH_SYNTH4_OFFSET 0x0000000c
+#define SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_MSB 31
+#define SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_LSB 31
+#define SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_MASK 0x80000000
+#define SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_GET(x) (((x) & SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_MASK) >> SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_LSB)
+#define SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_SET(x) (((x) << SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_LSB) & SYNTH_SYNTH4_DIS_LIN_CAPSEARCH_MASK)
+#define SYNTH_SYNTH4_DIS_LOSTVC_MSB 30
+#define SYNTH_SYNTH4_DIS_LOSTVC_LSB 30
+#define SYNTH_SYNTH4_DIS_LOSTVC_MASK 0x40000000
+#define SYNTH_SYNTH4_DIS_LOSTVC_GET(x) (((x) & SYNTH_SYNTH4_DIS_LOSTVC_MASK) >> SYNTH_SYNTH4_DIS_LOSTVC_LSB)
+#define SYNTH_SYNTH4_DIS_LOSTVC_SET(x) (((x) << SYNTH_SYNTH4_DIS_LOSTVC_LSB) & SYNTH_SYNTH4_DIS_LOSTVC_MASK)
+#define SYNTH_SYNTH4_ALWAYS_SHORTR_MSB 29
+#define SYNTH_SYNTH4_ALWAYS_SHORTR_LSB 29
+#define SYNTH_SYNTH4_ALWAYS_SHORTR_MASK 0x20000000
+#define SYNTH_SYNTH4_ALWAYS_SHORTR_GET(x) (((x) & SYNTH_SYNTH4_ALWAYS_SHORTR_MASK) >> SYNTH_SYNTH4_ALWAYS_SHORTR_LSB)
+#define SYNTH_SYNTH4_ALWAYS_SHORTR_SET(x) (((x) << SYNTH_SYNTH4_ALWAYS_SHORTR_LSB) & SYNTH_SYNTH4_ALWAYS_SHORTR_MASK)
+#define SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_MSB 28
+#define SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_LSB 28
+#define SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_MASK 0x10000000
+#define SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_GET(x) (((x) & SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_MASK) >> SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_LSB)
+#define SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_SET(x) (((x) << SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_LSB) & SYNTH_SYNTH4_SHORTR_UNTIL_LOCKED_MASK)
+#define SYNTH_SYNTH4_FORCE_PINVC_MSB 27
+#define SYNTH_SYNTH4_FORCE_PINVC_LSB 27
+#define SYNTH_SYNTH4_FORCE_PINVC_MASK 0x08000000
+#define SYNTH_SYNTH4_FORCE_PINVC_GET(x) (((x) & SYNTH_SYNTH4_FORCE_PINVC_MASK) >> SYNTH_SYNTH4_FORCE_PINVC_LSB)
+#define SYNTH_SYNTH4_FORCE_PINVC_SET(x) (((x) << SYNTH_SYNTH4_FORCE_PINVC_LSB) & SYNTH_SYNTH4_FORCE_PINVC_MASK)
+#define SYNTH_SYNTH4_FORCE_VCOCAP_MSB 26
+#define SYNTH_SYNTH4_FORCE_VCOCAP_LSB 26
+#define SYNTH_SYNTH4_FORCE_VCOCAP_MASK 0x04000000
+#define SYNTH_SYNTH4_FORCE_VCOCAP_GET(x) (((x) & SYNTH_SYNTH4_FORCE_VCOCAP_MASK) >> SYNTH_SYNTH4_FORCE_VCOCAP_LSB)
+#define SYNTH_SYNTH4_FORCE_VCOCAP_SET(x) (((x) << SYNTH_SYNTH4_FORCE_VCOCAP_LSB) & SYNTH_SYNTH4_FORCE_VCOCAP_MASK)
+#define SYNTH_SYNTH4_VCOCAP_OVR_MSB 25
+#define SYNTH_SYNTH4_VCOCAP_OVR_LSB 18
+#define SYNTH_SYNTH4_VCOCAP_OVR_MASK 0x03fc0000
+#define SYNTH_SYNTH4_VCOCAP_OVR_GET(x) (((x) & SYNTH_SYNTH4_VCOCAP_OVR_MASK) >> SYNTH_SYNTH4_VCOCAP_OVR_LSB)
+#define SYNTH_SYNTH4_VCOCAP_OVR_SET(x) (((x) << SYNTH_SYNTH4_VCOCAP_OVR_LSB) & SYNTH_SYNTH4_VCOCAP_OVR_MASK)
+#define SYNTH_SYNTH4_VCOCAPPULLUP_MSB 17
+#define SYNTH_SYNTH4_VCOCAPPULLUP_LSB 17
+#define SYNTH_SYNTH4_VCOCAPPULLUP_MASK 0x00020000
+#define SYNTH_SYNTH4_VCOCAPPULLUP_GET(x) (((x) & SYNTH_SYNTH4_VCOCAPPULLUP_MASK) >> SYNTH_SYNTH4_VCOCAPPULLUP_LSB)
+#define SYNTH_SYNTH4_VCOCAPPULLUP_SET(x) (((x) << SYNTH_SYNTH4_VCOCAPPULLUP_LSB) & SYNTH_SYNTH4_VCOCAPPULLUP_MASK)
+#define SYNTH_SYNTH4_REFDIVSEL_MSB 16
+#define SYNTH_SYNTH4_REFDIVSEL_LSB 15
+#define SYNTH_SYNTH4_REFDIVSEL_MASK 0x00018000
+#define SYNTH_SYNTH4_REFDIVSEL_GET(x) (((x) & SYNTH_SYNTH4_REFDIVSEL_MASK) >> SYNTH_SYNTH4_REFDIVSEL_LSB)
+#define SYNTH_SYNTH4_REFDIVSEL_SET(x) (((x) << SYNTH_SYNTH4_REFDIVSEL_LSB) & SYNTH_SYNTH4_REFDIVSEL_MASK)
+#define SYNTH_SYNTH4_PFDDELAY_MSB 14
+#define SYNTH_SYNTH4_PFDDELAY_LSB 14
+#define SYNTH_SYNTH4_PFDDELAY_MASK 0x00004000
+#define SYNTH_SYNTH4_PFDDELAY_GET(x) (((x) & SYNTH_SYNTH4_PFDDELAY_MASK) >> SYNTH_SYNTH4_PFDDELAY_LSB)
+#define SYNTH_SYNTH4_PFDDELAY_SET(x) (((x) << SYNTH_SYNTH4_PFDDELAY_LSB) & SYNTH_SYNTH4_PFDDELAY_MASK)
+#define SYNTH_SYNTH4_PFD_DISABLE_MSB 13
+#define SYNTH_SYNTH4_PFD_DISABLE_LSB 13
+#define SYNTH_SYNTH4_PFD_DISABLE_MASK 0x00002000
+#define SYNTH_SYNTH4_PFD_DISABLE_GET(x) (((x) & SYNTH_SYNTH4_PFD_DISABLE_MASK) >> SYNTH_SYNTH4_PFD_DISABLE_LSB)
+#define SYNTH_SYNTH4_PFD_DISABLE_SET(x) (((x) << SYNTH_SYNTH4_PFD_DISABLE_LSB) & SYNTH_SYNTH4_PFD_DISABLE_MASK)
+#define SYNTH_SYNTH4_PRESCSEL_MSB 12
+#define SYNTH_SYNTH4_PRESCSEL_LSB 11
+#define SYNTH_SYNTH4_PRESCSEL_MASK 0x00001800
+#define SYNTH_SYNTH4_PRESCSEL_GET(x) (((x) & SYNTH_SYNTH4_PRESCSEL_MASK) >> SYNTH_SYNTH4_PRESCSEL_LSB)
+#define SYNTH_SYNTH4_PRESCSEL_SET(x) (((x) << SYNTH_SYNTH4_PRESCSEL_LSB) & SYNTH_SYNTH4_PRESCSEL_MASK)
+#define SYNTH_SYNTH4_RESET_PRESC_MSB 10
+#define SYNTH_SYNTH4_RESET_PRESC_LSB 10
+#define SYNTH_SYNTH4_RESET_PRESC_MASK 0x00000400
+#define SYNTH_SYNTH4_RESET_PRESC_GET(x) (((x) & SYNTH_SYNTH4_RESET_PRESC_MASK) >> SYNTH_SYNTH4_RESET_PRESC_LSB)
+#define SYNTH_SYNTH4_RESET_PRESC_SET(x) (((x) << SYNTH_SYNTH4_RESET_PRESC_LSB) & SYNTH_SYNTH4_RESET_PRESC_MASK)
+#define SYNTH_SYNTH4_SDM_DISABLE_MSB 9
+#define SYNTH_SYNTH4_SDM_DISABLE_LSB 9
+#define SYNTH_SYNTH4_SDM_DISABLE_MASK 0x00000200
+#define SYNTH_SYNTH4_SDM_DISABLE_GET(x) (((x) & SYNTH_SYNTH4_SDM_DISABLE_MASK) >> SYNTH_SYNTH4_SDM_DISABLE_LSB)
+#define SYNTH_SYNTH4_SDM_DISABLE_SET(x) (((x) << SYNTH_SYNTH4_SDM_DISABLE_LSB) & SYNTH_SYNTH4_SDM_DISABLE_MASK)
+#define SYNTH_SYNTH4_SDM_MODE_MSB 8
+#define SYNTH_SYNTH4_SDM_MODE_LSB 8
+#define SYNTH_SYNTH4_SDM_MODE_MASK 0x00000100
+#define SYNTH_SYNTH4_SDM_MODE_GET(x) (((x) & SYNTH_SYNTH4_SDM_MODE_MASK) >> SYNTH_SYNTH4_SDM_MODE_LSB)
+#define SYNTH_SYNTH4_SDM_MODE_SET(x) (((x) << SYNTH_SYNTH4_SDM_MODE_LSB) & SYNTH_SYNTH4_SDM_MODE_MASK)
+#define SYNTH_SYNTH4_SDM_DITHER_MSB 7
+#define SYNTH_SYNTH4_SDM_DITHER_LSB 6
+#define SYNTH_SYNTH4_SDM_DITHER_MASK 0x000000c0
+#define SYNTH_SYNTH4_SDM_DITHER_GET(x) (((x) & SYNTH_SYNTH4_SDM_DITHER_MASK) >> SYNTH_SYNTH4_SDM_DITHER_LSB)
+#define SYNTH_SYNTH4_SDM_DITHER_SET(x) (((x) << SYNTH_SYNTH4_SDM_DITHER_LSB) & SYNTH_SYNTH4_SDM_DITHER_MASK)
+#define SYNTH_SYNTH4_PSCOUNT_FBSEL_MSB 5
+#define SYNTH_SYNTH4_PSCOUNT_FBSEL_LSB 5
+#define SYNTH_SYNTH4_PSCOUNT_FBSEL_MASK 0x00000020
+#define SYNTH_SYNTH4_PSCOUNT_FBSEL_GET(x) (((x) & SYNTH_SYNTH4_PSCOUNT_FBSEL_MASK) >> SYNTH_SYNTH4_PSCOUNT_FBSEL_LSB)
+#define SYNTH_SYNTH4_PSCOUNT_FBSEL_SET(x) (((x) << SYNTH_SYNTH4_PSCOUNT_FBSEL_LSB) & SYNTH_SYNTH4_PSCOUNT_FBSEL_MASK)
+#define SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_MSB 4
+#define SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_LSB 4
+#define SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_MASK 0x00000010
+#define SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_GET(x) (((x) & SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_MASK) >> SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_LSB)
+#define SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_SET(x) (((x) << SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_LSB) & SYNTH_SYNTH4_SEL_CLKXTAL_EDGE_MASK)
+#define SYNTH_SYNTH4_SPARE_MISC_MSB 3
+#define SYNTH_SYNTH4_SPARE_MISC_LSB 2
+#define SYNTH_SYNTH4_SPARE_MISC_MASK 0x0000000c
+#define SYNTH_SYNTH4_SPARE_MISC_GET(x) (((x) & SYNTH_SYNTH4_SPARE_MISC_MASK) >> SYNTH_SYNTH4_SPARE_MISC_LSB)
+#define SYNTH_SYNTH4_SPARE_MISC_SET(x) (((x) << SYNTH_SYNTH4_SPARE_MISC_LSB) & SYNTH_SYNTH4_SPARE_MISC_MASK)
+#define SYNTH_SYNTH4_LONGSHIFTSEL_MSB 1
+#define SYNTH_SYNTH4_LONGSHIFTSEL_LSB 1
+#define SYNTH_SYNTH4_LONGSHIFTSEL_MASK 0x00000002
+#define SYNTH_SYNTH4_LONGSHIFTSEL_GET(x) (((x) & SYNTH_SYNTH4_LONGSHIFTSEL_MASK) >> SYNTH_SYNTH4_LONGSHIFTSEL_LSB)
+#define SYNTH_SYNTH4_LONGSHIFTSEL_SET(x) (((x) << SYNTH_SYNTH4_LONGSHIFTSEL_LSB) & SYNTH_SYNTH4_LONGSHIFTSEL_MASK)
+#define SYNTH_SYNTH4_FORCE_SHIFTREG_MSB 0
+#define SYNTH_SYNTH4_FORCE_SHIFTREG_LSB 0
+#define SYNTH_SYNTH4_FORCE_SHIFTREG_MASK 0x00000001
+#define SYNTH_SYNTH4_FORCE_SHIFTREG_GET(x) (((x) & SYNTH_SYNTH4_FORCE_SHIFTREG_MASK) >> SYNTH_SYNTH4_FORCE_SHIFTREG_LSB)
+#define SYNTH_SYNTH4_FORCE_SHIFTREG_SET(x) (((x) << SYNTH_SYNTH4_FORCE_SHIFTREG_LSB) & SYNTH_SYNTH4_FORCE_SHIFTREG_MASK)
+
+#define SYNTH_SYNTH5_ADDRESS 0x00000010
+#define SYNTH_SYNTH5_OFFSET 0x00000010
+#define SYNTH_SYNTH5_LOOP_IP0_MSB 31
+#define SYNTH_SYNTH5_LOOP_IP0_LSB 28
+#define SYNTH_SYNTH5_LOOP_IP0_MASK 0xf0000000
+#define SYNTH_SYNTH5_LOOP_IP0_GET(x) (((x) & SYNTH_SYNTH5_LOOP_IP0_MASK) >> SYNTH_SYNTH5_LOOP_IP0_LSB)
+#define SYNTH_SYNTH5_LOOP_IP0_SET(x) (((x) << SYNTH_SYNTH5_LOOP_IP0_LSB) & SYNTH_SYNTH5_LOOP_IP0_MASK)
+#define SYNTH_SYNTH5_SLOPE_IP_MSB 27
+#define SYNTH_SYNTH5_SLOPE_IP_LSB 25
+#define SYNTH_SYNTH5_SLOPE_IP_MASK 0x0e000000
+#define SYNTH_SYNTH5_SLOPE_IP_GET(x) (((x) & SYNTH_SYNTH5_SLOPE_IP_MASK) >> SYNTH_SYNTH5_SLOPE_IP_LSB)
+#define SYNTH_SYNTH5_SLOPE_IP_SET(x) (((x) << SYNTH_SYNTH5_SLOPE_IP_LSB) & SYNTH_SYNTH5_SLOPE_IP_MASK)
+#define SYNTH_SYNTH5_CPBIAS_MSB 24
+#define SYNTH_SYNTH5_CPBIAS_LSB 23
+#define SYNTH_SYNTH5_CPBIAS_MASK 0x01800000
+#define SYNTH_SYNTH5_CPBIAS_GET(x) (((x) & SYNTH_SYNTH5_CPBIAS_MASK) >> SYNTH_SYNTH5_CPBIAS_LSB)
+#define SYNTH_SYNTH5_CPBIAS_SET(x) (((x) << SYNTH_SYNTH5_CPBIAS_LSB) & SYNTH_SYNTH5_CPBIAS_MASK)
+#define SYNTH_SYNTH5_CPSTEERING_EN_MSB 22
+#define SYNTH_SYNTH5_CPSTEERING_EN_LSB 22
+#define SYNTH_SYNTH5_CPSTEERING_EN_MASK 0x00400000
+#define SYNTH_SYNTH5_CPSTEERING_EN_GET(x) (((x) & SYNTH_SYNTH5_CPSTEERING_EN_MASK) >> SYNTH_SYNTH5_CPSTEERING_EN_LSB)
+#define SYNTH_SYNTH5_CPSTEERING_EN_SET(x) (((x) << SYNTH_SYNTH5_CPSTEERING_EN_LSB) & SYNTH_SYNTH5_CPSTEERING_EN_MASK)
+#define SYNTH_SYNTH5_CPLOWLK_MSB 21
+#define SYNTH_SYNTH5_CPLOWLK_LSB 21
+#define SYNTH_SYNTH5_CPLOWLK_MASK 0x00200000
+#define SYNTH_SYNTH5_CPLOWLK_GET(x) (((x) & SYNTH_SYNTH5_CPLOWLK_MASK) >> SYNTH_SYNTH5_CPLOWLK_LSB)
+#define SYNTH_SYNTH5_CPLOWLK_SET(x) (((x) << SYNTH_SYNTH5_CPLOWLK_LSB) & SYNTH_SYNTH5_CPLOWLK_MASK)
+#define SYNTH_SYNTH5_LOOPLEAKCUR_MSB 20
+#define SYNTH_SYNTH5_LOOPLEAKCUR_LSB 17
+#define SYNTH_SYNTH5_LOOPLEAKCUR_MASK 0x001e0000
+#define SYNTH_SYNTH5_LOOPLEAKCUR_GET(x) (((x) & SYNTH_SYNTH5_LOOPLEAKCUR_MASK) >> SYNTH_SYNTH5_LOOPLEAKCUR_LSB)
+#define SYNTH_SYNTH5_LOOPLEAKCUR_SET(x) (((x) << SYNTH_SYNTH5_LOOPLEAKCUR_LSB) & SYNTH_SYNTH5_LOOPLEAKCUR_MASK)
+#define SYNTH_SYNTH5_CAPRANGE1_MSB 16
+#define SYNTH_SYNTH5_CAPRANGE1_LSB 13
+#define SYNTH_SYNTH5_CAPRANGE1_MASK 0x0001e000
+#define SYNTH_SYNTH5_CAPRANGE1_GET(x) (((x) & SYNTH_SYNTH5_CAPRANGE1_MASK) >> SYNTH_SYNTH5_CAPRANGE1_LSB)
+#define SYNTH_SYNTH5_CAPRANGE1_SET(x) (((x) << SYNTH_SYNTH5_CAPRANGE1_LSB) & SYNTH_SYNTH5_CAPRANGE1_MASK)
+#define SYNTH_SYNTH5_CAPRANGE2_MSB 12
+#define SYNTH_SYNTH5_CAPRANGE2_LSB 9
+#define SYNTH_SYNTH5_CAPRANGE2_MASK 0x00001e00
+#define SYNTH_SYNTH5_CAPRANGE2_GET(x) (((x) & SYNTH_SYNTH5_CAPRANGE2_MASK) >> SYNTH_SYNTH5_CAPRANGE2_LSB)
+#define SYNTH_SYNTH5_CAPRANGE2_SET(x) (((x) << SYNTH_SYNTH5_CAPRANGE2_LSB) & SYNTH_SYNTH5_CAPRANGE2_MASK)
+#define SYNTH_SYNTH5_CAPRANGE3_MSB 8
+#define SYNTH_SYNTH5_CAPRANGE3_LSB 5
+#define SYNTH_SYNTH5_CAPRANGE3_MASK 0x000001e0
+#define SYNTH_SYNTH5_CAPRANGE3_GET(x) (((x) & SYNTH_SYNTH5_CAPRANGE3_MASK) >> SYNTH_SYNTH5_CAPRANGE3_LSB)
+#define SYNTH_SYNTH5_CAPRANGE3_SET(x) (((x) << SYNTH_SYNTH5_CAPRANGE3_LSB) & SYNTH_SYNTH5_CAPRANGE3_MASK)
+#define SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_MSB 4
+#define SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_LSB 4
+#define SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_MASK 0x00000010
+#define SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_GET(x) (((x) & SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_MASK) >> SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_LSB)
+#define SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_SET(x) (((x) << SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_LSB) & SYNTH_SYNTH5_FORCE_LOBUF5GTUNE_MASK)
+#define SYNTH_SYNTH5_LOBUF5GTUNE_OVR_MSB 3
+#define SYNTH_SYNTH5_LOBUF5GTUNE_OVR_LSB 2
+#define SYNTH_SYNTH5_LOBUF5GTUNE_OVR_MASK 0x0000000c
+#define SYNTH_SYNTH5_LOBUF5GTUNE_OVR_GET(x) (((x) & SYNTH_SYNTH5_LOBUF5GTUNE_OVR_MASK) >> SYNTH_SYNTH5_LOBUF5GTUNE_OVR_LSB)
+#define SYNTH_SYNTH5_LOBUF5GTUNE_OVR_SET(x) (((x) << SYNTH_SYNTH5_LOBUF5GTUNE_OVR_LSB) & SYNTH_SYNTH5_LOBUF5GTUNE_OVR_MASK)
+#define SYNTH_SYNTH5_SPARE_MSB 1
+#define SYNTH_SYNTH5_SPARE_LSB 0
+#define SYNTH_SYNTH5_SPARE_MASK 0x00000003
+#define SYNTH_SYNTH5_SPARE_GET(x) (((x) & SYNTH_SYNTH5_SPARE_MASK) >> SYNTH_SYNTH5_SPARE_LSB)
+#define SYNTH_SYNTH5_SPARE_SET(x) (((x) << SYNTH_SYNTH5_SPARE_LSB) & SYNTH_SYNTH5_SPARE_MASK)
+
+#define SYNTH_SYNTH6_ADDRESS 0x00000014
+#define SYNTH_SYNTH6_OFFSET 0x00000014
+#define SYNTH_SYNTH6_IRCP_MSB 31
+#define SYNTH_SYNTH6_IRCP_LSB 29
+#define SYNTH_SYNTH6_IRCP_MASK 0xe0000000
+#define SYNTH_SYNTH6_IRCP_GET(x) (((x) & SYNTH_SYNTH6_IRCP_MASK) >> SYNTH_SYNTH6_IRCP_LSB)
+#define SYNTH_SYNTH6_IRCP_SET(x) (((x) << SYNTH_SYNTH6_IRCP_LSB) & SYNTH_SYNTH6_IRCP_MASK)
+#define SYNTH_SYNTH6_IRVCMON_MSB 28
+#define SYNTH_SYNTH6_IRVCMON_LSB 26
+#define SYNTH_SYNTH6_IRVCMON_MASK 0x1c000000
+#define SYNTH_SYNTH6_IRVCMON_GET(x) (((x) & SYNTH_SYNTH6_IRVCMON_MASK) >> SYNTH_SYNTH6_IRVCMON_LSB)
+#define SYNTH_SYNTH6_IRVCMON_SET(x) (((x) << SYNTH_SYNTH6_IRVCMON_LSB) & SYNTH_SYNTH6_IRVCMON_MASK)
+#define SYNTH_SYNTH6_IRSPARE_MSB 25
+#define SYNTH_SYNTH6_IRSPARE_LSB 23
+#define SYNTH_SYNTH6_IRSPARE_MASK 0x03800000
+#define SYNTH_SYNTH6_IRSPARE_GET(x) (((x) & SYNTH_SYNTH6_IRSPARE_MASK) >> SYNTH_SYNTH6_IRSPARE_LSB)
+#define SYNTH_SYNTH6_IRSPARE_SET(x) (((x) << SYNTH_SYNTH6_IRSPARE_LSB) & SYNTH_SYNTH6_IRSPARE_MASK)
+#define SYNTH_SYNTH6_ICPRESC_MSB 22
+#define SYNTH_SYNTH6_ICPRESC_LSB 20
+#define SYNTH_SYNTH6_ICPRESC_MASK 0x00700000
+#define SYNTH_SYNTH6_ICPRESC_GET(x) (((x) & SYNTH_SYNTH6_ICPRESC_MASK) >> SYNTH_SYNTH6_ICPRESC_LSB)
+#define SYNTH_SYNTH6_ICPRESC_SET(x) (((x) << SYNTH_SYNTH6_ICPRESC_LSB) & SYNTH_SYNTH6_ICPRESC_MASK)
+#define SYNTH_SYNTH6_ICLODIV_MSB 19
+#define SYNTH_SYNTH6_ICLODIV_LSB 17
+#define SYNTH_SYNTH6_ICLODIV_MASK 0x000e0000
+#define SYNTH_SYNTH6_ICLODIV_GET(x) (((x) & SYNTH_SYNTH6_ICLODIV_MASK) >> SYNTH_SYNTH6_ICLODIV_LSB)
+#define SYNTH_SYNTH6_ICLODIV_SET(x) (((x) << SYNTH_SYNTH6_ICLODIV_LSB) & SYNTH_SYNTH6_ICLODIV_MASK)
+#define SYNTH_SYNTH6_ICLOMIX_MSB 16
+#define SYNTH_SYNTH6_ICLOMIX_LSB 14
+#define SYNTH_SYNTH6_ICLOMIX_MASK 0x0001c000
+#define SYNTH_SYNTH6_ICLOMIX_GET(x) (((x) & SYNTH_SYNTH6_ICLOMIX_MASK) >> SYNTH_SYNTH6_ICLOMIX_LSB)
+#define SYNTH_SYNTH6_ICLOMIX_SET(x) (((x) << SYNTH_SYNTH6_ICLOMIX_LSB) & SYNTH_SYNTH6_ICLOMIX_MASK)
+#define SYNTH_SYNTH6_ICSPAREA_MSB 13
+#define SYNTH_SYNTH6_ICSPAREA_LSB 11
+#define SYNTH_SYNTH6_ICSPAREA_MASK 0x00003800
+#define SYNTH_SYNTH6_ICSPAREA_GET(x) (((x) & SYNTH_SYNTH6_ICSPAREA_MASK) >> SYNTH_SYNTH6_ICSPAREA_LSB)
+#define SYNTH_SYNTH6_ICSPAREA_SET(x) (((x) << SYNTH_SYNTH6_ICSPAREA_LSB) & SYNTH_SYNTH6_ICSPAREA_MASK)
+#define SYNTH_SYNTH6_ICSPAREB_MSB 10
+#define SYNTH_SYNTH6_ICSPAREB_LSB 8
+#define SYNTH_SYNTH6_ICSPAREB_MASK 0x00000700
+#define SYNTH_SYNTH6_ICSPAREB_GET(x) (((x) & SYNTH_SYNTH6_ICSPAREB_MASK) >> SYNTH_SYNTH6_ICSPAREB_LSB)
+#define SYNTH_SYNTH6_ICSPAREB_SET(x) (((x) << SYNTH_SYNTH6_ICSPAREB_LSB) & SYNTH_SYNTH6_ICSPAREB_MASK)
+#define SYNTH_SYNTH6_ICVCO_MSB 7
+#define SYNTH_SYNTH6_ICVCO_LSB 5
+#define SYNTH_SYNTH6_ICVCO_MASK 0x000000e0
+#define SYNTH_SYNTH6_ICVCO_GET(x) (((x) & SYNTH_SYNTH6_ICVCO_MASK) >> SYNTH_SYNTH6_ICVCO_LSB)
+#define SYNTH_SYNTH6_ICVCO_SET(x) (((x) << SYNTH_SYNTH6_ICVCO_LSB) & SYNTH_SYNTH6_ICVCO_MASK)
+#define SYNTH_SYNTH6_VCOBUFBIAS_MSB 4
+#define SYNTH_SYNTH6_VCOBUFBIAS_LSB 3
+#define SYNTH_SYNTH6_VCOBUFBIAS_MASK 0x00000018
+#define SYNTH_SYNTH6_VCOBUFBIAS_GET(x) (((x) & SYNTH_SYNTH6_VCOBUFBIAS_MASK) >> SYNTH_SYNTH6_VCOBUFBIAS_LSB)
+#define SYNTH_SYNTH6_VCOBUFBIAS_SET(x) (((x) << SYNTH_SYNTH6_VCOBUFBIAS_LSB) & SYNTH_SYNTH6_VCOBUFBIAS_MASK)
+#define SYNTH_SYNTH6_SPARE_BIAS_MSB 2
+#define SYNTH_SYNTH6_SPARE_BIAS_LSB 0
+#define SYNTH_SYNTH6_SPARE_BIAS_MASK 0x00000007
+#define SYNTH_SYNTH6_SPARE_BIAS_GET(x) (((x) & SYNTH_SYNTH6_SPARE_BIAS_MASK) >> SYNTH_SYNTH6_SPARE_BIAS_LSB)
+#define SYNTH_SYNTH6_SPARE_BIAS_SET(x) (((x) << SYNTH_SYNTH6_SPARE_BIAS_LSB) & SYNTH_SYNTH6_SPARE_BIAS_MASK)
+
+#define SYNTH_SYNTH7_ADDRESS 0x00000018
+#define SYNTH_SYNTH7_OFFSET 0x00000018
+#define SYNTH_SYNTH7_SYNTH_ON_MSB 31
+#define SYNTH_SYNTH7_SYNTH_ON_LSB 31
+#define SYNTH_SYNTH7_SYNTH_ON_MASK 0x80000000
+#define SYNTH_SYNTH7_SYNTH_ON_GET(x) (((x) & SYNTH_SYNTH7_SYNTH_ON_MASK) >> SYNTH_SYNTH7_SYNTH_ON_LSB)
+#define SYNTH_SYNTH7_SYNTH_ON_SET(x) (((x) << SYNTH_SYNTH7_SYNTH_ON_LSB) & SYNTH_SYNTH7_SYNTH_ON_MASK)
+#define SYNTH_SYNTH7_SYNTH_SM_STATE_MSB 30
+#define SYNTH_SYNTH7_SYNTH_SM_STATE_LSB 27
+#define SYNTH_SYNTH7_SYNTH_SM_STATE_MASK 0x78000000
+#define SYNTH_SYNTH7_SYNTH_SM_STATE_GET(x) (((x) & SYNTH_SYNTH7_SYNTH_SM_STATE_MASK) >> SYNTH_SYNTH7_SYNTH_SM_STATE_LSB)
+#define SYNTH_SYNTH7_SYNTH_SM_STATE_SET(x) (((x) << SYNTH_SYNTH7_SYNTH_SM_STATE_LSB) & SYNTH_SYNTH7_SYNTH_SM_STATE_MASK)
+#define SYNTH_SYNTH7_CAP_SEARCH_MSB 26
+#define SYNTH_SYNTH7_CAP_SEARCH_LSB 26
+#define SYNTH_SYNTH7_CAP_SEARCH_MASK 0x04000000
+#define SYNTH_SYNTH7_CAP_SEARCH_GET(x) (((x) & SYNTH_SYNTH7_CAP_SEARCH_MASK) >> SYNTH_SYNTH7_CAP_SEARCH_LSB)
+#define SYNTH_SYNTH7_CAP_SEARCH_SET(x) (((x) << SYNTH_SYNTH7_CAP_SEARCH_LSB) & SYNTH_SYNTH7_CAP_SEARCH_MASK)
+#define SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_MSB 25
+#define SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_LSB 25
+#define SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_MASK 0x02000000
+#define SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_GET(x) (((x) & SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_MASK) >> SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_LSB)
+#define SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_SET(x) (((x) << SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_LSB) & SYNTH_SYNTH7_SYNTH_LOCK_VC_OK_MASK)
+#define SYNTH_SYNTH7_PIN_VC_MSB 24
+#define SYNTH_SYNTH7_PIN_VC_LSB 24
+#define SYNTH_SYNTH7_PIN_VC_MASK 0x01000000
+#define SYNTH_SYNTH7_PIN_VC_GET(x) (((x) & SYNTH_SYNTH7_PIN_VC_MASK) >> SYNTH_SYNTH7_PIN_VC_LSB)
+#define SYNTH_SYNTH7_PIN_VC_SET(x) (((x) << SYNTH_SYNTH7_PIN_VC_LSB) & SYNTH_SYNTH7_PIN_VC_MASK)
+#define SYNTH_SYNTH7_VCO_CAP_ST_MSB 23
+#define SYNTH_SYNTH7_VCO_CAP_ST_LSB 16
+#define SYNTH_SYNTH7_VCO_CAP_ST_MASK 0x00ff0000
+#define SYNTH_SYNTH7_VCO_CAP_ST_GET(x) (((x) & SYNTH_SYNTH7_VCO_CAP_ST_MASK) >> SYNTH_SYNTH7_VCO_CAP_ST_LSB)
+#define SYNTH_SYNTH7_VCO_CAP_ST_SET(x) (((x) << SYNTH_SYNTH7_VCO_CAP_ST_LSB) & SYNTH_SYNTH7_VCO_CAP_ST_MASK)
+#define SYNTH_SYNTH7_SHORT_R_MSB 15
+#define SYNTH_SYNTH7_SHORT_R_LSB 15
+#define SYNTH_SYNTH7_SHORT_R_MASK 0x00008000
+#define SYNTH_SYNTH7_SHORT_R_GET(x) (((x) & SYNTH_SYNTH7_SHORT_R_MASK) >> SYNTH_SYNTH7_SHORT_R_LSB)
+#define SYNTH_SYNTH7_SHORT_R_SET(x) (((x) << SYNTH_SYNTH7_SHORT_R_LSB) & SYNTH_SYNTH7_SHORT_R_MASK)
+#define SYNTH_SYNTH7_RESET_RFD_MSB 14
+#define SYNTH_SYNTH7_RESET_RFD_LSB 14
+#define SYNTH_SYNTH7_RESET_RFD_MASK 0x00004000
+#define SYNTH_SYNTH7_RESET_RFD_GET(x) (((x) & SYNTH_SYNTH7_RESET_RFD_MASK) >> SYNTH_SYNTH7_RESET_RFD_LSB)
+#define SYNTH_SYNTH7_RESET_RFD_SET(x) (((x) << SYNTH_SYNTH7_RESET_RFD_LSB) & SYNTH_SYNTH7_RESET_RFD_MASK)
+#define SYNTH_SYNTH7_RESET_PFD_MSB 13
+#define SYNTH_SYNTH7_RESET_PFD_LSB 13
+#define SYNTH_SYNTH7_RESET_PFD_MASK 0x00002000
+#define SYNTH_SYNTH7_RESET_PFD_GET(x) (((x) & SYNTH_SYNTH7_RESET_PFD_MASK) >> SYNTH_SYNTH7_RESET_PFD_LSB)
+#define SYNTH_SYNTH7_RESET_PFD_SET(x) (((x) << SYNTH_SYNTH7_RESET_PFD_LSB) & SYNTH_SYNTH7_RESET_PFD_MASK)
+#define SYNTH_SYNTH7_RESET_PSCOUNTERS_MSB 12
+#define SYNTH_SYNTH7_RESET_PSCOUNTERS_LSB 12
+#define SYNTH_SYNTH7_RESET_PSCOUNTERS_MASK 0x00001000
+#define SYNTH_SYNTH7_RESET_PSCOUNTERS_GET(x) (((x) & SYNTH_SYNTH7_RESET_PSCOUNTERS_MASK) >> SYNTH_SYNTH7_RESET_PSCOUNTERS_LSB)
+#define SYNTH_SYNTH7_RESET_PSCOUNTERS_SET(x) (((x) << SYNTH_SYNTH7_RESET_PSCOUNTERS_LSB) & SYNTH_SYNTH7_RESET_PSCOUNTERS_MASK)
+#define SYNTH_SYNTH7_RESET_SDM_B_MSB 11
+#define SYNTH_SYNTH7_RESET_SDM_B_LSB 11
+#define SYNTH_SYNTH7_RESET_SDM_B_MASK 0x00000800
+#define SYNTH_SYNTH7_RESET_SDM_B_GET(x) (((x) & SYNTH_SYNTH7_RESET_SDM_B_MASK) >> SYNTH_SYNTH7_RESET_SDM_B_LSB)
+#define SYNTH_SYNTH7_RESET_SDM_B_SET(x) (((x) << SYNTH_SYNTH7_RESET_SDM_B_LSB) & SYNTH_SYNTH7_RESET_SDM_B_MASK)
+#define SYNTH_SYNTH7_VC2HIGH_MSB 10
+#define SYNTH_SYNTH7_VC2HIGH_LSB 10
+#define SYNTH_SYNTH7_VC2HIGH_MASK 0x00000400
+#define SYNTH_SYNTH7_VC2HIGH_GET(x) (((x) & SYNTH_SYNTH7_VC2HIGH_MASK) >> SYNTH_SYNTH7_VC2HIGH_LSB)
+#define SYNTH_SYNTH7_VC2HIGH_SET(x) (((x) << SYNTH_SYNTH7_VC2HIGH_LSB) & SYNTH_SYNTH7_VC2HIGH_MASK)
+#define SYNTH_SYNTH7_VC2LOW_MSB 9
+#define SYNTH_SYNTH7_VC2LOW_LSB 9
+#define SYNTH_SYNTH7_VC2LOW_MASK 0x00000200
+#define SYNTH_SYNTH7_VC2LOW_GET(x) (((x) & SYNTH_SYNTH7_VC2LOW_MASK) >> SYNTH_SYNTH7_VC2LOW_LSB)
+#define SYNTH_SYNTH7_VC2LOW_SET(x) (((x) << SYNTH_SYNTH7_VC2LOW_LSB) & SYNTH_SYNTH7_VC2LOW_MASK)
+#define SYNTH_SYNTH7_LOOP_IP_MSB 8
+#define SYNTH_SYNTH7_LOOP_IP_LSB 5
+#define SYNTH_SYNTH7_LOOP_IP_MASK 0x000001e0
+#define SYNTH_SYNTH7_LOOP_IP_GET(x) (((x) & SYNTH_SYNTH7_LOOP_IP_MASK) >> SYNTH_SYNTH7_LOOP_IP_LSB)
+#define SYNTH_SYNTH7_LOOP_IP_SET(x) (((x) << SYNTH_SYNTH7_LOOP_IP_LSB) & SYNTH_SYNTH7_LOOP_IP_MASK)
+#define SYNTH_SYNTH7_LOBUF5GTUNE_MSB 4
+#define SYNTH_SYNTH7_LOBUF5GTUNE_LSB 3
+#define SYNTH_SYNTH7_LOBUF5GTUNE_MASK 0x00000018
+#define SYNTH_SYNTH7_LOBUF5GTUNE_GET(x) (((x) & SYNTH_SYNTH7_LOBUF5GTUNE_MASK) >> SYNTH_SYNTH7_LOBUF5GTUNE_LSB)
+#define SYNTH_SYNTH7_LOBUF5GTUNE_SET(x) (((x) << SYNTH_SYNTH7_LOBUF5GTUNE_LSB) & SYNTH_SYNTH7_LOBUF5GTUNE_MASK)
+#define SYNTH_SYNTH7_SPARE_READ_MSB 2
+#define SYNTH_SYNTH7_SPARE_READ_LSB 0
+#define SYNTH_SYNTH7_SPARE_READ_MASK 0x00000007
+#define SYNTH_SYNTH7_SPARE_READ_GET(x) (((x) & SYNTH_SYNTH7_SPARE_READ_MASK) >> SYNTH_SYNTH7_SPARE_READ_LSB)
+#define SYNTH_SYNTH7_SPARE_READ_SET(x) (((x) << SYNTH_SYNTH7_SPARE_READ_LSB) & SYNTH_SYNTH7_SPARE_READ_MASK)
+
+#define SYNTH_SYNTH8_ADDRESS 0x0000001c
+#define SYNTH_SYNTH8_OFFSET 0x0000001c
+#define SYNTH_SYNTH8_LOADSYNTHCHANNEL_MSB 31
+#define SYNTH_SYNTH8_LOADSYNTHCHANNEL_LSB 31
+#define SYNTH_SYNTH8_LOADSYNTHCHANNEL_MASK 0x80000000
+#define SYNTH_SYNTH8_LOADSYNTHCHANNEL_GET(x) (((x) & SYNTH_SYNTH8_LOADSYNTHCHANNEL_MASK) >> SYNTH_SYNTH8_LOADSYNTHCHANNEL_LSB)
+#define SYNTH_SYNTH8_LOADSYNTHCHANNEL_SET(x) (((x) << SYNTH_SYNTH8_LOADSYNTHCHANNEL_LSB) & SYNTH_SYNTH8_LOADSYNTHCHANNEL_MASK)
+#define SYNTH_SYNTH8_FRACMODE_MSB 30
+#define SYNTH_SYNTH8_FRACMODE_LSB 30
+#define SYNTH_SYNTH8_FRACMODE_MASK 0x40000000
+#define SYNTH_SYNTH8_FRACMODE_GET(x) (((x) & SYNTH_SYNTH8_FRACMODE_MASK) >> SYNTH_SYNTH8_FRACMODE_LSB)
+#define SYNTH_SYNTH8_FRACMODE_SET(x) (((x) << SYNTH_SYNTH8_FRACMODE_LSB) & SYNTH_SYNTH8_FRACMODE_MASK)
+#define SYNTH_SYNTH8_AMODEREFSEL_MSB 29
+#define SYNTH_SYNTH8_AMODEREFSEL_LSB 28
+#define SYNTH_SYNTH8_AMODEREFSEL_MASK 0x30000000
+#define SYNTH_SYNTH8_AMODEREFSEL_GET(x) (((x) & SYNTH_SYNTH8_AMODEREFSEL_MASK) >> SYNTH_SYNTH8_AMODEREFSEL_LSB)
+#define SYNTH_SYNTH8_AMODEREFSEL_SET(x) (((x) << SYNTH_SYNTH8_AMODEREFSEL_LSB) & SYNTH_SYNTH8_AMODEREFSEL_MASK)
+#define SYNTH_SYNTH8_SPARE_MSB 27
+#define SYNTH_SYNTH8_SPARE_LSB 27
+#define SYNTH_SYNTH8_SPARE_MASK 0x08000000
+#define SYNTH_SYNTH8_SPARE_GET(x) (((x) & SYNTH_SYNTH8_SPARE_MASK) >> SYNTH_SYNTH8_SPARE_LSB)
+#define SYNTH_SYNTH8_SPARE_SET(x) (((x) << SYNTH_SYNTH8_SPARE_LSB) & SYNTH_SYNTH8_SPARE_MASK)
+#define SYNTH_SYNTH8_CHANSEL_MSB 26
+#define SYNTH_SYNTH8_CHANSEL_LSB 18
+#define SYNTH_SYNTH8_CHANSEL_MASK 0x07fc0000
+#define SYNTH_SYNTH8_CHANSEL_GET(x) (((x) & SYNTH_SYNTH8_CHANSEL_MASK) >> SYNTH_SYNTH8_CHANSEL_LSB)
+#define SYNTH_SYNTH8_CHANSEL_SET(x) (((x) << SYNTH_SYNTH8_CHANSEL_LSB) & SYNTH_SYNTH8_CHANSEL_MASK)
+#define SYNTH_SYNTH8_CHANFRAC_MSB 17
+#define SYNTH_SYNTH8_CHANFRAC_LSB 1
+#define SYNTH_SYNTH8_CHANFRAC_MASK 0x0003fffe
+#define SYNTH_SYNTH8_CHANFRAC_GET(x) (((x) & SYNTH_SYNTH8_CHANFRAC_MASK) >> SYNTH_SYNTH8_CHANFRAC_LSB)
+#define SYNTH_SYNTH8_CHANFRAC_SET(x) (((x) << SYNTH_SYNTH8_CHANFRAC_LSB) & SYNTH_SYNTH8_CHANFRAC_MASK)
+#define SYNTH_SYNTH8_FORCE_FRACLSB_MSB 0
+#define SYNTH_SYNTH8_FORCE_FRACLSB_LSB 0
+#define SYNTH_SYNTH8_FORCE_FRACLSB_MASK 0x00000001
+#define SYNTH_SYNTH8_FORCE_FRACLSB_GET(x) (((x) & SYNTH_SYNTH8_FORCE_FRACLSB_MASK) >> SYNTH_SYNTH8_FORCE_FRACLSB_LSB)
+#define SYNTH_SYNTH8_FORCE_FRACLSB_SET(x) (((x) << SYNTH_SYNTH8_FORCE_FRACLSB_LSB) & SYNTH_SYNTH8_FORCE_FRACLSB_MASK)
+
+#define RF5G_RF5G1_ADDRESS 0x00000020
+#define RF5G_RF5G1_OFFSET 0x00000020
+#define RF5G_RF5G1_PDTXLO5_MSB 31
+#define RF5G_RF5G1_PDTXLO5_LSB 31
+#define RF5G_RF5G1_PDTXLO5_MASK 0x80000000
+#define RF5G_RF5G1_PDTXLO5_GET(x) (((x) & RF5G_RF5G1_PDTXLO5_MASK) >> RF5G_RF5G1_PDTXLO5_LSB)
+#define RF5G_RF5G1_PDTXLO5_SET(x) (((x) << RF5G_RF5G1_PDTXLO5_LSB) & RF5G_RF5G1_PDTXLO5_MASK)
+#define RF5G_RF5G1_PDTXMIX5_MSB 30
+#define RF5G_RF5G1_PDTXMIX5_LSB 30
+#define RF5G_RF5G1_PDTXMIX5_MASK 0x40000000
+#define RF5G_RF5G1_PDTXMIX5_GET(x) (((x) & RF5G_RF5G1_PDTXMIX5_MASK) >> RF5G_RF5G1_PDTXMIX5_LSB)
+#define RF5G_RF5G1_PDTXMIX5_SET(x) (((x) << RF5G_RF5G1_PDTXMIX5_LSB) & RF5G_RF5G1_PDTXMIX5_MASK)
+#define RF5G_RF5G1_PDTXBUF5_MSB 29
+#define RF5G_RF5G1_PDTXBUF5_LSB 29
+#define RF5G_RF5G1_PDTXBUF5_MASK 0x20000000
+#define RF5G_RF5G1_PDTXBUF5_GET(x) (((x) & RF5G_RF5G1_PDTXBUF5_MASK) >> RF5G_RF5G1_PDTXBUF5_LSB)
+#define RF5G_RF5G1_PDTXBUF5_SET(x) (((x) << RF5G_RF5G1_PDTXBUF5_LSB) & RF5G_RF5G1_PDTXBUF5_MASK)
+#define RF5G_RF5G1_PDPADRV5_MSB 28
+#define RF5G_RF5G1_PDPADRV5_LSB 28
+#define RF5G_RF5G1_PDPADRV5_MASK 0x10000000
+#define RF5G_RF5G1_PDPADRV5_GET(x) (((x) & RF5G_RF5G1_PDPADRV5_MASK) >> RF5G_RF5G1_PDPADRV5_LSB)
+#define RF5G_RF5G1_PDPADRV5_SET(x) (((x) << RF5G_RF5G1_PDPADRV5_LSB) & RF5G_RF5G1_PDPADRV5_MASK)
+#define RF5G_RF5G1_PDPAOUT5_MSB 27
+#define RF5G_RF5G1_PDPAOUT5_LSB 27
+#define RF5G_RF5G1_PDPAOUT5_MASK 0x08000000
+#define RF5G_RF5G1_PDPAOUT5_GET(x) (((x) & RF5G_RF5G1_PDPAOUT5_MASK) >> RF5G_RF5G1_PDPAOUT5_LSB)
+#define RF5G_RF5G1_PDPAOUT5_SET(x) (((x) << RF5G_RF5G1_PDPAOUT5_LSB) & RF5G_RF5G1_PDPAOUT5_MASK)
+#define RF5G_RF5G1_TUNE_PADRV5_MSB 26
+#define RF5G_RF5G1_TUNE_PADRV5_LSB 24
+#define RF5G_RF5G1_TUNE_PADRV5_MASK 0x07000000
+#define RF5G_RF5G1_TUNE_PADRV5_GET(x) (((x) & RF5G_RF5G1_TUNE_PADRV5_MASK) >> RF5G_RF5G1_TUNE_PADRV5_LSB)
+#define RF5G_RF5G1_TUNE_PADRV5_SET(x) (((x) << RF5G_RF5G1_TUNE_PADRV5_LSB) & RF5G_RF5G1_TUNE_PADRV5_MASK)
+#define RF5G_RF5G1_PWDTXPKD_MSB 23
+#define RF5G_RF5G1_PWDTXPKD_LSB 21
+#define RF5G_RF5G1_PWDTXPKD_MASK 0x00e00000
+#define RF5G_RF5G1_PWDTXPKD_GET(x) (((x) & RF5G_RF5G1_PWDTXPKD_MASK) >> RF5G_RF5G1_PWDTXPKD_LSB)
+#define RF5G_RF5G1_PWDTXPKD_SET(x) (((x) << RF5G_RF5G1_PWDTXPKD_LSB) & RF5G_RF5G1_PWDTXPKD_MASK)
+#define RF5G_RF5G1_DB5_MSB 20
+#define RF5G_RF5G1_DB5_LSB 18
+#define RF5G_RF5G1_DB5_MASK 0x001c0000
+#define RF5G_RF5G1_DB5_GET(x) (((x) & RF5G_RF5G1_DB5_MASK) >> RF5G_RF5G1_DB5_LSB)
+#define RF5G_RF5G1_DB5_SET(x) (((x) << RF5G_RF5G1_DB5_LSB) & RF5G_RF5G1_DB5_MASK)
+#define RF5G_RF5G1_OB5_MSB 17
+#define RF5G_RF5G1_OB5_LSB 15
+#define RF5G_RF5G1_OB5_MASK 0x00038000
+#define RF5G_RF5G1_OB5_GET(x) (((x) & RF5G_RF5G1_OB5_MASK) >> RF5G_RF5G1_OB5_LSB)
+#define RF5G_RF5G1_OB5_SET(x) (((x) << RF5G_RF5G1_OB5_LSB) & RF5G_RF5G1_OB5_MASK)
+#define RF5G_RF5G1_TX5_ATB_SEL_MSB 14
+#define RF5G_RF5G1_TX5_ATB_SEL_LSB 12
+#define RF5G_RF5G1_TX5_ATB_SEL_MASK 0x00007000
+#define RF5G_RF5G1_TX5_ATB_SEL_GET(x) (((x) & RF5G_RF5G1_TX5_ATB_SEL_MASK) >> RF5G_RF5G1_TX5_ATB_SEL_LSB)
+#define RF5G_RF5G1_TX5_ATB_SEL_SET(x) (((x) << RF5G_RF5G1_TX5_ATB_SEL_LSB) & RF5G_RF5G1_TX5_ATB_SEL_MASK)
+#define RF5G_RF5G1_PDLO5DIV_MSB 11
+#define RF5G_RF5G1_PDLO5DIV_LSB 11
+#define RF5G_RF5G1_PDLO5DIV_MASK 0x00000800
+#define RF5G_RF5G1_PDLO5DIV_GET(x) (((x) & RF5G_RF5G1_PDLO5DIV_MASK) >> RF5G_RF5G1_PDLO5DIV_LSB)
+#define RF5G_RF5G1_PDLO5DIV_SET(x) (((x) << RF5G_RF5G1_PDLO5DIV_LSB) & RF5G_RF5G1_PDLO5DIV_MASK)
+#define RF5G_RF5G1_PDLO5MIX_MSB 10
+#define RF5G_RF5G1_PDLO5MIX_LSB 10
+#define RF5G_RF5G1_PDLO5MIX_MASK 0x00000400
+#define RF5G_RF5G1_PDLO5MIX_GET(x) (((x) & RF5G_RF5G1_PDLO5MIX_MASK) >> RF5G_RF5G1_PDLO5MIX_LSB)
+#define RF5G_RF5G1_PDLO5MIX_SET(x) (((x) << RF5G_RF5G1_PDLO5MIX_LSB) & RF5G_RF5G1_PDLO5MIX_MASK)
+#define RF5G_RF5G1_PDQBUF5_MSB 9
+#define RF5G_RF5G1_PDQBUF5_LSB 9
+#define RF5G_RF5G1_PDQBUF5_MASK 0x00000200
+#define RF5G_RF5G1_PDQBUF5_GET(x) (((x) & RF5G_RF5G1_PDQBUF5_MASK) >> RF5G_RF5G1_PDQBUF5_LSB)
+#define RF5G_RF5G1_PDQBUF5_SET(x) (((x) << RF5G_RF5G1_PDQBUF5_LSB) & RF5G_RF5G1_PDQBUF5_MASK)
+#define RF5G_RF5G1_PDLO5AGC_MSB 8
+#define RF5G_RF5G1_PDLO5AGC_LSB 8
+#define RF5G_RF5G1_PDLO5AGC_MASK 0x00000100
+#define RF5G_RF5G1_PDLO5AGC_GET(x) (((x) & RF5G_RF5G1_PDLO5AGC_MASK) >> RF5G_RF5G1_PDLO5AGC_LSB)
+#define RF5G_RF5G1_PDLO5AGC_SET(x) (((x) << RF5G_RF5G1_PDLO5AGC_LSB) & RF5G_RF5G1_PDLO5AGC_MASK)
+#define RF5G_RF5G1_PDREGLO5_MSB 7
+#define RF5G_RF5G1_PDREGLO5_LSB 7
+#define RF5G_RF5G1_PDREGLO5_MASK 0x00000080
+#define RF5G_RF5G1_PDREGLO5_GET(x) (((x) & RF5G_RF5G1_PDREGLO5_MASK) >> RF5G_RF5G1_PDREGLO5_LSB)
+#define RF5G_RF5G1_PDREGLO5_SET(x) (((x) << RF5G_RF5G1_PDREGLO5_LSB) & RF5G_RF5G1_PDREGLO5_MASK)
+#define RF5G_RF5G1_LO5_ATB_SEL_MSB 6
+#define RF5G_RF5G1_LO5_ATB_SEL_LSB 4
+#define RF5G_RF5G1_LO5_ATB_SEL_MASK 0x00000070
+#define RF5G_RF5G1_LO5_ATB_SEL_GET(x) (((x) & RF5G_RF5G1_LO5_ATB_SEL_MASK) >> RF5G_RF5G1_LO5_ATB_SEL_LSB)
+#define RF5G_RF5G1_LO5_ATB_SEL_SET(x) (((x) << RF5G_RF5G1_LO5_ATB_SEL_LSB) & RF5G_RF5G1_LO5_ATB_SEL_MASK)
+#define RF5G_RF5G1_LO5CONTROL_MSB 3
+#define RF5G_RF5G1_LO5CONTROL_LSB 3
+#define RF5G_RF5G1_LO5CONTROL_MASK 0x00000008
+#define RF5G_RF5G1_LO5CONTROL_GET(x) (((x) & RF5G_RF5G1_LO5CONTROL_MASK) >> RF5G_RF5G1_LO5CONTROL_LSB)
+#define RF5G_RF5G1_LO5CONTROL_SET(x) (((x) << RF5G_RF5G1_LO5CONTROL_LSB) & RF5G_RF5G1_LO5CONTROL_MASK)
+#define RF5G_RF5G1_REGLO_BYPASS5_MSB 2
+#define RF5G_RF5G1_REGLO_BYPASS5_LSB 2
+#define RF5G_RF5G1_REGLO_BYPASS5_MASK 0x00000004
+#define RF5G_RF5G1_REGLO_BYPASS5_GET(x) (((x) & RF5G_RF5G1_REGLO_BYPASS5_MASK) >> RF5G_RF5G1_REGLO_BYPASS5_LSB)
+#define RF5G_RF5G1_REGLO_BYPASS5_SET(x) (((x) << RF5G_RF5G1_REGLO_BYPASS5_LSB) & RF5G_RF5G1_REGLO_BYPASS5_MASK)
+#define RF5G_RF5G1_SPARE_MSB 1
+#define RF5G_RF5G1_SPARE_LSB 0
+#define RF5G_RF5G1_SPARE_MASK 0x00000003
+#define RF5G_RF5G1_SPARE_GET(x) (((x) & RF5G_RF5G1_SPARE_MASK) >> RF5G_RF5G1_SPARE_LSB)
+#define RF5G_RF5G1_SPARE_SET(x) (((x) << RF5G_RF5G1_SPARE_LSB) & RF5G_RF5G1_SPARE_MASK)
+
+#define RF5G_RF5G2_ADDRESS 0x00000024
+#define RF5G_RF5G2_OFFSET 0x00000024
+#define RF5G_RF5G2_AGCLO_B_MSB 31
+#define RF5G_RF5G2_AGCLO_B_LSB 29
+#define RF5G_RF5G2_AGCLO_B_MASK 0xe0000000
+#define RF5G_RF5G2_AGCLO_B_GET(x) (((x) & RF5G_RF5G2_AGCLO_B_MASK) >> RF5G_RF5G2_AGCLO_B_LSB)
+#define RF5G_RF5G2_AGCLO_B_SET(x) (((x) << RF5G_RF5G2_AGCLO_B_LSB) & RF5G_RF5G2_AGCLO_B_MASK)
+#define RF5G_RF5G2_RX5_ATB_SEL_MSB 28
+#define RF5G_RF5G2_RX5_ATB_SEL_LSB 26
+#define RF5G_RF5G2_RX5_ATB_SEL_MASK 0x1c000000
+#define RF5G_RF5G2_RX5_ATB_SEL_GET(x) (((x) & RF5G_RF5G2_RX5_ATB_SEL_MASK) >> RF5G_RF5G2_RX5_ATB_SEL_LSB)
+#define RF5G_RF5G2_RX5_ATB_SEL_SET(x) (((x) << RF5G_RF5G2_RX5_ATB_SEL_LSB) & RF5G_RF5G2_RX5_ATB_SEL_MASK)
+#define RF5G_RF5G2_PDCMOSLO5_MSB 25
+#define RF5G_RF5G2_PDCMOSLO5_LSB 25
+#define RF5G_RF5G2_PDCMOSLO5_MASK 0x02000000
+#define RF5G_RF5G2_PDCMOSLO5_GET(x) (((x) & RF5G_RF5G2_PDCMOSLO5_MASK) >> RF5G_RF5G2_PDCMOSLO5_LSB)
+#define RF5G_RF5G2_PDCMOSLO5_SET(x) (((x) << RF5G_RF5G2_PDCMOSLO5_LSB) & RF5G_RF5G2_PDCMOSLO5_MASK)
+#define RF5G_RF5G2_PDVGM5_MSB 24
+#define RF5G_RF5G2_PDVGM5_LSB 24
+#define RF5G_RF5G2_PDVGM5_MASK 0x01000000
+#define RF5G_RF5G2_PDVGM5_GET(x) (((x) & RF5G_RF5G2_PDVGM5_MASK) >> RF5G_RF5G2_PDVGM5_LSB)
+#define RF5G_RF5G2_PDVGM5_SET(x) (((x) << RF5G_RF5G2_PDVGM5_LSB) & RF5G_RF5G2_PDVGM5_MASK)
+#define RF5G_RF5G2_PDCSLNA5_MSB 23
+#define RF5G_RF5G2_PDCSLNA5_LSB 23
+#define RF5G_RF5G2_PDCSLNA5_MASK 0x00800000
+#define RF5G_RF5G2_PDCSLNA5_GET(x) (((x) & RF5G_RF5G2_PDCSLNA5_MASK) >> RF5G_RF5G2_PDCSLNA5_LSB)
+#define RF5G_RF5G2_PDCSLNA5_SET(x) (((x) << RF5G_RF5G2_PDCSLNA5_LSB) & RF5G_RF5G2_PDCSLNA5_MASK)
+#define RF5G_RF5G2_PDRFVGA5_MSB 22
+#define RF5G_RF5G2_PDRFVGA5_LSB 22
+#define RF5G_RF5G2_PDRFVGA5_MASK 0x00400000
+#define RF5G_RF5G2_PDRFVGA5_GET(x) (((x) & RF5G_RF5G2_PDRFVGA5_MASK) >> RF5G_RF5G2_PDRFVGA5_LSB)
+#define RF5G_RF5G2_PDRFVGA5_SET(x) (((x) << RF5G_RF5G2_PDRFVGA5_LSB) & RF5G_RF5G2_PDRFVGA5_MASK)
+#define RF5G_RF5G2_PDREGFE5_MSB 21
+#define RF5G_RF5G2_PDREGFE5_LSB 21
+#define RF5G_RF5G2_PDREGFE5_MASK 0x00200000
+#define RF5G_RF5G2_PDREGFE5_GET(x) (((x) & RF5G_RF5G2_PDREGFE5_MASK) >> RF5G_RF5G2_PDREGFE5_LSB)
+#define RF5G_RF5G2_PDREGFE5_SET(x) (((x) << RF5G_RF5G2_PDREGFE5_LSB) & RF5G_RF5G2_PDREGFE5_MASK)
+#define RF5G_RF5G2_TUNE_RFVGA5_MSB 20
+#define RF5G_RF5G2_TUNE_RFVGA5_LSB 18
+#define RF5G_RF5G2_TUNE_RFVGA5_MASK 0x001c0000
+#define RF5G_RF5G2_TUNE_RFVGA5_GET(x) (((x) & RF5G_RF5G2_TUNE_RFVGA5_MASK) >> RF5G_RF5G2_TUNE_RFVGA5_LSB)
+#define RF5G_RF5G2_TUNE_RFVGA5_SET(x) (((x) << RF5G_RF5G2_TUNE_RFVGA5_LSB) & RF5G_RF5G2_TUNE_RFVGA5_MASK)
+#define RF5G_RF5G2_BRFVGA5_MSB 17
+#define RF5G_RF5G2_BRFVGA5_LSB 15
+#define RF5G_RF5G2_BRFVGA5_MASK 0x00038000
+#define RF5G_RF5G2_BRFVGA5_GET(x) (((x) & RF5G_RF5G2_BRFVGA5_MASK) >> RF5G_RF5G2_BRFVGA5_LSB)
+#define RF5G_RF5G2_BRFVGA5_SET(x) (((x) << RF5G_RF5G2_BRFVGA5_LSB) & RF5G_RF5G2_BRFVGA5_MASK)
+#define RF5G_RF5G2_BCSLNA5_MSB 14
+#define RF5G_RF5G2_BCSLNA5_LSB 12
+#define RF5G_RF5G2_BCSLNA5_MASK 0x00007000
+#define RF5G_RF5G2_BCSLNA5_GET(x) (((x) & RF5G_RF5G2_BCSLNA5_MASK) >> RF5G_RF5G2_BCSLNA5_LSB)
+#define RF5G_RF5G2_BCSLNA5_SET(x) (((x) << RF5G_RF5G2_BCSLNA5_LSB) & RF5G_RF5G2_BCSLNA5_MASK)
+#define RF5G_RF5G2_BVGM5_MSB 11
+#define RF5G_RF5G2_BVGM5_LSB 9
+#define RF5G_RF5G2_BVGM5_MASK 0x00000e00
+#define RF5G_RF5G2_BVGM5_GET(x) (((x) & RF5G_RF5G2_BVGM5_MASK) >> RF5G_RF5G2_BVGM5_LSB)
+#define RF5G_RF5G2_BVGM5_SET(x) (((x) << RF5G_RF5G2_BVGM5_LSB) & RF5G_RF5G2_BVGM5_MASK)
+#define RF5G_RF5G2_REGFE_BYPASS5_MSB 8
+#define RF5G_RF5G2_REGFE_BYPASS5_LSB 8
+#define RF5G_RF5G2_REGFE_BYPASS5_MASK 0x00000100
+#define RF5G_RF5G2_REGFE_BYPASS5_GET(x) (((x) & RF5G_RF5G2_REGFE_BYPASS5_MASK) >> RF5G_RF5G2_REGFE_BYPASS5_LSB)
+#define RF5G_RF5G2_REGFE_BYPASS5_SET(x) (((x) << RF5G_RF5G2_REGFE_BYPASS5_LSB) & RF5G_RF5G2_REGFE_BYPASS5_MASK)
+#define RF5G_RF5G2_LNA5_ATTENMODE_MSB 7
+#define RF5G_RF5G2_LNA5_ATTENMODE_LSB 6
+#define RF5G_RF5G2_LNA5_ATTENMODE_MASK 0x000000c0
+#define RF5G_RF5G2_LNA5_ATTENMODE_GET(x) (((x) & RF5G_RF5G2_LNA5_ATTENMODE_MASK) >> RF5G_RF5G2_LNA5_ATTENMODE_LSB)
+#define RF5G_RF5G2_LNA5_ATTENMODE_SET(x) (((x) << RF5G_RF5G2_LNA5_ATTENMODE_LSB) & RF5G_RF5G2_LNA5_ATTENMODE_MASK)
+#define RF5G_RF5G2_ENABLE_PCA_MSB 5
+#define RF5G_RF5G2_ENABLE_PCA_LSB 5
+#define RF5G_RF5G2_ENABLE_PCA_MASK 0x00000020
+#define RF5G_RF5G2_ENABLE_PCA_GET(x) (((x) & RF5G_RF5G2_ENABLE_PCA_MASK) >> RF5G_RF5G2_ENABLE_PCA_LSB)
+#define RF5G_RF5G2_ENABLE_PCA_SET(x) (((x) << RF5G_RF5G2_ENABLE_PCA_LSB) & RF5G_RF5G2_ENABLE_PCA_MASK)
+#define RF5G_RF5G2_TUNE_LO_MSB 4
+#define RF5G_RF5G2_TUNE_LO_LSB 2
+#define RF5G_RF5G2_TUNE_LO_MASK 0x0000001c
+#define RF5G_RF5G2_TUNE_LO_GET(x) (((x) & RF5G_RF5G2_TUNE_LO_MASK) >> RF5G_RF5G2_TUNE_LO_LSB)
+#define RF5G_RF5G2_TUNE_LO_SET(x) (((x) << RF5G_RF5G2_TUNE_LO_LSB) & RF5G_RF5G2_TUNE_LO_MASK)
+#define RF5G_RF5G2_SPARE_MSB 1
+#define RF5G_RF5G2_SPARE_LSB 0
+#define RF5G_RF5G2_SPARE_MASK 0x00000003
+#define RF5G_RF5G2_SPARE_GET(x) (((x) & RF5G_RF5G2_SPARE_MASK) >> RF5G_RF5G2_SPARE_LSB)
+#define RF5G_RF5G2_SPARE_SET(x) (((x) << RF5G_RF5G2_SPARE_LSB) & RF5G_RF5G2_SPARE_MASK)
+
+#define RF2G_RF2G1_ADDRESS 0x00000028
+#define RF2G_RF2G1_OFFSET 0x00000028
+#define RF2G_RF2G1_BLNA1_MSB 31
+#define RF2G_RF2G1_BLNA1_LSB 29
+#define RF2G_RF2G1_BLNA1_MASK 0xe0000000
+#define RF2G_RF2G1_BLNA1_GET(x) (((x) & RF2G_RF2G1_BLNA1_MASK) >> RF2G_RF2G1_BLNA1_LSB)
+#define RF2G_RF2G1_BLNA1_SET(x) (((x) << RF2G_RF2G1_BLNA1_LSB) & RF2G_RF2G1_BLNA1_MASK)
+#define RF2G_RF2G1_BLNA1F_MSB 28
+#define RF2G_RF2G1_BLNA1F_LSB 26
+#define RF2G_RF2G1_BLNA1F_MASK 0x1c000000
+#define RF2G_RF2G1_BLNA1F_GET(x) (((x) & RF2G_RF2G1_BLNA1F_MASK) >> RF2G_RF2G1_BLNA1F_LSB)
+#define RF2G_RF2G1_BLNA1F_SET(x) (((x) << RF2G_RF2G1_BLNA1F_LSB) & RF2G_RF2G1_BLNA1F_MASK)
+#define RF2G_RF2G1_BLNA1BUF_MSB 25
+#define RF2G_RF2G1_BLNA1BUF_LSB 23
+#define RF2G_RF2G1_BLNA1BUF_MASK 0x03800000
+#define RF2G_RF2G1_BLNA1BUF_GET(x) (((x) & RF2G_RF2G1_BLNA1BUF_MASK) >> RF2G_RF2G1_BLNA1BUF_LSB)
+#define RF2G_RF2G1_BLNA1BUF_SET(x) (((x) << RF2G_RF2G1_BLNA1BUF_LSB) & RF2G_RF2G1_BLNA1BUF_MASK)
+#define RF2G_RF2G1_BLNA2_MSB 22
+#define RF2G_RF2G1_BLNA2_LSB 20
+#define RF2G_RF2G1_BLNA2_MASK 0x00700000
+#define RF2G_RF2G1_BLNA2_GET(x) (((x) & RF2G_RF2G1_BLNA2_MASK) >> RF2G_RF2G1_BLNA2_LSB)
+#define RF2G_RF2G1_BLNA2_SET(x) (((x) << RF2G_RF2G1_BLNA2_LSB) & RF2G_RF2G1_BLNA2_MASK)
+#define RF2G_RF2G1_DB_MSB 19
+#define RF2G_RF2G1_DB_LSB 17
+#define RF2G_RF2G1_DB_MASK 0x000e0000
+#define RF2G_RF2G1_DB_GET(x) (((x) & RF2G_RF2G1_DB_MASK) >> RF2G_RF2G1_DB_LSB)
+#define RF2G_RF2G1_DB_SET(x) (((x) << RF2G_RF2G1_DB_LSB) & RF2G_RF2G1_DB_MASK)
+#define RF2G_RF2G1_OB_MSB 16
+#define RF2G_RF2G1_OB_LSB 14
+#define RF2G_RF2G1_OB_MASK 0x0001c000
+#define RF2G_RF2G1_OB_GET(x) (((x) & RF2G_RF2G1_OB_MASK) >> RF2G_RF2G1_OB_LSB)
+#define RF2G_RF2G1_OB_SET(x) (((x) << RF2G_RF2G1_OB_LSB) & RF2G_RF2G1_OB_MASK)
+#define RF2G_RF2G1_FE_ATB_SEL_MSB 13
+#define RF2G_RF2G1_FE_ATB_SEL_LSB 11
+#define RF2G_RF2G1_FE_ATB_SEL_MASK 0x00003800
+#define RF2G_RF2G1_FE_ATB_SEL_GET(x) (((x) & RF2G_RF2G1_FE_ATB_SEL_MASK) >> RF2G_RF2G1_FE_ATB_SEL_LSB)
+#define RF2G_RF2G1_FE_ATB_SEL_SET(x) (((x) << RF2G_RF2G1_FE_ATB_SEL_LSB) & RF2G_RF2G1_FE_ATB_SEL_MASK)
+#define RF2G_RF2G1_RF_ATB_SEL_MSB 10
+#define RF2G_RF2G1_RF_ATB_SEL_LSB 8
+#define RF2G_RF2G1_RF_ATB_SEL_MASK 0x00000700
+#define RF2G_RF2G1_RF_ATB_SEL_GET(x) (((x) & RF2G_RF2G1_RF_ATB_SEL_MASK) >> RF2G_RF2G1_RF_ATB_SEL_LSB)
+#define RF2G_RF2G1_RF_ATB_SEL_SET(x) (((x) << RF2G_RF2G1_RF_ATB_SEL_LSB) & RF2G_RF2G1_RF_ATB_SEL_MASK)
+#define RF2G_RF2G1_SELLNA_MSB 7
+#define RF2G_RF2G1_SELLNA_LSB 7
+#define RF2G_RF2G1_SELLNA_MASK 0x00000080
+#define RF2G_RF2G1_SELLNA_GET(x) (((x) & RF2G_RF2G1_SELLNA_MASK) >> RF2G_RF2G1_SELLNA_LSB)
+#define RF2G_RF2G1_SELLNA_SET(x) (((x) << RF2G_RF2G1_SELLNA_LSB) & RF2G_RF2G1_SELLNA_MASK)
+#define RF2G_RF2G1_LOCONTROL_MSB 6
+#define RF2G_RF2G1_LOCONTROL_LSB 6
+#define RF2G_RF2G1_LOCONTROL_MASK 0x00000040
+#define RF2G_RF2G1_LOCONTROL_GET(x) (((x) & RF2G_RF2G1_LOCONTROL_MASK) >> RF2G_RF2G1_LOCONTROL_LSB)
+#define RF2G_RF2G1_LOCONTROL_SET(x) (((x) << RF2G_RF2G1_LOCONTROL_LSB) & RF2G_RF2G1_LOCONTROL_MASK)
+#define RF2G_RF2G1_SHORTLNA2_MSB 5
+#define RF2G_RF2G1_SHORTLNA2_LSB 5
+#define RF2G_RF2G1_SHORTLNA2_MASK 0x00000020
+#define RF2G_RF2G1_SHORTLNA2_GET(x) (((x) & RF2G_RF2G1_SHORTLNA2_MASK) >> RF2G_RF2G1_SHORTLNA2_LSB)
+#define RF2G_RF2G1_SHORTLNA2_SET(x) (((x) << RF2G_RF2G1_SHORTLNA2_LSB) & RF2G_RF2G1_SHORTLNA2_MASK)
+#define RF2G_RF2G1_SPARE_MSB 4
+#define RF2G_RF2G1_SPARE_LSB 0
+#define RF2G_RF2G1_SPARE_MASK 0x0000001f
+#define RF2G_RF2G1_SPARE_GET(x) (((x) & RF2G_RF2G1_SPARE_MASK) >> RF2G_RF2G1_SPARE_LSB)
+#define RF2G_RF2G1_SPARE_SET(x) (((x) << RF2G_RF2G1_SPARE_LSB) & RF2G_RF2G1_SPARE_MASK)
+
+#define RF2G_RF2G2_ADDRESS 0x0000002c
+#define RF2G_RF2G2_OFFSET 0x0000002c
+#define RF2G_RF2G2_PDCGLNA_MSB 31
+#define RF2G_RF2G2_PDCGLNA_LSB 31
+#define RF2G_RF2G2_PDCGLNA_MASK 0x80000000
+#define RF2G_RF2G2_PDCGLNA_GET(x) (((x) & RF2G_RF2G2_PDCGLNA_MASK) >> RF2G_RF2G2_PDCGLNA_LSB)
+#define RF2G_RF2G2_PDCGLNA_SET(x) (((x) << RF2G_RF2G2_PDCGLNA_LSB) & RF2G_RF2G2_PDCGLNA_MASK)
+#define RF2G_RF2G2_PDCGLNABUF_MSB 30
+#define RF2G_RF2G2_PDCGLNABUF_LSB 30
+#define RF2G_RF2G2_PDCGLNABUF_MASK 0x40000000
+#define RF2G_RF2G2_PDCGLNABUF_GET(x) (((x) & RF2G_RF2G2_PDCGLNABUF_MASK) >> RF2G_RF2G2_PDCGLNABUF_LSB)
+#define RF2G_RF2G2_PDCGLNABUF_SET(x) (((x) << RF2G_RF2G2_PDCGLNABUF_LSB) & RF2G_RF2G2_PDCGLNABUF_MASK)
+#define RF2G_RF2G2_PDCSLNA_MSB 29
+#define RF2G_RF2G2_PDCSLNA_LSB 29
+#define RF2G_RF2G2_PDCSLNA_MASK 0x20000000
+#define RF2G_RF2G2_PDCSLNA_GET(x) (((x) & RF2G_RF2G2_PDCSLNA_MASK) >> RF2G_RF2G2_PDCSLNA_LSB)
+#define RF2G_RF2G2_PDCSLNA_SET(x) (((x) << RF2G_RF2G2_PDCSLNA_LSB) & RF2G_RF2G2_PDCSLNA_MASK)
+#define RF2G_RF2G2_PDDIV_MSB 28
+#define RF2G_RF2G2_PDDIV_LSB 28
+#define RF2G_RF2G2_PDDIV_MASK 0x10000000
+#define RF2G_RF2G2_PDDIV_GET(x) (((x) & RF2G_RF2G2_PDDIV_MASK) >> RF2G_RF2G2_PDDIV_LSB)
+#define RF2G_RF2G2_PDDIV_SET(x) (((x) << RF2G_RF2G2_PDDIV_LSB) & RF2G_RF2G2_PDDIV_MASK)
+#define RF2G_RF2G2_PDPADRV_MSB 27
+#define RF2G_RF2G2_PDPADRV_LSB 27
+#define RF2G_RF2G2_PDPADRV_MASK 0x08000000
+#define RF2G_RF2G2_PDPADRV_GET(x) (((x) & RF2G_RF2G2_PDPADRV_MASK) >> RF2G_RF2G2_PDPADRV_LSB)
+#define RF2G_RF2G2_PDPADRV_SET(x) (((x) << RF2G_RF2G2_PDPADRV_LSB) & RF2G_RF2G2_PDPADRV_MASK)
+#define RF2G_RF2G2_PDPAOUT_MSB 26
+#define RF2G_RF2G2_PDPAOUT_LSB 26
+#define RF2G_RF2G2_PDPAOUT_MASK 0x04000000
+#define RF2G_RF2G2_PDPAOUT_GET(x) (((x) & RF2G_RF2G2_PDPAOUT_MASK) >> RF2G_RF2G2_PDPAOUT_LSB)
+#define RF2G_RF2G2_PDPAOUT_SET(x) (((x) << RF2G_RF2G2_PDPAOUT_LSB) & RF2G_RF2G2_PDPAOUT_MASK)
+#define RF2G_RF2G2_PDREGLNA_MSB 25
+#define RF2G_RF2G2_PDREGLNA_LSB 25
+#define RF2G_RF2G2_PDREGLNA_MASK 0x02000000
+#define RF2G_RF2G2_PDREGLNA_GET(x) (((x) & RF2G_RF2G2_PDREGLNA_MASK) >> RF2G_RF2G2_PDREGLNA_LSB)
+#define RF2G_RF2G2_PDREGLNA_SET(x) (((x) << RF2G_RF2G2_PDREGLNA_LSB) & RF2G_RF2G2_PDREGLNA_MASK)
+#define RF2G_RF2G2_PDREGLO_MSB 24
+#define RF2G_RF2G2_PDREGLO_LSB 24
+#define RF2G_RF2G2_PDREGLO_MASK 0x01000000
+#define RF2G_RF2G2_PDREGLO_GET(x) (((x) & RF2G_RF2G2_PDREGLO_MASK) >> RF2G_RF2G2_PDREGLO_LSB)
+#define RF2G_RF2G2_PDREGLO_SET(x) (((x) << RF2G_RF2G2_PDREGLO_LSB) & RF2G_RF2G2_PDREGLO_MASK)
+#define RF2G_RF2G2_PDRFGM_MSB 23
+#define RF2G_RF2G2_PDRFGM_LSB 23
+#define RF2G_RF2G2_PDRFGM_MASK 0x00800000
+#define RF2G_RF2G2_PDRFGM_GET(x) (((x) & RF2G_RF2G2_PDRFGM_MASK) >> RF2G_RF2G2_PDRFGM_LSB)
+#define RF2G_RF2G2_PDRFGM_SET(x) (((x) << RF2G_RF2G2_PDRFGM_LSB) & RF2G_RF2G2_PDRFGM_MASK)
+#define RF2G_RF2G2_PDRXLO_MSB 22
+#define RF2G_RF2G2_PDRXLO_LSB 22
+#define RF2G_RF2G2_PDRXLO_MASK 0x00400000
+#define RF2G_RF2G2_PDRXLO_GET(x) (((x) & RF2G_RF2G2_PDRXLO_MASK) >> RF2G_RF2G2_PDRXLO_LSB)
+#define RF2G_RF2G2_PDRXLO_SET(x) (((x) << RF2G_RF2G2_PDRXLO_LSB) & RF2G_RF2G2_PDRXLO_MASK)
+#define RF2G_RF2G2_PDTXLO_MSB 21
+#define RF2G_RF2G2_PDTXLO_LSB 21
+#define RF2G_RF2G2_PDTXLO_MASK 0x00200000
+#define RF2G_RF2G2_PDTXLO_GET(x) (((x) & RF2G_RF2G2_PDTXLO_MASK) >> RF2G_RF2G2_PDTXLO_LSB)
+#define RF2G_RF2G2_PDTXLO_SET(x) (((x) << RF2G_RF2G2_PDTXLO_LSB) & RF2G_RF2G2_PDTXLO_MASK)
+#define RF2G_RF2G2_PDTXMIX_MSB 20
+#define RF2G_RF2G2_PDTXMIX_LSB 20
+#define RF2G_RF2G2_PDTXMIX_MASK 0x00100000
+#define RF2G_RF2G2_PDTXMIX_GET(x) (((x) & RF2G_RF2G2_PDTXMIX_MASK) >> RF2G_RF2G2_PDTXMIX_LSB)
+#define RF2G_RF2G2_PDTXMIX_SET(x) (((x) << RF2G_RF2G2_PDTXMIX_LSB) & RF2G_RF2G2_PDTXMIX_MASK)
+#define RF2G_RF2G2_REGLNA_BYPASS_MSB 19
+#define RF2G_RF2G2_REGLNA_BYPASS_LSB 19
+#define RF2G_RF2G2_REGLNA_BYPASS_MASK 0x00080000
+#define RF2G_RF2G2_REGLNA_BYPASS_GET(x) (((x) & RF2G_RF2G2_REGLNA_BYPASS_MASK) >> RF2G_RF2G2_REGLNA_BYPASS_LSB)
+#define RF2G_RF2G2_REGLNA_BYPASS_SET(x) (((x) << RF2G_RF2G2_REGLNA_BYPASS_LSB) & RF2G_RF2G2_REGLNA_BYPASS_MASK)
+#define RF2G_RF2G2_REGLO_BYPASS_MSB 18
+#define RF2G_RF2G2_REGLO_BYPASS_LSB 18
+#define RF2G_RF2G2_REGLO_BYPASS_MASK 0x00040000
+#define RF2G_RF2G2_REGLO_BYPASS_GET(x) (((x) & RF2G_RF2G2_REGLO_BYPASS_MASK) >> RF2G_RF2G2_REGLO_BYPASS_LSB)
+#define RF2G_RF2G2_REGLO_BYPASS_SET(x) (((x) << RF2G_RF2G2_REGLO_BYPASS_LSB) & RF2G_RF2G2_REGLO_BYPASS_MASK)
+#define RF2G_RF2G2_ENABLE_PCB_MSB 17
+#define RF2G_RF2G2_ENABLE_PCB_LSB 17
+#define RF2G_RF2G2_ENABLE_PCB_MASK 0x00020000
+#define RF2G_RF2G2_ENABLE_PCB_GET(x) (((x) & RF2G_RF2G2_ENABLE_PCB_MASK) >> RF2G_RF2G2_ENABLE_PCB_LSB)
+#define RF2G_RF2G2_ENABLE_PCB_SET(x) (((x) << RF2G_RF2G2_ENABLE_PCB_LSB) & RF2G_RF2G2_ENABLE_PCB_MASK)
+#define RF2G_RF2G2_SPARE_MSB 16
+#define RF2G_RF2G2_SPARE_LSB 0
+#define RF2G_RF2G2_SPARE_MASK 0x0001ffff
+#define RF2G_RF2G2_SPARE_GET(x) (((x) & RF2G_RF2G2_SPARE_MASK) >> RF2G_RF2G2_SPARE_LSB)
+#define RF2G_RF2G2_SPARE_SET(x) (((x) << RF2G_RF2G2_SPARE_LSB) & RF2G_RF2G2_SPARE_MASK)
+
+#define TOP_GAIN_ADDRESS 0x00000030
+#define TOP_GAIN_OFFSET 0x00000030
+#define TOP_GAIN_TX6DBLOQGAIN_MSB 31
+#define TOP_GAIN_TX6DBLOQGAIN_LSB 30
+#define TOP_GAIN_TX6DBLOQGAIN_MASK 0xc0000000
+#define TOP_GAIN_TX6DBLOQGAIN_GET(x) (((x) & TOP_GAIN_TX6DBLOQGAIN_MASK) >> TOP_GAIN_TX6DBLOQGAIN_LSB)
+#define TOP_GAIN_TX6DBLOQGAIN_SET(x) (((x) << TOP_GAIN_TX6DBLOQGAIN_LSB) & TOP_GAIN_TX6DBLOQGAIN_MASK)
+#define TOP_GAIN_TX1DBLOQGAIN_MSB 29
+#define TOP_GAIN_TX1DBLOQGAIN_LSB 27
+#define TOP_GAIN_TX1DBLOQGAIN_MASK 0x38000000
+#define TOP_GAIN_TX1DBLOQGAIN_GET(x) (((x) & TOP_GAIN_TX1DBLOQGAIN_MASK) >> TOP_GAIN_TX1DBLOQGAIN_LSB)
+#define TOP_GAIN_TX1DBLOQGAIN_SET(x) (((x) << TOP_GAIN_TX1DBLOQGAIN_LSB) & TOP_GAIN_TX1DBLOQGAIN_MASK)
+#define TOP_GAIN_TXV2IGAIN_MSB 26
+#define TOP_GAIN_TXV2IGAIN_LSB 25
+#define TOP_GAIN_TXV2IGAIN_MASK 0x06000000
+#define TOP_GAIN_TXV2IGAIN_GET(x) (((x) & TOP_GAIN_TXV2IGAIN_MASK) >> TOP_GAIN_TXV2IGAIN_LSB)
+#define TOP_GAIN_TXV2IGAIN_SET(x) (((x) << TOP_GAIN_TXV2IGAIN_LSB) & TOP_GAIN_TXV2IGAIN_MASK)
+#define TOP_GAIN_PABUF5GN_MSB 24
+#define TOP_GAIN_PABUF5GN_LSB 24
+#define TOP_GAIN_PABUF5GN_MASK 0x01000000
+#define TOP_GAIN_PABUF5GN_GET(x) (((x) & TOP_GAIN_PABUF5GN_MASK) >> TOP_GAIN_PABUF5GN_LSB)
+#define TOP_GAIN_PABUF5GN_SET(x) (((x) << TOP_GAIN_PABUF5GN_LSB) & TOP_GAIN_PABUF5GN_MASK)
+#define TOP_GAIN_PADRVGN_MSB 23
+#define TOP_GAIN_PADRVGN_LSB 21
+#define TOP_GAIN_PADRVGN_MASK 0x00e00000
+#define TOP_GAIN_PADRVGN_GET(x) (((x) & TOP_GAIN_PADRVGN_MASK) >> TOP_GAIN_PADRVGN_LSB)
+#define TOP_GAIN_PADRVGN_SET(x) (((x) << TOP_GAIN_PADRVGN_LSB) & TOP_GAIN_PADRVGN_MASK)
+#define TOP_GAIN_PAOUT2GN_MSB 20
+#define TOP_GAIN_PAOUT2GN_LSB 18
+#define TOP_GAIN_PAOUT2GN_MASK 0x001c0000
+#define TOP_GAIN_PAOUT2GN_GET(x) (((x) & TOP_GAIN_PAOUT2GN_MASK) >> TOP_GAIN_PAOUT2GN_LSB)
+#define TOP_GAIN_PAOUT2GN_SET(x) (((x) << TOP_GAIN_PAOUT2GN_LSB) & TOP_GAIN_PAOUT2GN_MASK)
+#define TOP_GAIN_LNAON_MSB 17
+#define TOP_GAIN_LNAON_LSB 17
+#define TOP_GAIN_LNAON_MASK 0x00020000
+#define TOP_GAIN_LNAON_GET(x) (((x) & TOP_GAIN_LNAON_MASK) >> TOP_GAIN_LNAON_LSB)
+#define TOP_GAIN_LNAON_SET(x) (((x) << TOP_GAIN_LNAON_LSB) & TOP_GAIN_LNAON_MASK)
+#define TOP_GAIN_LNAGAIN_MSB 16
+#define TOP_GAIN_LNAGAIN_LSB 13
+#define TOP_GAIN_LNAGAIN_MASK 0x0001e000
+#define TOP_GAIN_LNAGAIN_GET(x) (((x) & TOP_GAIN_LNAGAIN_MASK) >> TOP_GAIN_LNAGAIN_LSB)
+#define TOP_GAIN_LNAGAIN_SET(x) (((x) << TOP_GAIN_LNAGAIN_LSB) & TOP_GAIN_LNAGAIN_MASK)
+#define TOP_GAIN_RFVGA5GAIN_MSB 12
+#define TOP_GAIN_RFVGA5GAIN_LSB 11
+#define TOP_GAIN_RFVGA5GAIN_MASK 0x00001800
+#define TOP_GAIN_RFVGA5GAIN_GET(x) (((x) & TOP_GAIN_RFVGA5GAIN_MASK) >> TOP_GAIN_RFVGA5GAIN_LSB)
+#define TOP_GAIN_RFVGA5GAIN_SET(x) (((x) << TOP_GAIN_RFVGA5GAIN_LSB) & TOP_GAIN_RFVGA5GAIN_MASK)
+#define TOP_GAIN_RFGMGN_MSB 10
+#define TOP_GAIN_RFGMGN_LSB 8
+#define TOP_GAIN_RFGMGN_MASK 0x00000700
+#define TOP_GAIN_RFGMGN_GET(x) (((x) & TOP_GAIN_RFGMGN_MASK) >> TOP_GAIN_RFGMGN_LSB)
+#define TOP_GAIN_RFGMGN_SET(x) (((x) << TOP_GAIN_RFGMGN_LSB) & TOP_GAIN_RFGMGN_MASK)
+#define TOP_GAIN_RX6DBLOQGAIN_MSB 7
+#define TOP_GAIN_RX6DBLOQGAIN_LSB 6
+#define TOP_GAIN_RX6DBLOQGAIN_MASK 0x000000c0
+#define TOP_GAIN_RX6DBLOQGAIN_GET(x) (((x) & TOP_GAIN_RX6DBLOQGAIN_MASK) >> TOP_GAIN_RX6DBLOQGAIN_LSB)
+#define TOP_GAIN_RX6DBLOQGAIN_SET(x) (((x) << TOP_GAIN_RX6DBLOQGAIN_LSB) & TOP_GAIN_RX6DBLOQGAIN_MASK)
+#define TOP_GAIN_RX1DBLOQGAIN_MSB 5
+#define TOP_GAIN_RX1DBLOQGAIN_LSB 3
+#define TOP_GAIN_RX1DBLOQGAIN_MASK 0x00000038
+#define TOP_GAIN_RX1DBLOQGAIN_GET(x) (((x) & TOP_GAIN_RX1DBLOQGAIN_MASK) >> TOP_GAIN_RX1DBLOQGAIN_LSB)
+#define TOP_GAIN_RX1DBLOQGAIN_SET(x) (((x) << TOP_GAIN_RX1DBLOQGAIN_LSB) & TOP_GAIN_RX1DBLOQGAIN_MASK)
+#define TOP_GAIN_RX6DBHIQGAIN_MSB 2
+#define TOP_GAIN_RX6DBHIQGAIN_LSB 1
+#define TOP_GAIN_RX6DBHIQGAIN_MASK 0x00000006
+#define TOP_GAIN_RX6DBHIQGAIN_GET(x) (((x) & TOP_GAIN_RX6DBHIQGAIN_MASK) >> TOP_GAIN_RX6DBHIQGAIN_LSB)
+#define TOP_GAIN_RX6DBHIQGAIN_SET(x) (((x) << TOP_GAIN_RX6DBHIQGAIN_LSB) & TOP_GAIN_RX6DBHIQGAIN_MASK)
+#define TOP_GAIN_SPARE_MSB 0
+#define TOP_GAIN_SPARE_LSB 0
+#define TOP_GAIN_SPARE_MASK 0x00000001
+#define TOP_GAIN_SPARE_GET(x) (((x) & TOP_GAIN_SPARE_MASK) >> TOP_GAIN_SPARE_LSB)
+#define TOP_GAIN_SPARE_SET(x) (((x) << TOP_GAIN_SPARE_LSB) & TOP_GAIN_SPARE_MASK)
+
+#define TOP_TOP_ADDRESS 0x00000034
+#define TOP_TOP_OFFSET 0x00000034
+#define TOP_TOP_LOCALTXGAIN_MSB 31
+#define TOP_TOP_LOCALTXGAIN_LSB 31
+#define TOP_TOP_LOCALTXGAIN_MASK 0x80000000
+#define TOP_TOP_LOCALTXGAIN_GET(x) (((x) & TOP_TOP_LOCALTXGAIN_MASK) >> TOP_TOP_LOCALTXGAIN_LSB)
+#define TOP_TOP_LOCALTXGAIN_SET(x) (((x) << TOP_TOP_LOCALTXGAIN_LSB) & TOP_TOP_LOCALTXGAIN_MASK)
+#define TOP_TOP_LOCALRXGAIN_MSB 30
+#define TOP_TOP_LOCALRXGAIN_LSB 30
+#define TOP_TOP_LOCALRXGAIN_MASK 0x40000000
+#define TOP_TOP_LOCALRXGAIN_GET(x) (((x) & TOP_TOP_LOCALRXGAIN_MASK) >> TOP_TOP_LOCALRXGAIN_LSB)
+#define TOP_TOP_LOCALRXGAIN_SET(x) (((x) << TOP_TOP_LOCALRXGAIN_LSB) & TOP_TOP_LOCALRXGAIN_MASK)
+#define TOP_TOP_LOCALMODE_MSB 29
+#define TOP_TOP_LOCALMODE_LSB 29
+#define TOP_TOP_LOCALMODE_MASK 0x20000000
+#define TOP_TOP_LOCALMODE_GET(x) (((x) & TOP_TOP_LOCALMODE_MASK) >> TOP_TOP_LOCALMODE_LSB)
+#define TOP_TOP_LOCALMODE_SET(x) (((x) << TOP_TOP_LOCALMODE_LSB) & TOP_TOP_LOCALMODE_MASK)
+#define TOP_TOP_CALFC_MSB 28
+#define TOP_TOP_CALFC_LSB 28
+#define TOP_TOP_CALFC_MASK 0x10000000
+#define TOP_TOP_CALFC_GET(x) (((x) & TOP_TOP_CALFC_MASK) >> TOP_TOP_CALFC_LSB)
+#define TOP_TOP_CALFC_SET(x) (((x) << TOP_TOP_CALFC_LSB) & TOP_TOP_CALFC_MASK)
+#define TOP_TOP_CALDC_MSB 27
+#define TOP_TOP_CALDC_LSB 27
+#define TOP_TOP_CALDC_MASK 0x08000000
+#define TOP_TOP_CALDC_GET(x) (((x) & TOP_TOP_CALDC_MASK) >> TOP_TOP_CALDC_LSB)
+#define TOP_TOP_CALDC_SET(x) (((x) << TOP_TOP_CALDC_LSB) & TOP_TOP_CALDC_MASK)
+#define TOP_TOP_CAL_RESIDUE_MSB 26
+#define TOP_TOP_CAL_RESIDUE_LSB 26
+#define TOP_TOP_CAL_RESIDUE_MASK 0x04000000
+#define TOP_TOP_CAL_RESIDUE_GET(x) (((x) & TOP_TOP_CAL_RESIDUE_MASK) >> TOP_TOP_CAL_RESIDUE_LSB)
+#define TOP_TOP_CAL_RESIDUE_SET(x) (((x) << TOP_TOP_CAL_RESIDUE_LSB) & TOP_TOP_CAL_RESIDUE_MASK)
+#define TOP_TOP_BMODE_MSB 25
+#define TOP_TOP_BMODE_LSB 25
+#define TOP_TOP_BMODE_MASK 0x02000000
+#define TOP_TOP_BMODE_GET(x) (((x) & TOP_TOP_BMODE_MASK) >> TOP_TOP_BMODE_LSB)
+#define TOP_TOP_BMODE_SET(x) (((x) << TOP_TOP_BMODE_LSB) & TOP_TOP_BMODE_MASK)
+#define TOP_TOP_SYNTHON_MSB 24
+#define TOP_TOP_SYNTHON_LSB 24
+#define TOP_TOP_SYNTHON_MASK 0x01000000
+#define TOP_TOP_SYNTHON_GET(x) (((x) & TOP_TOP_SYNTHON_MASK) >> TOP_TOP_SYNTHON_LSB)
+#define TOP_TOP_SYNTHON_SET(x) (((x) << TOP_TOP_SYNTHON_LSB) & TOP_TOP_SYNTHON_MASK)
+#define TOP_TOP_RXON_MSB 23
+#define TOP_TOP_RXON_LSB 23
+#define TOP_TOP_RXON_MASK 0x00800000
+#define TOP_TOP_RXON_GET(x) (((x) & TOP_TOP_RXON_MASK) >> TOP_TOP_RXON_LSB)
+#define TOP_TOP_RXON_SET(x) (((x) << TOP_TOP_RXON_LSB) & TOP_TOP_RXON_MASK)
+#define TOP_TOP_TXON_MSB 22
+#define TOP_TOP_TXON_LSB 22
+#define TOP_TOP_TXON_MASK 0x00400000
+#define TOP_TOP_TXON_GET(x) (((x) & TOP_TOP_TXON_MASK) >> TOP_TOP_TXON_LSB)
+#define TOP_TOP_TXON_SET(x) (((x) << TOP_TOP_TXON_LSB) & TOP_TOP_TXON_MASK)
+#define TOP_TOP_PAON_MSB 21
+#define TOP_TOP_PAON_LSB 21
+#define TOP_TOP_PAON_MASK 0x00200000
+#define TOP_TOP_PAON_GET(x) (((x) & TOP_TOP_PAON_MASK) >> TOP_TOP_PAON_LSB)
+#define TOP_TOP_PAON_SET(x) (((x) << TOP_TOP_PAON_LSB) & TOP_TOP_PAON_MASK)
+#define TOP_TOP_CALTX_MSB 20
+#define TOP_TOP_CALTX_LSB 20
+#define TOP_TOP_CALTX_MASK 0x00100000
+#define TOP_TOP_CALTX_GET(x) (((x) & TOP_TOP_CALTX_MASK) >> TOP_TOP_CALTX_LSB)
+#define TOP_TOP_CALTX_SET(x) (((x) << TOP_TOP_CALTX_LSB) & TOP_TOP_CALTX_MASK)
+#define TOP_TOP_LOCALADDAC_MSB 19
+#define TOP_TOP_LOCALADDAC_LSB 19
+#define TOP_TOP_LOCALADDAC_MASK 0x00080000
+#define TOP_TOP_LOCALADDAC_GET(x) (((x) & TOP_TOP_LOCALADDAC_MASK) >> TOP_TOP_LOCALADDAC_LSB)
+#define TOP_TOP_LOCALADDAC_SET(x) (((x) << TOP_TOP_LOCALADDAC_LSB) & TOP_TOP_LOCALADDAC_MASK)
+#define TOP_TOP_PWDPLL_MSB 18
+#define TOP_TOP_PWDPLL_LSB 18
+#define TOP_TOP_PWDPLL_MASK 0x00040000
+#define TOP_TOP_PWDPLL_GET(x) (((x) & TOP_TOP_PWDPLL_MASK) >> TOP_TOP_PWDPLL_LSB)
+#define TOP_TOP_PWDPLL_SET(x) (((x) << TOP_TOP_PWDPLL_LSB) & TOP_TOP_PWDPLL_MASK)
+#define TOP_TOP_PWDADC_MSB 17
+#define TOP_TOP_PWDADC_LSB 17
+#define TOP_TOP_PWDADC_MASK 0x00020000
+#define TOP_TOP_PWDADC_GET(x) (((x) & TOP_TOP_PWDADC_MASK) >> TOP_TOP_PWDADC_LSB)
+#define TOP_TOP_PWDADC_SET(x) (((x) << TOP_TOP_PWDADC_LSB) & TOP_TOP_PWDADC_MASK)
+#define TOP_TOP_PWDDAC_MSB 16
+#define TOP_TOP_PWDDAC_LSB 16
+#define TOP_TOP_PWDDAC_MASK 0x00010000
+#define TOP_TOP_PWDDAC_GET(x) (((x) & TOP_TOP_PWDDAC_MASK) >> TOP_TOP_PWDDAC_LSB)
+#define TOP_TOP_PWDDAC_SET(x) (((x) << TOP_TOP_PWDDAC_LSB) & TOP_TOP_PWDDAC_MASK)
+#define TOP_TOP_LOCALXTAL_MSB 15
+#define TOP_TOP_LOCALXTAL_LSB 15
+#define TOP_TOP_LOCALXTAL_MASK 0x00008000
+#define TOP_TOP_LOCALXTAL_GET(x) (((x) & TOP_TOP_LOCALXTAL_MASK) >> TOP_TOP_LOCALXTAL_LSB)
+#define TOP_TOP_LOCALXTAL_SET(x) (((x) << TOP_TOP_LOCALXTAL_LSB) & TOP_TOP_LOCALXTAL_MASK)
+#define TOP_TOP_PWDCLKIN_MSB 14
+#define TOP_TOP_PWDCLKIN_LSB 14
+#define TOP_TOP_PWDCLKIN_MASK 0x00004000
+#define TOP_TOP_PWDCLKIN_GET(x) (((x) & TOP_TOP_PWDCLKIN_MASK) >> TOP_TOP_PWDCLKIN_LSB)
+#define TOP_TOP_PWDCLKIN_SET(x) (((x) << TOP_TOP_PWDCLKIN_LSB) & TOP_TOP_PWDCLKIN_MASK)
+#define TOP_TOP_OSCON_MSB 13
+#define TOP_TOP_OSCON_LSB 13
+#define TOP_TOP_OSCON_MASK 0x00002000
+#define TOP_TOP_OSCON_GET(x) (((x) & TOP_TOP_OSCON_MASK) >> TOP_TOP_OSCON_LSB)
+#define TOP_TOP_OSCON_SET(x) (((x) << TOP_TOP_OSCON_LSB) & TOP_TOP_OSCON_MASK)
+#define TOP_TOP_SCLKEN_FORCE_MSB 12
+#define TOP_TOP_SCLKEN_FORCE_LSB 12
+#define TOP_TOP_SCLKEN_FORCE_MASK 0x00001000
+#define TOP_TOP_SCLKEN_FORCE_GET(x) (((x) & TOP_TOP_SCLKEN_FORCE_MASK) >> TOP_TOP_SCLKEN_FORCE_LSB)
+#define TOP_TOP_SCLKEN_FORCE_SET(x) (((x) << TOP_TOP_SCLKEN_FORCE_LSB) & TOP_TOP_SCLKEN_FORCE_MASK)
+#define TOP_TOP_SYNTHON_FORCE_MSB 11
+#define TOP_TOP_SYNTHON_FORCE_LSB 11
+#define TOP_TOP_SYNTHON_FORCE_MASK 0x00000800
+#define TOP_TOP_SYNTHON_FORCE_GET(x) (((x) & TOP_TOP_SYNTHON_FORCE_MASK) >> TOP_TOP_SYNTHON_FORCE_LSB)
+#define TOP_TOP_SYNTHON_FORCE_SET(x) (((x) << TOP_TOP_SYNTHON_FORCE_LSB) & TOP_TOP_SYNTHON_FORCE_MASK)
+#define TOP_TOP_PDBIAS_MSB 10
+#define TOP_TOP_PDBIAS_LSB 10
+#define TOP_TOP_PDBIAS_MASK 0x00000400
+#define TOP_TOP_PDBIAS_GET(x) (((x) & TOP_TOP_PDBIAS_MASK) >> TOP_TOP_PDBIAS_LSB)
+#define TOP_TOP_PDBIAS_SET(x) (((x) << TOP_TOP_PDBIAS_LSB) & TOP_TOP_PDBIAS_MASK)
+#define TOP_TOP_DATAOUTSEL_MSB 9
+#define TOP_TOP_DATAOUTSEL_LSB 8
+#define TOP_TOP_DATAOUTSEL_MASK 0x00000300
+#define TOP_TOP_DATAOUTSEL_GET(x) (((x) & TOP_TOP_DATAOUTSEL_MASK) >> TOP_TOP_DATAOUTSEL_LSB)
+#define TOP_TOP_DATAOUTSEL_SET(x) (((x) << TOP_TOP_DATAOUTSEL_LSB) & TOP_TOP_DATAOUTSEL_MASK)
+#define TOP_TOP_REVID_MSB 7
+#define TOP_TOP_REVID_LSB 5
+#define TOP_TOP_REVID_MASK 0x000000e0
+#define TOP_TOP_REVID_GET(x) (((x) & TOP_TOP_REVID_MASK) >> TOP_TOP_REVID_LSB)
+#define TOP_TOP_REVID_SET(x) (((x) << TOP_TOP_REVID_LSB) & TOP_TOP_REVID_MASK)
+#define TOP_TOP_INT2PAD_MSB 4
+#define TOP_TOP_INT2PAD_LSB 4
+#define TOP_TOP_INT2PAD_MASK 0x00000010
+#define TOP_TOP_INT2PAD_GET(x) (((x) & TOP_TOP_INT2PAD_MASK) >> TOP_TOP_INT2PAD_LSB)
+#define TOP_TOP_INT2PAD_SET(x) (((x) << TOP_TOP_INT2PAD_LSB) & TOP_TOP_INT2PAD_MASK)
+#define TOP_TOP_INTH2PAD_MSB 3
+#define TOP_TOP_INTH2PAD_LSB 3
+#define TOP_TOP_INTH2PAD_MASK 0x00000008
+#define TOP_TOP_INTH2PAD_GET(x) (((x) & TOP_TOP_INTH2PAD_MASK) >> TOP_TOP_INTH2PAD_LSB)
+#define TOP_TOP_INTH2PAD_SET(x) (((x) << TOP_TOP_INTH2PAD_LSB) & TOP_TOP_INTH2PAD_MASK)
+#define TOP_TOP_PAD2GND_MSB 2
+#define TOP_TOP_PAD2GND_LSB 2
+#define TOP_TOP_PAD2GND_MASK 0x00000004
+#define TOP_TOP_PAD2GND_GET(x) (((x) & TOP_TOP_PAD2GND_MASK) >> TOP_TOP_PAD2GND_LSB)
+#define TOP_TOP_PAD2GND_SET(x) (((x) << TOP_TOP_PAD2GND_LSB) & TOP_TOP_PAD2GND_MASK)
+#define TOP_TOP_INT2GND_MSB 1
+#define TOP_TOP_INT2GND_LSB 1
+#define TOP_TOP_INT2GND_MASK 0x00000002
+#define TOP_TOP_INT2GND_GET(x) (((x) & TOP_TOP_INT2GND_MASK) >> TOP_TOP_INT2GND_LSB)
+#define TOP_TOP_INT2GND_SET(x) (((x) << TOP_TOP_INT2GND_LSB) & TOP_TOP_INT2GND_MASK)
+#define TOP_TOP_FORCE_XPAON_MSB 0
+#define TOP_TOP_FORCE_XPAON_LSB 0
+#define TOP_TOP_FORCE_XPAON_MASK 0x00000001
+#define TOP_TOP_FORCE_XPAON_GET(x) (((x) & TOP_TOP_FORCE_XPAON_MASK) >> TOP_TOP_FORCE_XPAON_LSB)
+#define TOP_TOP_FORCE_XPAON_SET(x) (((x) << TOP_TOP_FORCE_XPAON_LSB) & TOP_TOP_FORCE_XPAON_MASK)
+
+#define BIAS_BIAS_SEL_ADDRESS 0x00000038
+#define BIAS_BIAS_SEL_OFFSET 0x00000038
+#def