add atheros ar6003 wifi driver

need to remove bt support in menuconfig: Networking support ---> Bluetooth subsystem support.
This commit is contained in:
hwg 2011-11-29 15:41:58 +08:00
parent b941652d87
commit b38c45814d
438 changed files with 231122 additions and 0 deletions

View File

@ -70,6 +70,7 @@ choice
(4) Murata SP-8HEP-P
source "drivers/net/wireless/rtl8192c/Kconfig"
source "drivers/net/wireless/ar6003/Kconfig"
endchoice
endif

View File

@ -6,4 +6,5 @@ obj-$(CONFIG_BCM4329) += bcm4329/
obj-$(CONFIG_MV8686) += mv8686/
obj-$(CONFIG_BCM4319) += bcm4319/
obj-$(CONFIG_RTL8192CU) += rtl8192c/
obj-$(CONFIG_AR6003) += ar6003/
#obj-m += wlan/

View File

@ -0,0 +1,9 @@
config AR6003
depends on WLAN_80211 && MMC
select WIRELESS_EXT
select IEEE80211
select FW_LOADER
bool "Atheros AR6003/AR6302 SDIO"
---help---
Atheros ROC AR6003/AR6302.

View File

@ -0,0 +1,77 @@
AR6003_SRC_PATH := drivers/net/wireless/ar6003
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/host/include
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/include
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/host/wlan/include
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/host/os/linux/include
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/host/os/
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/host/bmi/include
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/include/AR6002
EXTRA_CFLAGS += -I${AR6003_SRC_PATH}/host/hif/sdio/linux_sdio/include
EXTRA_CFLAGS += -Idrivers/net/wireless
EXTRA_CFLAGS += -DLINUX -D__KERNEL__ -DTCMD -DSEND_EVENT_TO_APP -DUSER_KEYS -DNO_SYNC_FLUSH -DHTC_EP_STAT_PROFILING -DWLAN_HEADERS -DATH_AR6K_11N_SUPPORT -DATH_SUPPORT_DFS -DANDROID_ENV -D__linux__ -DINIT_MODE_DRV_ENABLED -DBMIENABLE_SET -DAR600x_SD31_XXX -DATH6KL_SKIP_ABI_VERSION_CHECK -DATH6KL_CONFIG_HIF_VIRTUAL_SCATTER -DCONFIG_HOST_TCMD_SUPPORT -DCONFIG_AP_VIRTUAL_ADAPTER_SUPPORT -DSOFTMAC_FILE_USED -DDEBUG -DATH_DEBUG_MODULE -DAR6002_HEADERS_DEF -DAR6003_HEADERS_DEF -DMCKINLEY_HEADERS_DEF -DKERNEL_2_6
ifeq ($(CONFIG_BT),y)
EXTRA_CFLAGS += -DATH_AR6K_ENABLE_GMBOX
EXTRA_CFLAGS += -DHCI_TRANSPORT_SDIO
EXTRA_CFLAGS += -DSETUPHCI_ENABLED
EXTRA_CFLAGS += -DSETUPBTDEV_ENABLED
endif
EXTRA_CFLAGS += -DRK29
EXTRA_CFLAGS += -DTCHIP
olca3-objs := host/hif/sdio/linux_sdio/src/hif.o \
host/hif/sdio/linux_sdio/src/hif_scatter.o \
host/hif/common/hif_bmi_reg_access.o \
host/hif/common/hif_diag_reg_access.o \
host/wmi/wmi.o \
host/reorder/rcv_aggr.o \
host/htc2/AR6000/ar6k.o \
host/htc2/AR6000/ar6k_events.o \
host/htc2/htc_services.o \
host/htc2/htc.o \
host/htc2/htc_send.o \
host/htc2/htc_recv.o \
host/wlan/src/wlan_recv_beacon.o \
host/wlan/src/wlan_utils.o \
host/wlan/src/wlan_node.o \
host/bmi/src/bmi.o \
host/miscdrv/credit_dist.o \
host/miscdrv/common_drv.o \
host/os/linux/hci_bridge.o \
host/os/linux/netbuf.o \
host/os/linux/ar6000_android.o \
host/os/linux/ioctl.o \
host/os/linux/wireless_ext.o \
host/os/linux/ar6000_pm.o \
host/os/linux/ar6000_raw_if.o \
host/os/linux/ar6000_drv.o \
host/os/linux/ar6k_pal.o \
host/regtable/regtable.o \
host/regtable/AR6002def.o \
host/regtable/MCKINLEYdef.o \
host/regtable/AR6003def.o \
host/dfs/dfs_debug.o \
host/dfs/dfs_process_phyerr.o \
host/dfs/dfs.o \
host/dfs/dfs_misc.o \
host/dfs/dfs_bindetects.o \
host/dfs/dfs_init.o \
host/dfs/dfs_host_project.o \
host/dfs/dfs_staggered.o \
host/dfs/dfs_ar.o \
host/dfs/dfs_process_radarevent.o \
host/dfs/dfs_fcc_bin5.o
ifeq ($(CONFIG_BT),y)
olca3-objs += host/htc2/AR6000/ar6k_gmbox.o \
host/htc2/AR6000/ar6k_gmbox_hciuart.o \
host/miscdrv/ar3kconfig.o \
host/miscdrv/ar3kps/ar3kpsconfig.o \
host/miscdrv/ar3kps/ar3kpsparser.o
endif
obj-$(CONFIG_AR6003) += olca3.o

View File

@ -0,0 +1,5 @@
#!/bin/bash
find . \( -not -path "*.output*" -a -name '*.[oas]' -o -name core -o -name '.*.flags' -o -name '.ko' -o -name '.*.cmd' -o -name 'Module.symvers' -o -name 'modules.order' \) -type f -print \
| grep -v lxdialog/ | xargs rm -f
find . \( -name '.tmp_versions' \) -type d -print | grep -v lxdialog/ | xargs rm -rf

View File

@ -0,0 +1,125 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-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"
#==============================================================================
ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
ATH_ANDROID_SRC_BASE:= $(BOARD_WLAN_ATHEROS_SDK)
export ATH_BUILD_TYPE=ANDROID_ARM_NATIVEMMC
export ATH_BUS_TYPE=sdio
export ATH_OS_SUB_TYPE=linux_2_6
ATH_ANDROID_ROOT:= $(CURDIR)
export ATH_SRC_BASE:=$(ATH_ANDROID_ROOT)/$(BOARD_WLAN_ATHEROS_SDK)/host
#ATH_CROSS_COMPILE_TYPE:=$(ATH_ANDROID_ROOT)/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-
ATH_TARGET_OUTPUT:=$(ATH_ANDROID_ROOT)
ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),qsd8250_surf qsd8250_ffa msm7627_surf msm7627_ffa msm7627a msm7625_ffa msm7625_surf msm7630_surf))
export ATH_LINUXPATH=$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
ATH_CROSS_COMPILE_TYPE:=$(ATH_ANDROID_ROOT)/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-
endif
ifndef ATH_LINUXPATH
#check for Nvidia-base platform
ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),harmony ventana))
export ATH_LINUXPATH=$(ATH_ANDROID_ROOT)/$(TARGET_OUT_INTERMEDIATES)/KERNEL
ATH_CROSS_COMPILE_TYPE:=$(CROSS_COMPILE)
endif
endif
ifndef ATH_LINUXPATH
#check for IMX51 platform
ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),imx51_bbg))
export ATH_LINUXPATH=$(ATH_ANDROID_ROOT)/kernel_imx
ATH_CROSS_COMPILE_TYPE:=$(ATH_ANDROID_ROOT)/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-
endif
endif
ifndef ATH_LINUXPATH
# Comment out the following variable and $(error) for your platform
# Link your kernel into android SDK directory as 'kernel' directory
# export ATH_LINUXPATH= [Your android/kernel path ]
ATH_CROSS_COMPILE_TYPE:=$(ATH_ANDROID_ROOT)/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-
$(error define your kernel path here for ATH_LINUXPATH)
endif
export ATH_ARCH_CPU_TYPE=arm
export ATH_BUS_SUBTYPE=linux_sdio
export ATH_ANDROID_ENV=yes
export ATH_SOFTMAC_FILE_USED=no
export ATH_CFG80211_ENV=no
export ATH_DEBUG_DRIVER=yes
export ATH_HTC_RAW_INT_ENV=yes
export ATH_AR6K_OTA_TEST_MODE=no
export ATH_BUILD_P2P=yes
ATH_HIF_TYPE:=sdio
ifneq ($(PLATFORM_VERSION),$(filter $(PLATFORM_VERSION),1.5 1.6))
ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),msm7627_surf msm7627_ffa GT-I5500))
ATH_ANDROID_BUILD_FLAGS=-D__LINUX_ARM_ARCH__=6 -march=armv6 -DUSE_4BYTE_REGISTER_ACCESS
#-fstack-check="generic"
endif
ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),qsd8250_surf qsd8250_ffa msm7630_surf smdkc100))
ATH_ANDROID_BUILD_FLAGS=-D__LINUX_ARM_ARCH__=7 -march=armv7-a -DUSE_4BYTE_REGISTER_ACCESS
#-fstack-check="generic"
endif
endif # ECLAIR
ifeq ($(TARGET_PRODUCT),$(filter $(TARGET_PRODUCT),smdk6410))
ATH_ANDROID_BUILD_FLAGS += -DATH6KL_CONFIG_HIF_VIRTUAL_SCATTER
endif
#Uncomment the following define in order to enable OTA mode
#ATH_ANDROID_BUILD_FLAGS += -DATH6K_CONFIG_OTA_MODE
export ATH_ANDROID_BUILD_FLAGS
mod_cleanup := $(ATH_TARGET_OUTPUT)/$(ATH_ANDROID_SRC_BASE)/dummy
$(mod_cleanup) :
rm -f `find $(ATH_TARGET_OUTPUT)/$(ATH_ANDROID_SRC_BASE) -name "*.o"`
mkdir -p $(TARGET_OUT)/wifi/ath6k/AR6003/hw2.0/
mod_file := os/linux/ar6000.ko
$(ATH_ANDROID_SRC_BASE)/host/$(mod_file) : $(mod_cleanup) $(TARGET_PREBUILT_KERNEL) $(ACP)
$(MAKE) ARCH=arm CROSS_COMPILE=$(ATH_CROSS_COMPILE_TYPE) -C $(ATH_LINUXPATH) ATH_HIF_TYPE=$(ATH_HIF_TYPE) SUBDIRS=$(ATH_SRC_BASE)/os/linux modules
$(ATH_CROSS_COMPILE_TYPE)strip -g -S -d $(ATH_ANDROID_SRC_BASE)/host/$(mod_file)
$(ACP) -fpt $(ATH_ANDROID_SRC_BASE)/host/$(mod_file) $(TARGET_OUT)/wifi
LOCAL_MODULE := ar6000.ko
LOCAL_MODULE_TAGS := debug eng optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT)/wifi
LOCAL_SRC_FILES := $(mod_file)
include $(BUILD_PREBUILT)
include $(LOCAL_PATH)/tools/Android.mk
endif

View File

@ -0,0 +1,174 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-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"
#==============================================================================
# AR6K Host driver makefile
#
# Minimal build invocation:
#
# make (all | clean | clobber)
#
# Extended Make invocation:
#
# make ATH_BUILD_TYPE=<build type> ATH_SDIO_STACK_BASE=<sdio stack install path> (all | clean | clobber)
#
# Notes:
# 1. This makefile must be invoked from the host/ directory
# 2. The <build type> must match an entry in localmake.linux.inc.
# 3. The localmake.linux.inc can be overridden using an include file outside the build tree.
# This file (name and path) can be set via the ATH_MAKE_INCLUDE_OVERRIDE variable.
# ** If ATH_MAKE_INCLUDE_OVERRIDE is used, you can define all build variables in that file
# instead of using command line arguments **. This feature is provided for developers
# that may want to customize the build using a single include file.
#
# For example :
#
# " make ATH_MAKE_INCLUDE_OVERRIDE=$HOME/mymake.inc "
#
# could be used, as long as "mymake.inc" defines all the required variables (see below)
#
# Required Variables:
#
# ATH_OS_SUB_TYPE - on linux, this must be "linux_2_4" for 2.4 kernels or left blank for 2.6 kernels.
# ATH_LINUXPATH - linux kernel source path
# ATH_CROSS_COMPILE_TYPE - optional cross compiler path , leave blank for local gcc compilation
# ATH_ARCH_CPU_TYPE - CPU architecture type, leave blank for local gcc compilation
# ATH_SDIO_STACK_BASE - SDIO Stack installation path to compile the SDIO HIF layer against an externally supplied
# SDIO stack source.
#
# Override variables:
#
# ATH_MAKE_INCLUDE_OVERRIDE - full path to include file which overrides the default (localmake.linux.inc)
# this file can contain other overrides specific to a developers
# workspace environment.
# ATH_BUILD_OUTPUT_OVERRIDE - output path override for compiled executable and
# database image
#
# Include local variables
ifdef ATH_MAKE_INCLUDE_OVERRIDE
_LOCALMAKE_INCLUDE = $(ATH_MAKE_INCLUDE_OVERRIDE)
else
_LOCALMAKE_INCLUDE = localmake.linux.inc
endif
-include $(_LOCALMAKE_INCLUDE)
export ATH_SRC_BASE
export ATH_BUILD_TYPE
export ATH_OS_SUB_TYPE
export ATH_LINUXPATH
export ATH_CROSS_COMPILE_TYPE
export ATH_ARCH_CPU_TYPE
export ATH_SDIO_STACK_BASE
export ATH_BUS_TYPE
export ATH_BUS_SUBTYPE
export ATH_HC_DRIVERS
export ATH_HTC_RAW_INT_ENV
export ATH_ANDROID_ENV
export ATH_SOFTMAC_FILE_USED
export ATH_CFG80211_ENV
export ATH_DEBUG_DRIVER
export ATH_AR6K_HCI_PAL
export ATH_AR6K_DEBUG_ALLOC
#export ATH_BUILD_P2P
ATH_SRC_BASE :=$(shell pwd)
MAKE :=make
CC :=$(ATH_CROSS_COMPILE_TYPE)gcc
LD :=$(ATH_CROSS_COMPILE_TYPE)ld
STRIP :=$(ATH_CROSS_COMPILE_TYPE)strip
ATH_HIF_TYPE :=`echo $(ATH_BUS_TYPE) | tr [:upper:] [:lower:]`
export STRIP
#export compiler variables for 3rd party applications (like the WPA supplicant)
export CC
export LD
export STRIP
# Set cross compile type (if any)
ifdef ATH_CROSS_COMPILE_TYPE
_CROSS_COMPILE_LINE := ARCH=$(ATH_ARCH_CPU_TYPE) CROSS_COMPILE=$(ATH_CROSS_COMPILE_TYPE)
endif
# Figure out module extension
ifneq ($(ATH_OS_SUB_TYPE),linux_2_4)
KMOD_EXTENSION :=ko
endif
ifeq ($(ATH_OS_SUB_TYPE),linux_2_4)
KMOD_EXTENSION :=o
endif
# Set up object output areas
ifdef ATH_BUILD_OUTPUT_OVERRIDE
_COMPILED_OBJECTS_PATH :=$(ATH_BUILD_OUTPUT_OVERRIDE)
COMPILED_BIN_OBJECTS_PATH :=$(ATH_BUILD_OUTPUT_OVERRIDE)
COMPILED_IMAGE_OBJECTS_PATH :=$(ATH_BUILD_OUTPUT_OVERRIDE)
_MAKE_IMAGE_OUTPUT_DIR :=
_MAKE_BIN_OUTPUT_DIR :=
_CLEAN_IMAGE_OUTPUT_DIR :=
_CLEAN_BIN_OUTPUT_DIR :=
else
_COMPILED_OBJECTS_PATH := $(ATH_SRC_BASE)/.output/$(ATH_BUILD_TYPE)-$(ATH_BUS_TYPE)
COMPILED_BIN_OBJECTS_PATH := $(ATH_SRC_BASE)/.output/bin
COMPILED_IMAGE_OBJECTS_PATH :=$(_COMPILED_OBJECTS_PATH)/$(COMPILED_OBJECTS_PREFIX)image
_MAKE_IMAGE_OUTPUT_DIR := mkdir --parents $(COMPILED_IMAGE_OBJECTS_PATH)
_MAKE_BIN_OUTPUT_DIR := mkdir --parents $(COMPILED_BIN_OBJECTS_PATH)
_CLEAN_IMAGE_OUTPUT_DIR := rm -R -f $(COMPILED_IMAGE_OBJECTS_PATH)
_CLEAN_BIN_OUTPUT_DIR := rm -R -f $(COMPILED_BIN_OBJECTS_PATH)
endif
# Export the required variables to other Makefiles in the system
export COMPILED_IMAGE_OBJECTS_PATH
export COMPILED_BIN_OBJECTS_PATH
all: modules
modules:
ifndef ATH_BUILD_TYPE
@echo "Please edit the $(_LOCALMAKE_INCLUDE) file"
exit 1
endif
$(_MAKE_IMAGE_OUTPUT_DIR)
$(_MAKE_BIN_OUTPUT_DIR)
$(MAKE) $(_CROSS_COMPILE_LINE) -C $(ATH_LINUXPATH) ATH_HIF_TYPE=$(ATH_HIF_TYPE) SUBDIRS=$(ATH_SRC_BASE)/os/linux modules
$(MAKE) -C hif/$(ATH_HIF_TYPE)
# $(MAKE) -C tools/wmiconfig/
# $(MAKE) -C tools/recEvent/
cp -f $(ATH_SRC_BASE)/os/linux/ar6000.$(KMOD_EXTENSION) $(COMPILED_IMAGE_OBJECTS_PATH)
$(STRIP) -g -S -d $(COMPILED_IMAGE_OBJECTS_PATH)/ar6000.$(KMOD_EXTENSION)
# cp -f tools/wmiconfig/wmiconfig $(COMPILED_IMAGE_OBJECTS_PATH)
# cp -f tools/recEvent/recEvent $(COMPILED_IMAGE_OBJECTS_PATH)
# cp -f tools/recEvent/restore.sh $(COMPILED_IMAGE_OBJECTS_PATH)
clean:
rm -f os/linux/ar6000.mod.c os/linux/*.o os/linux/*.ko wmi/*.o htc/AR6000/src/*.o htc/*.o \
bmi/src/*.o wlan/src/*.o driver/* tools/wmiconfig/wmiconfig \
tools/recEvent/recEvent
# The kernel module build process leaves some intermediate files, this will clean up all these files
find $(ATH_SRC_BASE) \( -not -path "*.output*" -a -name '*.[oas]' -o -name core -o -name '.*.flags' -o -name '.ko' -o -name '.*.cmd' \) -type f -print \
| grep -v lxdialog/ | xargs rm -f
$(MAKE) -C hif/$(ATH_HIF_TYPE) clean
clobber:clean
rm -rf .output

View File

@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
// <copyright file="bmi_internal.h" company="Atheros">
// Copyright (c) 2004-2008 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 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 "bmi_msg.h"
#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
/* ------ Global Variable Declarations ------- */
A_BOOL bmiDone;
#endif

View File

@ -0,0 +1,774 @@
//------------------------------------------------------------------------------
// <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"
//==============================================================================
#include "hif.h"
#include "bmi.h"
#include "bmi_internal.h"
#ifdef DEBUG
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_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)
#define BMI_EXCHANGE_TIMEOUT_MS 1000
/* APIs visible to the driver */
void
BMIInit(void)
{
bmiDone = 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 (!pBMICmdBuf) {
pBMICmdBuf = (A_UCHAR *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
A_ASSERT(pBMICmdBuf);
}
A_REGISTER_MODULE_DEBUG_INFO(bmi);
}
void
BMICleanup(void)
{
#if 0
if (pBMICmdCredits) {
A_FREE(pBMICmdCredits);
pBMICmdCredits = NULL;
}
#endif
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;
A_MEMCPY(pBMICmdBuf,&cid,sizeof(cid));
status = HIFExchangeBMIMsg(device, pBMICmdBuf, sizeof(cid), NULL, NULL, 0);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
return A_ERROR;
}
if (pBMICmdBuf) {
A_FREE(pBMICmdBuf);
pBMICmdBuf = NULL;
}
AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
return A_OK;
}
#ifndef HIF_MESSAGE_BASED
extern A_STATUS HIFRegBasedGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info);
#endif
A_STATUS
BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
{
if (bmiDone) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Get Target Info Command disallowed\n"));
return A_ERROR;
}
#ifndef HIF_MESSAGE_BASED
/* getting the target ID requires special handling because of the variable length
* message */
return HIFRegBasedGetTargetInfo(device,targ_info);
#else
/* TODO */
return A_ERROR;
#endif
}
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 = HIFExchangeBMIMsg(device,
pBMICmdBuf,
offset,
pBMICmdBuf, /* note we reuse the same buffer to receive on */
&rxlen,
BMI_EXCHANGE_TIMEOUT_MS);
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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, BMI_EXCHANGE_TIMEOUT_MS);
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_UINT32 paramLen;
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);
paramLen = sizeof(*param);
status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMICmdBuf, &paramLen, 0);
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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0);
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,paramLen;
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);
paramLen = sizeof(*param);
status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMICmdBuf, &paramLen, BMI_EXCHANGE_TIMEOUT_MS);
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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0);
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,responseLen;
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);
responseLen = sizeof(*rompatch_id);
status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMICmdBuf, &responseLen, BMI_EXCHANGE_TIMEOUT_MS);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to install ROM patch\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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0);
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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0);
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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0);
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 = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, NULL, NULL, 0);
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;
}
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
BMInvramProcess(HIF_DEVICE *device, A_UCHAR *seg_name, A_UINT32 *retval)
{
A_UINT32 cid;
A_STATUS status;
A_UINT32 offset;
A_UINT32 retvalLen;
A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + BMI_NVRAM_SEG_NAME_SZ));
if (bmiDone) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
return A_ERROR;
}
AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
("BMI NVRAM Process: Enter (device: 0x%p, name: %s)\n",
device, seg_name));
cid = BMI_NVRAM_PROCESS;
offset = 0;
A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
offset += sizeof(cid);
A_MEMCPY(&(pBMICmdBuf[offset]), seg_name, BMI_NVRAM_SEG_NAME_SZ);
offset += BMI_NVRAM_SEG_NAME_SZ;
retvalLen = sizeof(*retval);
status = HIFExchangeBMIMsg(device, pBMICmdBuf, offset, pBMICmdBuf, &retvalLen, 0);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to access the device\n"));
return A_ERROR;
}
A_MEMCPY(retval, pBMICmdBuf, sizeof(*retval));
AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI NVRAM Process: Exit\n"));
return A_OK;
}
#ifdef HIF_MESSAGE_BASED
/* TODO.. stubs.. for message-based HIFs, the RAW access APIs need to be changed
*/
A_STATUS
BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length)
{
/* TODO */
return A_ERROR;
}
A_STATUS
BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout)
{
/* TODO */
return A_ERROR;
}
#endif

View File

@ -0,0 +1,26 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-2007 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 $(_MAKEENVROOT)\makefile.def

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) 2002-2006, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
#include "dfs_common.h"
struct ath_dfs_host *dfs_attach_host(DEV_HDL dev, OS_HDL os, ATH_DFS_CAPINFO *cap_info)
{
int i,n;
struct ath_dfs_host *dfs;
dfs = (struct ath_dfs_host *)DFS_MALLOC(os, sizeof(struct ath_dfs_host));
if (dfs == NULL) {
A_PRINTF("%s: ath_dfs allocation failed\n", __func__);
return dfs;
}
OS_MEMZERO(dfs, sizeof (struct ath_dfs_host));
dfs->dev_hdl = dev;
dfs->os_hdl = os;
dfs->dfs_debug_level=ATH_DEBUG_DFS;
ATH_DFSQ_LOCK_INIT(dfs);
STAILQ_INIT(&dfs->dfs_radarq);
ATH_ARQ_LOCK_INIT(dfs);
STAILQ_INIT(&dfs->dfs_arq);
STAILQ_INIT(&(dfs->dfs_eventq));
ATH_DFSEVENTQ_LOCK_INIT(dfs);
OS_INIT_TIMER(&dfs->dfs_radar_task_timer, dfs_radar_task, dfs);
dfs->events = (struct dfs_event *)DFS_MALLOC(os,
sizeof(struct dfs_event)*DFS_MAX_EVENTS);
if (dfs->events == NULL) {
OS_FREE(dfs);
dfs = NULL;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"%s: events allocation failed\n", __func__);
return dfs;
}
for (i=0; i< DFS_MAX_EVENTS; i++) {
STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], re_list);
}
dfs->pulses = (struct dfs_pulseline *)DFS_MALLOC(os, sizeof(struct dfs_pulseline));
if (dfs->pulses == NULL) {
OS_FREE(dfs->events);
dfs->events = NULL;
OS_FREE(dfs);
dfs = NULL;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"%s: pulse buffer allocation failed\n", __func__);
return dfs;
}
dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
#ifdef ATH_ENABLE_AR
if(cap_info->enable_ar){
dfs_reset_ar(dfs);
dfs_reset_arq(dfs);
dfs->dfs_proc_phyerr |= DFS_AR_EN;
}
#endif /* ATH_ENABLE_AR */
if(cap_info->enable_radar) {
/* Allocate memory for radar filters */
for (n=0; n<DFS_MAX_RADAR_TYPES; n++) {
dfs->dfs_radarf[n] = (struct dfs_filtertype *)DFS_MALLOC(os, sizeof(struct dfs_filtertype));
if (dfs->dfs_radarf[n] == NULL) {
DFS_DPRINTK(dfs,ATH_DEBUG_DFS,
"%s: cannot allocate memory for radar filter types\n",
__func__);
goto bad1;
}
}
/* Allocate memory for radar table */
dfs->dfs_radartable = (int8_t **)DFS_MALLOC(os, 256*sizeof(int8_t *));
if (dfs->dfs_radartable == NULL) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: cannot allocate memory for radar table\n",
__func__);
goto bad1;
}
for (n=0; n<256; n++) {
dfs->dfs_radartable[n] = DFS_MALLOC(os, DFS_MAX_RADAR_OVERLAP*sizeof(int8_t));
if (dfs->dfs_radartable[n] == NULL) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"%s: cannot allocate memory for radar table entry\n",
__func__);
goto bad2;
}
}
/* Init the Bin5 chirping related data */
dfs->dfs_rinfo.dfs_bin5_chirp_ts = cap_info->ext_chan_busy_ts;
dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR;
dfs->dfs_b5radars = NULL;
}
return dfs;
bad2:
OS_FREE(dfs->dfs_radartable);
dfs->dfs_radartable = NULL;
bad1:
for (n=0; n<DFS_MAX_RADAR_TYPES; n++) {
if (dfs->dfs_radarf[n] != NULL) {
OS_FREE(dfs->dfs_radarf[n]);
dfs->dfs_radarf[n] = NULL;
}
}
if (dfs->pulses) {
OS_FREE(dfs->pulses);
dfs->pulses = NULL;
}
if (dfs->events) {
OS_FREE(dfs->events);
dfs->events = NULL;
}
return dfs;
}
void
dfs_detach_host(struct ath_dfs_host *dfs)
{
int n, empty;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return;
}
OS_CANCEL_TIMER(&dfs->dfs_radar_task_timer);
/* Return radar events to free q*/
dfs_reset_radarq(dfs);
dfs_reset_alldelaylines(dfs);
/* Free up pulse log*/
if (dfs->pulses != NULL) {
OS_FREE(dfs->pulses);
dfs->pulses = NULL;
}
for (n=0; n<DFS_MAX_RADAR_TYPES;n++) {
if (dfs->dfs_radarf[n] != NULL) {
OS_FREE(dfs->dfs_radarf[n]);
dfs->dfs_radarf[n] = NULL;
}
}
if (dfs->dfs_radartable != NULL) {
for (n=0; n<256; n++) {
if (dfs->dfs_radartable[n] != NULL) {
OS_FREE(dfs->dfs_radartable[n]);
dfs->dfs_radartable[n] = NULL;
}
}
OS_FREE(dfs->dfs_radartable);
dfs->dfs_radartable = NULL;
}
if (dfs->dfs_b5radars != NULL) {
OS_FREE(dfs->dfs_b5radars);
dfs->dfs_b5radars=NULL;
}
dfs_reset_ar(dfs);
ATH_ARQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_arq));
ATH_ARQ_UNLOCK(dfs);
if (!empty) {
dfs_reset_arq(dfs);
}
if (dfs->events != NULL) {
OS_FREE(dfs->events);
dfs->events = NULL;
}
OS_FREE(dfs);
dfs = NULL;
}
void dfs_bangradar_enable(struct ath_dfs_host *dfs, u_int8_t enable)
{
dfs->dfs_bangradar = enable;
}
void dfs_set_dur_multiplier(struct ath_dfs_host *dfs, u_int32_t dur_multiplier)
{
dfs->dur_multiplier = dur_multiplier;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
"%s: duration multiplier is %d\n", __func__, dfs->dur_multiplier);
}
void dfs_set_debug_level_host(struct ath_dfs_host *dfs, u_int32_t level)
{
dfs->dfs_debug_level = level;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS3,
"%s: debug level is %d\n", __func__, dfs->dfs_debug_level);
}
#endif /* ATH_UPPORT_DFS */

View File

@ -0,0 +1,262 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
#define UPDATE_TOP_THREE_PEAKS(_histo, _peakPtrList, _currWidth) { \
if ((_histo)[(_peakPtrList)[0]] < (_histo)[(_currWidth)]) { \
(_peakPtrList)[2] = (_currWidth != (_peakPtrList)[1]) ? \
(_peakPtrList)[1] : (_peakPtrList)[2]; \
(_peakPtrList)[1] = (_peakPtrList)[0]; \
(_peakPtrList)[0] = (_currWidth); \
} else if ((_currWidth != (_peakPtrList)[0]) \
&& ((_histo)[(_peakPtrList)[1]] < (_histo)[(_currWidth)])) { \
(_peakPtrList)[2] = (_peakPtrList)[1]; \
(_peakPtrList)[1] = (_currWidth); \
} else if ((_currWidth != (_peakPtrList)[1]) \
&& (_currWidth != (_peakPtrList)[0]) \
&& ((_histo)[(_peakPtrList)[2]] < (_histo)[(_currWidth)])) { \
(_peakPtrList)[2] = (_currWidth); \
} \
}
u_int32_t dfs_process_ar_event(struct ath_dfs_host *dfs)
{
struct dfs_ar_state *ar;
struct dfs_event *re=NULL;
u_int32_t sumpeak=0,numpeaks,rssi,width,origregionsum=0, i;
u_int16_t thistimestamp;
int empty;
u_int32_t result = 0;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return result;
}
ar = (struct dfs_ar_state *) &(dfs->dfs_ar_state);
ATH_ARQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_arq));
ATH_ARQ_UNLOCK(dfs);
while (!empty) {
ATH_ARQ_LOCK(dfs);
re = STAILQ_FIRST(&(dfs->dfs_arq));
if (re != NULL)
STAILQ_REMOVE_HEAD(&(dfs->dfs_arq), re_list);
ATH_ARQ_UNLOCK(dfs);
if (re == NULL)
return result;
thistimestamp = re->re_ts;
rssi = re->re_rssi;
width = re->re_dur;
/* Return the dfs event to the free event list */
OS_MEMZERO(re, sizeof(struct dfs_event));
ATH_DFSEVENTQ_LOCK(dfs);
STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), re, re_list);
ATH_DFSEVENTQ_UNLOCK(dfs);
/* determine if current radar is an extension of previous radar */
if (ar->ar_prevwidth == 255) {
/* tag on previous width for consideraion of low data rate ACKs */
ar->ar_prevwidth += width;
width = (width == 255) ? 255 : ar->ar_prevwidth;
} else if ((width == 255) &&
(ar->ar_prevwidth == 510 ||
ar->ar_prevwidth == 765 ||
ar->ar_prevwidth == 1020)) {
/* Aggregate up to 5 consecuate max radar widths
* to consider 11Mbps long preamble 1500-byte pkts
*/
ar->ar_prevwidth += width;
} else if (ar->ar_prevwidth == 1275 && width != 255) {
/* Found 5th consecute maxed out radar, reset history */
width += ar->ar_prevwidth;
ar->ar_prevwidth = 0;
} else if (ar->ar_prevwidth > 255) {
/* Ignore if there are less than 5 consecutive maxed out radars */
ar->ar_prevwidth = width;
width = 255;
} else {
ar->ar_prevwidth = width;
}
/* For ignoring noises with radar duration in ranges of 3-30: AP4x */
if ((width >= 257 && width <= 278) || /* Region 7 - 5.5Mbps (long pre) ACK = 270 = 216 us */
(width >= 295 && width <= 325) || /* Region 8 - 2Mbps (long pre) ACKC = 320 = 256us */
(width >= 1280 && width <= 1300)) {
u_int16_t wraparoundadj=0;
u_int16_t base = (width >= 1280) ? 1275 : 255;
if (thistimestamp < ar->ar_prevtimestamp) {
wraparoundadj = 32768;
}
if ((thistimestamp + wraparoundadj - ar->ar_prevtimestamp) !=
(width - base)) {
width = 1;
}
}
if (width <= 10) {
ATH_ARQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_arq));
ATH_ARQ_UNLOCK(dfs);
continue;
}
/*
* Overloading the width=2 in: Store a count of radars w/max duration
* and high RSSI (not noise)
*/
if ((width == 255) && (rssi > DFS_AR_RSSI_THRESH_STRONG_PKTS))
width = 2;
/*
* Overloading the width=3 bin:
* Double and store a count of rdars of durtaion that matches 11Mbps (long preamble)
* TCP ACKs or 1500-byte data packets
*/
if ((width >= 1280 && width <= 1300) ||
(width >= 318 && width <= 325)) {
width = 3;
ar->ar_phyerrcount[3] += 2;
ar->ar_acksum += 2;
}
/* build histogram of radar duration */
if (width > 0 && width <= 510)
ar->ar_phyerrcount[width]++;
else {
/* invalid radar width, throw it away */
ATH_ARQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_arq));
ATH_ARQ_UNLOCK(dfs);
continue;
}
/* Received radar of interest (i.e., signature match), proceed to check if
* there is enough neighboring traffic to drop out of Turbo
*/
if ((width >= 33 && width <= 38) || /* Region 0: 24Mbps ACK = 35 = 28us */
(width >= 39 && width <= 44) || /* Region 1: 12Mbps ACK = 40 = 32us */
(width >= 53 && width <= 58) || /* Region 2: 6Mbps ACK = 55 = 44us */
(width >= 126 && width <= 140) || /* Region 3: 11Mbps ACK = 135 = 108us */
(width >= 141 && width <= 160) || /* Region 4: 5.5Mbps ACK = 150 = 120us */
(width >= 189 && width <= 210) || /* Region 5: 2Mbps ACK = 200 = 160us */
(width >= 360 && width <= 380) || /* Region 6 1Mbps ACK = 400 = 320us */
(width >= 257 && width <= 270) || /* Region 7 5.5Mbps (Long Pre) ACK = 270 = 216us */
(width >= 295 && width <= 302) || /* Region 8 2Mbps (Long Pre) ACK = 320 = 256us */
/* Ignoring Region 9 due to overlap with 255 which is same as board noise */
/* Region 9 11Mbps (Long Pre) ACK = 255 = 204us */
(width == 3)) {
ar->ar_acksum++;
/* double the count for strong radars that match one of the ACK signatures */
if (rssi > DFS_AR_RSSI_DOUBLE_THRESHOLD) {
ar->ar_phyerrcount[width]++;
ar->ar_acksum++;
}
UPDATE_TOP_THREE_PEAKS(ar->ar_phyerrcount,
ar->ar_peaklist, width);
/* sum the counts of these peaks */
numpeaks = DFS_AR_MAX_NUM_PEAKS;
origregionsum = ar->ar_acksum;
for (i=0; i<= DFS_AR_MAX_NUM_PEAKS; i++) {
if (ar->ar_peaklist[i] > 0) {
if ((i==0) &&
(ar->ar_peaklist[i] == 3) &&
(ar->ar_phyerrcount[3] <
ar->ar_phyerrcount[2]) &&
(ar->ar_phyerrcount[3] > 6)) {
/*
* If the top peak is one that
* maches the 11Mbps long
* preamble TCP Ack/1500-byte
* data, include the count for
* radars that hav emax
* duration and high rssi
* (width = 2) to boost the
* sum for the PAR test that
* follows */
sumpeak += (ar->ar_phyerrcount[2]
+ ar->ar_phyerrcount[3]);
ar->ar_acksum += (ar->ar_phyerrcount[2]
+ ar->ar_phyerrcount[3]);
} else {
sumpeak += ar->ar_phyerrcount[ar->ar_peaklist[i]];
}
} else
numpeaks--;
}
/*
* If sum of patterns matches exceeds packet threshold,
* perform comparison between peak-to-avg ratio against parThreshold
*/
if ((ar->ar_acksum > ar->ar_packetthreshold) &&
((sumpeak * DFS_AR_REGION_WIDTH) > (ar->ar_parthreshold * numpeaks *
ar->ar_acksum))) {
/* neighboring traffic detected, get out of Turbo */
result = TRAFFIC_DETECTED;
OS_MEMZERO(ar->ar_peaklist, sizeof(ar->ar_peaklist));
ar->ar_acksum = 0;
OS_MEMZERO(ar->ar_phyerrcount, sizeof(ar->ar_phyerrcount));
} else {
/*
* reset sum of matches to discount the count of
* strong radars with max duration
*/
ar->ar_acksum = origregionsum;
}
}
ar->ar_prevtimestamp = thistimestamp;
ATH_ARQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_arq));
ATH_ARQ_UNLOCK(dfs);
}
return result;
}
void dfs_reset_ar(struct ath_dfs_host *dfs)
{
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return;
}
OS_MEMZERO(&dfs->dfs_ar_state, sizeof(dfs->dfs_ar_state));
dfs->dfs_ar_state.ar_packetthreshold = DFS_AR_PKT_COUNT_THRESH;
dfs->dfs_ar_state.ar_parthreshold = DFS_AR_ACK_DETECT_PAR_THRESH;
dfs->dfs_ar_state.ar_radarrssi = DFS_AR_RADAR_RSSI_THR;
}
void dfs_reset_arq(struct ath_dfs_host *dfs)
{
struct dfs_event *event;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return;
}
ATH_ARQ_LOCK(dfs);
ATH_DFSEVENTQ_LOCK(dfs);
while (!STAILQ_EMPTY(&(dfs->dfs_arq))) {
event = STAILQ_FIRST(&(dfs->dfs_arq));
STAILQ_REMOVE_HEAD(&(dfs->dfs_arq), re_list);
OS_MEMZERO(event, sizeof(struct dfs_event));
STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
}
ATH_DFSEVENTQ_UNLOCK(dfs);
ATH_ARQ_UNLOCK(dfs);
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,340 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
int dfs_bin_fixedpattern_check(struct ath_dfs_host *dfs, struct dfs_filter *rf, u_int32_t dur, int ext_chan_flag, u_int32_t ext_chan_busy)
{
struct dfs_pulseline *pl = dfs->pulses;
int i, n, refpri, primargin, numpulses=0;
u_int64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, window_start, window_end;
u_int32_t index, next_index, deltadur;
/* For fixed pattern types, rf->rf_patterntype=1*/
primargin = dfs_get_pri_margin(ext_chan_flag, (rf->rf_patterntype==1),dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy);
refpri = (rf->rf_minpri + rf->rf_maxpri)/2;
index = pl->pl_lastelem;
end_ts = pl->pl_elems[index].p_time;
start_ts = end_ts - (refpri*rf->rf_numpulses);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, "lastelem ts=%llu start_ts=%llu, end_ts=%llu\n", (unsigned long long)pl->pl_elems[index].p_time, (unsigned long long)start_ts, (unsigned long long)end_ts);
/* find the index of first element in our window of interest */
for(i=0;i<pl->pl_numelems;i++) {
index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK;
if(pl->pl_elems[index].p_time >= start_ts )
continue;
else {
index = (index) & DFS_MAX_PULSE_BUFFER_MASK;
break;
}
}
for (n=0;n<=rf->rf_numpulses; n++) {
window_start = (start_ts + (refpri*n))-(primargin+n);
window_end = window_start + 2*(primargin+n);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"window_start %u window_end %u \n",
(u_int32_t)window_start, (u_int32_t)window_end);
for(i=0;i<pl->pl_numelems;i++) {
prev_event_ts = pl->pl_elems[index].p_time;
index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK;
event_ts = pl->pl_elems[index].p_time;
next_index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK;
next_event_ts = pl->pl_elems[next_index].p_time;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"ts %u \n", (u_int32_t)event_ts);
if( (event_ts <= window_end) && (event_ts >= window_start)){
deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur);
if( (pl->pl_elems[index].p_dur == 1) ||
((dur != 1) && (deltadur <= 2))) {
numpulses++;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"numpulses %u \n", numpulses);
break;
}
}
else if( event_ts > window_end) {
index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK;
break;
}
else if( event_ts == prev_event_ts) {
if( ((next_event_ts - event_ts) > refpri) ||
((next_event_ts - event_ts) == 0)) {
deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur);
if( (pl->pl_elems[index].p_dur == 1) ||
((pl->pl_elems[index].p_dur != 1) && (deltadur <= 2))) {
numpulses++;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"zero PRI: numpulses %u \n", numpulses);
break;
}
}
}
}
}
if (numpulses >= dfs_get_filter_threshold(rf, ext_chan_flag, dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy)) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s FOUND filterID=%u numpulses=%d unadj thresh=%d\n", __func__, rf->rf_pulseid, numpulses, rf->rf_threshold);
return 1;
}
else
return 0;
}
void
dfs_add_pulse(struct ath_dfs_host *dfs, struct dfs_filter *rf, struct dfs_event *re,
u_int32_t deltaT)
{
u_int32_t index,n, window, pri;
struct dfs_delayline *dl;
dl = &rf->rf_dl;
/* Circular buffer of size 2^n */
index = (dl->dl_lastelem + 1) & DFS_MAX_DL_MASK;
//if ((dl->dl_numelems+1) == DFS_MAX_DL_SIZE)
if ((dl->dl_numelems) == DFS_MAX_DL_SIZE)
dl->dl_firstelem = (dl->dl_firstelem + 1) & DFS_MAX_DL_MASK;
else
dl->dl_numelems++;
dl->dl_lastelem = index;
dl->dl_elems[index].de_time = deltaT;
window = deltaT;
dl->dl_elems[index].de_dur = re->re_dur;
dl->dl_elems[index].de_rssi = re->re_rssi;
for (n=0;n<dl->dl_numelems-1; n++) {
index = (index-1) & DFS_MAX_DL_MASK;
pri = dl->dl_elems[index].de_time;
window += pri;
if (window > rf->rf_filterlen) {
dl->dl_firstelem = (index+1) & DFS_MAX_DL_MASK;
dl->dl_numelems = n+1;
}
}
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"dl firstElem = %d lastElem = %d\n",dl->dl_firstelem,
dl->dl_lastelem);
}
int dfs_bin_check(struct ath_dfs_host *dfs, struct dfs_filter *rf,
u_int32_t deltaT, u_int32_t width, int ext_chan_flag, u_int32_t ext_chan_busy)
{
u_int32_t refpri, refdur, searchpri, deltapri, averagerefpri;
u_int32_t n, i, primargin, durmargin, highscore, highscoreindex;
int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0;
struct dfs_delayline *dl;
u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff;
int numpulses=0;
dl = &rf->rf_dl;
if( dl->dl_numelems < (rf->rf_threshold-1)) {
return 0;
}
if( deltaT > rf->rf_filterlen)
return 0;
primargin = dfs_get_pri_margin(ext_chan_flag, (rf->rf_patterntype==1),
dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy);
if(rf->rf_maxdur < 10) {
durmargin = 4;
}
else {
durmargin = 6;
}
if( rf->rf_patterntype == 1 ){
found = dfs_bin_fixedpattern_check(dfs, rf, width, ext_chan_flag, ext_chan_busy);
if(found) {
dl->dl_numelems = 0;
}
return found;
}
OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE);
/* find out the lowest pri */
for (n=0;n<dl->dl_numelems; n++) {
delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
refpri = dl->dl_elems[delayindex].de_time;
if( refpri == 0)
continue;
else if(refpri < lowpri) {
lowpri = dl->dl_elems[delayindex].de_time;
lowpriindex = n;
}
}
/* find out the each delay element's pri score */
for (n=0;n<dl->dl_numelems; n++) {
delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
refpri = dl->dl_elems[delayindex].de_time;
if( refpri == 0)
continue;
for (i=0;i<dl->dl_numelems; i++) {
dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
searchpri = dl->dl_elems[dindex].de_time;
deltapri = DFS_DIFF(searchpri, refpri);
if( deltapri < primargin)
score[n]++;
}
if( score[n] > rf->rf_threshold) {
/* we got the most possible candidate,
* no need to continue further */
break;
}
}
/* find out the high scorer */
highscore = 0;
highscoreindex = 0;
for (n=0;n<dl->dl_numelems; n++) {
if( score[n] > highscore) {
highscore = score[n];
highscoreindex = n;
}
else if( score[n] == highscore ) {
/*more than one pri has highscore take the least pri */
delayindex = (dl->dl_firstelem + highscoreindex) & DFS_MAX_DL_MASK;
dindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
if( dl->dl_elems[dindex].de_time <=
dl->dl_elems[delayindex].de_time ) {
highscoreindex = n;
}
}
}
/* find the average pri of pulses around the pri of highscore or
* the pulses around the lowest pri */
if( highscore < 3) {
scoreindex = lowpriindex;
}
else {
scoreindex = highscoreindex;
}
/* We got the possible pri, save its parameters as reference */
delayindex = (dl->dl_firstelem + scoreindex) & DFS_MAX_DL_MASK;
refdur = dl->dl_elems[delayindex].de_dur;
refpri = dl->dl_elems[delayindex].de_time;
averagerefpri = 0;
numpulses = dfs_bin_pri_check(dfs, rf, dl, score[scoreindex], refpri, refdur, ext_chan_flag, ext_chan_busy);
if (numpulses >= dfs_get_filter_threshold(rf, ext_chan_flag, dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy)) {
found = 1;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "ext_flag=%d MATCH filter=%u numpulses=%u thresh=%u refpri=%d primargin=%d\n", ext_chan_flag, rf->rf_pulseid, numpulses,rf->rf_threshold, refpri, primargin);
dfs_print_delayline(dfs, &rf->rf_dl);
dfs_print_filter(dfs, rf);
}
return found;
}
int dfs_bin_pri_check(struct ath_dfs_host *dfs, struct dfs_filter *rf,
struct dfs_delayline *dl, u_int32_t score,
u_int32_t refpri, u_int32_t refdur, int ext_chan_flag, u_int32_t ext_chan_busy)
{
u_int32_t searchpri, searchdur, searchrssi, deltapri, deltadur, averagerefpri=0;
int primultiples[6];
int delayindex, dindex;
u_int32_t i, j, primargin, durmargin, highscore=score, highscoreindex=0;
int numpulses=1; //first pulse in the burst is most likely being filtered out based on maxfilterlen
//Use the adjusted PRI margin to reduce false alarms
/* For non fixed pattern types, rf->rf_patterntype=0*/
primargin = dfs_get_pri_margin(ext_chan_flag, (rf->rf_patterntype==1),
dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy);
if(rf->rf_maxdur < 10) {
durmargin = 4;
}
else {
durmargin = 6;
}
if( score > 1) {
for (i=0;i<dl->dl_numelems; i++) {
dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
searchpri = dl->dl_elems[dindex].de_time;
deltapri = DFS_DIFF(searchpri, refpri);
if( deltapri < primargin)
averagerefpri += searchpri;
}
refpri = (averagerefpri/score); //average
}
/* Note: Following primultiple calculation should be done once per filter
* during initialization stage (dfs_attach) and stored in its array
* atleast for fixed frequency types like FCC Bin1 to save some CPU cycles.
* multiplication, devide operators in the following code are left as it is
* for readability hoping the complier will use left/right shifts wherever possible
*/
if( refpri > rf->rf_maxpri) {
primultiples[0] = (refpri - refdur)/2;
primultiples[1] = refpri;
primultiples[2] = refpri + primultiples[0];
primultiples[3] = (refpri - refdur)*2;
primultiples[4] = primultiples[3] + primultiples[0];
primultiples[5] = primultiples[3] + refpri;
}
else {
primultiples[0] = refpri;
primultiples[1] = refpri + primultiples[0];
primultiples[2] = refpri + primultiples[1];
primultiples[3] = refpri + primultiples[2];
primultiples[4] = refpri + primultiples[3];
primultiples[5] = refpri + primultiples[4];
}
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"pri0 = %d pri1 = %d pri2 = %d pri3 = %d pri4 = %d pri5 = %d\n",
primultiples[0], primultiples[1], primultiples[2],
primultiples[3], primultiples[4], primultiples[5]);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"refpri = %d high score = %d index = %d numpulses = %d\n",
refpri, highscore, highscoreindex, numpulses);
/* Count the other delay elements that have pri and dur with in the
* acceptable range from the reference one */
for (i=0; i<dl->dl_numelems; i++) {
delayindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
searchpri = dl->dl_elems[delayindex].de_time;
if( searchpri == 0) {
/* This events PRI is zero, take it as a
* valid pulse but decrement next event's PRI by refpri
*/
dindex = (delayindex+1)& DFS_MAX_DL_MASK;
dl->dl_elems[dindex].de_time -= refpri;
searchpri = refpri;
}
searchdur = dl->dl_elems[delayindex].de_dur;
searchrssi = dl->dl_elems[delayindex].de_rssi;
deltadur = DFS_DIFF(searchdur, refdur);
for(j=0; j<6; j++) {
deltapri = DFS_DIFF(searchpri, primultiples[j]);
/* May need to revisit this as this increases the primargin by 5*/
/* if( deltapri < (primargin+j)) { */
if( deltapri < (primargin)) {
if( deltadur < durmargin) {
if( (refdur < 8) || ((refdur >=8)&&
(searchrssi < 250))) {
numpulses++;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"rf->minpri=%d rf->maxpri=%d searchpri = %d index = %d numpulses = %d deltapri=%d j=%d\n",
rf->rf_minpri, rf->rf_maxpri, searchpri, i, numpulses, deltapri, j);
}
}
break;
}
}
}
return numpulses;
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
void
dfs_print_delayline(struct ath_dfs_host *dfs, struct dfs_delayline *dl)
{
int i=0,index;
struct dfs_delayelem *de;
index = dl->dl_lastelem;
for (i=0; i<dl->dl_numelems; i++) {
de = &dl->dl_elems[index];
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"Elem %d: ts = %u (0x%x) dur=%u\n",i,
de->de_time, de->de_time, de->de_dur);
index = (index - 1)& DFS_MAX_DL_MASK;
}
}
void
dfs_print_filter(struct ath_dfs_host *dfs, struct dfs_filter *rf)
{
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "filterID[%d] rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n", rf->rf_pulseid, rf->rf_numpulses, rf->rf_minpri, rf->rf_maxpri, rf->rf_threshold, rf->rf_filterlen, rf->rf_mindur, rf->rf_maxdur);
}
void
dfs_print_filters(struct ath_dfs_host *dfs)
{
struct dfs_filtertype *ft = NULL;
struct dfs_filter *rf;
int i,j;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return;
}
for (i=0; i<DFS_MAX_RADAR_TYPES; i++) {
if (dfs->dfs_radarf[i] != NULL) {
ft = dfs->dfs_radarf[i];
if((ft->ft_numfilters > DFS_MAX_NUM_RADAR_FILTERS) || (!ft->ft_numfilters))
continue;
printk("===========ft->ft_numfilters=%u===========\n", ft->ft_numfilters);
for (j=0; j<ft->ft_numfilters; j++) {
rf = &(ft->ft_filters[j]);
printk("filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n",j, rf->rf_pulseid,
rf->rf_numpulses, rf->rf_minpri, rf->rf_maxpri, rf->rf_threshold, rf->rf_filterlen, rf->rf_mindur, rf->rf_maxdur);
}
}
}
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
int dfs_bin5_addpulse(struct ath_dfs_host *dfs, struct dfs_bin5radars *br,
struct dfs_event *re, u_int64_t thists)
{
u_int32_t index,stop;
u_int64_t tsDelta;
/* Check if this pulse is a valid pulse in terms of repetition,
* if not, return without adding it to the queue.
* PRI : Pulse Repitetion Interval
* BRI : Burst Repitetion Interval */
if( br->br_numelems != 0){
index = br->br_lastelem;
tsDelta = thists - br->br_elems[index].be_ts;
if( (tsDelta < DFS_BIN5_PRI_LOWER_LIMIT) ||
( (tsDelta > DFS_BIN5_PRI_HIGHER_LIMIT) &&
(tsDelta < DFS_BIN5_BRI_LOWER_LIMIT))) {
return 0;
}
}
/* Circular buffer of size 2^n */
index = (br->br_lastelem +1) & DFS_MAX_B5_MASK;
br->br_lastelem = index;
if (br->br_numelems == DFS_MAX_B5_SIZE)
br->br_firstelem = (br->br_firstelem+1)&DFS_MAX_B5_MASK;
else
br->br_numelems++;
br->br_elems[index].be_ts = thists;
br->br_elems[index].be_rssi = re->re_rssi;
br->br_elems[index].be_dur = re->re_dur;
stop = 0;
index = br->br_firstelem;
while ((!stop) && (br->br_numelems-1) > 0) {
if ((thists - br->br_elems[index].be_ts) >
((u_int64_t) br->br_pulse.b5_timewindow)) {
br->br_numelems--;
br->br_firstelem = (br->br_firstelem +1) & DFS_MAX_B5_MASK;
index = br->br_firstelem;
} else
stop = 1;
}
return 1;
}
/*
* If the dfs structure is NULL (which should be illegal if everyting is working
* properly, then signify that a bin5 radar was found
*/
int dfs_bin5_check(struct ath_dfs_host *dfs)
{
struct dfs_bin5radars *br;
int index[DFS_MAX_B5_SIZE];
u_int32_t n, i, this, prev, rssi_diff, width_diff, bursts= 0;
u_int32_t total_diff=0, average_diff, total_width=0, average_width, numevents=0;
u_int64_t pri;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return 1;
}
for (n=0;n<dfs->dfs_rinfo.rn_numbin5radars; n++) {
br = &(dfs->dfs_b5radars[n]);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
"Num elems = %d\n", br->br_numelems);
prev = br->br_firstelem;
for(i=0;i<br->br_numelems;i++){
this = ((br->br_firstelem +i) & DFS_MAX_B5_MASK);
/* Rule 1: 1000 <= PRI <= 2000 + some margin */
if( br->br_elems[this].be_ts >= br->br_elems[prev].be_ts ) {
pri = br->br_elems[this].be_ts - br->br_elems[prev].be_ts;
}
else {//roll over case
//pri = (0xffffffffffffffff - br->br_elems[prev].be_ts) + br->br_elems[this].be_ts;
pri = br->br_elems[this].be_ts;
}
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2," pri=%llu this.ts=%llu prev.ts=%llu\n", pri, br->br_elems[this].be_ts, br->br_elems[prev].be_ts);
if(( (pri >= DFS_BIN5_PRI_LOWER_LIMIT) && (pri <= DFS_BIN5_PRI_HIGHER_LIMIT))) { //pri: pulse repitition interval in us
/* Rule 2: pulse width of the pulses in the burst should be same (+/- margin) */
if( br->br_elems[this].be_dur >= br->br_elems[prev].be_dur) {
width_diff = br->br_elems[this].be_dur - br->br_elems[prev].be_dur;
}
else {
width_diff = br->br_elems[prev].be_dur - br->br_elems[this].be_dur;
}
if( width_diff <= DFS_BIN5_WIDTH_MARGIN ) {
/* Rule 3: RSSI of the pulses in the burst should be same (+/- margin) */
if( br->br_elems[this].be_rssi >= br->br_elems[prev].be_rssi) {
rssi_diff = br->br_elems[this].be_rssi - br->br_elems[prev].be_rssi;
}
else {
rssi_diff = br->br_elems[prev].be_rssi - br->br_elems[this].be_rssi;
}
if( rssi_diff <= DFS_BIN5_RSSI_MARGIN ) {
bursts++;
/* Save the indexes of this pair for later width variance check */
if( numevents >= 2 ) {
/* make sure the event is not duplicated,
* possible in a 3 pulse burst */
if( index[numevents-1] != prev) {
index[numevents++] = prev;
}
}
else {
index[numevents++] = prev; }
index[numevents++] = this;
} else {
DFS_DPRINTK(dfs,ATH_DEBUG_DFS2,"%s %d Bin5 rssi_diff=%d\n", __func__, __LINE__, rssi_diff);
}
} else {
DFS_DPRINTK(dfs,ATH_DEBUG_DFS2,"%s %d Bin5 width_diff=%d\n", __func__, __LINE__, width_diff);
}
} else {
DFS_DPRINTK(dfs,ATH_DEBUG_DFS2,"%s %d Bin5 PRI check fail pri=%llu\n", __func__, __LINE__,pri);
}
prev = this;
}
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "bursts=%u numevents=%u\n", bursts, numevents);
if ( bursts >= br->br_pulse.b5_threshold) {
if( (br->br_elems[br->br_lastelem].be_ts - br->br_elems[br->br_firstelem].be_ts) < 3000000 ) {
return 0;
}
else {
for (i=0; i<numevents; i++){
total_width += br->br_elems[index[i]].be_dur;
}
average_width = total_width/numevents;
for (i=0; i<numevents; i++){
total_diff += DFS_DIFF(br->br_elems[index[i]].be_dur, average_width);
}
average_diff = total_diff/numevents;
if( average_diff > DFS_BIN5_WIDTH_MARGIN ) {
return 1;
} else {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "bursts=%u numevents=%u total_width=%d average_width=%d total_diff=%d average_diff=%d\n", bursts, numevents, total_width, average_width, total_diff, average_diff);
}
}
}
}
return 0;
}
u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs_host *dfs, u_int32_t diff_ts, u_int8_t old_dur)
{
// Pulses may get split into 2 during chirping, this print is only to show that it happened, we do not handle this condition if we cannot detect the chirping
// SPLIT pulses will have a time stamp difference of < 50
if (diff_ts < 50) {
DFS_DPRINTK(dfs,ATH_DEBUG_DFS1,"%s SPLIT pulse diffTs=%u dur=%d (old_dur=%d)\n", __func__, diff_ts, dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur);
}
// Check if this is the 2nd or 3rd pulse in the same burst, PRI will be between 1000 and 2000 us
if(((diff_ts >= DFS_BIN5_PRI_LOWER_LIMIT) && (diff_ts <= DFS_BIN5_PRI_HIGHER_LIMIT))) {
//This pulse belongs to the same burst as the pulse before, so return the same random duration for it
DFS_DPRINTK(dfs,ATH_DEBUG_DFS1,"%s this pulse belongs to the same burst as before, give it same dur=%d (old_dur=%d)\n", __func__, dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur);
return (dfs->dfs_rinfo.dfs_last_bin5_dur);
}
// This pulse does not belong to this burst, return unchanged duration
return old_dur;
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
#include "dfs_target_api.h"
void dfs_radar_task (unsigned long arg)
{
struct ath_dfs_host *dfs = (struct ath_dfs_host *)arg;
A_INT16 chan_index;
A_UINT8 bangradar;
//printk("\n%s\n",__func__);
if(dfs_process_radarevent_host(dfs, &chan_index, &bangradar)){
if(!bangradar){
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Radar detected on channel idx %d\n",
__func__, chan_index);
}
/* TODO: The radar detected event is sent from host in timer
* context which could potentially cause issues with sleepable
* WMI. Change this to process context later. */
DFS_RADAR_DETECTED(dfs->dev_hdl, chan_index, bangradar);
}
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,375 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
#include "dfs_target_api.h"
struct dfs_pulse ar6000_etsi_radars[] = {
/* TYPE 1 */
{15, 2, 750, 750, 0, 24, 7, 0, 2, 21, 0, -10, 0},
/* TYPE 2 */
{10, 5, 200, 200, 0, 24, 5, 1, 9, 21, 0, 3, 1},
{10, 5, 300, 300, 0, 24, 8, 1, 9, 21, 0, 3, 2},
{10, 5, 500, 500, 0, 24, 8, 1, 9, 21, 1, 3, 3},
{10, 5, 800, 800, 0, 24, 8, 1, 9, 21, 1, 3, 4},
{10, 5, 1001, 1001, 0, 30, 8, 1, 9, 21, 0, 3, 5},
/* TYPE 3 */
{15, 16, 200, 200, 0, 24, 6, 10, 19, 22, 0, 3, 6},
{15, 16, 300, 300, 0, 24, 6, 10, 19, 22, 0, 3, 7},
{15, 16, 503, 503, 0, 24, 7, 10, 19, 22, 0, 3, 8},
{15, 16, 809, 809, 0, 24, 7, 10, 19, 22, 0, 3, 9},
{15, 16, 1014, 1014, 0, 30, 7, 10, 19, 22, 0, 3, 10},
/* TYPE 4 */
{15, 5, 1200, 1200, 0, 24, 7, 1, 9, 21, 0, 3, 11},
{15, 5, 1500, 1500, 0, 30, 7, 1, 9, 21, 0, 3, 12},
{15, 5, 1600, 1600, 0, 24, 7, 1, 9, 21, 0, 3, 13},
{15, 16, 1200, 1200, 0, 30, 7, 10, 19, 22, 0, 3, 14},
{15, 16, 1500, 1500, 0, 24, 7, 10, 19, 22, 0, 3, 15},
{15, 16, 1600, 1600, 0, 24, 7, 10, 19, 22, 0, 3, 16},
/* TYPE 5 */
{25, 5, 2305, 2305, 0, 24, 12, 1, 9, 21, 0, 3, 17},
{25, 5, 3009, 3009, 0, 24, 12, 1, 9, 21, 0, 3, 18},
{25, 5, 3500, 3500, 0, 24, 12, 1, 9, 21, 0, 3, 19},
{25, 5, 4000, 4000, 0, 24, 12, 1, 9, 21, 0, 3, 20},
{25, 16, 2300, 2300, 0, 24, 12, 10, 20, 22, 0, 3, 21},
{25, 16, 3000, 3000, 0, 24, 12, 10, 20, 22, 0, 3, 22},
{25, 16, 3500, 3500, 0, 24, 12, 10, 20, 22, 0, 3, 23},
{25, 16, 3850, 3850, 0, 24, 12, 10, 20, 22, 0, 3, 24},
/* TYPE 6 */
{20, 25, 2000, 2000, 0, 24, 10, 20, 26, 22, 0, 3, 25},
{20, 25, 3000, 3000, 0, 24, 10, 20, 26, 22, 0, 3, 26},
{20, 25, 4000, 4000, 0, 24, 10, 20, 26, 22, 0, 3, 27},
{20, 37, 2000, 2000, 0, 24, 10, 30, 36, 22, 0, 3, 28},
{20, 37, 3000, 3000, 0, 24, 10, 30, 36, 22, 0, 3, 29},
{20, 37, 4000, 4000, 0, 24, 10, 30, 36, 22, 0, 3, 30},
/* TYPE staggered pulse */
{20, 2, 300, 400, 2, 30, 10, 0, 2, 22, 0, 3, 31}, //0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each
{30, 2, 400, 1200, 2, 30, 15, 0, 2, 22, 0, 3, 32}, //0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each
/* constant PRF based */
{10, 5, 200, 1000, 0, 24, 6, 0, 8, 21, 0, -10, 33}, /*0.8-5us , 200-1000 PRF, 10 pulses */
{15, 15, 200, 1600, 0, 24, 7, 0, 18, 21, 0, -10, 34}, /*0.8-15us , 200-1600 PRF, 15 pulses */
{25, 15, 2300, 4000, 0, 24, 12, 0, 18, 21, 0, -10, 35}, /* 0.8-15 us, 2300-4000 PRF, 25 pulses*/
{20, 30, 2000, 4000, 0, 24, 10, 19, 33, 21, 0, -10, 36}, /* 20-30us, 2000-4000 PRF, 20 pulses*/
};
/* The following are for FCC Bin 1-4 pulses */
struct dfs_pulse ar6000_fcc_radars[] = {
/* following two filters are specific to Japan/MKK4 */
{18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 17}, // 1389 +/- 6 us
{18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 18}, // 4000 +/- 6 us
{18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 19}, // 3846 +/- 7 us
/* following filters are common to both FCC and JAPAN */
{18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 1428 +/- 7 us
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1}, // 333 +/- 7 us
{23, 5, 6250, 6250, 0, 15, 11, 0, 7, 22, 0, 3, 2}, // 160 +/- 15 us
{23, 5, 5263, 5263, 0, 18, 11, 0, 7, 22, 0, 3, 3}, // 190 +/- 15 us
{23, 5, 4545, 4545, 0, 18, 11, 0, 7, 22, 0, 3, 4}, // 220 +/- 15 us
{18, 10, 4444, 4444, 0, 35, 6, 7, 13, 22, 0, 3, 5}, // 225 +/- 30 us
{18, 10, 3636, 3636, 0, 25, 6, 7, 13, 22, 0, 3, 6}, // 275 +/- 25 us
{18, 10, 3076, 3076, 0, 25, 8, 7, 13, 22, 0, 3, 7}, // 325 +/- 25 us
{18, 10, 2666, 2666, 0, 25, 8, 7, 13, 22, 0, 3, 8}, // 375 +/- 25 us
{18, 10, 2352, 2352, 0, 25, 8, 7, 13, 22, 0, 3, 9}, // 425 +/- 25 us
{18, 10, 2105, 2105, 0, 30, 8, 7, 13, 22, 0, 3, 10}, // 475 +/- 30 us
{14, 15, 4444, 4444, 0, 35, 5, 13, 21, 22, 0, 3, 11}, // 225 +/- 30 us
{14, 15, 3636, 3636, 0, 25, 5, 13, 24, 22, 0, 3, 12}, // 275 +/- 25 us
{14, 15, 3076, 3076, 0, 25, 7, 13, 23, 22, 0, 3, 13}, // 325 +/- 25 us
{14, 15, 2666, 2666, 0, 25, 7, 13, 23, 22, 0, 3, 14}, // 375 +/- 25 us
{14, 15, 2352, 2352, 0, 25, 7, 13, 21, 22, 0, 3, 15}, // 425 +/- 25 us
{12, 15, 2105, 2105, 0, 30, 7, 13, 21, 22, 0, 3, 16}, // 475 +/- 30 us
};
struct dfs_bin5pulse ar6000_bin5pulses[] = {
{4, 28, 105, 12, 22, 5},
};
/*
* Clear all delay lines for all filter types
*/
void dfs_reset_alldelaylines(struct ath_dfs_host *dfs)
{
struct dfs_filtertype *ft = NULL;
struct dfs_filter *rf;
struct dfs_delayline *dl;
struct dfs_pulseline *pl;
int i,j;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return;
}
pl = dfs->pulses;
/* reset the pulse log */
pl->pl_firstelem = pl->pl_numelems = 0;
pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
for (i=0; i<DFS_MAX_RADAR_TYPES; i++) {
if (dfs->dfs_radarf[i] != NULL) {
ft = dfs->dfs_radarf[i];
for (j=0; j<ft->ft_numfilters; j++) {
rf = &(ft->ft_filters[j]);
dl = &(rf->rf_dl);
if(dl != NULL) {
OS_MEMZERO(dl, sizeof(struct dfs_delayline));
dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK;
}
}
}
}
for (i=0; i<dfs->dfs_rinfo.rn_numbin5radars; i++) {
OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]), sizeof(struct dfs_bin5elem)*DFS_MAX_B5_SIZE);
dfs->dfs_b5radars[i].br_firstelem = 0;
dfs->dfs_b5radars[i].br_numelems = 0;
dfs->dfs_b5radars[i].br_lastelem = (0xFFFFFFFF)&DFS_MAX_B5_MASK;
}
}
/*
* Clear only a single delay line
*/
void dfs_reset_delayline(struct dfs_delayline *dl)
{
OS_MEMZERO(&(dl->dl_elems[0]), sizeof(dl->dl_elems));
dl->dl_lastelem = (0xFFFFFFFF)&DFS_MAX_DL_MASK;
}
void dfs_reset_filter_delaylines(struct dfs_filtertype *dft)
{
int i;
struct dfs_filter *df;
for (i=0; i< DFS_MAX_NUM_RADAR_FILTERS; i++) {
df = &dft->ft_filters[i];
dfs_reset_delayline(&(df->rf_dl));
}
}
void
dfs_reset_radarq(struct ath_dfs_host *dfs)
{
struct dfs_event *event;
if (dfs == NULL) {
A_PRINTF("%s: sc_dfs is NULL\n", __func__);
return;
}
ATH_DFSQ_LOCK(dfs);
ATH_DFSEVENTQ_LOCK(dfs);
while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) {
event = STAILQ_FIRST(&(dfs->dfs_radarq));
STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
OS_MEMZERO(event, sizeof(struct dfs_event));
STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
}
ATH_DFSEVENTQ_UNLOCK(dfs);
ATH_DFSQ_UNLOCK(dfs);
}
struct dfs_pulse *dfs_get_radars(u_int32_t dfsdomain, u_int32_t *numradars, struct dfs_bin5pulse **bin5pulses, u_int32_t *numb5radars)
{
#define N(a) (sizeof(a)/sizeof(a[0]))
struct dfs_pulse *dfs_radars = NULL;
switch (dfsdomain) {
case DFS_FCC_DOMAIN:
dfs_radars = &ar6000_fcc_radars[3];
*numradars= N(ar6000_fcc_radars)-3;
*bin5pulses = &ar6000_bin5pulses[0];
*numb5radars = N(ar6000_bin5pulses);
break;
case DFS_ETSI_DOMAIN:
dfs_radars = &ar6000_etsi_radars[0];
*numradars = N(ar6000_etsi_radars);
*bin5pulses = &ar6000_bin5pulses[0];
*numb5radars = N(ar6000_bin5pulses);
break;
case DFS_MKK4_DOMAIN:
dfs_radars = &ar6000_fcc_radars[0];
*numradars = N(ar6000_fcc_radars);
*bin5pulses = &ar6000_bin5pulses[0];
*numb5radars = N(ar6000_bin5pulses);
break;
default:
return NULL;
}
return dfs_radars;
#undef N
}
int dfs_init_radar_filters_host( struct ath_dfs_host *dfs, struct ath_dfs_info *dfs_info)
{
u_int32_t T, Tmax;
int numpulses,p,n, i;
struct dfs_filtertype *ft = NULL;
struct dfs_filter *rf=NULL;
struct dfs_pulse *dfs_radars;
struct dfs_bin5pulse *b5pulses;
int32_t min_rssithresh=DFS_MAX_RSSI_VALUE;
u_int32_t max_pulsedur=0;
u_int32_t numb5radars;
u_int32_t numradars;
dfs_radars = dfs_get_radars(dfs_info->dfs_domain, &numradars, &b5pulses, &numb5radars);
/* If DFS not enabled return immediately.*/
if (!dfs_radars) {
return 0;
}
dfs->dfs_rinfo.rn_numradars = 0;
/* Clear filter type table */
for (n=0; n<256; n++) {
for (i=0;i<DFS_MAX_RADAR_OVERLAP; i++)
(dfs->dfs_radartable[n])[i] = -1;
}
/* Now, initialize the radar filters */
for (p=0; p < numradars; p++) {
ft = NULL;
for (n=0; n<dfs->dfs_rinfo.rn_numradars; n++) {
if ((dfs_radars[p].rp_pulsedur == dfs->dfs_radarf[n]->ft_filterdur) &&
(dfs_radars[p].rp_numpulses == dfs->dfs_radarf[n]->ft_numpulses) &&
(dfs_radars[p].rp_mindur == dfs->dfs_radarf[n]->ft_mindur) &&
(dfs_radars[p].rp_maxdur == dfs->dfs_radarf[n]->ft_maxdur)) {
ft = dfs->dfs_radarf[n];
break;
}
}
if (ft == NULL) {
/* No filter of the appropriate dur was found */
if ((dfs->dfs_rinfo.rn_numradars+1) >DFS_MAX_RADAR_TYPES) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Too many filter types\n",
__func__);
goto bad4;
}
ft = dfs->dfs_radarf[dfs->dfs_rinfo.rn_numradars];
ft->ft_numfilters = 0;
ft->ft_numpulses = dfs_radars[p].rp_numpulses;
ft->ft_patterntype = dfs_radars[p].rp_patterntype;
ft->ft_mindur = dfs_radars[p].rp_mindur;
ft->ft_maxdur = dfs_radars[p].rp_maxdur;
ft->ft_filterdur = dfs_radars[p].rp_pulsedur;
ft->ft_rssithresh = dfs_radars[p].rp_rssithresh;
ft->ft_rssimargin = dfs_radars[p].rp_rssimargin;
ft->ft_minpri = 1000000;
if (ft->ft_rssithresh < min_rssithresh)
min_rssithresh = ft->ft_rssithresh;
if (ft->ft_maxdur > max_pulsedur)
max_pulsedur = ft->ft_maxdur;
for (i=ft->ft_mindur; i<=ft->ft_maxdur; i++) {
u_int32_t stop=0,tableindex=0;
while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) {
if ((dfs->dfs_radartable[i])[tableindex] == -1)
stop = 1;
else
tableindex++;
}
if (stop) {
(dfs->dfs_radartable[i])[tableindex] =
(int8_t) (dfs->dfs_rinfo.rn_numradars);
} else {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"%s: Too many overlapping radar filters\n",
__func__);
goto bad4;
}
}
dfs->dfs_rinfo.rn_numradars++;
}
rf = &(ft->ft_filters[ft->ft_numfilters++]);
dfs_reset_delayline(&rf->rf_dl);
numpulses = dfs_radars[p].rp_numpulses;
rf->rf_numpulses = numpulses;
rf->rf_patterntype = dfs_radars[p].rp_patterntype;
rf->rf_pulseid = dfs_radars[p].rp_pulseid;
rf->rf_mindur = dfs_radars[p].rp_mindur;
rf->rf_maxdur = dfs_radars[p].rp_maxdur;
rf->rf_numpulses = dfs_radars[p].rp_numpulses;
T = (100000000/dfs_radars[p].rp_max_pulsefreq) -
100*(dfs_radars[p].rp_meanoffset);
rf->rf_minpri =
dfs_round((int32_t)T - (100*(dfs_radars[p].rp_pulsevar)));
Tmax = (100000000/dfs_radars[p].rp_pulsefreq) -
100*(dfs_radars[p].rp_meanoffset);
rf->rf_maxpri =
dfs_round((int32_t)Tmax + (100*(dfs_radars[p].rp_pulsevar)));
if( rf->rf_minpri < ft->ft_minpri )
ft->ft_minpri = rf->rf_minpri;
rf->rf_threshold = dfs_radars[p].rp_threshold;
rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "minprf = %d maxprf = %d pulsevar = %d thresh=%d\n",
dfs_radars[p].rp_pulsefreq, dfs_radars[p].rp_max_pulsefreq, dfs_radars[p].rp_pulsevar, rf->rf_threshold);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"minpri = %d maxpri = %d filterlen = %d filterID = %d\n",
rf->rf_minpri, rf->rf_maxpri, rf->rf_filterlen, rf->rf_pulseid);
}
#ifdef DFS_DEBUG
dfs_print_filters(dfs);
#endif
dfs->dfs_rinfo.rn_numbin5radars = numb5radars;
if ( dfs->dfs_b5radars == NULL ) {
dfs->dfs_b5radars = (struct dfs_bin5radars *)DFS_MALLOC(dfs->os_hdl, numb5radars * sizeof(struct dfs_bin5radars));
if (dfs->dfs_b5radars == NULL) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"%s: cannot allocate memory for bin5 radars\n",
__func__);
goto bad4;
}
}
for (n=0; n<numb5radars; n++) {
dfs->dfs_b5radars[n].br_pulse = b5pulses[n];
dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000;
if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < min_rssithresh)
min_rssithresh = dfs->dfs_b5radars[n].br_pulse.b5_rssithresh;
if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur )
max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur;
}
dfs_reset_alldelaylines(dfs);
dfs_reset_radarq(dfs);
DFS_SET_MINRSSITHRESH(dfs->dev_hdl, min_rssithresh);
DFS_SET_MAXPULSEDUR(dfs->dev_hdl, dfs_round((int32_t)((max_pulsedur*100/80)*100)));
return 0;
bad4:
for (n=0; n<ft->ft_numfilters; n++) {
rf = &(ft->ft_filters[n]);
}
return 1;
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
int adjust_pri_per_chan_busy(int ext_chan_busy, int pri_margin)
{
int adjust_pri=0;
if(ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) {
adjust_pri = (ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) * (pri_margin);
adjust_pri /= 100;
}
return adjust_pri;
}
int adjust_thresh_per_chan_busy(int ext_chan_busy, int thresh)
{
int adjust_thresh=0;
if(ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) {
adjust_thresh = (ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) * thresh;
adjust_thresh /= 100;
}
return adjust_thresh;
}
/* For the extension channel, if legacy traffic is present, we see a lot of false alarms,
so make the PRI margin narrower depending on the busy % for the extension channel.*/
int dfs_get_pri_margin(int is_extchan_detect, int is_fixed_pattern, u_int64_t lastfull_ts, u_int32_t ext_chan_busy)
{
int adjust_pri=0;
int pri_margin;
// struct ath_dfs_target *dfs = sc->sc_dfs_tgt;
if (is_fixed_pattern)
pri_margin = DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN;
else
pri_margin = DFS_DEFAULT_PRI_MARGIN;
/*XXX: Does cached value make sense here? */
#if 0
if(ext_chan_busy) {
dfs->dfs_rinfo.ext_chan_busy_ts = ath_hal_gettsf64(sc->sc_ah);
dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy;
} else {
// Check to see if the cached value of ext_chan_busy can be used
if (dfs->dfs_rinfo.dfs_ext_chan_busy) {
if (lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) {
ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2," PRI Use cached copy of ext_chan_busy extchanbusy=%d \n", ext_chan_busy);
}
}
}
#endif
adjust_pri = adjust_pri_per_chan_busy(ext_chan_busy, pri_margin);
pri_margin -= adjust_pri;
return pri_margin;
}
/* For the extension channel, if legacy traffic is present, we see a lot of false alarms,
so make the thresholds higher depending on the busy % for the extension channel.*/
int dfs_get_filter_threshold(struct dfs_filter *rf, int is_extchan_detect, u_int64_t lastfull_ts, u_int32_t ext_chan_busy)
{
int thresh, adjust_thresh=0;
// struct ath_dfs_target *dfs = sc->sc_dfs_tgt;
thresh = rf->rf_threshold;
/*XXX: Does cached value make sense here? */
#if 0
if(ext_chan_busy) {
dfs->dfs_rinfo.ext_chan_busy_ts = ath_hal_gettsf64(sc->sc_ah);
dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy;
} else {
// Check to see if the cached value of ext_chan_busy can be used
if (dfs->dfs_rinfo.dfs_ext_chan_busy) {
if (lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) {
ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2," THRESH Use cached copy of ext_chan_busy extchanbusy=%d lastfull_ts=%llu ext_chan_busy_ts=%llu\n", ext_chan_busy ,lastfull_ts, dfs->dfs_rinfo.ext_chan_busy_ts);
}
}
}
#endif
adjust_thresh = adjust_thresh_per_chan_busy(ext_chan_busy, thresh);
//DFS_DPRINTK(dfs, ATH_DEBUG_DFS2," filterID=%d extchanbusy=%d adjust_thresh=%d\n", rf->rf_pulseid, ext_chan_busy, adjust_thresh);
thresh += adjust_thresh;
return thresh;
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
void
dfs_queue_phyerr(struct ath_dfs_host *dfs, struct dfs_event_info *ev_info);
void
dfs_process_phyerr_host(struct ath_dfs_host *dfs, WMI_DFS_PHYERR_EVENT *ev)
{
int i;
for(i=0; i<ev->num_events; i++)
dfs_queue_phyerr(dfs, &ev->ev_info[i]);
}
void
dfs_queue_phyerr(struct ath_dfs_host *dfs, struct dfs_event_info *ev_info)
{
struct dfs_event *event;
int empty;
ATH_DFSEVENTQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_eventq));
ATH_DFSEVENTQ_UNLOCK(dfs);
if (empty) {
return;
}
/* XXX: Lot of common code. Optimize */
if((ev_info->flags & EVENT_TYPE_MASK) == AR_EVENT){
ATH_DFSEVENTQ_LOCK(dfs);
event = STAILQ_FIRST(&(dfs->dfs_eventq));
if (event == NULL) {
ATH_DFSEVENTQ_UNLOCK(dfs);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: no more events space left\n",
__func__);
return;
}
STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
ATH_DFSEVENTQ_UNLOCK(dfs);
event->re_rssi = ev_info->rssi;
event->re_dur = ev_info->dur;
event->re_full_ts = ev_info->full_ts;
event->re_ts = ev_info->ts;
event->re_chanindex = ev_info->chanindex;
event->re_chanindextype = ev_info->flags & CH_TYPE_MASK;
ATH_ARQ_LOCK(dfs);
STAILQ_INSERT_TAIL(&(dfs->dfs_arq), event, re_list);
ATH_ARQ_UNLOCK(dfs);
}
else { /* DFS event */
ATH_DFSEVENTQ_LOCK(dfs);
event = STAILQ_FIRST(&(dfs->dfs_eventq));
if (event == NULL) {
ATH_DFSEVENTQ_UNLOCK(dfs);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: no more events space left\n",
__func__);
return;
}
STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list);
ATH_DFSEVENTQ_UNLOCK(dfs);
event->re_rssi = ev_info->rssi;
event->re_dur = ev_info->dur;
event->re_full_ts = ev_info->full_ts;
event->re_ts = ev_info->ts;
event->re_chanindex = ev_info->chanindex;
event->re_chanindextype = ev_info->flags & CH_TYPE_MASK;
event->re_ext_chan_busy = ev_info->ext_chan_busy;
ATH_DFSQ_LOCK(dfs);
STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list);
ATH_DFSQ_UNLOCK(dfs);
}
/* TODO: The radar detected event is sent from host in timer
* context which could potentially cause issues with sleepable
* WMI. Change this to process context later. */
A_TIMEOUT_MS(&dfs->dfs_radar_task_timer, 0, 0);
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,316 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
static char debug_dup[33];
static int debug_dup_cnt;
u_int32_t dfs_round(int32_t val)
{
u_int32_t ival,rem;
if (val < 0)
return 0;
ival = val/100;
rem = val-(ival*100);
if (rem <50)
return ival;
else
return(ival+1);
}
static inline u_int8_t
dfs_process_pulse_dur(struct ath_dfs_host *dfs, u_int8_t re_dur)
{
if (re_dur == 0) {
return 1;
} else {
/* Convert 0.8us durations to TSF ticks (usecs) */
return (u_int8_t)dfs_round((int32_t)((dfs->dur_multiplier)*re_dur));
}
}
int
dfs_process_radarevent_host(struct ath_dfs_host *dfs, int16_t *chan_index, u_int8_t *bangradar)
{
struct dfs_event re,*event;
struct dfs_filtertype *ft;
struct dfs_filter *rf;
int found, retval=0,p, empty;
int events_processed=0;
u_int32_t tabledepth, index;
u_int64_t deltafull_ts = 0,this_ts, deltaT;
struct dfs_pulseline *pl;
static u_int32_t test_ts = 0;
static u_int32_t diff_ts = 0;
int ext_chan_event_flag=0;
if (dfs == NULL) {
A_PRINTF("%s: sc_sfs is NULL\n", __func__);
return 0;
}
pl = dfs->pulses;
/* TEST : Simulate radar bang, make sure we add the channel to NOL (bug 29968) */
if (dfs->dfs_bangradar) {
/* bangradar will always simulate radar found on the primary channel */
*bangradar = 1;
dfs->dfs_bangradar = 0; /* reset */
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: bangradar\n", __func__);
retval = 1;
}
else
*bangradar = 0;
ATH_DFSQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
ATH_DFSQ_UNLOCK(dfs);
while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) {
ATH_DFSQ_LOCK(dfs);
event = STAILQ_FIRST(&(dfs->dfs_radarq));
if (event != NULL)
STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
ATH_DFSQ_UNLOCK(dfs);
if (event == NULL) {
empty = 1;
break;
}
events_processed++;
re = *event;
OS_MEMZERO(event, sizeof(struct dfs_event));
ATH_DFSEVENTQ_LOCK(dfs);
STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
ATH_DFSEVENTQ_UNLOCK(dfs);
found = 0;
if (re.re_chanindex < DFS_NUM_RADAR_STATES)
*chan_index = re.re_chanindex;
else {
ATH_DFSQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
ATH_DFSQ_UNLOCK(dfs);
continue;
}
if (dfs->dfs_rinfo.rn_lastfull_ts == 0) {
/*
* Either not started, or 64-bit rollover exactly to zero
* Just prepend zeros to the 15-bit ts
*/
dfs->dfs_rinfo.rn_ts_prefix = 0;
this_ts = (u_int64_t) re.re_ts;
} else {
/* WAR 23031- patch duplicate ts on very short pulses */
/* This pacth has two problems in linux environment.
* 1)The time stamp created and hence PRI depends entirely on the latency.
* If the latency is high, it possibly can split two consecutive
* pulses in the same burst so far away (the same amount of latency)
* that make them look like they are from differenct bursts. It is
* observed to happen too often. It sure makes the detection fail.
* 2)Even if the latency is not that bad, it simply shifts the duplicate
* timestamps to a new duplicate timestamp based on how they are processed.
* This is not worse but not good either.
*
* Take this pulse as a good one and create a probable PRI later
*/
if (re.re_dur == 0 && re.re_ts == dfs->dfs_rinfo.rn_last_unique_ts) {
debug_dup[debug_dup_cnt++] = '1';
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "\n %s deltaT is 0 \n", __func__);
} else {
dfs->dfs_rinfo.rn_last_unique_ts = re.re_ts;
debug_dup[debug_dup_cnt++] = '0';
}
if (debug_dup_cnt >= 32){
debug_dup_cnt = 0;
}
if (re.re_ts <= dfs->dfs_rinfo.rn_last_ts) {
dfs->dfs_rinfo.rn_ts_prefix +=
(((u_int64_t) 1) << DFS_TSSHIFT);
/* Now, see if it's been more than 1 wrap */
deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts;
if (deltafull_ts >
((u_int64_t)((DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts)))
deltafull_ts -= (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts;
deltafull_ts = deltafull_ts >> DFS_TSSHIFT;
if (deltafull_ts > 1) {
dfs->dfs_rinfo.rn_ts_prefix +=
((deltafull_ts - 1) << DFS_TSSHIFT);
}
} else {
deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts;
if (deltafull_ts > (u_int64_t) DFS_TSMASK) {
deltafull_ts = deltafull_ts >> DFS_TSSHIFT;
dfs->dfs_rinfo.rn_ts_prefix +=
((deltafull_ts - 1) << DFS_TSSHIFT);
}
}
this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((u_int64_t) re.re_ts);
}
dfs->dfs_rinfo.rn_lastfull_ts = re.re_full_ts;
dfs->dfs_rinfo.rn_last_ts = re.re_ts;
re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur);
if (re.re_dur != 1) {
this_ts -= re.re_dur;
}
/* Save the pulse parameters in the pulse buffer(pulse line) */
index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK;
if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE)
pl->pl_firstelem = (pl->pl_firstelem+1) & DFS_MAX_PULSE_BUFFER_MASK;
else
pl->pl_numelems++;
pl->pl_lastelem = index;
pl->pl_elems[index].p_time = this_ts;
pl->pl_elems[index].p_dur = re.re_dur;
pl->pl_elems[index].p_rssi = re.re_rssi;
diff_ts = (u_int32_t)this_ts - test_ts;
test_ts = (u_int32_t)this_ts;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,"ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu\n",(u_int32_t)this_ts, re.re_dur, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time);
found = 0;
for (p=0; (p<dfs->dfs_rinfo.rn_numbin5radars)&&(!found); p++) {
struct dfs_bin5radars *br;
u_int32_t b5_rssithresh;
br = &(dfs->dfs_b5radars[p]);
b5_rssithresh = br->br_pulse.b5_rssithresh;
/* Adjust the filter threshold for rssi in non TURBO mode*/
//XXX: If turbo mode, ar events would be used?
//if( ! (sc->sc_curchan.channelFlags & CHANNEL_TURBO) ) {
b5_rssithresh += br->br_pulse.b5_rssimargin;
//}
if ((re.re_dur >= br->br_pulse.b5_mindur) &&
(re.re_dur <= br->br_pulse.b5_maxdur) &&
(re.re_rssi >= b5_rssithresh)) {
// This is a valid Bin5 pulse, check if it belongs to a burst
re.re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts, re.re_dur);
// Remember our computed duration for the next pulse in the burst (if needed)
dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts;
dfs->dfs_rinfo.dfs_last_bin5_dur = re.re_dur;
if( dfs_bin5_addpulse(dfs, br, &re, this_ts) ) {
found |= dfs_bin5_check(dfs);
}
} else
DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, "%s too low to be Bin5 pulse (%d)\n", __func__, re.re_dur);
}
if (found) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Found bin5 radar\n", __func__);
retval |= found;
goto dfsfound;
}
tabledepth = 0;
rf = NULL;
while ((tabledepth < DFS_MAX_RADAR_OVERLAP) &&
((dfs->dfs_radartable[re.re_dur])[tabledepth] != -1) &&
(!retval)) {
ft = dfs->dfs_radarf[((dfs->dfs_radartable[re.re_dur])[tabledepth])];
if (re.re_rssi < ft->ft_rssithresh && re.re_dur > 4) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,"%s : Rejecting on rssi rssi=%u thresh=%u\n", __func__, re.re_rssi, ft->ft_rssithresh);
tabledepth++;
ATH_DFSQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
ATH_DFSQ_UNLOCK(dfs);
continue;
}
deltaT = this_ts - ft->ft_last_ts;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,"deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)\n",(unsigned long long)deltaT, (unsigned long long)this_ts, (unsigned long long)ft->ft_last_ts);
if ((deltaT < ft->ft_minpri) && (deltaT !=0)){
/* This check is for the whole filter type. Individual filters
will check this again. This is first line of filtering.*/
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: Rejecting on pri pri=%lld minpri=%u\n", __func__, (unsigned long long)deltaT, ft->ft_minpri);
tabledepth++;
continue;
}
for (p=0, found = 0; (p<ft->ft_numfilters) && (!found); p++) {
rf = &(ft->ft_filters[p]);
if ((re.re_dur >= rf->rf_mindur) && (re.re_dur <= rf->rf_maxdur)) {
/* The above check is probably not necessary */
deltaT = this_ts - rf->rf_dl.dl_last_ts;
if (deltaT < 0)
deltaT = (int64_t) ((DFS_TSF_WRAP - rf->rf_dl.dl_last_ts) + this_ts +1);
if ((deltaT < rf->rf_minpri) && (deltaT != 0)) {
/* Second line of PRI filtering. */
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"filterID %d : Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u\n",
rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri);
continue;
}
if ((rf->rf_patterntype==2) && (deltaT > rf->rf_maxpri) ) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"filterID %d : Staggered - Rejecting on individual filter max PRI deltaT=%lld rf->rf_maxpri=%u\n",
rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_maxpri);
/* But update the last time stamp */
rf->rf_dl.dl_last_ts = this_ts;
continue;
}
if ((rf->rf_patterntype!= 2) && (deltaT > rf->rf_maxpri) && (deltaT < (2*rf->rf_minpri))) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
"filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n",
rf->rf_pulseid, (unsigned long long)deltaT, rf->rf_minpri);
/* But update the last time stamp */
rf->rf_dl.dl_last_ts = this_ts;
continue;
}
dfs_add_pulse(dfs, rf, &re, deltaT);
/* If this is an extension channel event, flag it for false alarm reduction */
if (re.re_chanindextype == EXT_CH)
ext_chan_event_flag = 1;
if (rf->rf_patterntype == 2)
found = dfs_staggered_check(dfs, rf, (u_int32_t) deltaT, re.re_dur, re.re_ext_chan_busy);
else
found = dfs_bin_check(dfs, rf, (u_int32_t) deltaT, re.re_dur, ext_chan_event_flag, re.re_ext_chan_busy);
dfs_print_delayline(dfs, &rf->rf_dl);
rf->rf_dl.dl_last_ts = this_ts;
}
}
ft->ft_last_ts = this_ts;
retval |= found;
if (found) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
"Found on channel minDur = %d, filterId = %d\n",ft->ft_mindur,
rf != NULL ? rf->rf_pulseid : -1);
}
tabledepth++;
}
ATH_DFSQ_LOCK(dfs);
empty = STAILQ_EMPTY(&(dfs->dfs_radarq));
ATH_DFSQ_UNLOCK(dfs);
}
dfsfound:
return retval;
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2002-2010, Atheros Communications Inc.
*
* 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.
*/
#ifdef ATH_SUPPORT_DFS
#include "dfs_host.h"
int is_pri_multiple(u_int32_t sample_pri, u_int32_t refpri)
{
#define MAX_ALLOWED_MISSED 3
int i;
if (sample_pri < refpri || (!refpri))
return 0;
for (i=1; i<= MAX_ALLOWED_MISSED; i++) {
if((sample_pri%(i*refpri) <= 5)) {
//printk("sample_pri=%d is a multiple of refpri=%d\n", sample_pri, refpri);
return 1;
}
}
return 0;
#undef MAX_ALLOWED_MISSED
}
int is_unique_pri(u_int32_t highestpri , u_int32_t midpri,
u_int32_t lowestpri , u_int32_t refpri )
{
#define DFS_STAGGERED_PRI_MARGIN_MIN 20
#define DFS_STAGGERED_PRI_MARGIN_MAX 400
if ((DFS_DIFF(lowestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
(DFS_DIFF(midpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
(DFS_DIFF(highestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN)) {
return 1;
} else {
if ((is_pri_multiple(refpri, highestpri)) || (is_pri_multiple(refpri, lowestpri)) ||
(is_pri_multiple(refpri, midpri)))
return 0;
}
return 0;
#undef DFS_STAGGERED_PRI_MARGIN_MIN
#undef DFS_STAGGERED_PRI_MARGIN_MAX
}
int dfs_staggered_check(struct ath_dfs_host *dfs, struct dfs_filter *rf,
u_int32_t deltaT, u_int32_t width, u_int32_t ext_chan_busy)
{
u_int32_t refpri, refdur, searchpri=0, deltapri;//, averagerefpri;
u_int32_t n, i, primargin, durmargin;
int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0;
struct dfs_delayline *dl;
u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff;
int numpulses=0, higherthan, lowerthan, numscores;
u_int32_t lowestscore=0, lowestscoreindex=0, lowestpri=0;
u_int32_t midscore=0, midscoreindex=0, midpri=0;
u_int32_t highestscore=0, highestscoreindex=0, highestpri=0;
dl = &rf->rf_dl;
if( dl->dl_numelems < (rf->rf_threshold-1)) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "numelems %d < threshold for filter %d\n", dl->dl_numelems, rf->rf_pulseid);
return 0;
}
if( deltaT > rf->rf_filterlen) {
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "numelems %d < threshold for filter %d\n", dl->dl_numelems, rf->rf_pulseid);
return 0;
}
primargin = 10;
if(rf->rf_maxdur < 10) {
durmargin = 4;
}
else {
durmargin = 6;
}
OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE);
/* find out the lowest pri */
for (n=0;n<dl->dl_numelems; n++) {
delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
refpri = dl->dl_elems[delayindex].de_time;
if( refpri == 0)
continue;
else if(refpri < lowpri) {
lowpri = dl->dl_elems[delayindex].de_time;
lowpriindex = n;
}
}
/* find out the each delay element's pri score */
for (n=0;n<dl->dl_numelems; n++) {
delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
refpri = dl->dl_elems[delayindex].de_time;
if( refpri == 0)
continue;
for (i=0;i<dl->dl_numelems; i++) {
dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
searchpri = dl->dl_elems[dindex].de_time;
deltapri = DFS_DIFF(searchpri, refpri);
if( deltapri < primargin)
score[n]++;
}
if( score[n] > rf->rf_threshold) {
/* we got the most possible candidate,
* no need to continue further */
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "THRESH score[%d]=%d pri=%d\n", n, score[n], searchpri);
break;
}
}
for (n=0;n<dl->dl_numelems; n++) {
delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
refdur = dl->dl_elems[delayindex].de_time;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "score[%d]=%d pri=%d\n", n, score[n], refdur);
}
/* find out the 2 or 3 highest scorers */
scoreindex = 0;
highestscore=0;
highestscoreindex=0;
highestpri=0; numscores=0; lowestscore=0;
for (n=0;n<dl->dl_numelems; n++) {
higherthan=0;
lowerthan=0;
delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
refpri = dl->dl_elems[delayindex].de_time;
if ((score[n] >= highestscore) &&
(is_unique_pri(highestpri, midpri, lowestpri, refpri))) {
lowestscore = midscore;
lowestpri = midpri;
lowestscoreindex = midscoreindex;
midscore = highestscore;
midpri = highestpri;
midscoreindex = highestscoreindex;
highestscore = score[n];
highestpri = refpri;
highestscoreindex = n;
} else {
if ((score[n] >= midscore) &&
(is_unique_pri(highestpri, midpri, lowestpri, refpri))) {
lowestscore = midscore;
lowestpri = midpri;
lowestscoreindex = midscoreindex;
midscore = score[n];
midpri = refpri;
midscoreindex = n;
} else if ((score[n] >= lowestscore) &&
(is_unique_pri(highestpri, midpri, lowestpri, refpri))) {
lowestscore = score[n];
lowestpri = refpri;
lowestscoreindex = n;
}
}
}
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "FINAL highestscore=%d highestscoreindex=%d highestpri=%d\n", highestscore, highestscoreindex, highestpri);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "FINAL lowestscore=%d lowestscoreindex=%d lowpri=%d\n", lowestscore, lowestscoreindex, lowestpri);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "FINAL midscore=%d midscoreindex=%d midpri=%d\n", midscore, midscoreindex, midpri);
delayindex = (dl->dl_firstelem + highestscoreindex) & DFS_MAX_DL_MASK;
refdur = dl->dl_elems[delayindex].de_dur;
refpri = dl->dl_elems[delayindex].de_time;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "highscoreindex=%d refdur=%d refpri=%d\n", highestscoreindex, refdur, refpri);
numpulses += dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur, 0, ext_chan_busy);
; delayindex = (dl->dl_firstelem + midscoreindex) & DFS_MAX_DL_MASK;
refdur = dl->dl_elems[delayindex].de_dur;
refpri = dl->dl_elems[delayindex].de_time;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "midscoreindex=%d refdur=%d refpri=%d\n", midscoreindex, refdur, refpri);
numpulses += dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur, 0, ext_chan_busy);
;
delayindex = (dl->dl_firstelem + lowestscoreindex) & DFS_MAX_DL_MASK;
refdur = dl->dl_elems[delayindex].de_dur;
refpri = dl->dl_elems[delayindex].de_time;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "lowestscoreindex=%d refdur=%d refpri=%d\n", lowestscoreindex, refdur, refpri);
numpulses += dfs_bin_pri_check(dfs, rf, dl, lowestscore, refpri, refdur, 0, ext_chan_busy);
DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "numpulses=%d\n",numpulses);
if (numpulses >= rf->rf_threshold) {
found = 1;
DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "MATCH filter=%u numpulses=%u thresh=%u\n", rf->rf_pulseid, numpulses,rf->rf_threshold);
}
return found;
}
#endif /* ATH_SUPPORT_DFS */

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2005-2006 Atheros Communications, Inc.
*
* 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 _DFS_TARGET_API_H_
#define _DFS_TARGET_API_H_
#ifdef ATH_SUPPORT_DFS
#include "ar6000_api.h"
#define DFS_SET_MINRSSITHRESH(dev_hdl, value) ar6000_dfs_set_minrssithresh_cmd((dev_hdl),(value))
#define DFS_SET_MAXPULSEDUR(dev_hdl, value) ar6000_dfs_set_maxpulsedur_cmd((dev_hdl),(value))
#define DFS_RADAR_DETECTED(dev_hdl, ch_idx, bangradar) ar6000_dfs_radar_detected_cmd((dev_hdl),(ch_idx),(bangradar))
#endif /* ATH_SUPPORT_DFS */
#endif /* _DFS_TARGET_API_ */

View File

@ -0,0 +1,26 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-2007 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 $(_MAKEENVROOT)\makefile.def

View File

@ -0,0 +1,379 @@
//------------------------------------------------------------------------------
// <copyright file="hif_bmi_diag_access.c" company="Atheros">
// Copyright (c) 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 BMI access handling for register-based HIFs
// This module implements BMI message exchanges on behalf of the BMI module for
// HIFs that are based on a register access model
//
// Author(s): ="Atheros"
//==============================================================================
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#define ATH_MODULE_NAME bmi
#include "a_debug.h"
#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
#include "hif.h"
#include "bmi.h"
#include "htc_api.h"
#include "target_reg_table.h"
#include "host_reg_table.h"
#define BMI_COMMUNICATION_TIMEOUT 100000
static A_BOOL pendingEventsFuncCheck = FALSE;
static A_UINT32 commandCredits = 0;
static A_UINT32 *pBMICmdCredits = &commandCredits;
/* BMI Access routines */
static 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;
}
static 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(HIF_PENDING_EVENTS_FUNC));
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 HIFRegBasedGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
{
A_STATUS status;
A_UINT32 cid;
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;
}
} else {
/*
* Target must be an AR6001 whose firmware does not
* support BMI_GET_TARGET_INFO. Construct the data
* that it would have sent.
*/
targ_info->target_info_byte_count=sizeof(*targ_info);
targ_info->target_type=TARGET_TYPE_AR6001;
}
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 HIFExchangeBMIMsg(HIF_DEVICE *device,
A_UINT8 *pSendMessage,
A_UINT32 Length,
A_UINT8 *pResponseMessage,
A_UINT32 *pResponseLength,
A_UINT32 TimeoutMS)
{
A_STATUS status = A_OK;
do {
status = bmiBufferSend(device, pSendMessage, Length);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI : Unable to Send Message to device \n"));
break;
}
if (pResponseMessage != NULL) {
status = bmiBufferReceive(device, pResponseMessage, *pResponseLength, TimeoutMS ? TRUE : FALSE);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI : Unable to read response from device \n"));
break;
}
}
} while (FALSE);
return status;
}
/* TODO .. the following APIs are a relic of the old register based interface */
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);
}

View File

@ -0,0 +1,266 @@
//------------------------------------------------------------------------------
// <copyright file="hif_bmi_diag_access.c" company="Atheros">
// Copyright (c) 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 Diagnostic access handling for register-based HIFs
// This module implements diagnostic accesses on behalf of the diagnostic window module for
// HIFs that are based on a register access model
//
//
// Author(s): ="Atheros"
//==============================================================================
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#define ATH_MODULE_NAME misc
#include "a_debug.h"
#include "targaddrs.h"
#include "hif.h"
#include "host_reg_table.h"
#define CPU_DBG_SEL_ADDRESS 0x00000483
#define CPU_DBG_ADDRESS 0x00000484
#ifdef USE_4BYTE_REGISTER_ACCESS
/* set the window address register (using 4-byte register access ).
* This mitigates host interconnect issues with non-4byte aligned bus requests, some
* interconnects use bus adapters that impose strict limitations.
* Since diag window access is not intended for performance critical operations, the 4byte mode should
* be satisfactory even though it generates 4X the bus activity. */
static A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
{
A_STATUS status;
static A_UINT8 addrValue[4];
A_INT32 i;
static A_UINT32 address;
address = Address;
/* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
* last to initiate the access cycle */
for (i = 1; i <= 3; i++) {
/* fill the buffer with the address byte value we want to hit 4 times*/
addrValue[0] = ((A_UINT8 *)&Address)[i];
addrValue[1] = addrValue[0];
addrValue[2] = addrValue[0];
addrValue[3] = addrValue[0];
/* hit each byte of the register address with a 4-byte write operation to the same address,
* this is a harmless operation */
status = HIFReadWrite(hifDevice,
RegisterAddr+i,
addrValue,
4,
HIF_WR_SYNC_BYTE_FIX,
NULL);
if (status != A_OK) {
break;
}
}
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
Address, RegisterAddr));
return status;
}
/* write the address register again, this time write the whole 4-byte value.
* The effect here is that the LSB write causes the cycle to start, the extra
* 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
status = HIFReadWrite(hifDevice,
RegisterAddr,
(A_UCHAR *)(&address),
4,
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
Address, RegisterAddr));
return status;
}
return A_OK;
}
#else
/* set the window address register */
A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
{
A_STATUS status;
/* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
* last to initiate the access cycle */
status = HIFReadWrite(hifDevice,
RegisterAddr+1, /* write upper 3 bytes */
((A_UCHAR *)(&Address))+1,
sizeof(A_UINT32)-1,
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
RegisterAddr, Address));
return status;
}
/* write the LSB of the register, this initiates the operation */
status = HIFReadWrite(hifDevice,
RegisterAddr,
(A_UCHAR *)(&Address),
sizeof(A_UINT8),
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
RegisterAddr, Address));
return status;
}
return A_OK;
}
#endif //USE_4BYTE_REGISTER_ACCESS
/*
* Read from the AR6000 through its diagnostic window.
* No cooperation from the Target is required for this.
*/
A_STATUS
HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 *data)
{
A_STATUS status;
static A_UINT32 readvalue;
/* set window register to start read cycle */
status = ar6000_SetAddressWindowRegister(hifDevice,
WINDOW_READ_ADDR_ADDRESS,
address);
if (status != A_OK) {
return status;
}
/* read the data */
status = HIFReadWrite(hifDevice,
WINDOW_DATA_ADDRESS,
(A_UCHAR *)&readvalue,
sizeof(A_UINT32),
HIF_RD_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
return status;
}
*data = readvalue;
return status;
}
/*
* Write to the AR6000 through its diagnostic window.
* No cooperation from the Target is required for this.
*/
A_STATUS HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 data)
{
A_STATUS status;
static A_UINT32 writeValue;
writeValue = data;
/* set write data */
status = HIFReadWrite(hifDevice,
WINDOW_DATA_ADDRESS,
(A_UCHAR *)&writeValue,
sizeof(A_UINT32),
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", data));
return status;
}
/* set window register, which starts the write cycle */
return ar6000_SetAddressWindowRegister(hifDevice,
WINDOW_WRITE_ADDR_ADDRESS,
address);
}
/* TODO .. the following APIs are only available on register-based HIFs where the CPU_DBG_SEL_ADDRESS
* register is available */
A_STATUS
ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
{
A_STATUS status;
A_UCHAR vals[4];
A_UCHAR register_selection[4];
register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff);
status = HIFReadWrite(hifDevice,
CPU_DBG_SEL_ADDRESS,
register_selection,
4,
HIF_WR_SYNC_BYTE_FIX,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel));
return status;
}
status = HIFReadWrite(hifDevice,
CPU_DBG_ADDRESS,
(A_UCHAR *)vals,
sizeof(vals),
HIF_RD_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n"));
return status;
}
*regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24;
return status;
}
void
ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs)
{
int i;
A_UINT32 val;
for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) {
val=0xffffffff;
(void)ar6k_ReadTargetRegister(hifDevice, i, &val);
targregs[i] = val;
}
}

View File

@ -0,0 +1,102 @@
//------------------------------------------------------------------------------
// 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_MCKINLEY_BASE 0x400 /*FIXME use the correct ID,
Right now MCKINLEY masquerades as AR6002*/
#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 */
/**** FIXME .. MCKINLEY currently masquerades as an AR6002 device
* and thus it's actual extended window size will be incorrectly
* set. Temporarily force the location and size to match MCKINLEY ****/
//pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR;
//pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002;
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
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;
case MANUFACTURER_ID_MCKINLEY_BASE :
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; /* TBDXXX */
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
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_*/

View File

@ -0,0 +1,12 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-2007 Atheros Corporation. All rights reserved.
#
#
#
#------------------------------------------------------------------------------
#==============================================================================
# Author(s): ="Atheros"
#==============================================================================
!INCLUDE $(_MAKEENVROOT)\makefile.def

View File

@ -0,0 +1,90 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-2008 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"
#==============================================================================
#
#SDIO HIF makefile for atheros SDIO stack
#
# Check for SDIO stack
ifdef ATH_SDIO_STACK_BASE
# Someone already set it on entry, the stack resides outside this tree, we will try to build it
_SDIO_STACK = YES
else
# Check for SDIO stack within this tree
_SDIO_STACK = $(shell if [ -f $(ATH_SRC_BASE)/sdiostack/src/Makefile ]; then echo "YES"; else echo "NO"; fi)
ifeq ($(_SDIO_STACK), YES)
# SDIO stack is part of the kit and will need to be compiled
ATH_SDIO_STACK_BASE := $(ATH_SRC_BASE)/sdiostack
endif
endif
ifeq ($(ATH_BUS_SUBTYPE),linux_sdio)
_HIF_SUB_TYPE = linux_sdio
_SDIO_STACK = NO
else
_HIF_SUB_TYPE = linux_athsdio
endif
ifeq ($(_SDIO_STACK), YES)
# Pass and translate build variables to the SDIO stack makefile
_SDIO_STACK_MAKE_PARAMS := CT_BUILD_TYPE=$(ATH_BUILD_TYPE) \
CT_OS_TYPE=linux \
CT_OS_SUB_TYPE=$(ATH_OS_SUB_TYPE) \
CT_LINUXPATH=$(ATH_LINUXPATH) \
CT_BUILD_TYPE=$(ATH_BUILD_TYPE) \
CT_CROSS_COMPILE_TYPE=$(ATH_CROSS_COMPILE_TYPE) \
CT_ARCH_CPU_TYPE=$(ATH_ARCH_CPU_TYPE) \
CT_HC_DRIVERS=$(ATH_HC_DRIVERS) \
CT_MAKE_INCLUDE_OVERRIDE=$(_LOCALMAKE_INCLUDE) \
CT_BUILD_OUTPUT_OVERRIDE=$(COMPILED_IMAGE_OBJECTS_PATH) \
BUS_BUILD=1
endif
EXTRA_CFLAGS += -I$(ATH_SRC_BASE)/hif/sdio/$(_HIF_SUB_TYPE)/include
EXTRA_CFLAGS += -DSDIO
EXTRA_CFLAGS += -I$(ATH_SDIO_STACK_BASE)/src/include
ifeq ($(ATH_OS_SUB_TYPE),linux_2_4)
obj-y += ../../hif/sdio/linux_athsdio/src/hif.o
obj-y += ../../hif/sdio/linux_athsdio/src/hif_scatter.o
endif
ifneq ($(ATH_OS_SUB_TYPE),linux_2_4)
ar6000-objs := ../../hif/sdio/$(_HIF_SUB_TYPE)/src/hif.o \
../../hif/sdio/$(_HIF_SUB_TYPE)/src/hif_scatter.o
endif
all:
ifeq ($(_SDIO_STACK),YES)
$(MAKE) $(_SDIO_STACK_MAKE_PARAMS) -C $(ATH_SDIO_STACK_BASE)/src default
-cp -f $(ATH_SDIO_STACK_BASE)/src/Module.symvers $(COMPILED_IMAGE_OBJECTS_PATH)
endif
clean:
ifeq ($(_SDIO_STACK),YES)
$(MAKE) $(_SDIO_STACK_MAKE_PARAMS) -C $(ATH_SDIO_STACK_BASE)/src clean
endif

View File

@ -0,0 +1,137 @@
//------------------------------------------------------------------------------
// <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"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#include <linux/scatterlist.h>
//#define HIF_LINUX_MMC_SCATTER_SUPPORT
#endif
#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;
struct mmc_host *host;
};
#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_

File diff suppressed because it is too large Load Diff

View File

@ -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_INFO,("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_INFO,("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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,399 @@
//------------------------------------------------------------------------------
// <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
/* 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);
A_STATUS DevCleanupMsgBundling(AR6K_DEVICE *pDev);
#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_*/

View File

@ -0,0 +1,767 @@
//------------------------------------------------------------------------------
// <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 "a_osapi.h"
#include "../htc_debug.h"
#include "hif.h"
#include "htc_packet.h"
#include "ar6k.h"
#include "target_reg_table.h"
#include "host_reg_table.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;
/* 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;
/* 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);
*
*/
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;
}
if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
DevDumpRegisters(pDev,
&pDev->IrqProcRegisters,
&pDev->IrqEnableRegisters);
}
/* 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;
}
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);
}

View File

@ -0,0 +1,757 @@
//------------------------------------------------------------------------------
// <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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-2007 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 $(_MAKEENVROOT)\makefile.def

View File

@ -0,0 +1,578 @@
//------------------------------------------------------------------------------
// <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 DEBUG
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_INFO, (" 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));
target->SendBundlingEnabled = TRUE;
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;
}
}
status = DevSetupGMbox(&target->Device);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" GMbox set up Failed!!\n"));
break;
}
/* 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);
if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
DumpCreditDistStates(target);
}
/* 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);
/* flush all send packets */
HTCFlushSendPkts(target);
/* flush all recv buffers */
HTCFlushRecvBuffers(target);
DevCleanupMsgBundling(&target->Device);
DevCleanupGMbox(&target->Device);
ResetEndpointStates(target);
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
}
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);
}
/* 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);
if (!(Endpoint < ENDPOINT_MAX)) {
return FALSE; /* in case panic_on_assert==0 */
}
/* 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;
}

View File

@ -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_*/

View File

@ -0,0 +1,217 @@
//------------------------------------------------------------------------------
// <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);
void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist);
void DumpCreditDistStates(HTC_TARGET *target);
void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
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_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,449 @@
//------------------------------------------------------------------------------
// <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));
/* dump header and message */
DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH,
pPacket->ActualLength + HTC_HDR_LENGTH,
"Unexpected ENDPOINT 0 Message");
}
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 = NULL;
HTC_ENDPOINT_CREDIT_DIST *pLastEntry = NULL;
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);
}
}

View File

@ -0,0 +1,57 @@
//------------------------------------------------------------------------------
// <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 ATHR_WM_NWF
#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 ATHR_WIN_NWF
#include "../os/windows/include/config.h"
#pragma warning( disable:4242)
#pragma warning( disable:4100)
#pragma warning( disable:4189)
#pragma warning( disable:4244)
#pragma warning( disable:4701)
#pragma warning( disable:4389)
#pragma warning( disable:4057)
#pragma warning( disable:28193)
#endif
#endif

View File

@ -0,0 +1,219 @@
//------------------------------------------------------------------------------
// <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 DEBUG
/* 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 /* !DEBUG */
/* NON DEBUG */
#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 ATHR_WM_NWF
#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 ATHR_WIN_NWF
#include "../os/windows/include/win/debug_win.h"
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
// <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 ATHR_WM_NWF
#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 ATHR_WIN_NWF
#include "../os/windows/include/athdrv.h"
#endif
#endif /* _ADRV_H_ */

View File

@ -0,0 +1,333 @@
//------------------------------------------------------------------------------
// <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, pEvt) \
ar6000_connect_event((devt), (pEvt))
#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
#ifdef P2P
#define A_WMI_P2PGONEG_EVENT(devt, res, len)\
p2p_go_neg_event((devt),(res), (len))
#define A_WMI_P2PGONEG_REQ_EVENT(devt, sa, dev_passwd_id)\
p2p_go_neg_req_event((devt), (sa), (dev_passwd_id))
#define A_WMI_P2P_INVITE_SENT_RESULT_EVENT(devt, res, len)\
p2p_invite_sent_result_event((devt), (res), (len))
#define A_WMI_P2P_INVITE_RCVD_RESULT_EVENT(devt, res, len)\
p2p_invite_rcvd_result_event((devt), (res), (len))
#define A_WMI_P2PDEV_EVENT(devt, addr, dev_addr, \
pri_dev_type, dev_name, dev_name_len, config_methods,\
dev_capab, grp_capab)\
ar6000_p2pdev_event((devt), (addr), (dev_addr),\
(pri_dev_type), (dev_name), (dev_name_len), (config_methods),\
(dev_capab), (grp_capab))
#define A_WMI_P2P_PROV_DISC_REQ_EVENT(devt, peer, config_methods, dev_addr, \
pri_dev_type, dev_name, dev_name_len, supp_config_methods,\
dev_capab, group_capab) \
ar6000_p2p_prov_disc_req_event((devt), (peer), (config_methods), \
(dev_addr), (pri_dev_type), (dev_name), (dev_name_len),\
(supp_config_methods), (dev_capab), (group_capab))
#define A_WMI_P2P_PROV_DISC_RESP_EVENT(devt, peer, config_methods) \
ar6000_p2p_prov_disc_resp_event((devt), (peer), (config_methods))
#define A_WMI_GET_P2P_CTX(devt) \
get_p2p_ctx((devt))
#define A_WMI_GET_WMI_CTX(devt) \
get_wmi_ctx((devt))
#define A_WMI_GET_DEV_NETWORK_SUBTYPE(devt) \
get_network_subtype((devt))
#define A_WMI_P2P_SD_RX_EVENT(devt, ev) \
ar6000_p2p_sd_rx_event((devt), (ev))
#endif /* P2P */
#ifdef CONFIG_WLAN_RFKILL
#define A_WMI_RFKILL_STATE_CHANGE_EVENT(devt,radiostate) \
ar6000_rfkill_state_change_event((devt),(radiostate))
#define A_WMI_RFKILL_GET_MODE_CMD_EVENT(devt,datap,len) \
ar6000_rfkill_get_mode_cmd_event_rx((devt),(datap));
#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))
#ifdef ATH_SUPPORT_DFS
#define A_WMI_DFS_ATTACH_EVENT(devt, capinfo) \
ar6000_dfs_attach_event((devt),(capinfo))
#define A_WMI_DFS_INIT_EVENT(devt, capinfo) \
ar6000_dfs_init_event((devt),(capinfo))
#define A_WMI_DFS_PHYERR_EVENT(devt, info) \
ar6000_dfs_phyerr_event((devt),(info))
#define A_WMI_DFS_RESET_DELAYLINES_EVENT(devt) \
ar6000_dfs_reset_delaylines_event((devt))
#define A_WMI_DFS_RESET_RADARQ_EVENT(devt) \
ar6000_dfs_reset_radarq_event((devt))
#define A_WMI_DFS_RESET_AR_EVENT(devt) \
ar6000_dfs_reset_ar_event((devt))
#define A_WMI_DFS_RESET_ARQ_EVENT(devt) \
ar6000_dfs_reset_arq_event((devt))
#define A_WMI_DFS_SET_DUR_MULTIPLIER_EVENT(devt, value) \
ar6000_dfs_set_dur_multiplier_event((devt), (value))
#define A_WMI_DFS_SET_BANGRADAR_EVENT(devt, value) \
ar6000_dfs_set_bangradar_event((devt), (value))
#define A_WMI_DFS_SET_DEBUGLEVEL_EVENT(devt, value) \
ar6000_dfs_set_debuglevel_event((devt), (value))
#endif /* ATH_SUPPORT_DFS */
#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(devt) \
ar6000_dbglog_init_done(devt);
#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))
#define A_WMI_WACINFO_EVENT(devt, pStats, len) \
ar6000_wacinfo_event((devt), (pStats), (len))
#ifdef CONFIG_HOST_GPIO_SUPPORT
#define A_WMI_GPIO_INTR_RX(devt, intr_mask, input_values) \
ar6000_gpio_intr_rx((devt), (intr_mask), (input_values))
#define A_WMI_GPIO_DATA_RX(devt, reg_id, value) \
ar6000_gpio_data_rx((devt), (reg_id), (value))
#define A_WMI_GPIO_ACK_RX(devt) \
ar6000_gpio_ack_rx((devt))
#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))
#define A_WMI_PROBERESP_RECV_EVENT(devt, datap, len, bssid)\
ar6000_indicate_proberesp((devt), (datap), (len), (bssid))
#define A_WMI_BEACON_RECV_EVENT(devt, datap, len, bssid)\
ar6000_indicate_beacon((devt), (datap), (len), (bssid))
#define A_WMI_ASSOC_REQ_REPORT_EVENT(devt, status, rspType, datap, len)\
ar6000_assoc_req_report_event((devt),(status),(rspType),(datap),(len))
#define A_WMI_GET_DEVICE_ADDR(devt, addr) \
ar6000_get_device_addr((devt), (addr))
/****************************************************************************/
/****************************************************************************/
/** **/
/** 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

View File

@ -0,0 +1,58 @@
//------------------------------------------------------------------------------
// <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 ATHR_WM_NWF
#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 ATHR_WIN_NWF
#include "../os/windows/include/win/osapi_win.h"
#include "../os/windows/include/netbuf.h"
#endif
#endif /* _OSAPI_H_ */

View File

@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
// <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 ATHR_WM_NWF
#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 ATHR_WIN_NWF
#include <athtypes_win.h>
#endif
#endif /* _ATHTYPES_H_ */

View File

@ -0,0 +1,156 @@
/*
*
* 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.
*
* Also 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.
* Returns A_OK if init success, else returns A_ERROR
*/
A_UINT8
aggr_init(ALLOC_NETBUFS netbuf_allocator, RX_CALLBACK fn);
/*
* aggr_init_conn:
* Initialises the data structures, allocates data queues and
* os buffers. Returns the context for a single conn aggr.
* For each supported conn, this API should be called.
*/
void *
aggr_init_conn(void);
/*
* 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.
*/
void
aggr_module_destroy(void);
/*
* * aggr_module_destroy_timers:
* * Disarm the timers.
* */
void
aggr_module_destroy_timers(void *cntxt);
/*
* aggr_module_destroy_conn:
* Frees up all the queues and frames in them. Releases the cntxt to OS.
*/
void
aggr_module_destroy_conn(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, void *dev);
#ifdef __cplusplus
}
#endif
#endif /*__AGGR_RECV_API_H__ */

View File

@ -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_UINT32 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_*/

View File

@ -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 ATHR_WM_NWF
#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 ATHR_WIN_NWF
#include "../os/windows/include/ar6xapi.h"
#endif
#endif /* _AR6000_API_H */

View File

@ -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_*/

View File

@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
// <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;
A_UINT8 wmode;
} station_t;
typedef struct {
station_t sta[AP_MAX_NUM_STA];
} ap_get_sta_t;
#endif /* _AR6KAP_COMMON_H_ */

View File

@ -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
A_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, A_UINT32 flags);
void AthBtFilter_Detach(ATH_BT_FILTER_INSTANCE *pInstance);
#ifdef __cplusplus
}
#endif
#endif /*ATHBTFILTER_H_*/

View File

@ -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 ATHR_WM_NWF
#include "../os/windows/include/athendpack.h"
#endif
#ifdef ATHR_CE_LEGACY
#include "../os/windows/include/athendpack.h"
#endif /* WINCE */
#ifdef ATHR_WIN_NWF
#include <athendpack_win.h>
#endif

View File

@ -0,0 +1,69 @@
//------------------------------------------------------------------------------
// <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 ATHR_WM_NWF
#include "../os/windows/include/athstartpack.h"
#define PREPACK
#endif
#ifdef ATHR_CE_LEGACY
#include "../os/windows/include/athstartpack.h"
#endif /* WINCE */
#ifdef ATHR_WIN_NWF
#ifndef PREPACK
#define PREPACK __declspec(align(1))
#endif
#include <athstartpack_win.h>
#define __ATTRIB_PACK POSTPACK
#endif
#if __LONG_MAX__ == __INT_MAX__
/* 32-bit compilation */
#define PREPACK64
#define POSTPACK64
#else
/* 64-bit compilation */
#define PREPACK64 PREPACK
#define POSTPACK64 POSTPACK
#endif

View File

@ -0,0 +1,140 @@
//------------------------------------------------------------------------------
// <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
BMInvramProcess(HIF_DEVICE *device,
A_UCHAR *seg_name,
A_UINT32 *retval);
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_ */

View File

@ -0,0 +1,107 @@
//------------------------------------------------------------------------------
// Copyright (c) 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 COMMON_DRV_H_
#define COMMON_DRV_H_
#include "hif.h"
#include "htc_packet.h"
#include "htc_api.h"
/* structure that is the state information for the default credit distribution callback
* drivers should instantiate (zero-init as well) this structure in their driver instance
* and pass it as a context to the HTC credit distribution functions */
typedef struct _COMMON_CREDIT_STATE_INFO {
int TotalAvailableCredits; /* total credits in the system at startup */
int CurrentFreeCredits; /* credits available in the pool that have not been
given out to endpoints */
HTC_ENDPOINT_CREDIT_DIST *pLowestPriEpDist; /* pointer to the lowest priority endpoint dist struct */
} COMMON_CREDIT_STATE_INFO;
typedef struct {
A_INT32 (*setupTransport)(void *ar);
void (*cleanupTransport)(void *ar);
} HCI_TRANSPORT_CALLBACKS;
typedef struct {
void *netDevice;
void *hifDevice;
void *htcHandle;
} HCI_TRANSPORT_MISC_HANDLES;
/* HTC TX packet tagging definitions */
#define AR6K_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED
#define AR6K_DATA_PKT_TAG (AR6K_CONTROL_PKT_TAG + 1)
#define AR6002_VERSION_REV2 0x20000188
#define AR6003_VERSION_REV2 0x30000384
#define AR6002_CUST_DATA_SIZE 112
#define AR6003_CUST_DATA_SIZE 16
#define MCKINLEY_CUST_DATA_SIZE 16
#ifdef __cplusplus
extern "C" {
#endif
/* OS-independent APIs */
A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo);
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_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset);
void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
A_UINT32 TargetType,
A_UINT32 MboxIsrYieldValue,
A_UINT8 HtcControlBuffers);
A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
A_UINT32 TargetType,
A_UINT32 TargetVersion);
A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
A_UINT32 TargetType,
A_UINT32 Flags);
void ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
A_UINT8 *ar6000_get_cust_data_buffer(A_UINT32 TargetType);
A_STATUS ar6000_setBTState(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
A_STATUS ar6000_setDevicePowerState(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
A_STATUS ar6000_setWowMode(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
A_STATUS ar6000_setHostMode(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
#ifdef __cplusplus
}
#endif
#endif /*COMMON_DRV_H_*/

View File

@ -0,0 +1,58 @@
//------------------------------------------------------------------------------
// <copyright file="dbglog_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 host side debug primitives.
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _DBGLOG_API_H_
#define _DBGLOG_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "dbglog.h"
#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE
#define DBGLOG_GET_DBGID(arg) \
((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET)
#define DBGLOG_GET_MODULEID(arg) \
((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET)
#define DBGLOG_GET_NUMARGS(arg) \
((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET)
#define DBGLOG_GET_TIMESTAMP(arg) \
((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET)
/**
@param lv 0->RAW info, 1->Breif translated info, 2->Full info
@param logbuf dbglog buffer
*/
int dbg_formater(int lv, char *output, size_t len, A_UINT32 ts, A_INT32 *logbuf);
#ifdef __cplusplus
}
#endif
#endif /* _DBGLOG_API_H_ */

View File

@ -0,0 +1,387 @@
/*
* Copyright (c) 2005-2006 Atheros Communications, Inc.
*
* 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 _DFS_HOST_H_
#define _DFS_HOST_H_
#ifdef ATH_SUPPORT_DFS
#include "dfs_host_project.h"
#define DFS_MIN(a,b) ((a)<(b)?(a):(b))
#define DFS_MAX(a,b) ((a)>(b)?(a):(b))
#define DFS_DIFF(a,b) (DFS_MAX(a,b) - DFS_MIN(a,b))
/*
* Maximum number of radar events to be processed in a single iteration.
* Allows soft watchdog to run.
*/
#define MAX_EVENTS 100
#define DFS_MARGIN_EQUAL(a, b, margin) ((DFS_DIFF(a,b)) <= margin)
#define DFS_MAX_STAGGERED_BURSTS 3
/* All filter thresholds in the radar filter tables are effective at a 50% channel loading */
#define DFS_CHAN_LOADING_THRESH 50
#define DFS_EXT_CHAN_LOADING_THRESH 30
#define DFS_DEFAULT_PRI_MARGIN 10
#define DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN 6
#define ATH_DFSQ_LOCK(_dfs) spin_lock(&(_dfs)->dfs_radarqlock)
#define ATH_DFSQ_UNLOCK(_dfs) spin_unlock(&(_dfs)->dfs_radarqlock)
#define ATH_DFSQ_LOCK_INIT(_dfs) spin_lock_init(&(_dfs)->dfs_radarqlock)
#define ATH_ARQ_LOCK(_dfs) spin_lock(&(_dfs)->dfs_arqlock)
#define ATH_ARQ_UNLOCK(_dfs) spin_unlock(&(_dfs)->dfs_arqlock)
#define ATH_ARQ_LOCK_INIT(_dfs) spin_lock_init(&(_dfs)->dfs_arqlock)
#define ATH_DFSEVENTQ_LOCK(_dfs) spin_lock(&(_dfs)->dfs_eventqlock)
#define ATH_DFSEVENTQ_UNLOCK(_dfs) spin_unlock(&(_dfs)->dfs_eventqlock)
#define ATH_DFSEVENTQ_LOCK_INIT(_dfs) spin_lock_init(&(_dfs)->dfs_eventqlock)
#define DFS_TSMASK 0xFFFFFFFF /* Mask for time stamp from descriptor */
#define DFS_TSSHIFT 32 /* Shift for time stamp from descriptor */
#define DFS_TSF_WRAP 0xFFFFFFFFFFFFFFFFULL /* 64 bit TSF wrap value */
#define DFS_64BIT_TSFMASK 0x0000000000007FFFULL /* TS mask for 64 bit value */
#define DFS_AR_RADAR_RSSI_THR 5 /* in dB */
#define DFS_AR_RADAR_RESET_INT 1 /* in secs */
#define DFS_AR_RADAR_MAX_HISTORY 500
#define DFS_AR_REGION_WIDTH 128
#define DFS_AR_RSSI_THRESH_STRONG_PKTS 17 /* in dB */
#define DFS_AR_RSSI_DOUBLE_THRESHOLD 15 /* in dB */
#define DFS_AR_MAX_NUM_ACK_REGIONS 9
#define DFS_AR_ACK_DETECT_PAR_THRESH 20
#define DFS_AR_PKT_COUNT_THRESH 20
#define DFS_MAX_DL_MASK 0x3F
#define DFS_NOL_TIME 30*60*1000000 /* 30 minutes in usecs */
#define DFS_WAIT_TIME 60*1000000 /* 1 minute in usecs */
#define DFS_DISABLE_TIME 3*60*1000000 /* 3 minutes in usecs */
#define DFS_MAX_B5_SIZE 128
#define DFS_MAX_B5_MASK 0x0000007F /* 128 */
#define DFS_MAX_RADAR_OVERLAP 16 /* Max number of overlapping filters */
#define DFS_MAX_EVENTS 1024 /* Max number of dfs events which can be q'd */
#define DFS_RADAR_EN 0x80000000 /* Radar detect is capable */
#define DFS_AR_EN 0x40000000 /* AR detect is capable */
#define DFS_MAX_RSSI_VALUE 0x7fffffff /* Max rssi value */
#define DFS_BIN_MAX_PULSES 60 /* max num of pulses in a burst */
#define DFS_BIN5_PRI_LOWER_LIMIT 990 /* us */
#define DFS_BIN5_PRI_HIGHER_LIMIT 2010 /* us */
#define DFS_BIN5_WIDTH_MARGIN 4 /* us */
#define DFS_BIN5_RSSI_MARGIN 5 /* dBm */
/*Following threshold is not specified but should be okay statistically*/
#define DFS_BIN5_BRI_LOWER_LIMIT 300000 /* us */
#define DFS_MAX_PULSE_BUFFER_SIZE 1024 /* Max number of pulses kept in buffer */
#define DFS_MAX_PULSE_BUFFER_MASK 0x3ff
#define DFS_FAST_CLOCK_MULTIPLIER (800/11)
#define DFS_NO_FAST_CLOCK_MULTIPLIER (80)
typedef spinlock_t dfsq_lock_t;
struct dfs_pulse {
A_UINT32 rp_numpulses; /* Num of pulses in radar burst */
A_UINT32 rp_pulsedur; /* Duration of each pulse in usecs */
A_UINT32 rp_pulsefreq; /* Frequency of pulses in burst */
A_UINT32 rp_max_pulsefreq; /* Frequency of pulses in burst */
A_UINT32 rp_patterntype; /*fixed or variable pattern type*/
A_UINT32 rp_pulsevar; /* Time variation of pulse duration for
matched filter (single-sided) in usecs */
A_UINT32 rp_threshold; /* Thershold for MF output to indicate
radar match */
A_UINT32 rp_mindur; /* Min pulse duration to be considered for
this pulse type */
A_UINT32 rp_maxdur; /* Max pusle duration to be considered for
this pulse type */
A_UINT32 rp_rssithresh; /* Minimum rssi to be considered a radar pulse */
A_UINT32 rp_meanoffset; /* Offset for timing adjustment */
A_INT32 rp_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dBm
* lower than in non TURBO mode. This will be used to offset
* that diff.*/
A_UINT32 rp_pulseid; /* Unique ID for identifying filter */
};
struct dfs_bin5pulse {
A_UINT32 b5_threshold; /* Number of bin5 pulses to indicate detection */
A_UINT32 b5_mindur; /* Min duration for a bin5 pulse */
A_UINT32 b5_maxdur; /* Max duration for a bin5 pulse */
A_UINT32 b5_timewindow; /* Window over which to count bin5 pulses */
A_UINT32 b5_rssithresh; /* Min rssi to be considered a pulse */
A_UINT32 b5_rssimargin; /* rssi threshold margin. In Turbo Mode HW reports rssi 3dB */
};
#define DFS_MAX_DL_SIZE 64
#include "athstartpack.h"
PREPACK struct dfs_delayelem {
u_int32_t de_time; /* Current "filter" time for start of pulse in usecs*/
u_int8_t de_dur; /* Duration of pulse in usecs*/
u_int8_t de_rssi; /* rssi of pulse in dB*/
} POSTPACK adf_os_packed;
/* NB: The first element in the circular buffer is the oldest element */
PREPACK struct dfs_delayline {
struct dfs_delayelem dl_elems[DFS_MAX_DL_SIZE]; /* Array of pulses in delay line */
u_int64_t dl_last_ts; /* Last timestamp the delay line was used (in usecs) */
u_int32_t dl_firstelem; /* Index of the first element */
u_int32_t dl_lastelem; /* Index of the last element */
u_int32_t dl_numelems; /* Number of elements in the delay line */
} POSTPACK adf_os_packed;
PREPACK struct dfs_filter {
struct dfs_delayline rf_dl; /* Delay line of pulses for this filter */
u_int32_t rf_numpulses; /* Number of pulses in the filter */
u_int32_t rf_minpri; /* min pri to be considered for this filter*/
u_int32_t rf_maxpri; /* max pri to be considered for this filter*/
u_int32_t rf_threshold; /* match filter output threshold for radar detect */
u_int32_t rf_filterlen; /* Length (in usecs) of the filter */
u_int32_t rf_patterntype; /* fixed or variable pattern type */
u_int32_t rf_mindur; /* Min duration for this radar filter */
u_int32_t rf_maxdur; /* Max duration for this radar filter */
u_int32_t rf_pulseid; /* Unique ID corresponding to the original filter ID */
} POSTPACK adf_os_packed;
PREPACK struct dfs_pulseparams {
u_int64_t p_time; /* time for start of pulse in usecs*/
u_int8_t p_dur; /* Duration of pulse in usecs*/
u_int8_t p_rssi; /* Duration of pulse in usecs*/
} POSTPACK adf_os_packed;
PREPACK struct dfs_pulseline {
/* pl_elems - array of pulses in delay line */
struct dfs_pulseparams pl_elems[DFS_MAX_PULSE_BUFFER_SIZE];
u_int32_t pl_firstelem; /* Index of the first element */
u_int32_t pl_lastelem; /* Index of the last element */
u_int32_t pl_numelems; /* Number of elements in the delay line */
} POSTPACK adf_os_packed;
PREPACK struct dfs_event {
u_int64_t re_full_ts; /* 64-bit full timestamp from interrupt time */
u_int32_t re_ts; /* Original 15 bit recv timestamp */
u_int32_t re_ext_chan_busy; /* Ext channel busy % */
u_int8_t re_rssi; /* rssi of radar event */
u_int8_t re_dur; /* duration of radar pulse */
u_int8_t re_chanindex; /* Channel of event */
u_int8_t re_chanindextype; /* Primary channel or extension channel */
STAILQ_ENTRY(dfs_event) re_list; /* List of radar events */
} POSTPACK adf_os_packed;
#include "athendpack.h"
#define DFS_AR_MAX_ACK_RADAR_DUR 511
#define DFS_AR_MAX_NUM_PEAKS 3
#define DFS_AR_ARQ_SIZE 2048 /* 8K AR events for buffer size */
#define DFS_AR_ARQ_SEQSIZE 2049 /* Sequence counter wrap for AR */
#define DFS_RADARQ_SIZE 512 /* 1K radar events for buffer size */
#define DFS_RADARQ_SEQSIZE 513 /* Sequence counter wrap for radar */
#define DFS_NUM_RADAR_STATES 64 /* Number of radar channels we keep state for */
#define DFS_MAX_NUM_RADAR_FILTERS 10 /* Max number radar filters for each type */
#define DFS_MAX_RADAR_TYPES 32 /* Number of different radar types */
struct dfs_ar_state {
u_int32_t ar_prevwidth;
u_int32_t ar_phyerrcount[DFS_AR_MAX_ACK_RADAR_DUR];
u_int32_t ar_acksum;
u_int32_t ar_packetthreshold; /* Thresh to determine traffic load */
u_int32_t ar_parthreshold; /* Thresh to determine peak */
u_int32_t ar_radarrssi; /* Rssi threshold for AR event */
u_int16_t ar_prevtimestamp;
u_int16_t ar_peaklist[DFS_AR_MAX_NUM_PEAKS];
};
struct dfs_filtertype {
struct dfs_filter ft_filters[DFS_MAX_NUM_RADAR_FILTERS];
u_int32_t ft_filterdur; /* Duration of pulse which specifies filter type*/
u_int32_t ft_numfilters; /* Num filters of this type */
u_int64_t ft_last_ts; /* Last timestamp this filtertype was used
* (in usecs) */
u_int32_t ft_mindur; /* min pulse duration to be considered
* for this filter type */
u_int32_t ft_maxdur; /* max pulse duration to be considered
* for this filter type */
u_int32_t ft_rssithresh; /* min rssi to be considered
* for this filter type */
u_int32_t ft_numpulses; /* Num pulses in each filter of this type */
u_int32_t ft_patterntype; /* fixed or variable pattern type */
u_int32_t ft_minpri; /* min pri to be considered for this type */
u_int32_t ft_rssimargin; /* rssi threshold margin. In Turbo Mode HW
* reports rssi 3dB lower than in non TURBO
* mode. This will offset that diff. */
};
#define DFS_NOL_TIMEOUT_S (30*60) /* 30 minutes in seconds */
#define DFS_NOL_TIMEOUT_MS (DFS_NOL_TIMEOUT_S * 1000)
#define DFS_NOL_TIMEOUT_US (DFS_NOL_TIMEOUT_MS * 1000)
#include "athstartpack.h"
PREPACK struct dfs_info_host {
u_int32_t rn_numradars; /* Number of different types of radars */
u_int64_t rn_lastfull_ts; /* Last 64 bit timstamp from recv interrupt */
u_int16_t rn_last_ts; /* last 15 bit ts from recv descriptor */
u_int32_t rn_last_unique_ts; /* last unique 32 bit ts from recv descriptor */
u_int64_t rn_ts_prefix; /* Prefix to prepend to 15 bit recv ts */
u_int32_t rn_numbin5radars; /* Number of bin5 radar pulses to search for */
u_int64_t dfs_bin5_chirp_ts;
u_int8_t dfs_last_bin5_dur;
} POSTPACK adf_os_packed;
#include "athendpack.h"
struct dfs_bin5elem {
u_int64_t be_ts; /* Timestamp for the bin5 element */
u_int32_t be_rssi; /* Rssi for the bin5 element */
u_int32_t be_dur; /* Duration of bin5 element */
};
struct dfs_bin5radars {
struct dfs_bin5elem br_elems[DFS_MAX_B5_SIZE]; /* List of bin5 elems that fall
* within the time window */
u_int32_t br_firstelem; /* Index of the first element */
u_int32_t br_lastelem; /* Index of the last element */
u_int32_t br_numelems; /* Number of elements in the delay line */
struct dfs_bin5pulse br_pulse; /* Original info about bin5 pulse */
};
#define ATH_DFS_RESET_TIME_S 7
#define ATH_DFS_WAIT (60 + ATH_DFS_RESET_TIME_S) /* 60 seconds */
#define ATH_DFS_WAIT_MS ((ATH_DFS_WAIT) * 1000) /*in MS*/
#define ATH_DFS_WEATHER_CHANNEL_WAIT_MIN 10 /*10 minutes*/
#define ATH_DFS_WEATHER_CHANNEL_WAIT_S (ATH_DFS_WEATHER_CHANNEL_WAIT_MIN * 60)
#define ATH_DFS_WEATHER_CHANNEL_WAIT_MS ((ATH_DFS_WEATHER_CHANNEL_WAIT_S) * 1000) /*in MS*/
#define ATH_DFS_WAIT_POLL_PERIOD 2 /* 2 seconds */
#define ATH_DFS_WAIT_POLL_PERIOD_MS ((ATH_DFS_WAIT_POLL_PERIOD) * 1000) /*in MS*/
#define ATH_DFS_TEST_RETURN_PERIOD 2 /* 2 seconds */
#define ATH_DFS_TEST_RETURN_PERIOD_MS ((ATH_DFS_TEST_RETURN_PERIOD) * 1000)/* n MS*/
#define IS_CHANNEL_WEATHER_RADAR(chan) ((chan->channel >= 5600) && (chan->channel <= 5650))
#define DFS_DEBUG_TIMEOUT_S 30 // debug timeout is 30 seconds
#define DFS_DEBUG_TIMEOUT_MS (DFS_DEBUG_TIMEOUT_S * 1000)
struct ath_dfs_host {
DEV_HDL dev_hdl;
u_int32_t dfs_debug_level;
OS_HDL os_hdl;
STAILQ_HEAD(,dfs_event) dfs_eventq; /* Q of free dfs event objects */
dfsq_lock_t dfs_eventqlock; /* Lock for free dfs event list */
STAILQ_HEAD(,dfs_event) dfs_radarq; /* Q of radar events */
dfsq_lock_t dfs_radarqlock; /* Lock for dfs q */
STAILQ_HEAD(,dfs_event) dfs_arq; /* Q of AR events */
dfsq_lock_t dfs_arqlock; /* Lock for AR q */
struct dfs_pulseline *pulses; /* pulse history */
struct dfs_event *events; /* Events structure */
/* dfs_radarf - One filter for each radar pulse type */
struct dfs_filtertype *dfs_radarf[DFS_MAX_RADAR_TYPES];
int8_t **dfs_radartable; /* map of radar durs to filter types */
struct dfs_bin5radars *dfs_b5radars;/* array of bin5 radar events */
struct dfs_ar_state dfs_ar_state; /* AR state */
struct dfs_info_host dfs_rinfo; /* State vars for radar processing */
u_int8_t dfs_bangradar;
u_int32_t dur_multiplier;
A_TIMER dfs_radar_task_timer;
};
#define HAL_CAP_RADAR 0
#define HAL_CAP_AR 1
#define HAL_CAP_STRONG_DIV 2
/* Attach, detach, handle ioctl prototypes */
struct ath_dfs_host *dfs_attach_host(DEV_HDL dev, OS_HDL os, ATH_DFS_CAPINFO *cap_info);
void dfs_detach_host(struct ath_dfs_host *sc);
/* PHY error and radar event handling */
void dfs_process_phyerr_host(struct ath_dfs_host *dfs, WMI_DFS_PHYERR_EVENT *ev);
int dfs_process_radarevent_host(struct ath_dfs_host *dfs, int16_t *chan_index, u_int8_t *bangradar);
/* FCC Bin5 detection prototypes */
int dfs_bin5_addpulse(struct ath_dfs_host *sc, struct dfs_bin5radars *br,
struct dfs_event *re, u_int64_t thists);
int dfs_bin5_check(struct ath_dfs_host *dfs);
u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs_host *dfs, u_int32_t diff_ts, u_int8_t old_dur);
/* Debug prototypes */
void dfs_print_delayline(struct ath_dfs_host *dfs, struct dfs_delayline *dl);
void dfs_print_filters(struct ath_dfs_host *dfs);
void dfs_print_filter(struct ath_dfs_host *dfs, struct dfs_filter *rf);
/* Misc prototypes */
u_int32_t dfs_round(int32_t val);
/* Reset and init data structures */
int dfs_init_radar_filters_host(struct ath_dfs_host *dfs, struct ath_dfs_info *dfs_info);
void dfs_reset_alldelaylines(struct ath_dfs_host *dfs);
void dfs_reset_delayline(struct dfs_delayline *dl);
void dfs_reset_filter_delaylines(struct dfs_filtertype *dft);
void dfs_reset_radarq(struct ath_dfs_host *dfs);
/* Detection algorithm prototypes */
void dfs_add_pulse(struct ath_dfs_host *dfs, struct dfs_filter *rf,
struct dfs_event *re, u_int32_t deltaT);
int dfs_bin_fixedpattern_check(struct ath_dfs_host *dfs, struct dfs_filter *rf, u_int32_t dur, int ext_chan_flag, u_int32_t ext_chan_busy);
int dfs_bin_check(struct ath_dfs_host *dfs, struct dfs_filter *rf,
u_int32_t deltaT, u_int32_t dur, int ext_chan_flag, u_int32_t ext_chan_busy);
int dfs_bin_pri_check(struct ath_dfs_host *dfs, struct dfs_filter *rf,
struct dfs_delayline *dl, u_int32_t score,
u_int32_t refpri, u_int32_t refdur, int ext_chan_flag, u_int32_t ext_chan_busy);
int dfs_staggered_check(struct ath_dfs_host *dfs, struct dfs_filter *rf,
u_int32_t deltaT, u_int32_t width, u_int32_t ext_chan_busy);
/* AR related prototypes */
u_int32_t dfs_process_ar_event(struct ath_dfs_host *dfs);
void dfs_reset_ar(struct ath_dfs_host *dfs);
void dfs_reset_arq(struct ath_dfs_host *dfs);
void dfs_bangradar_enable(struct ath_dfs_host *dfs, u_int8_t enable);
void dfs_set_dur_multiplier(struct ath_dfs_host *dfs, u_int32_t dur_multiplier);
void dfs_set_debug_level_host(struct ath_dfs_host *dfs, u_int32_t level);
/* False detection reduction */
int dfs_get_pri_margin(int is_extchan_detect, int is_fixed_pattern, u_int64_t lastfull_ts, u_int32_t ext_chan_busy);
int dfs_get_filter_threshold(struct dfs_filter *rf, int is_extchan_detect, u_int64_t lastfull_ts, u_int32_t ext_chan_busy);
#endif /* ATH_SUPPORT_DFS */
#endif /* _DFS_H_ */

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2005-2006 Atheros Communications, Inc.
*
* 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 _DFS_PROJECT_H_
#define _DFS_PROJECT_H_
#ifdef ATH_SUPPORT_DFS
#include <a_config.h>
#include <athdefs.h>
#include <a_types.h>
#include <a_osapi.h>
#include <a_debug.h>
#include <queue.h> /* XXX: This is in target dir */
#include "dfs_common.h"
#include "ar6000_drv.h"
#include "project.h"
#define ATH_DFS_CAPINFO WMI_DFS_HOST_ATTACH_EVENT
#define OS_HDL void *
#define DEV_HDL void *
#define DFS_MALLOC(os_hdl, nbytes) A_MALLOC(nbytes)
#define DFS_DPRINTK(pDfs, _m, _fmt, ...) do { \
if ((_m) <= pDfs->dfs_debug_level) { \
A_PRINTF(_fmt, __VA_ARGS__); \
} \
} while (0)
void dfs_radar_task (unsigned long arg);
#define adf_os_packed
typedef enum {
AH_FALSE = 0, /* NB: lots of code assumes false is zero */
AH_TRUE = 1,
} HAL_BOOL;
#endif /* ATH_SUPPORT_DFS */
#endif /* _DFS_PROJECT_H_ */

View File

@ -0,0 +1,153 @@
//------------------------------------------------------------------------------
// <copyright file="dl_list.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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Double-link list definitions (adapted from Atheros SDIO stack)
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef __DL_LIST_H___
#define __DL_LIST_H___
#include "a_osapi.h"
#define A_CONTAINING_STRUCT(address, struct_type, field_name)\
((struct_type *)((unsigned long)(address) - (unsigned long)(&((struct_type *)0)->field_name)))
/* list functions */
/* pointers for the list */
typedef struct _DL_LIST {
struct _DL_LIST *pPrev;
struct _DL_LIST *pNext;
}DL_LIST, *PDL_LIST;
/*
* DL_LIST_INIT , initialize doubly linked list
*/
#define DL_LIST_INIT(pList)\
{(pList)->pPrev = pList; (pList)->pNext = pList;}
/* faster macro to init list and add a single item */
#define DL_LIST_INIT_AND_ADD(pList,pItem) \
{ (pList)->pPrev = (pItem); \
(pList)->pNext = (pItem); \
(pItem)->pNext = (pList); \
(pItem)->pPrev = (pList); \
}
#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList)))
#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
/*
* ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
* NOT: do not use this function if the items in the list are deleted inside the
* iteration loop
*/
#define ITERATE_OVER_LIST(pStart, pTemp) \
for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
/* safe iterate macro that allows the item to be removed from the list
* the iteration continues to the next item in the list
*/
#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \
{ \
PDL_LIST pTemp; \
pTemp = (pStart)->pNext; \
while (pTemp != (pStart)) { \
(pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \
pTemp = pTemp->pNext; \
#define ITERATE_END }}
/*
* DL_ListInsertTail - insert pAdd to the end of the list
*/
static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
/* insert at tail */
pAdd->pPrev = pList->pPrev;
pAdd->pNext = pList;
pList->pPrev->pNext = pAdd;
pList->pPrev = pAdd;
return pAdd;
}
/*
* DL_ListInsertHead - insert pAdd into the head of the list
*/
static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
/* insert at head */
pAdd->pPrev = pList;
pAdd->pNext = pList->pNext;
pList->pNext->pPrev = pAdd;
pList->pNext = pAdd;
return pAdd;
}
#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem))
/*
* DL_ListRemove - remove pDel from list
*/
static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) {
pDel->pNext->pPrev = pDel->pPrev;
pDel->pPrev->pNext = pDel->pNext;
/* point back to itself just to be safe, incase remove is called again */
pDel->pNext = pDel;
pDel->pPrev = pDel;
return pDel;
}
/*
* DL_ListRemoveItemFromHead - get a list item from the head
*/
static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
PDL_LIST pItem = NULL;
if (pList->pNext != pList) {
pItem = pList->pNext;
/* remove the first item from head */
DL_ListRemove(pItem);
}
return pItem;
}
static INLINE PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) {
PDL_LIST pItem = NULL;
if (pList->pPrev != pList) {
pItem = pList->pPrev;
/* remove the item from tail */
DL_ListRemove(pItem);
}
return pItem;
}
/* transfer src list items to the tail of the destination list */
static INLINE void DL_ListTransferItemsToTail(PDL_LIST pDest, PDL_LIST pSrc) {
/* only concatenate if src is not empty */
if (!DL_LIST_IS_EMPTY(pSrc)) {
/* cut out circular list in src and re-attach to end of dest */
pSrc->pPrev->pNext = pDest;
pSrc->pNext->pPrev = pDest->pPrev;
pDest->pPrev->pNext = pSrc->pNext;
pDest->pPrev = pSrc->pPrev;
/* terminate src list, it is now empty */
pSrc->pPrev = pSrc;
pSrc->pNext = pSrc;
}
}
#endif /* __DL_LIST_H___ */

View File

@ -0,0 +1,65 @@
//------------------------------------------------------------------------------
// <copyright file="dset_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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Host-side DataSet API.
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _DSET_API_H_
#define _DSET_API_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Host-side DataSet support is optional, and is not
* currently required for correct operation. To disable
* Host-side DataSet support, set this to 0.
*/
#ifndef CONFIG_HOST_DSET_SUPPORT
#define CONFIG_HOST_DSET_SUPPORT 1
#endif
/* Called to send a DataSet Open Reply back to the Target. */
A_STATUS wmi_dset_open_reply(struct wmi_t *wmip,
A_UINT32 status,
A_UINT32 access_cookie,
A_UINT32 size,
A_UINT32 version,
A_UINT32 targ_handle,
A_UINT32 targ_reply_fn,
A_UINT32 targ_reply_arg);
/* Called to send a DataSet Data Reply back to the Target. */
A_STATUS wmi_dset_data_reply(struct wmi_t *wmip,
A_UINT32 status,
A_UINT8 *host_buf,
A_UINT32 length,
A_UINT32 targ_buf,
A_UINT32 targ_reply_fn,
A_UINT32 targ_reply_arg);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _DSET_API_H_ */

View File

@ -0,0 +1,59 @@
//------------------------------------------------------------------------------
// <copyright file="gpio_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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Host-side General Purpose I/O API.
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _GPIO_API_H_
#define _GPIO_API_H_
/*
* Send a command to the Target in order to change output on GPIO pins.
*/
A_STATUS wmi_gpio_output_set(struct wmi_t *wmip,
A_UINT32 set_mask,
A_UINT32 clear_mask,
A_UINT32 enable_mask,
A_UINT32 disable_mask);
/*
* Send a command to the Target requesting input state of GPIO pins.
*/
A_STATUS wmi_gpio_input_get(struct wmi_t *wmip);
/*
* Send a command to the Target to change the value of a GPIO register.
*/
A_STATUS wmi_gpio_register_set(struct wmi_t *wmip,
A_UINT32 gpioreg_id,
A_UINT32 value);
/*
* Send a command to the Target to fetch the value of a GPIO register.
*/
A_STATUS wmi_gpio_register_get(struct wmi_t *wmip, A_UINT32 gpioreg_id);
/*
* Send a command to the Target, acknowledging some GPIO interrupts.
*/
A_STATUS wmi_gpio_intr_ack(struct wmi_t *wmip, A_UINT32 ack_mask);
#endif /* _GPIO_API_H_ */

View File

@ -0,0 +1,259 @@
//------------------------------------------------------------------------------
// 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"
//==============================================================================
#ifndef _HCI_TRANSPORT_API_H_
#define _HCI_TRANSPORT_API_H_
/* Bluetooth HCI packets are stored in HTC packet containers */
#include "htc_packet.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef void *HCI_TRANSPORT_HANDLE;
typedef HTC_ENDPOINT_ID HCI_TRANSPORT_PACKET_TYPE;
/* we map each HCI packet class to a static Endpoint ID */
#define HCI_COMMAND_TYPE ENDPOINT_1
#define HCI_EVENT_TYPE ENDPOINT_2
#define HCI_ACL_TYPE ENDPOINT_3
#define HCI_PACKET_INVALID ENDPOINT_MAX
#define HCI_GET_PACKET_TYPE(pP) (pP)->Endpoint
#define HCI_SET_PACKET_TYPE(pP,s) (pP)->Endpoint = (s)
/* callback when an HCI packet was completely sent */
typedef void (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, HTC_PACKET *);
/* callback when an HCI packet is received */
typedef void (*HCI_TRANSPORT_RECV_PKT)(void *, HTC_PACKET *);
/* Optional receive buffer re-fill callback,
* On some OSes (like Linux) packets are allocated from a global pool and indicated up
* to the network stack. The driver never gets the packets back from the OS. For these OSes
* a refill callback can be used to allocate and re-queue buffers into HTC.
* A refill callback is used for the reception of ACL and EVENT packets. The caller must
* set the watermark trigger point to cause a refill.
*/
typedef void (*HCI_TRANSPORT_RECV_REFILL)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable);
/* Optional receive packet refill
* On some systems packet buffers are an extremely limited resource. Rather than
* queue largest-possible-sized buffers to the HCI bridge, some systems would rather
* allocate a specific size as the packet is received. The trade off is
* slightly more processing (callback invoked for each RX packet)
* for the benefit of committing fewer buffer resources into the bridge.
*
* The callback is provided the length of the pending packet to fetch. This includes the
* full transport header, HCI header, plus the length of payload. The callback can return a pointer to
* the allocated HTC packet for immediate use.
*
* NOTE*** This callback is mutually exclusive with the the refill callback above.
*
* */
typedef HTC_PACKET *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length);
typedef enum _HCI_SEND_FULL_ACTION {
HCI_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */
HCI_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */
} HCI_SEND_FULL_ACTION;
/* callback when an HCI send queue exceeds the caller's MaxSendQueueDepth threshold,
* the callback must return the send full action to take (either DROP or KEEP) */
typedef HCI_SEND_FULL_ACTION (*HCI_TRANSPORT_SEND_FULL)(void *, HTC_PACKET *);
typedef struct {
int HeadRoom; /* number of bytes in front of HCI packet for header space */
int TailRoom; /* number of bytes at the end of the HCI packet for tail space */
int IOBlockPad; /* I/O block padding required (always a power of 2) */
} HCI_TRANSPORT_PROPERTIES;
typedef struct _HCI_TRANSPORT_CONFIG_INFO {
int ACLRecvBufferWaterMark; /* low watermark to trigger recv refill */
int EventRecvBufferWaterMark; /* low watermark to trigger recv refill */
int MaxSendQueueDepth; /* max number of packets in the single send queue */
void *pContext; /* context for all callbacks */
void (*TransportFailure)(void *pContext, A_STATUS Status); /* transport failure callback */
A_STATUS (*TransportReady)(HCI_TRANSPORT_HANDLE, HCI_TRANSPORT_PROPERTIES *,void *pContext); /* transport is ready */
void (*TransportRemoved)(void *pContext); /* transport was removed */
/* packet processing callbacks */
HCI_TRANSPORT_SEND_PKT_COMPLETE pHCISendComplete;
HCI_TRANSPORT_RECV_PKT pHCIPktRecv;
HCI_TRANSPORT_RECV_REFILL pHCIPktRecvRefill;
HCI_TRANSPORT_RECV_ALLOC pHCIPktRecvAlloc;
HCI_TRANSPORT_SEND_FULL pHCISendFull;
} HCI_TRANSPORT_CONFIG_INFO;
/* ------ Function Prototypes ------ */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Attach to the HCI transport module
@function name: HCI_TransportAttach
@input: HTCHandle - HTC handle (see HTC apis)
pInfo - initialization information
@output:
@return: HCI_TRANSPORT_HANDLE on success, NULL on failure
@notes: The HTC module provides HCI transport services.
@example:
@see also: HCI_TransportDetach
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Detach from the HCI transport module
@function name: HCI_TransportDetach
@input: HciTrans - HCI transport handle
pInfo - initialization information
@output:
@return:
@notes:
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Add receive packets to the HCI transport
@function name: HCI_TransportAddReceivePkts
@input: HciTrans - HCI transport handle
pQueue - a queue holding one or more packets
@output:
@return: A_OK on success
@notes: user must supply HTC packets for capturing incomming HCI packets. The caller
must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
macro. Each packet in the queue must be of the same type and length
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Send an HCI packet packet
@function name: HCI_TransportSendPkt
@input: HciTrans - HCI transport handle
pPacket - packet to send
Synchronous - send the packet synchronously (blocking)
@output:
@return: A_OK
@notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() and
HCI_SET_PACKET_TYPE() macros to prepare the packet.
If Synchronous is set to FALSE the call is fully asynchronous. On error or completion,
the registered send complete callback will be called.
If Synchronous is set to TRUE, the call will block until the packet is sent, if the
interface cannot send the packet within a 2 second timeout, the function will return
the failure code : A_EBUSY.
Synchronous Mode should only be used at start-up to initialize the HCI device using
custom HCI commands. It should NOT be mixed with Asynchronous operations. Mixed synchronous
and asynchronous operation behavior is undefined.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Stop HCI transport
@function name: HCI_TransportStop
@input: HciTrans - hci transport handle
@output:
@return:
@notes: HCI transport communication will be halted. All receive and pending TX packets will
be flushed.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Start the HCI transport
@function name: HCI_TransportStart
@input: HciTrans - hci transport handle
@output:
@return: A_OK on success
@notes: HCI transport communication will begin, the caller can expect the arrival
of HCI recv packets as soon as this call returns.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Enable or Disable Asynchronous Recv
@function name: HCI_TransportEnableDisableAsyncRecv
@input: HciTrans - hci transport handle
Enable - enable or disable asynchronous recv
@output:
@return: A_OK on success
@notes: This API must be called when HCI recv is handled synchronously
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Receive an event packet from the HCI transport synchronously using polling
@function name: HCI_TransportRecvHCIEventSync
@input: HciTrans - hci transport handle
pPacket - HTC packet to hold the recv data
MaxPollMS - maximum polling duration in Milliseconds;
@output:
@return: A_OK on success
@notes: This API should be used only during HCI device initialization, the caller must call
HCI_TransportEnableDisableAsyncRecv with Enable=FALSE prior to using this API.
This API will only capture HCI Event packets.
@example:
@see also: HCI_TransportEnableDisableAsyncRecv
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
HTC_PACKET *pPacket,
int MaxPollMS);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Set the desired baud rate for the underlying transport layer
@function name: HCI_TransportSetBaudRate
@input: HciTrans - hci transport handle
Baud - baud rate in bps
@output:
@return: A_OK on success
@notes: This API should be used only after HCI device initialization
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Enable/Disable HCI Transport Power Management
@function name: HCI_TransportEnablePowerMgmt
@input: HciTrans - hci transport handle
Enable - 1 = Enable, 0 = Disable
@output:
@return: A_OK on success
@notes:
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
#ifdef __cplusplus
}
#endif
#endif /* _HCI_TRANSPORT_API_H_ */

View File

@ -0,0 +1,517 @@
//------------------------------------------------------------------------------
// <copyright file="hif.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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// HIF specific declarations and prototypes
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _HIF_H_
#define _HIF_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Header files */
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#include "dl_list.h"
typedef struct htc_callbacks HTC_CALLBACKS;
typedef struct hif_device HIF_DEVICE;
#define HIF_TYPE_AR6002 2
#define HIF_TYPE_AR6003 3
#define HIF_TYPE_MCKINLEY 5
/*
* direction - Direction of transfer (HIF_READ/HIF_WRITE).
*/
#define HIF_READ 0x00000001
#define HIF_WRITE 0x00000002
#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
/*
* type - An interface may support different kind of read/write commands.
* For example: SDIO supports CMD52/CMD53s. In case of MSIO it
* translates to using different kinds of TPCs. The command type
* is thus divided into a basic and an extended command and can
* be specified using HIF_BASIC_IO/HIF_EXTENDED_IO.
*/
#define HIF_BASIC_IO 0x00000004
#define HIF_EXTENDED_IO 0x00000008
#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO)
/*
* emode - This indicates the whether the command is to be executed in a
* blocking or non-blocking fashion (HIF_SYNCHRONOUS/
* HIF_ASYNCHRONOUS). The read/write data paths in HTC have been
* implemented using the asynchronous mode allowing the the bus
* driver to indicate the completion of operation through the
* registered callback routine. The requirement primarily comes
* from the contexts these operations get called from (a driver's
* transmit context or the ISR context in case of receive).
* Support for both of these modes is essential.
*/
#define HIF_SYNCHRONOUS 0x00000010
#define HIF_ASYNCHRONOUS 0x00000020
#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
/*
* dmode - An interface may support different kinds of commands based on
* the tradeoff between the amount of data it can carry and the
* setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/
* HIF_BLOCK_BASIS). In case of latter, the data is rounded off
* to the nearest block size by padding. The size of the block is
* configurable at compile time using the HIF_BLOCK_SIZE and is
* negotiated with the target during initialization after the
* AR6000 interrupts are enabled.
*/
#define HIF_BYTE_BASIS 0x00000040
#define HIF_BLOCK_BASIS 0x00000080
#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
/*
* amode - This indicates if the address has to be incremented on AR6000
* after every read/write operation (HIF?FIXED_ADDRESS/
* HIF_INCREMENTAL_ADDRESS).
*/
#define HIF_FIXED_ADDRESS 0x00000100
#define HIF_INCREMENTAL_ADDRESS 0x00000200
#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
#define HIF_WR_ASYNC_BYTE_FIX \
(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
#define HIF_WR_ASYNC_BYTE_INC \
(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_WR_ASYNC_BLOCK_INC \
(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_WR_SYNC_BYTE_FIX \
(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
#define HIF_WR_SYNC_BYTE_INC \
(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_WR_SYNC_BLOCK_INC \
(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_WR_ASYNC_BLOCK_FIX \
(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
#define HIF_WR_SYNC_BLOCK_FIX \
(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
#define HIF_RD_SYNC_BYTE_INC \
(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_RD_SYNC_BYTE_FIX \
(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
#define HIF_RD_ASYNC_BYTE_FIX \
(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
#define HIF_RD_ASYNC_BLOCK_FIX \
(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
#define HIF_RD_ASYNC_BYTE_INC \
(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_RD_ASYNC_BLOCK_INC \
(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_RD_SYNC_BLOCK_INC \
(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
#define HIF_RD_SYNC_BLOCK_FIX \
(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
typedef enum {
HIF_DEVICE_POWER_STATE = 0,
HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
HIF_DEVICE_GET_MBOX_ADDR,
HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
HIF_DEVICE_GET_IRQ_PROC_MODE,
HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
HIF_DEVICE_POWER_STATE_CHANGE,
HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT,
HIF_DEVICE_GET_OS_DEVICE,
HIF_DEVICE_DEBUG_BUS_STATE,
} HIF_DEVICE_CONFIG_OPCODE;
/*
* HIF CONFIGURE definitions:
*
* HIF_DEVICE_GET_MBOX_BLOCK_SIZE
* input : none
* output : array of 4 A_UINT32s
* notes: block size is returned for each mailbox (4)
*
* HIF_DEVICE_GET_MBOX_ADDR
* input : none
* output : HIF_DEVICE_MBOX_INFO
* notes:
*
* HIF_DEVICE_GET_PENDING_EVENTS_FUNC
* input : none
* output: HIF_PENDING_EVENTS_FUNC function pointer
* notes: this is optional for the HIF layer, if the request is
* not handled then it indicates that the upper layer can use
* the standard device methods to get pending events (IRQs, mailbox messages etc..)
* otherwise it can call the function pointer to check pending events.
*
* HIF_DEVICE_GET_IRQ_PROC_MODE
* input : none
* output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode)
* note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF
* layer can report whether IRQ processing is requires synchronous behavior or
* can be processed using asynchronous bus requests (typically faster).
*
* HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC
* input :
* output : HIF_MASK_UNMASK_RECV_EVENT function pointer
* notes: this is optional for the HIF layer. The HIF layer may require a special mechanism
* to mask receive message events. The upper layer can call this pointer when it needs
* to mask/unmask receive events (in case it runs out of buffers).
*
* HIF_DEVICE_POWER_STATE_CHANGE
*
* input : HIF_DEVICE_POWER_CHANGE_TYPE
* output : none
* note: this is optional for the HIF layer. The HIF layer can handle power on/off state change
* requests in an interconnect specific way. This is highly OS and bus driver dependent.
* The caller must guarantee that no HIF read/write requests will be made after the device
* is powered down.
*
* HIF_DEVICE_GET_IRQ_YIELD_PARAMS
*
* input : none
* output : HIF_DEVICE_IRQ_YIELD_PARAMS
* note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler.
* The DSR callback handler will exit after a fixed number of RX packets or events are processed.
* This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY.
* The HIF implementation can ignore this command if it does not desire the DSR callback to yield.
* The HIF layer can indicate the maximum number of IRQ processing units (RX packets) before the
* DSR handler callback must yield and return control back to the HIF layer. When a yield limit is
* used the DSR callback will not call HIFAckInterrupts() as it would normally do before returning.
* The HIF implementation that requires a yield count must call HIFAckInterrupt() when it is prepared
* to process interrupts again.
*
* HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT
* input : none
* output : HIF_DEVICE_SCATTER_SUPPORT_INFO
* note: This query checks if the HIF layer implements the SCATTER request interface. Scatter requests
* allows upper layers to submit mailbox I/O operations using a list of buffers. This is useful for
* multi-message transfers that can better utilize the bus interconnect.
*
*
* HIF_DEVICE_GET_OS_DEVICE
* intput : none
* output : HIF_DEVICE_OS_DEVICE_INFO;
* note: On some operating systems, the HIF layer has a parent device object for the bus. This object
* may be required to register certain types of logical devices.
*
* HIF_DEVICE_DEBUG_BUS_STATE
* input : none
* output : none
* note: This configure option triggers the HIF interface to dump as much bus interface state. This
* configuration request is optional (No-OP on some HIF implementations)
*
*/
typedef struct {
A_UINT32 ExtendedAddress; /* extended address for larger writes */
A_UINT32 ExtendedSize;
} HIF_MBOX_PROPERTIES;
#define HIF_MBOX_FLAG_NO_BUNDLING (1 << 0) /* do not allow bundling over the mailbox */
typedef struct {
A_UINT32 MboxAddresses[4]; /* must be first element for legacy HIFs that return the address in
and ARRAY of 32-bit words */
/* the following describe extended mailbox properties */
HIF_MBOX_PROPERTIES MboxProp[4];
/* if the HIF supports the GMbox extended address region it can report it
* here, some interfaces cannot support the GMBOX address range and not set this */
A_UINT32 GMboxAddress;
A_UINT32 GMboxSize;
A_UINT32 Flags; /* flags to describe mbox behavior or usage */
} HIF_DEVICE_MBOX_INFO;
typedef enum {
HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all
interrupts before returning */
HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts
using ASYNC I/O (that is HIFAckInterrupt can be called at a
later time */
} HIF_DEVICE_IRQ_PROCESSING_MODE;
typedef enum {
HIF_DEVICE_POWER_UP, /* HIF layer should power up interface and/or module */
HIF_DEVICE_POWER_DOWN, /* HIF layer should initiate bus-specific measures to minimize power */
HIF_DEVICE_POWER_CUT /* HIF layer should initiate bus-specific AND/OR platform-specific measures
to completely power-off the module and associated hardware (i.e. cut power supplies)
*/
} HIF_DEVICE_POWER_CHANGE_TYPE;
typedef struct {
int RecvPacketYieldCount; /* max number of packets to force DSR to return */
} HIF_DEVICE_IRQ_YIELD_PARAMS;
typedef struct _HIF_SCATTER_ITEM {
A_UINT8 *pBuffer; /* CPU accessible address of buffer */
int Length; /* length of transfer to/from this buffer */
void *pCallerContexts[2]; /* space for caller to insert a context associated with this item */
} HIF_SCATTER_ITEM;
struct _HIF_SCATTER_REQ;
typedef void ( *HIF_SCATTER_COMP_CB)(struct _HIF_SCATTER_REQ *);
typedef enum _HIF_SCATTER_METHOD {
HIF_SCATTER_NONE = 0,
HIF_SCATTER_DMA_REAL, /* Real SG support no restrictions */
HIF_SCATTER_DMA_BOUNCE, /* Uses SG DMA but HIF layer uses an internal bounce buffer */
} HIF_SCATTER_METHOD;
typedef struct _HIF_SCATTER_REQ {
DL_LIST ListLink; /* link management */
A_UINT32 Address; /* address for the read/write operation */
A_UINT32 Request; /* request flags */
A_UINT32 TotalLength; /* total length of entire transfer */
A_UINT32 CallerFlags; /* caller specific flags can be stored here */
HIF_SCATTER_COMP_CB CompletionRoutine; /* completion routine set by caller */
A_STATUS CompletionStatus; /* status of completion */
void *Context; /* caller context for this request */
int ValidScatterEntries; /* number of valid entries set by caller */
HIF_SCATTER_METHOD ScatterMethod; /* scatter method handled by HIF */
void *HIFPrivate[4]; /* HIF private area */
A_UINT8 *pScatterBounceBuffer; /* bounce buffer for upper layers to copy to/from */
HIF_SCATTER_ITEM ScatterList[1]; /* start of scatter list */
} HIF_SCATTER_REQ;
typedef HIF_SCATTER_REQ * ( *HIF_ALLOCATE_SCATTER_REQUEST)(HIF_DEVICE *device);
typedef void ( *HIF_FREE_SCATTER_REQUEST)(HIF_DEVICE *device, HIF_SCATTER_REQ *request);
typedef A_STATUS ( *HIF_READWRITE_SCATTER)(HIF_DEVICE *device, HIF_SCATTER_REQ *request);
typedef struct _HIF_DEVICE_SCATTER_SUPPORT_INFO {
/* information returned from HIF layer */
HIF_ALLOCATE_SCATTER_REQUEST pAllocateReqFunc;
HIF_FREE_SCATTER_REQUEST pFreeReqFunc;
HIF_READWRITE_SCATTER pReadWriteScatterFunc;
int MaxScatterEntries;
int MaxTransferSizePerScatterReq;
} HIF_DEVICE_SCATTER_SUPPORT_INFO;
typedef struct {
void *pOSDevice;
} HIF_DEVICE_OS_DEVICE_INFO;
#define HIF_MAX_DEVICES 1
struct htc_callbacks {
void *context; /* context to pass to the dsrhandler
note : rwCompletionHandler is provided the context passed to HIFReadWrite */
A_STATUS (* rwCompletionHandler)(void *rwContext, A_STATUS status);
A_STATUS (* dsrHandler)(void *context);
};
typedef struct osdrv_callbacks {
void *context; /* context to pass for all callbacks except deviceRemovedHandler
the deviceRemovedHandler is only called if the device is claimed */
A_STATUS (* deviceInsertedHandler)(void *context, void *hif_handle);
A_STATUS (* deviceRemovedHandler)(void *claimedContext, void *hif_handle);
A_STATUS (* deviceSuspendHandler)(void *context);
A_STATUS (* deviceResumeHandler)(void *context);
A_STATUS (* deviceWakeupHandler)(void *context);
A_STATUS (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config);
} OSDRV_CALLBACKS;
#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host
needs to read the register table to figure out what */
#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */
typedef struct _HIF_PENDING_EVENTS_INFO {
A_UINT32 Events;
A_UINT32 LookAhead;
A_UINT32 AvailableRecvBytes;
} HIF_PENDING_EVENTS_INFO;
/* function to get pending events , some HIF modules use special mechanisms
* to detect packet available and other interrupts */
typedef A_STATUS ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE *device,
HIF_PENDING_EVENTS_INFO *pEvents,
void *AsyncContext);
#define HIF_MASK_RECV TRUE
#define HIF_UNMASK_RECV FALSE
/* function to mask recv events */
typedef A_STATUS ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE *device,
A_BOOL Mask,
void *AsyncContext);
/*
* This API is used to perform any global initialization of the HIF layer
* and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer
*
*/
A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks);
/* This API claims the HIF device and provides a context for handling removal.
* The device removal callback is only called when the OSDRV layer claims
* a device. The claimed context must be non-NULL */
void HIFClaimDevice(HIF_DEVICE *device, void *claimedContext);
/* release the claimed device */
void HIFReleaseDevice(HIF_DEVICE *device);
/* This API allows the HTC layer to attach to the HIF device */
A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks);
/* This API detaches the HTC layer from the HIF device */
void HIFDetachHTC(HIF_DEVICE *device);
/*
* This API is used to provide the read/write interface over the specific bus
* interface.
* address - Starting address in the AR6000's address space. For mailbox
* writes, it refers to the start of the mbox boundary. It should
* be ensured that the last byte falls on the mailbox's EOM. For
* mailbox reads, it refers to the end of the mbox boundary.
* buffer - Pointer to the buffer containg the data to be transmitted or
* received.
* length - Amount of data to be transmitted or received.
* request - Characterizes the attributes of the command.
*/
A_STATUS
HIFReadWrite(HIF_DEVICE *device,
A_UINT32 address,
A_UCHAR *buffer,
A_UINT32 length,
A_UINT32 request,
void *context);
/*
* This can be initiated from the unload driver context when the OSDRV layer has no more use for
* the device.
*/
void HIFShutDownDevice(HIF_DEVICE *device);
/*
* This should translate to an acknowledgment to the bus driver indicating that
* the previous interrupt request has been serviced and the all the relevant
* sources have been cleared. HTC is ready to process more interrupts.
* This should prevent the bus driver from raising an interrupt unless the
* previous one has been serviced and acknowledged using the previous API.
*/
void HIFAckInterrupt(HIF_DEVICE *device);
void HIFMaskInterrupt(HIF_DEVICE *device);
void HIFUnMaskInterrupt(HIF_DEVICE *device);
A_STATUS
HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
void *config, A_UINT32 configLen);
/*
* This API wait for the remaining MBOX messages to be drained
* This should be moved to HTC AR6K layer
*/
A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device);
/****************************************************************/
/* message based HIF interfaces */
/****************************************************************/
#define HIF_BMI_EXCHANGE_NO_TIMEOUT ((A_UINT32)(0))
struct _HIF_MSG_OBJ;
typedef void (* HIF_MSG_RECV_CALLBACK)(void *, struct _HIF_MSG_OBJ *);
typedef void (* HIF_MSG_REQ_COMPLETION)(void *,struct _HIF_MSG_OBJ *);
typedef enum {
HIF_MSG_SIMPLE_BUFFER = 0, /* a simple buffer ptr and length */
HIF_MSG_NET_BUFFER = 1 /* advanced OS-specific network buffer */
} HIF_MSG_BUFFER_TYPE;
/* object to pass HIF message requests from upper layers */
typedef struct _HIF_MSG_OBJ {
DL_LIST ListLink; /* for list management */
A_INT32 PipeId; /* pipe number to send on or recv'd from*/
HIF_MSG_BUFFER_TYPE BufferType;
union {
struct HIF_MSG_NET_BUFFER {
void *pAppNetBuf; /* OS-specific net buf */
} AsNetBuffer;
struct HIF_MSG_SIMPLE_BUFFER {
void *pBuffer; /* for future use.... */
A_UINT32 Length;
} AsSimpleBuffer;
} BufferInfo;
void *pContext; /* caller context of message */
HIF_MSG_REQ_COMPLETION CompletionRoutine; /* completion routine */
A_STATUS Status; /* completion status */
A_UINT32 Flags; /* request flags */
void *HIFPriv[4]; /* private contexts for HIF layer to use */
} HIF_MSG_OBJ;
/* API to handle HIF-specific BMI message exchanges, this API is synchronous
* and only allowed to be called from a context that can block (sleep) */
A_STATUS HIFExchangeBMIMsg(HIF_DEVICE *device,
A_UINT8 *pSendMessage,
A_UINT32 Length,
A_UINT8 *pResponseMessage,
A_UINT32 *pResponseLength,
A_UINT32 TimeoutMS);
/* API to handle HIF specific diagnostic window read accesses, this API is synchronous
* and only allowed to be called from a context that can block (sleep) */
A_STATUS HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 *data);
/* API to handle HIF specific diagnostic window write accesses, this API is synchronous
* and only allowed to be called from a context that can block (sleep) */
A_STATUS HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 data);
/* get the Pipe ID associated with the service ID */
A_STATUS HIFGetPipeId(HIF_DEVICE *hifDevice, A_UINT16 ServiceId, A_INT32 *pId);
/* API to let HIF layer know that pipe communications should be enabled
* caller will start to exchange messages on service pipes */
A_STATUS HIFEnablePipes(HIF_DEVICE *hifDevice);
/* set the message recv handler for all incomming messages */
void HIFSetMsgRecvHandler(HIF_DEVICE *hifDevice,
HIF_MSG_RECV_CALLBACK Callback,
void *pContext);
/* upper layers should return the HIF_MSG_OBJ back to HIF as it may be associated
* with some recv resource. The objects could be returned in a chain (batch mode)
* Note, upper layers can take ownership of the buffer (free it) if it is of the type
* HIF_MSG_NET_BUFFER, in this case upper layers will set
* BufferInfo.AsNetBuffer.pAppNetBuf to NULL */
void HIFReturnRecvMsgObjects(HIF_DEVICE *hifDevice, HIF_MSG_OBJ *pMessageObj);
/* API for upper layers to send one or more messages. Note, HIF may
* take ownership of the buffer (it will free it) if it is of the type
* HIF_MSG_NET_BUFFER, in this case the HIF layer will set
* BufferInfo.AsNetBuffer.pAppNetBuf to NULL */
A_STATUS HIFSendMessages(HIF_DEVICE *hifDevice, HIF_MSG_OBJ *pMessages);
#ifdef __cplusplus
}
#endif
#endif /* _HIF_H_ */

View File

@ -0,0 +1,226 @@
//------------------------------------------------------------------------------
// <copyright file="target_reg_table.h" company="Atheros">
// Copyright (c) 2004-2008 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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Target register table macros and structure definitions
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef HOST_REG_TABLE_H_
#define HOST_REG_TABLE_H_
#include "targaddrs.h"
/*** WARNING : Add to the end of the TABLE! do not change the order ****/
typedef struct hostdef_s {
A_UINT32 d_INT_STATUS_ENABLE_ERROR_LSB;
A_UINT32 d_INT_STATUS_ENABLE_ERROR_MASK;
A_UINT32 d_INT_STATUS_ENABLE_CPU_LSB;
A_UINT32 d_INT_STATUS_ENABLE_CPU_MASK;
A_UINT32 d_INT_STATUS_ENABLE_COUNTER_LSB;
A_UINT32 d_INT_STATUS_ENABLE_COUNTER_MASK;
A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_LSB;
A_UINT32 d_INT_STATUS_ENABLE_MBOX_DATA_MASK;
A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB;
A_UINT32 d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK;
A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB;
A_UINT32 d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK;
A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_LSB;
A_UINT32 d_COUNTER_INT_STATUS_ENABLE_BIT_MASK;
A_UINT32 d_INT_STATUS_ENABLE_ADDRESS;
A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_LSB;
A_UINT32 d_CPU_INT_STATUS_ENABLE_BIT_MASK;
A_UINT32 d_HOST_INT_STATUS_ADDRESS;
A_UINT32 d_CPU_INT_STATUS_ADDRESS;
A_UINT32 d_ERROR_INT_STATUS_ADDRESS;
A_UINT32 d_ERROR_INT_STATUS_WAKEUP_MASK;
A_UINT32 d_ERROR_INT_STATUS_WAKEUP_LSB;
A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK;
A_UINT32 d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB;
A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_MASK;
A_UINT32 d_ERROR_INT_STATUS_TX_OVERFLOW_LSB;
A_UINT32 d_COUNT_DEC_ADDRESS;
A_UINT32 d_HOST_INT_STATUS_CPU_MASK;
A_UINT32 d_HOST_INT_STATUS_CPU_LSB;
A_UINT32 d_HOST_INT_STATUS_ERROR_MASK;
A_UINT32 d_HOST_INT_STATUS_ERROR_LSB;
A_UINT32 d_HOST_INT_STATUS_COUNTER_MASK;
A_UINT32 d_HOST_INT_STATUS_COUNTER_LSB;
A_UINT32 d_RX_LOOKAHEAD_VALID_ADDRESS;
A_UINT32 d_WINDOW_DATA_ADDRESS;
A_UINT32 d_WINDOW_READ_ADDR_ADDRESS;
A_UINT32 d_WINDOW_WRITE_ADDR_ADDRESS;
} HOST_REGISTER_TABLE;
#if defined(MY_HOST_DEF) /* { */
#if defined(ATHR_WIN_DEF)
#define ATH_REG_TABLE_DIRECT_ASSIGN
#endif
#ifdef ATH_REG_TABLE_DIRECT_ASSIGN
static struct hostdef_s my_host_def = {
INT_STATUS_ENABLE_ERROR_LSB,
INT_STATUS_ENABLE_ERROR_MASK,
INT_STATUS_ENABLE_CPU_LSB,
INT_STATUS_ENABLE_CPU_MASK,
INT_STATUS_ENABLE_COUNTER_LSB,
INT_STATUS_ENABLE_COUNTER_MASK,
INT_STATUS_ENABLE_MBOX_DATA_LSB,
INT_STATUS_ENABLE_MBOX_DATA_MASK,
ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB,
ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK,
ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB,
ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK,
COUNTER_INT_STATUS_ENABLE_BIT_LSB,
COUNTER_INT_STATUS_ENABLE_BIT_MASK,
INT_STATUS_ENABLE_ADDRESS,
CPU_INT_STATUS_ENABLE_BIT_LSB,
CPU_INT_STATUS_ENABLE_BIT_MASK,
HOST_INT_STATUS_ADDRESS,
CPU_INT_STATUS_ADDRESS,
ERROR_INT_STATUS_ADDRESS,
ERROR_INT_STATUS_WAKEUP_MASK,
ERROR_INT_STATUS_WAKEUP_LSB,
ERROR_INT_STATUS_RX_UNDERFLOW_MASK,
ERROR_INT_STATUS_RX_UNDERFLOW_LSB,
ERROR_INT_STATUS_TX_OVERFLOW_MASK,
ERROR_INT_STATUS_TX_OVERFLOW_LSB,
COUNT_DEC_ADDRESS,
HOST_INT_STATUS_CPU_MASK,
HOST_INT_STATUS_CPU_LSB,
HOST_INT_STATUS_ERROR_MASK,
HOST_INT_STATUS_ERROR_LSB,
HOST_INT_STATUS_COUNTER_MASK,
HOST_INT_STATUS_COUNTER_LSB,
RX_LOOKAHEAD_VALID_ADDRESS,
WINDOW_DATA_ADDRESS,
WINDOW_READ_ADDR_ADDRESS,
WINDOW_WRITE_ADDR_ADDRESS,
};
#else
static struct hostdef_s my_host_def = {
.d_INT_STATUS_ENABLE_ERROR_LSB = INT_STATUS_ENABLE_ERROR_LSB,
.d_INT_STATUS_ENABLE_ERROR_MASK = INT_STATUS_ENABLE_ERROR_MASK,
.d_INT_STATUS_ENABLE_CPU_LSB = INT_STATUS_ENABLE_CPU_LSB,
.d_INT_STATUS_ENABLE_CPU_MASK = INT_STATUS_ENABLE_CPU_MASK,
.d_INT_STATUS_ENABLE_COUNTER_LSB = INT_STATUS_ENABLE_COUNTER_LSB,
.d_INT_STATUS_ENABLE_COUNTER_MASK = INT_STATUS_ENABLE_COUNTER_MASK,
.d_INT_STATUS_ENABLE_MBOX_DATA_LSB = INT_STATUS_ENABLE_MBOX_DATA_LSB,
.d_INT_STATUS_ENABLE_MBOX_DATA_MASK = INT_STATUS_ENABLE_MBOX_DATA_MASK,
.d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB = ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB,
.d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK = ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK,
.d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB = ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB,
.d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK = ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK,
.d_COUNTER_INT_STATUS_ENABLE_BIT_LSB = COUNTER_INT_STATUS_ENABLE_BIT_LSB,
.d_COUNTER_INT_STATUS_ENABLE_BIT_MASK = COUNTER_INT_STATUS_ENABLE_BIT_MASK,
.d_INT_STATUS_ENABLE_ADDRESS = INT_STATUS_ENABLE_ADDRESS,
.d_CPU_INT_STATUS_ENABLE_BIT_LSB = CPU_INT_STATUS_ENABLE_BIT_LSB,
.d_CPU_INT_STATUS_ENABLE_BIT_MASK = CPU_INT_STATUS_ENABLE_BIT_MASK,
.d_HOST_INT_STATUS_ADDRESS = HOST_INT_STATUS_ADDRESS,
.d_CPU_INT_STATUS_ADDRESS = CPU_INT_STATUS_ADDRESS,
.d_ERROR_INT_STATUS_ADDRESS = ERROR_INT_STATUS_ADDRESS,
.d_ERROR_INT_STATUS_WAKEUP_MASK = ERROR_INT_STATUS_WAKEUP_MASK,
.d_ERROR_INT_STATUS_WAKEUP_LSB = ERROR_INT_STATUS_WAKEUP_LSB,
.d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK = ERROR_INT_STATUS_RX_UNDERFLOW_MASK,
.d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB = ERROR_INT_STATUS_RX_UNDERFLOW_LSB,
.d_ERROR_INT_STATUS_TX_OVERFLOW_MASK = ERROR_INT_STATUS_TX_OVERFLOW_MASK,
.d_ERROR_INT_STATUS_TX_OVERFLOW_LSB = ERROR_INT_STATUS_TX_OVERFLOW_LSB,
.d_COUNT_DEC_ADDRESS = COUNT_DEC_ADDRESS,
.d_HOST_INT_STATUS_CPU_MASK = HOST_INT_STATUS_CPU_MASK,
.d_HOST_INT_STATUS_CPU_LSB = HOST_INT_STATUS_CPU_LSB,
.d_HOST_INT_STATUS_ERROR_MASK = HOST_INT_STATUS_ERROR_MASK,
.d_HOST_INT_STATUS_ERROR_LSB = HOST_INT_STATUS_ERROR_LSB,
.d_HOST_INT_STATUS_COUNTER_MASK = HOST_INT_STATUS_COUNTER_MASK,
.d_HOST_INT_STATUS_COUNTER_LSB = HOST_INT_STATUS_COUNTER_LSB,
.d_RX_LOOKAHEAD_VALID_ADDRESS = RX_LOOKAHEAD_VALID_ADDRESS,
.d_WINDOW_DATA_ADDRESS = WINDOW_DATA_ADDRESS,
.d_WINDOW_READ_ADDR_ADDRESS = WINDOW_READ_ADDR_ADDRESS,
.d_WINDOW_WRITE_ADDR_ADDRESS = WINDOW_WRITE_ADDR_ADDRESS,
};
#endif
struct hostdef_s *MY_HOST_DEF = &my_host_def;
#else /* } { */
#define INT_STATUS_ENABLE_ERROR_LSB (hostdef->d_INT_STATUS_ENABLE_ERROR_LSB)
#define INT_STATUS_ENABLE_ERROR_MASK (hostdef->d_INT_STATUS_ENABLE_ERROR_MASK)
#define INT_STATUS_ENABLE_CPU_LSB (hostdef->d_INT_STATUS_ENABLE_CPU_LSB)
#define INT_STATUS_ENABLE_CPU_MASK (hostdef->d_INT_STATUS_ENABLE_CPU_MASK)
#define INT_STATUS_ENABLE_COUNTER_LSB (hostdef->d_INT_STATUS_ENABLE_COUNTER_LSB)
#define INT_STATUS_ENABLE_COUNTER_MASK (hostdef->d_INT_STATUS_ENABLE_COUNTER_MASK)
#define INT_STATUS_ENABLE_MBOX_DATA_LSB (hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_LSB)
#define INT_STATUS_ENABLE_MBOX_DATA_MASK (hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_MASK)
#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB (hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB)
#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK (hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK)
#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB (hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB)
#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK (hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK)
#define COUNTER_INT_STATUS_ENABLE_BIT_LSB (hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_LSB)
#define COUNTER_INT_STATUS_ENABLE_BIT_MASK (hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_MASK)
#define INT_STATUS_ENABLE_ADDRESS (hostdef->d_INT_STATUS_ENABLE_ADDRESS)
#define CPU_INT_STATUS_ENABLE_BIT_LSB (hostdef->d_CPU_INT_STATUS_ENABLE_BIT_LSB)
#define CPU_INT_STATUS_ENABLE_BIT_MASK (hostdef->d_CPU_INT_STATUS_ENABLE_BIT_MASK)
#define HOST_INT_STATUS_ADDRESS (hostdef->d_HOST_INT_STATUS_ADDRESS)
#define CPU_INT_STATUS_ADDRESS (hostdef->d_CPU_INT_STATUS_ADDRESS)
#define ERROR_INT_STATUS_ADDRESS (hostdef->d_ERROR_INT_STATUS_ADDRESS)
#define ERROR_INT_STATUS_WAKEUP_MASK (hostdef->d_ERROR_INT_STATUS_WAKEUP_MASK)
#define ERROR_INT_STATUS_WAKEUP_LSB (hostdef->d_ERROR_INT_STATUS_WAKEUP_LSB)
#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK (hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK)
#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB (hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB)
#define ERROR_INT_STATUS_TX_OVERFLOW_MASK (hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_MASK)
#define ERROR_INT_STATUS_TX_OVERFLOW_LSB (hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_LSB)
#define COUNT_DEC_ADDRESS (hostdef->d_COUNT_DEC_ADDRESS)
#define HOST_INT_STATUS_CPU_MASK (hostdef->d_HOST_INT_STATUS_CPU_MASK)
#define HOST_INT_STATUS_CPU_LSB (hostdef->d_HOST_INT_STATUS_CPU_LSB)
#define HOST_INT_STATUS_ERROR_MASK (hostdef->d_HOST_INT_STATUS_ERROR_MASK)
#define HOST_INT_STATUS_ERROR_LSB (hostdef->d_HOST_INT_STATUS_ERROR_LSB)
#define HOST_INT_STATUS_COUNTER_MASK (hostdef->d_HOST_INT_STATUS_COUNTER_MASK)
#define HOST_INT_STATUS_COUNTER_LSB (hostdef->d_HOST_INT_STATUS_COUNTER_LSB)
#define RX_LOOKAHEAD_VALID_ADDRESS (hostdef->d_RX_LOOKAHEAD_VALID_ADDRESS)
#define WINDOW_DATA_ADDRESS (hostdef->d_WINDOW_DATA_ADDRESS)
#define WINDOW_READ_ADDR_ADDRESS (hostdef->d_WINDOW_READ_ADDR_ADDRESS)
#define WINDOW_WRITE_ADDR_ADDRESS (hostdef->d_WINDOW_WRITE_ADDR_ADDRESS)
/* SET macros */
#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK)
#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK)
#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK)
#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK)
#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK)
#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK)
#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK)
#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK)
#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB)
#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB)
#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB)
#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB)
#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB)
#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB)
extern struct hostdef_s *hostdef;
#endif /* } */
#endif /*HOST_REG_TABLE_H_*/

View File

@ -0,0 +1,52 @@
//------------------------------------------------------------------------------
// <copyright file="host_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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// This file contains version information for the sample host driver for the
// AR6000 chip
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _HOST_VERSION_H_
#define _HOST_VERSION_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <AR6002/AR6K_version.h>
/*
* The version number is made up of major, minor, patch and build
* numbers. These are 16 bit numbers. The build and release script will
* set the build number using a Perforce counter. Here the build number is
* set to 9999 so that builds done without the build-release script are easily
* identifiable.
*/
#define ATH_SW_VER_MAJOR __VER_MAJOR_
#define ATH_SW_VER_MINOR __VER_MINOR_
#define ATH_SW_VER_PATCH __VER_PATCH_
#define ATH_SW_VER_BUILD __BUILD_NUMBER_
#ifdef __cplusplus
}
#endif
#endif /* _HOST_VERSION_H_ */

View File

@ -0,0 +1,575 @@
//------------------------------------------------------------------------------
// <copyright file="htc_api.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_API_H_
#define _HTC_API_H_
#include "htc_packet.h"
#include <htc.h>
#include <htc_services.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* TODO.. for BMI */
#define ENDPOINT1 0
// TODO -remove me, but we have to fix BMI first
#define HTC_MAILBOX_NUM_MAX 4
/* this is the amount of header room required by users of HTC */
#define HTC_HEADER_LEN HTC_HDR_LENGTH
typedef void *HTC_HANDLE;
typedef A_UINT16 HTC_SERVICE_ID;
typedef struct _HTC_INIT_INFO {
void *pContext; /* context for target failure notification */
void (*TargetFailure)(void *Instance, A_STATUS Status);
} HTC_INIT_INFO;
/* per service connection send completion */
typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,HTC_PACKET *);
/* per service connection callback when a plurality of packets have been sent
* The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback)
* to hold a list of completed send packets.
* If the handler cannot fully traverse the packet queue before returning, it should
* transfer the items of the queue into the caller's private queue using:
* HTC_PACKET_ENQUEUE() */
typedef void (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,HTC_PACKET_QUEUE *);
/* per service connection pkt received */
typedef void (*HTC_EP_RECV_PKT)(void *,HTC_PACKET *);
/* per service connection callback when a plurality of packets are received
* The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback)
* to hold a list of recv packets.
* If the handler cannot fully traverse the packet queue before returning, it should
* transfer the items of the queue into the caller's private queue using:
* HTC_PACKET_ENQUEUE() */
typedef void (*HTC_EP_RECV_PKT_MULTIPLE)(void *,HTC_PACKET_QUEUE *);
/* Optional per service connection receive buffer re-fill callback,
* On some OSes (like Linux) packets are allocated from a global pool and indicated up
* to the network stack. The driver never gets the packets back from the OS. For these OSes
* a refill callback can be used to allocate and re-queue buffers into HTC.
*
* On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and
* the driver can re-queue these buffers into HTC. In this regard a refill callback is
* unnecessary */
typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint);
/* Optional per service connection receive buffer allocation callback.
* On some systems packet buffers are an extremely limited resource. Rather than
* queue largest-possible-sized buffers to HTC, some systems would rather
* allocate a specific size as the packet is received. The trade off is
* slightly more processing (callback invoked for each RX packet)
* for the benefit of committing fewer buffer resources into HTC.
*
* The callback is provided the length of the pending packet to fetch. This includes the
* HTC header length plus the length of payload. The callback can return a pointer to
* the allocated HTC packet for immediate use.
*
* Alternatively a variant of this handler can be used to allocate large receive packets as needed.
* For example an application can use the refill mechanism for normal packets and the recv-alloc mechanism to
* handle the case where a large packet buffer is required. This can significantly reduce the
* amount of "committed" memory used to receive packets.
*
* */
typedef HTC_PACKET *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length);
typedef enum _HTC_SEND_FULL_ACTION {
HTC_SEND_FULL_KEEP = 0, /* packet that overflowed should be kept in the queue */
HTC_SEND_FULL_DROP = 1, /* packet that overflowed should be dropped */
} HTC_SEND_FULL_ACTION;
/* Optional per service connection callback when a send queue is full. This can occur if the
* host continues queueing up TX packets faster than credits can arrive
* To prevent the host (on some Oses like Linux) from continuously queueing packets
* and consuming resources, this callback is provided so that that the host
* can disable TX in the subsystem (i.e. network stack).
* This callback is invoked for each packet that "overflows" the HTC queue. The callback can
* determine whether the new packet that overflowed the queue can be kept (HTC_SEND_FULL_KEEP) or
* dropped (HTC_SEND_FULL_DROP). If a packet is dropped, the EpTxComplete handler will be called
* and the packet's status field will be set to A_NO_RESOURCE.
* Other OSes require a "per-packet" indication for each completed TX packet, this
* closed loop mechanism will prevent the network stack from overunning the NIC
* The packet to keep or drop is passed for inspection to the registered handler the handler
* must ONLY inspect the packet, it may not free or reclaim the packet. */
typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_PACKET *pPacket);
typedef struct _HTC_EP_CALLBACKS {
void *pContext; /* context for each callback */
HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */
HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */
HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */
HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */
HTC_EP_RECV_ALLOC EpRecvAlloc; /* OPTIONAL recv allocation callback */
HTC_EP_RECV_ALLOC EpRecvAllocThresh; /* OPTIONAL recv allocation callback based on a threshold */
HTC_EP_SEND_PKT_COMP_MULTIPLE EpTxCompleteMultiple; /* OPTIONAL completion handler for multiple complete
indications (EpTxComplete must be NULL) */
HTC_EP_RECV_PKT_MULTIPLE EpRecvPktMultiple; /* OPTIONAL completion handler for multiple
recv packet indications (EpRecv must be NULL) */
int RecvAllocThreshold; /* if EpRecvAllocThresh is non-NULL, HTC will compare the
threshold value to the current recv packet length and invoke
the EpRecvAllocThresh callback to acquire a packet buffer */
int RecvRefillWaterMark; /* if a EpRecvRefill handler is provided, this value
can be used to set a trigger refill callback
when the recv queue drops below this value
if set to 0, the refill is only called when packets
are empty */
} HTC_EP_CALLBACKS;
/* service connection information */
typedef struct _HTC_SERVICE_CONNECT_REQ {
HTC_SERVICE_ID ServiceID; /* service ID to connect to */
A_UINT16 ConnectionFlags; /* connection flags, see htc protocol definition */
A_UINT8 *pMetaData; /* ptr to optional service-specific meta-data */
A_UINT8 MetaDataLength; /* optional meta data length */
HTC_EP_CALLBACKS EpCallbacks; /* endpoint callbacks */
int MaxSendQueueDepth; /* maximum depth of any send queue */
A_UINT32 LocalConnectionFlags; /* HTC flags for the host-side (local) connection */
unsigned int MaxSendMsgSize; /* override max message size in send direction */
} HTC_SERVICE_CONNECT_REQ;
#define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0) /* enable send bundle padding for this endpoint */
/* service connection response information */
typedef struct _HTC_SERVICE_CONNECT_RESP {
A_UINT8 *pMetaData; /* caller supplied buffer to optional meta-data */
A_UINT8 BufferLength; /* length of caller supplied buffer */
A_UINT8 ActualLength; /* actual length of meta data */
HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */
unsigned int MaxMsgLength; /* max length of all messages over this endpoint */
A_UINT8 ConnectRespCode; /* connect response code from target */
} HTC_SERVICE_CONNECT_RESP;
/* endpoint distribution structure */
typedef struct _HTC_ENDPOINT_CREDIT_DIST {
struct _HTC_ENDPOINT_CREDIT_DIST *pNext;
struct _HTC_ENDPOINT_CREDIT_DIST *pPrev;
HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */
HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */
A_UINT32 DistFlags; /* distribution flags, distribution function can
set default activity using SET_EP_ACTIVE() macro */
int TxCreditsNorm; /* credits for normal operation, anything above this
indicates the endpoint is over-subscribed, this field
is only relevant to the credit distribution function */
int TxCreditsMin; /* floor for credit distribution, this field is
only relevant to the credit distribution function */
int TxCreditsAssigned; /* number of credits assigned to this EP, this field
is only relevant to the credit dist function */
int TxCredits; /* current credits available, this field is used by
HTC to determine whether a message can be sent or
must be queued */
int TxCreditsToDist; /* pending credits to distribute on this endpoint, this
is set by HTC when credit reports arrive.
The credit distribution functions sets this to zero
when it distributes the credits */
int TxCreditsSeek; /* this is the number of credits that the current pending TX
packet needs to transmit. This is set by HTC when
and endpoint needs credits in order to transmit */
int TxCreditSize; /* size in bytes of each credit (set by HTC) */
int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */
void *pHTCReserved; /* reserved for HTC use */
int TxQueueDepth; /* current depth of TX queue , i.e. messages waiting for credits
This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE
or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
that has non-zero credits to recover
*/
} HTC_ENDPOINT_CREDIT_DIST;
#define HTC_EP_ACTIVE ((A_UINT32) (1u << 31))
/* macro to check if an endpoint has gone active, useful for credit
* distributions */
#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE)
#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE
/* credit distibution code that is passed into the distrbution function,
* there are mandatory and optional codes that must be handled */
typedef enum _HTC_CREDIT_DIST_REASON {
HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed
send operations (MANDATORY) resulting in credit reports */
HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occured (OPTIONAL) */
HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */
HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by
the distribution function */
} HTC_CREDIT_DIST_REASON;
typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context,
HTC_ENDPOINT_CREDIT_DIST *pEPList,
HTC_CREDIT_DIST_REASON Reason);
typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context,
HTC_ENDPOINT_CREDIT_DIST *pEPList,
int TotalCredits);
/* endpoint statistics action */
typedef enum _HTC_ENDPOINT_STAT_ACTION {
HTC_EP_STAT_SAMPLE = 0, /* only read statistics */
HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */
HTC_EP_STAT_CLEAR /* clear only */
} HTC_ENDPOINT_STAT_ACTION;
/* endpoint statistics */
typedef struct _HTC_ENDPOINT_STATS {
A_UINT32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on
this endpoint */
A_UINT32 TxIssued; /* running count of total TX packets issued */
A_UINT32 TxPacketsBundled; /* running count of TX packets that were issued in bundles */
A_UINT32 TxBundles; /* running count of TX bundles that were issued */
A_UINT32 TxDropped; /* tx packets that were dropped */
A_UINT32 TxCreditRpts; /* running count of total credit reports received for this endpoint */
A_UINT32 TxCreditRptsFromRx; /* credit reports received from this endpoint's RX packets */
A_UINT32 TxCreditRptsFromOther; /* credit reports received from RX packets of other endpoints */
A_UINT32 TxCreditRptsFromEp0; /* credit reports received from endpoint 0 RX packets */
A_UINT32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */
A_UINT32 TxCreditsFromOther; /* count of credits received via another endpoint */
A_UINT32 TxCreditsFromEp0; /* count of credits received via another endpoint */
A_UINT32 TxCreditsConsummed; /* count of consummed credits */
A_UINT32 TxCreditsReturned; /* count of credits returned */
A_UINT32 RxReceived; /* count of RX packets received */
A_UINT32 RxLookAheads; /* count of lookahead records
found in messages received on this endpoint */
A_UINT32 RxPacketsBundled; /* count of recv packets received in a bundle */
A_UINT32 RxBundleLookAheads; /* count of number of bundled lookaheads */
A_UINT32 RxBundleIndFromHdr; /* count of the number of bundle indications from the HTC header */
A_UINT32 RxAllocThreshHit; /* count of the number of times the recv allocation threshhold was hit */
A_UINT32 RxAllocThreshBytes; /* total number of bytes */
} HTC_ENDPOINT_STATS;
/* ------ Function Prototypes ------ */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Create an instance of HTC over the underlying HIF device
@function name: HTCCreate
@input: HifDevice - hif device handle,
pInfo - initialization information
@output:
@return: HTC_HANDLE on success, NULL on failure
@notes:
@example:
@see also: HTCDestroy
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
HTC_HANDLE HTCCreate(void *HifDevice, HTC_INIT_INFO *pInfo);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Get the underlying HIF device handle
@function name: HTCGetHifDevice
@input: HTCHandle - handle passed into the AddInstance callback
@output:
@return: opaque HIF device handle usable in HIF API calls.
@notes:
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void *HTCGetHifDevice(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Set credit distribution parameters
@function name: HTCSetCreditDistribution
@input: HTCHandle - HTC handle
pCreditDistCont - caller supplied context to pass into distribution functions
CreditDistFunc - Distribution function callback
CreditDistInit - Credit Distribution initialization callback
ServicePriorityOrder - Array containing list of service IDs, lowest index is highest
priority
ListLength - number of elements in ServicePriorityOrder
@output:
@return:
@notes: The user can set a custom credit distribution function to handle special requirements
for each endpoint. A default credit distribution routine can be used by setting
CreditInitFunc to NULL. The default credit distribution is only provided for simple
"fair" credit distribution without regard to any prioritization.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCSetCreditDistribution(HTC_HANDLE HTCHandle,
void *pCreditDistContext,
HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
HTC_SERVICE_ID ServicePriorityOrder[],
int ListLength);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Wait for the target to indicate the HTC layer is ready
@function name: HTCWaitTarget
@input: HTCHandle - HTC handle
@output:
@return:
@notes: This API blocks until the target responds with an HTC ready message.
The caller should not connect services until the target has indicated it is
ready.
@example:
@see also: HTCConnectService
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Start target service communications
@function name: HTCStart
@input: HTCHandle - HTC handle
@output:
@return:
@notes: This API indicates to the target that the service connection phase is complete
and the target can freely start all connected services. This API should only be
called AFTER all service connections have been made. TCStart will issue a
SETUP_COMPLETE message to the target to indicate that all service connections
have been made and the target can start communicating over the endpoints.
@example:
@see also: HTCConnectService
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCStart(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Add receive packet to HTC
@function name: HTCAddReceivePkt
@input: HTCHandle - HTC handle
pPacket - HTC receive packet to add
@output:
@return: A_OK on success
@notes: user must supply HTC packets for capturing incomming HTC frames. The caller
must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
macro.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Connect to an HTC service
@function name: HTCConnectService
@input: HTCHandle - HTC handle
pReq - connection details
@output: pResp - connection response
@return:
@notes: Service connections must be performed before HTCStart. User provides callback handlers
for various endpoint events.
@example:
@see also: HTCStart
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCConnectService(HTC_HANDLE HTCHandle,
HTC_SERVICE_CONNECT_REQ *pReq,
HTC_SERVICE_CONNECT_RESP *pResp);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Send an HTC packet
@function name: HTCSendPkt
@input: HTCHandle - HTC handle
pPacket - packet to send
@output:
@return: A_OK
@notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro.
This interface is fully asynchronous. On error, HTC SendPkt will
call the registered Endpoint callback to cleanup the packet.
@example:
@see also: HTCFlushEndpoint
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Stop HTC service communications
@function name: HTCStop
@input: HTCHandle - HTC handle
@output:
@return:
@notes: HTC communications is halted. All receive and pending TX packets will
be flushed.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCStop(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Destory HTC service
@function name: HTCDestroy
@input: HTCHandle
@output:
@return:
@notes: This cleans up all resources allocated by HTCCreate().
@example:
@see also: HTCCreate
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCDestroy(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Flush pending TX packets
@function name: HTCFlushEndpoint
@input: HTCHandle - HTC handle
Endpoint - Endpoint to flush
Tag - flush tag
@output:
@return:
@notes: The Tag parameter is used to selectively flush packets with matching tags.
The value of 0 forces all packets to be flush regardless of tag.
@example:
@see also: HTCSendPkt
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Dump credit distribution state
@function name: HTCDumpCreditStates
@input: HTCHandle - HTC handle
@output:
@return:
@notes: This dumps all credit distribution information to the debugger
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCDumpCreditStates(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Indicate a traffic activity change on an endpoint
@function name: HTCIndicateActivityChange
@input: HTCHandle - HTC handle
Endpoint - endpoint in which activity has changed
Active - TRUE if active, FALSE if it has become inactive
@output:
@return:
@notes: This triggers the registered credit distribution function to
re-adjust credits for active/inactive endpoints.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
HTC_ENDPOINT_ID Endpoint,
A_BOOL Active);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Get endpoint statistics
@function name: HTCGetEndpointStatistics
@input: HTCHandle - HTC handle
Endpoint - Endpoint identifier
Action - action to take with statistics
@output:
pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR)
@return: TRUE if statistics profiling is enabled, otherwise FALSE.
@notes: Statistics is a compile-time option and this function may return FALSE
if HTC is not compiled with profiling.
The caller can specify the statistic "action" to take when sampling
the statistics. This includes:
HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values.
HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics
are cleared.
HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for
pStats
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
HTC_ENDPOINT_ID Endpoint,
HTC_ENDPOINT_STAT_ACTION Action,
HTC_ENDPOINT_STATS *pStats);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Unblock HTC message reception
@function name: HTCUnblockRecv
@input: HTCHandle - HTC handle
@output:
@return:
@notes:
HTC will block the receiver if the EpRecvAlloc callback fails to provide a packet.
The caller can use this API to indicate to HTC when resources (buffers) are available
such that the receiver can be unblocked and HTC may re-attempt fetching the pending message.
This API is not required if the user uses the EpRecvRefill callback or uses the HTCAddReceivePacket()
API to recycle or provide receive packets to HTC.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void HTCUnblockRecv(HTC_HANDLE HTCHandle);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: send a series of HTC packets
@function name: HTCSendPktsMultiple
@input: HTCHandle - HTC handle
pPktQueue - local queue holding packets to send
@output:
@return: A_OK
@notes: Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro.
The queue must only contain packets directed at the same endpoint.
Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the TX packets in FIFO order.
This API will remove the packets from the pkt queue and place them into the HTC Tx Queue
and bundle messages where possible.
The caller may allocate the pkt queue on the stack to hold the packets.
This interface is fully asynchronous. On error, HTCSendPkts will
call the registered Endpoint callback to cleanup the packet.
@example:
@see also: HTCFlushEndpoint
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Add multiple receive packets to HTC
@function name: HTCAddReceivePktMultiple
@input: HTCHandle - HTC handle
pPktQueue - HTC receive packet queue holding packets to add
@output:
@return: A_OK on success
@notes: user must supply HTC packets for capturing incomming HTC frames. The caller
must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
macro. The queue must only contain recv packets for the same endpoint.
Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the recv packet.
This API will remove the packets from the pkt queue and place them into internal
recv packet list.
The caller may allocate the pkt queue on the stack to hold the packets.
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Check if an endpoint is marked active
@function name: HTCIsEndpointActive
@input: HTCHandle - HTC handle
Endpoint - endpoint to check for active state
@output:
@return: returns TRUE if Endpoint is Active
@notes:
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
A_BOOL HTCIsEndpointActive(HTC_HANDLE HTCHandle,
HTC_ENDPOINT_ID Endpoint);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@desc: Get the number of recv buffers currently queued into an HTC endpoint
@function name: HTCGetNumRecvBuffers
@input: HTCHandle - HTC handle
Endpoint - endpoint to check
@output:
@return: returns number of buffers in queue
@notes:
@example:
@see also:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle,
HTC_ENDPOINT_ID Endpoint);
/* internally used functions for testing... */
void HTCEnableRecv(HTC_HANDLE HTCHandle);
void HTCDisableRecv(HTC_HANDLE HTCHandle);
A_STATUS HTCWaitForPendingRecv(HTC_HANDLE HTCHandle,
A_UINT32 TimeoutInMs,
A_BOOL *pbIsRecvPending);
#ifdef __cplusplus
}
#endif
#endif /* _HTC_API_H_ */

View File

@ -0,0 +1,227 @@
//------------------------------------------------------------------------------
// <copyright file="htc_packet.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_PACKET_H_
#define HTC_PACKET_H_
#include "dl_list.h"
/* ------ Endpoint IDS ------ */
typedef enum
{
ENDPOINT_UNUSED = -1,
ENDPOINT_0 = 0,
ENDPOINT_1 = 1,
ENDPOINT_2 = 2,
ENDPOINT_3,
ENDPOINT_4,
ENDPOINT_5,
ENDPOINT_6,
ENDPOINT_7,
ENDPOINT_8,
ENDPOINT_MAX,
} HTC_ENDPOINT_ID;
struct _HTC_PACKET;
typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *);
typedef A_UINT16 HTC_TX_TAG;
typedef struct _HTC_TX_PACKET_INFO {
HTC_TX_TAG Tag; /* tag used to selective flush packets */
int CreditsUsed; /* number of credits used for this TX packet (HTC internal) */
A_UINT8 SendFlags; /* send flags (HTC internal) */
int SeqNo; /* internal seq no for debugging (HTC internal) */
} HTC_TX_PACKET_INFO;
#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */
#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */
#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */
typedef struct _HTC_RX_PACKET_INFO {
A_UINT32 ExpectedHdr; /* HTC internal use */
A_UINT32 HTCRxFlags; /* HTC internal use */
A_UINT32 IndicationFlags; /* indication flags set on each RX packet indication */
} HTC_RX_PACKET_INFO;
#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) /* more packets on this endpoint are being fetched */
/* wrapper around endpoint-specific packets */
typedef struct _HTC_PACKET {
DL_LIST ListLink; /* double link */
void *pPktContext; /* caller's per packet specific context */
A_UINT8 *pBufferStart; /* the true buffer start , the caller can
store the real buffer start here. In
receive callbacks, the HTC layer sets pBuffer
to the start of the payload past the header. This
field allows the caller to reset pBuffer when it
recycles receive packets back to HTC */
/*
* Pointer to the start of the buffer. In the transmit
* direction this points to the start of the payload. In the
* receive direction, however, the buffer when queued up
* points to the start of the HTC header but when returned
* to the caller points to the start of the payload
*/
A_UINT8 *pBuffer; /* payload start (RX/TX) */
A_UINT32 BufferLength; /* length of buffer */
A_UINT32 ActualLength; /* actual length of payload */
HTC_ENDPOINT_ID Endpoint; /* endpoint that this packet was sent/recv'd from */
A_STATUS Status; /* completion status */
union {
HTC_TX_PACKET_INFO AsTx; /* Tx Packet specific info */
HTC_RX_PACKET_INFO AsRx; /* Rx Packet specific info */
} PktInfo;
/* the following fields are for internal HTC use */
HTC_PACKET_COMPLETION Completion; /* completion */
void *pContext; /* HTC private completion context */
} HTC_PACKET;
#define COMPLETE_HTC_PACKET(p,status) \
{ \
(p)->Status = (status); \
(p)->Completion((p)->pContext,(p)); \
}
#define INIT_HTC_PACKET_INFO(p,b,len) \
{ \
(p)->pBufferStart = (b); \
(p)->BufferLength = (len); \
}
/* macro to set an initial RX packet for refilling HTC */
#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \
{ \
(p)->pPktContext = (c); \
(p)->pBuffer = (b); \
(p)->pBufferStart = (b); \
(p)->BufferLength = (len); \
(p)->Endpoint = (ep); \
}
/* fast macro to recycle an RX packet that will be re-queued to HTC */
#define HTC_PACKET_RESET_RX(p) \
{ (p)->pBuffer = (p)->pBufferStart; (p)->ActualLength = 0; }
/* macro to set packet parameters for TX */
#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \
{ \
(p)->pPktContext = (c); \
(p)->pBuffer = (b); \
(p)->ActualLength = (len); \
(p)->Endpoint = (ep); \
(p)->PktInfo.AsTx.Tag = (tag); \
}
/* HTC Packet Queueing Macros */
typedef struct _HTC_PACKET_QUEUE {
DL_LIST QueueHead;
int Depth;
} HTC_PACKET_QUEUE;
/* initialize queue */
#define INIT_HTC_PACKET_QUEUE(pQ) \
{ \
DL_LIST_INIT(&(pQ)->QueueHead); \
(pQ)->Depth = 0; \
}
/* enqueue HTC packet to the tail of the queue */
#define HTC_PACKET_ENQUEUE(pQ,p) \
{ DL_ListInsertTail(&(pQ)->QueueHead,&(p)->ListLink); \
(pQ)->Depth++; \
}
/* enqueue HTC packet to the tail of the queue */
#define HTC_PACKET_ENQUEUE_TO_HEAD(pQ,p) \
{ DL_ListInsertHead(&(pQ)->QueueHead,&(p)->ListLink); \
(pQ)->Depth++; \
}
/* test if a queue is empty */
#define HTC_QUEUE_EMPTY(pQ) ((pQ)->Depth == 0)
/* get packet at head without removing it */
static INLINE HTC_PACKET *HTC_GET_PKT_AT_HEAD(HTC_PACKET_QUEUE *queue) {
if (queue->Depth == 0) {
return NULL;
}
return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),HTC_PACKET,ListLink);
}
/* remove a packet from a queue, where-ever it is in the queue */
#define HTC_PACKET_REMOVE(pQ,p) \
{ \
DL_ListRemove(&(p)->ListLink); \
(pQ)->Depth--; \
}
/* dequeue an HTC packet from the head of the queue */
static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE(HTC_PACKET_QUEUE *queue) {
DL_LIST *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead);
if (pItem != NULL) {
queue->Depth--;
return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
}
return NULL;
}
/* dequeue an HTC packet from the tail of the queue */
static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE_TAIL(HTC_PACKET_QUEUE *queue) {
DL_LIST *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead);
if (pItem != NULL) {
queue->Depth--;
return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
}
return NULL;
}
#define HTC_PACKET_QUEUE_DEPTH(pQ) (pQ)->Depth
#define HTC_GET_ENDPOINT_FROM_PKT(p) (p)->Endpoint
#define HTC_GET_TAG_FROM_PKT(p) (p)->PktInfo.AsTx.Tag
/* transfer the packets from one queue to the tail of another queue */
#define HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(pQDest,pQSrc) \
{ \
DL_ListTransferItemsToTail(&(pQDest)->QueueHead,&(pQSrc)->QueueHead); \
(pQDest)->Depth += (pQSrc)->Depth; \
(pQSrc)->Depth = 0; \
}
/* fast version to init and add a single packet to a queue */
#define INIT_HTC_PACKET_QUEUE_AND_ADD(pQ,pP) \
{ \
DL_LIST_INIT_AND_ADD(&(pQ)->QueueHead,&(pP)->ListLink) \
(pQ)->Depth = 1; \
}
#define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \
ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), HTC_PACKET, ListLink)
#define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END
#endif /*HTC_PACKET_H_*/

View File

@ -0,0 +1,116 @@
//------------------------------------------------------------------------------
// <copyright file="p2p_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 definitions exported by the P2P host module.
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _HOST_P2P_API_H_
#define _HOST_P2P_API_H_
#include "utils_api.h"
#include "wmi.h"
#ifdef __cplusplus
extern "C" {
#endif
#define P2P_OUI 0x99a6f50
static int __inline
isp2poui(const A_UINT8 *frm)
{
return frm[1] > 3 && LE_READ_4(frm+2) == (P2P_OUI);
}
/* API function declarations */
void *p2p_init(void *dev);
struct host_p2p_dev *p2p_get_device(void *p2p_dev_ctx, const A_UINT8 *addr);
void *p2p_bssinfo_rx(void *p2p_dev_ctx, WMI_BI_FTYPE fType, A_UINT8 *addr, A_UINT16 channel, const A_UINT8 *data, A_UINT32 len);
void p2p_go_neg_req_rx(void *p2p_dev_ctx, const A_UINT8 *datap, A_UINT8 len);
void p2p_invite_req_rx(void *p2p_dev_ctx, const A_UINT8 *datap, A_UINT8 len);
void p2p_prov_disc_req_rx(void *p2p_dev_ctx, const A_UINT8 *datap, A_UINT8 len);
void p2p_prov_disc_resp_rx(void *p2p_dev_ctx,
const A_UINT8 *datap, A_UINT8 len);
void p2p_start_sdpd_event_rx(void *p2p_dev_ctx);
void p2p_sdpd_rx_event_rx(void *p2p_dev_ctx,
const A_UINT8 *datap, A_UINT8 len);
void p2p_free_all_devices(void *ctx);
void p2p_device_free(void *peer_dev);
A_STATUS p2p_auth_go_neg(void *ctx,
WMI_P2P_GO_NEG_START_CMD *auth_go_neg_param);
A_STATUS p2p_auth_invite(void *ctx, A_UINT8 *auth_peer);
A_STATUS p2p_peer_reject(void *ctx, A_UINT8 *peer_addr);
A_STATUS p2p_go_neg_start(void *ctx, WMI_P2P_GO_NEG_START_CMD *go_neg_param);
A_STATUS p2p_invite_cmd(void *ctx, WMI_P2P_INVITE_CMD *invite_param);
A_STATUS p2p_prov_disc_req(void *ctx, A_UINT8 *peer, A_UINT16 wps_method);
A_STATUS p2p_peer(void *ctx, A_UINT8 *peer, A_UINT8 next);
A_STATUS p2p_get_device_p2p_buf(void *ctx, A_UINT8 *peer, A_UINT8 **p2p_buf, A_UINT8 *p2p_buf_len);
A_STATUS wmi_p2p_get_go_params(void *ctx, A_UINT8 *go_dev_addr,
A_UINT16 *oper_freq, A_UINT8 *ssid, A_UINT8 *ssid_len);
A_STATUS p2p_get_devaddr (void *ctx, A_UINT8 *intf_addr);
A_STATUS p2p_get_ifaddr (void *ctx, A_UINT8 *dev_addr);
struct host_p2p_dev *p2p_get_device_intf_addrs(void *ctx, const A_UINT8 *intfaddr);
void p2p_increment_dev_ref_count(struct host_p2p_dev *dev);
void p2p_free_all_sd_queries(void *ctx);
A_STATUS p2p_sd_request(void *ctx, A_UINT8 *peer_addr, A_UINT8 *tlvbuf,
A_UINT8 tlv_buflen, A_UINT32 *qid);
A_STATUS p2p_sdpd_tx_cmd(void *ctx, WMI_P2P_SDPD_TX_CMD *sdpd_tx_cmd, A_UINT32 *qid);
A_STATUS p2p_sd_cancel_request(void *ctx, A_UINT32 qid);
void p2p_go_neg_complete_rx(void *ctx, const A_UINT8 *datap, A_UINT8 len);
int p2p_get_peer_info(void *ctx, A_UINT8 *peer_addr, A_UINT8 *buf, A_UINT32 buflen);
int p2p_get_next_addr(void *ctx, A_UINT8 *addr, A_UINT8 *buf, A_UINT32 buflen, int first_element);
void p2p_clear_peers_reported_flag(void *ctx);
void p2p_clear_peers_authorized_flag(void *ctx, const A_UINT8 *addr);
#ifdef __cplusplus
}
#endif
#endif /* _HOST_P2P_API_H_ */

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2008 Atheros Communications Inc.
*
* 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 _PROJECT_H_
#define _PROJECT_H_
#include "queue.h"
#define OS_TIMER_FUNC(fn) void fn(A_HANDLE hdl, void *context)
#define OS_TIMER_FUNC_PTR(fn) void (* fn)(A_HANDLE hdl, void *context)
#define OS_CANCEL_TIMER(timer_hdl) A_UNTIMEOUT(timer_hdl)
#define OS_SET_TIMER(timer_hdl, period, repeat) A_TIMEOUT_MS(timer_hdl, period, repeat)
#define OS_INIT_TIMER(timer_hdl, fn, arg) A_INIT_TIMER(timer_hdl, fn, arg)
typedef A_TIMER os_timer_t;
/* Memory related */
#define OS_MEMZERO(ptr, size) A_MEMZERO(ptr, size)
#define OS_MEMCPY(dst, src, len) A_MEMCPY(dst, src, len)
#define OS_MALLOC(nbytes) A_MALLOC(nbytes)
#define OS_FREE(ptr) A_FREE(ptr)
#endif

View File

@ -0,0 +1,349 @@
//------------------------------------------------------------------------------
// <copyright file="target_reg_table.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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Target register table macros and structure definitions
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef TARGET_REG_TABLE_H_
#define TARGET_REG_TABLE_H_
#include "targaddrs.h"
/*** WARNING : Add to the end of the TABLE! do not change the order ****/
typedef struct targetdef_s {
A_UINT32 d_RTC_SOC_BASE_ADDRESS;
A_UINT32 d_RTC_WMAC_BASE_ADDRESS;
A_UINT32 d_SYSTEM_SLEEP_OFFSET;
A_UINT32 d_WLAN_SYSTEM_SLEEP_OFFSET;
A_UINT32 d_WLAN_SYSTEM_SLEEP_DISABLE_LSB;
A_UINT32 d_WLAN_SYSTEM_SLEEP_DISABLE_MASK;
A_UINT32 d_CLOCK_CONTROL_OFFSET;
A_UINT32 d_CLOCK_CONTROL_SI0_CLK_MASK;
A_UINT32 d_RESET_CONTROL_OFFSET;
A_UINT32 d_RESET_CONTROL_MBOX_RST_MASK;
A_UINT32 d_RESET_CONTROL_SI0_RST_MASK;
A_UINT32 d_WLAN_RESET_CONTROL_OFFSET;
A_UINT32 d_WLAN_RESET_CONTROL_COLD_RST_MASK;
A_UINT32 d_WLAN_RESET_CONTROL_WARM_RST_MASK;
A_UINT32 d_GPIO_BASE_ADDRESS;
A_UINT32 d_GPIO_PIN0_OFFSET;
A_UINT32 d_GPIO_PIN1_OFFSET;
A_UINT32 d_GPIO_PIN0_CONFIG_MASK;
A_UINT32 d_GPIO_PIN1_CONFIG_MASK;
A_UINT32 d_SI_CONFIG_BIDIR_OD_DATA_LSB;
A_UINT32 d_SI_CONFIG_BIDIR_OD_DATA_MASK;
A_UINT32 d_SI_CONFIG_I2C_LSB;
A_UINT32 d_SI_CONFIG_I2C_MASK;
A_UINT32 d_SI_CONFIG_POS_SAMPLE_LSB;
A_UINT32 d_SI_CONFIG_POS_SAMPLE_MASK;
A_UINT32 d_SI_CONFIG_INACTIVE_CLK_LSB;
A_UINT32 d_SI_CONFIG_INACTIVE_CLK_MASK;
A_UINT32 d_SI_CONFIG_INACTIVE_DATA_LSB;
A_UINT32 d_SI_CONFIG_INACTIVE_DATA_MASK;
A_UINT32 d_SI_CONFIG_DIVIDER_LSB;
A_UINT32 d_SI_CONFIG_DIVIDER_MASK;
A_UINT32 d_SI_BASE_ADDRESS;
A_UINT32 d_SI_CONFIG_OFFSET;
A_UINT32 d_SI_TX_DATA0_OFFSET;
A_UINT32 d_SI_TX_DATA1_OFFSET;
A_UINT32 d_SI_RX_DATA0_OFFSET;
A_UINT32 d_SI_RX_DATA1_OFFSET;
A_UINT32 d_SI_CS_OFFSET;
A_UINT32 d_SI_CS_DONE_ERR_MASK;
A_UINT32 d_SI_CS_DONE_INT_MASK;
A_UINT32 d_SI_CS_START_LSB;
A_UINT32 d_SI_CS_START_MASK;
A_UINT32 d_SI_CS_RX_CNT_LSB;
A_UINT32 d_SI_CS_RX_CNT_MASK;
A_UINT32 d_SI_CS_TX_CNT_LSB;
A_UINT32 d_SI_CS_TX_CNT_MASK;
A_UINT32 d_BOARD_DATA_SZ;
A_UINT32 d_BOARD_EXT_DATA_SZ;
A_UINT32 d_MBOX_BASE_ADDRESS;
A_UINT32 d_LOCAL_SCRATCH_OFFSET;
A_UINT32 d_CPU_CLOCK_OFFSET;
A_UINT32 d_LPO_CAL_OFFSET;
A_UINT32 d_GPIO_PIN10_OFFSET;
A_UINT32 d_GPIO_PIN11_OFFSET;
A_UINT32 d_GPIO_PIN12_OFFSET;
A_UINT32 d_GPIO_PIN13_OFFSET;
A_UINT32 d_CLOCK_GPIO_OFFSET;
A_UINT32 d_CPU_CLOCK_STANDARD_LSB;
A_UINT32 d_CPU_CLOCK_STANDARD_MASK;
A_UINT32 d_LPO_CAL_ENABLE_LSB;
A_UINT32 d_LPO_CAL_ENABLE_MASK;
A_UINT32 d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB;
A_UINT32 d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK;
A_UINT32 d_ANALOG_INTF_BASE_ADDRESS;
} TARGET_REGISTER_TABLE;
#define ATH_UNSUPPORTED_REG_OFFSET 0xffffffff
#define ATH_SUPPORTED_BY_TARGET(reg_offset) ((reg_offset) != ATH_UNSUPPORTED_REG_OFFSET)
#define BOARD_DATA_SZ_MAX 2048
#if defined(MY_TARGET_DEF) /* { */
#if defined(ATHR_WIN_DEF)
#define ATH_REG_TABLE_DIRECT_ASSIGN
#endif
/* Cross-platform compatibility */
#if !defined(SOC_RESET_CONTROL_OFFSET) && defined(RESET_CONTROL_OFFSET)
#define SOC_RESET_CONTROL_OFFSET RESET_CONTROL_OFFSET
#endif
#if !defined(CLOCK_GPIO_OFFSET)
#define CLOCK_GPIO_OFFSET ATH_UNSUPPORTED_REG_OFFSET
#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB 0
#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0
#endif
#ifdef ATH_REG_TABLE_DIRECT_ASSIGN
static struct targetdef_s my_target_def = {
RTC_SOC_BASE_ADDRESS,
RTC_WMAC_BASE_ADDRESS,
SYSTEM_SLEEP_OFFSET,
WLAN_SYSTEM_SLEEP_OFFSET,
WLAN_SYSTEM_SLEEP_DISABLE_LSB,
WLAN_SYSTEM_SLEEP_DISABLE_MASK,
CLOCK_CONTROL_OFFSET,
CLOCK_CONTROL_SI0_CLK_MASK,
SOC_RESET_CONTROL_OFFSET,
RESET_CONTROL_MBOX_RST_MASK,
RESET_CONTROL_SI0_RST_MASK,
WLAN_RESET_CONTROL_OFFSET,
WLAN_RESET_CONTROL_COLD_RST_MASK,
WLAN_RESET_CONTROL_WARM_RST_MASK,
GPIO_BASE_ADDRESS,
GPIO_PIN0_OFFSET,
GPIO_PIN1_OFFSET,
GPIO_PIN0_CONFIG_MASK,
GPIO_PIN1_CONFIG_MASK,
SI_CONFIG_BIDIR_OD_DATA_LSB,
SI_CONFIG_BIDIR_OD_DATA_MASK,
SI_CONFIG_I2C_LSB,
SI_CONFIG_I2C_MASK,
SI_CONFIG_POS_SAMPLE_LSB,
SI_CONFIG_POS_SAMPLE_MASK,
SI_CONFIG_INACTIVE_CLK_LSB,
SI_CONFIG_INACTIVE_CLK_MASK,
SI_CONFIG_INACTIVE_DATA_LSB,
SI_CONFIG_INACTIVE_DATA_MASK,
SI_CONFIG_DIVIDER_LSB,
SI_CONFIG_DIVIDER_MASK,
SI_BASE_ADDRESS,
SI_CONFIG_OFFSET,
SI_TX_DATA0_OFFSET,
SI_TX_DATA1_OFFSET,
SI_RX_DATA0_OFFSET,
SI_RX_DATA1_OFFSET,
SI_CS_OFFSET,
SI_CS_DONE_ERR_MASK,
SI_CS_DONE_INT_MASK,
SI_CS_START_LSB,
SI_CS_START_MASK,
SI_CS_RX_CNT_LSB,
SI_CS_RX_CNT_MASK,
SI_CS_TX_CNT_LSB,
SI_CS_TX_CNT_MASK,
MY_TARGET_BOARD_DATA_SZ,
MY_TARGET_BOARD_EXT_DATA_SZ,
MBOX_BASE_ADDRESS,
LOCAL_SCRATCH_OFFSET,
CPU_CLOCK_OFFSET,
LPO_CAL_OFFSET,
GPIO_PIN10_OFFSET,
GPIO_PIN11_OFFSET,
GPIO_PIN12_OFFSET,
GPIO_PIN13_OFFSET,
CLOCK_GPIO_OFFSET,
CPU_CLOCK_STANDARD_LSB,
CPU_CLOCK_STANDARD_MASK,
LPO_CAL_ENABLE_LSB,
LPO_CAL_ENABLE_MASK,
CLOCK_GPIO_BT_CLK_OUT_EN_LSB,
CLOCK_GPIO_BT_CLK_OUT_EN_MASK,
ANALOG_INTF_BASE_ADDRESS,
};
#else
static struct targetdef_s my_target_def = {
.d_RTC_SOC_BASE_ADDRESS = RTC_SOC_BASE_ADDRESS,
.d_RTC_WMAC_BASE_ADDRESS = RTC_WMAC_BASE_ADDRESS,
.d_SYSTEM_SLEEP_OFFSET = WLAN_SYSTEM_SLEEP_OFFSET,
.d_WLAN_SYSTEM_SLEEP_OFFSET = WLAN_SYSTEM_SLEEP_OFFSET,
.d_WLAN_SYSTEM_SLEEP_DISABLE_LSB = WLAN_SYSTEM_SLEEP_DISABLE_LSB,
.d_WLAN_SYSTEM_SLEEP_DISABLE_MASK = WLAN_SYSTEM_SLEEP_DISABLE_MASK,
.d_CLOCK_CONTROL_OFFSET = CLOCK_CONTROL_OFFSET,
.d_CLOCK_CONTROL_SI0_CLK_MASK = CLOCK_CONTROL_SI0_CLK_MASK,
.d_RESET_CONTROL_OFFSET = SOC_RESET_CONTROL_OFFSET,
.d_RESET_CONTROL_MBOX_RST_MASK = RESET_CONTROL_MBOX_RST_MASK,
.d_RESET_CONTROL_SI0_RST_MASK = RESET_CONTROL_SI0_RST_MASK,
.d_WLAN_RESET_CONTROL_OFFSET = WLAN_RESET_CONTROL_OFFSET,
.d_WLAN_RESET_CONTROL_COLD_RST_MASK = WLAN_RESET_CONTROL_COLD_RST_MASK,
.d_WLAN_RESET_CONTROL_WARM_RST_MASK = WLAN_RESET_CONTROL_WARM_RST_MASK,
.d_GPIO_BASE_ADDRESS = GPIO_BASE_ADDRESS,
.d_GPIO_PIN0_OFFSET = GPIO_PIN0_OFFSET,
.d_GPIO_PIN1_OFFSET = GPIO_PIN1_OFFSET,
.d_GPIO_PIN0_CONFIG_MASK = GPIO_PIN0_CONFIG_MASK,
.d_GPIO_PIN1_CONFIG_MASK = GPIO_PIN1_CONFIG_MASK,
.d_SI_CONFIG_BIDIR_OD_DATA_LSB = SI_CONFIG_BIDIR_OD_DATA_LSB,
.d_SI_CONFIG_BIDIR_OD_DATA_MASK = SI_CONFIG_BIDIR_OD_DATA_MASK,
.d_SI_CONFIG_I2C_LSB = SI_CONFIG_I2C_LSB,
.d_SI_CONFIG_I2C_MASK = SI_CONFIG_I2C_MASK,
.d_SI_CONFIG_POS_SAMPLE_LSB = SI_CONFIG_POS_SAMPLE_LSB,
.d_SI_CONFIG_POS_SAMPLE_MASK = SI_CONFIG_POS_SAMPLE_MASK,
.d_SI_CONFIG_INACTIVE_CLK_LSB = SI_CONFIG_INACTIVE_CLK_LSB,
.d_SI_CONFIG_INACTIVE_CLK_MASK = SI_CONFIG_INACTIVE_CLK_MASK,
.d_SI_CONFIG_INACTIVE_DATA_LSB = SI_CONFIG_INACTIVE_DATA_LSB,
.d_SI_CONFIG_INACTIVE_DATA_MASK = SI_CONFIG_INACTIVE_DATA_MASK,
.d_SI_CONFIG_DIVIDER_LSB = SI_CONFIG_DIVIDER_LSB,
.d_SI_CONFIG_DIVIDER_MASK = SI_CONFIG_DIVIDER_MASK,
.d_SI_BASE_ADDRESS = SI_BASE_ADDRESS,
.d_SI_CONFIG_OFFSET = SI_CONFIG_OFFSET,
.d_SI_TX_DATA0_OFFSET = SI_TX_DATA0_OFFSET,
.d_SI_TX_DATA1_OFFSET = SI_TX_DATA1_OFFSET,
.d_SI_RX_DATA0_OFFSET = SI_RX_DATA0_OFFSET,
.d_SI_RX_DATA1_OFFSET = SI_RX_DATA1_OFFSET,
.d_SI_CS_OFFSET = SI_CS_OFFSET,
.d_SI_CS_DONE_ERR_MASK = SI_CS_DONE_ERR_MASK,
.d_SI_CS_DONE_INT_MASK = SI_CS_DONE_INT_MASK,
.d_SI_CS_START_LSB = SI_CS_START_LSB,
.d_SI_CS_START_MASK = SI_CS_START_MASK,
.d_SI_CS_RX_CNT_LSB = SI_CS_RX_CNT_LSB,
.d_SI_CS_RX_CNT_MASK = SI_CS_RX_CNT_MASK,
.d_SI_CS_TX_CNT_LSB = SI_CS_TX_CNT_LSB,
.d_SI_CS_TX_CNT_MASK = SI_CS_TX_CNT_MASK,
.d_BOARD_DATA_SZ = MY_TARGET_BOARD_DATA_SZ,
.d_BOARD_EXT_DATA_SZ = MY_TARGET_BOARD_EXT_DATA_SZ,
.d_MBOX_BASE_ADDRESS = MBOX_BASE_ADDRESS,
.d_LOCAL_SCRATCH_OFFSET = LOCAL_SCRATCH_OFFSET,
.d_CPU_CLOCK_OFFSET = CPU_CLOCK_OFFSET,
.d_LPO_CAL_OFFSET = LPO_CAL_OFFSET,
.d_GPIO_PIN10_OFFSET = GPIO_PIN10_OFFSET,
.d_GPIO_PIN11_OFFSET = GPIO_PIN11_OFFSET,
.d_GPIO_PIN12_OFFSET = GPIO_PIN12_OFFSET,
.d_GPIO_PIN13_OFFSET = GPIO_PIN13_OFFSET,
.d_CLOCK_GPIO_OFFSET = CLOCK_GPIO_OFFSET,
.d_CPU_CLOCK_STANDARD_LSB = CPU_CLOCK_STANDARD_LSB,
.d_CPU_CLOCK_STANDARD_MASK = CPU_CLOCK_STANDARD_MASK,
.d_LPO_CAL_ENABLE_LSB = LPO_CAL_ENABLE_LSB,
.d_LPO_CAL_ENABLE_MASK = LPO_CAL_ENABLE_MASK,
.d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB = CLOCK_GPIO_BT_CLK_OUT_EN_LSB,
.d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK = CLOCK_GPIO_BT_CLK_OUT_EN_MASK,
.d_ANALOG_INTF_BASE_ADDRESS = ANALOG_INTF_BASE_ADDRESS,
};
#endif
#if MY_TARGET_BOARD_DATA_SZ > BOARD_DATA_SZ_MAX
#error "BOARD_DATA_SZ_MAX is too small"
#endif
struct targetdef_s *MY_TARGET_DEF = &my_target_def;
#else /* } { */
#define RTC_SOC_BASE_ADDRESS (targetdef->d_RTC_SOC_BASE_ADDRESS)
#define RTC_WMAC_BASE_ADDRESS (targetdef->d_RTC_WMAC_BASE_ADDRESS)
#define SYSTEM_SLEEP_OFFSET (targetdef->d_SYSTEM_SLEEP_OFFSET)
#define WLAN_SYSTEM_SLEEP_OFFSET (targetdef->d_WLAN_SYSTEM_SLEEP_OFFSET)
#define WLAN_SYSTEM_SLEEP_DISABLE_LSB (targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_LSB)
#define WLAN_SYSTEM_SLEEP_DISABLE_MASK (targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_MASK)
#define CLOCK_CONTROL_OFFSET (targetdef->d_CLOCK_CONTROL_OFFSET)
#define CLOCK_CONTROL_SI0_CLK_MASK (targetdef->d_CLOCK_CONTROL_SI0_CLK_MASK)
#define RESET_CONTROL_OFFSET (targetdef->d_RESET_CONTROL_OFFSET)
#define RESET_CONTROL_MBOX_RST_MASK (targetdef->d_RESET_CONTROL_MBOX_RST_MASK)
#define RESET_CONTROL_SI0_RST_MASK (targetdef->d_RESET_CONTROL_SI0_RST_MASK)
#define WLAN_RESET_CONTROL_OFFSET (targetdef->d_WLAN_RESET_CONTROL_OFFSET)
#define WLAN_RESET_CONTROL_COLD_RST_MASK (targetdef->d_WLAN_RESET_CONTROL_COLD_RST_MASK)
#define WLAN_RESET_CONTROL_WARM_RST_MASK (targetdef->d_WLAN_RESET_CONTROL_WARM_RST_MASK)
#define GPIO_BASE_ADDRESS (targetdef->d_GPIO_BASE_ADDRESS)
#define GPIO_PIN0_OFFSET (targetdef->d_GPIO_PIN0_OFFSET)
#define GPIO_PIN1_OFFSET (targetdef->d_GPIO_PIN1_OFFSET)
#define GPIO_PIN0_CONFIG_MASK (targetdef->d_GPIO_PIN0_CONFIG_MASK)
#define GPIO_PIN1_CONFIG_MASK (targetdef->d_GPIO_PIN1_CONFIG_MASK)
#define SI_CONFIG_BIDIR_OD_DATA_LSB (targetdef->d_SI_CONFIG_BIDIR_OD_DATA_LSB)
#define SI_CONFIG_BIDIR_OD_DATA_MASK (targetdef->d_SI_CONFIG_BIDIR_OD_DATA_MASK)
#define SI_CONFIG_I2C_LSB (targetdef->d_SI_CONFIG_I2C_LSB)
#define SI_CONFIG_I2C_MASK (targetdef->d_SI_CONFIG_I2C_MASK)
#define SI_CONFIG_POS_SAMPLE_LSB (targetdef->d_SI_CONFIG_POS_SAMPLE_LSB)
#define SI_CONFIG_POS_SAMPLE_MASK (targetdef->d_SI_CONFIG_POS_SAMPLE_MASK)
#define SI_CONFIG_INACTIVE_CLK_LSB (targetdef->d_SI_CONFIG_INACTIVE_CLK_LSB)
#define SI_CONFIG_INACTIVE_CLK_MASK (targetdef->d_SI_CONFIG_INACTIVE_CLK_MASK)
#define SI_CONFIG_INACTIVE_DATA_LSB (targetdef->d_SI_CONFIG_INACTIVE_DATA_LSB)
#define SI_CONFIG_INACTIVE_DATA_MASK (targetdef->d_SI_CONFIG_INACTIVE_DATA_MASK)
#define SI_CONFIG_DIVIDER_LSB (targetdef->d_SI_CONFIG_DIVIDER_LSB)
#define SI_CONFIG_DIVIDER_MASK (targetdef->d_SI_CONFIG_DIVIDER_MASK)
#define SI_BASE_ADDRESS (targetdef->d_SI_BASE_ADDRESS)
#define SI_CONFIG_OFFSET (targetdef->d_SI_CONFIG_OFFSET)
#define SI_TX_DATA0_OFFSET (targetdef->d_SI_TX_DATA0_OFFSET)
#define SI_TX_DATA1_OFFSET (targetdef->d_SI_TX_DATA1_OFFSET)
#define SI_RX_DATA0_OFFSET (targetdef->d_SI_RX_DATA0_OFFSET)
#define SI_RX_DATA1_OFFSET (targetdef->d_SI_RX_DATA1_OFFSET)
#define SI_CS_OFFSET (targetdef->d_SI_CS_OFFSET)
#define SI_CS_DONE_ERR_MASK (targetdef->d_SI_CS_DONE_ERR_MASK)
#define SI_CS_DONE_INT_MASK (targetdef->d_SI_CS_DONE_INT_MASK)
#define SI_CS_START_LSB (targetdef->d_SI_CS_START_LSB)
#define SI_CS_START_MASK (targetdef->d_SI_CS_START_MASK)
#define SI_CS_RX_CNT_LSB (targetdef->d_SI_CS_RX_CNT_LSB)
#define SI_CS_RX_CNT_MASK (targetdef->d_SI_CS_RX_CNT_MASK)
#define SI_CS_TX_CNT_LSB (targetdef->d_SI_CS_TX_CNT_LSB)
#define SI_CS_TX_CNT_MASK (targetdef->d_SI_CS_TX_CNT_MASK)
#define EEPROM_SZ (targetdef->d_BOARD_DATA_SZ)
#define EEPROM_EXT_SZ (targetdef->d_BOARD_EXT_DATA_SZ)
#define MBOX_BASE_ADDRESS (targetdef->d_MBOX_BASE_ADDRESS)
#define LOCAL_SCRATCH_OFFSET (targetdef->d_LOCAL_SCRATCH_OFFSET)
#define CPU_CLOCK_OFFSET (targetdef->d_CPU_CLOCK_OFFSET)
#define LPO_CAL_OFFSET (targetdef->d_LPO_CAL_OFFSET)
#define GPIO_PIN10_OFFSET (targetdef->d_GPIO_PIN10_OFFSET)
#define GPIO_PIN11_OFFSET (targetdef->d_GPIO_PIN11_OFFSET)
#define GPIO_PIN12_OFFSET (targetdef->d_GPIO_PIN12_OFFSET)
#define GPIO_PIN13_OFFSET (targetdef->d_GPIO_PIN13_OFFSET)
#define CLOCK_GPIO_OFFSET (targetdef->d_CLOCK_GPIO_OFFSET)
#define CPU_CLOCK_STANDARD_LSB (targetdef->d_CPU_CLOCK_STANDARD_LSB)
#define CPU_CLOCK_STANDARD_MASK (targetdef->d_CPU_CLOCK_STANDARD_MASK)
#define LPO_CAL_ENABLE_LSB (targetdef->d_LPO_CAL_ENABLE_LSB)
#define LPO_CAL_ENABLE_MASK (targetdef->d_LPO_CAL_ENABLE_MASK)
#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB (targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB)
#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK (targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK)
#define ANALOG_INTF_BASE_ADDRESS (targetdef->d_ANALOG_INTF_BASE_ADDRESS)
/* SET macros */
#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & WLAN_SYSTEM_SLEEP_DISABLE_MASK)
#define SI_CONFIG_BIDIR_OD_DATA_SET(x) (((x) << SI_CONFIG_BIDIR_OD_DATA_LSB) & SI_CONFIG_BIDIR_OD_DATA_MASK)
#define SI_CONFIG_I2C_SET(x) (((x) << SI_CONFIG_I2C_LSB) & SI_CONFIG_I2C_MASK)
#define SI_CONFIG_POS_SAMPLE_SET(x) (((x) << SI_CONFIG_POS_SAMPLE_LSB) & SI_CONFIG_POS_SAMPLE_MASK)
#define SI_CONFIG_INACTIVE_CLK_SET(x) (((x) << SI_CONFIG_INACTIVE_CLK_LSB) & SI_CONFIG_INACTIVE_CLK_MASK)
#define SI_CONFIG_INACTIVE_DATA_SET(x) (((x) << SI_CONFIG_INACTIVE_DATA_LSB) & SI_CONFIG_INACTIVE_DATA_MASK)
#define SI_CONFIG_DIVIDER_SET(x) (((x) << SI_CONFIG_DIVIDER_LSB) & SI_CONFIG_DIVIDER_MASK)
#define SI_CS_START_SET(x) (((x) << SI_CS_START_LSB) & SI_CS_START_MASK)
#define SI_CS_RX_CNT_SET(x) (((x) << SI_CS_RX_CNT_LSB) & SI_CS_RX_CNT_MASK)
#define SI_CS_TX_CNT_SET(x) (((x) << SI_CS_TX_CNT_LSB) & SI_CS_TX_CNT_MASK)
#define LPO_CAL_ENABLE_SET(x) (((x) << LPO_CAL_ENABLE_LSB) & LPO_CAL_ENABLE_MASK)
#define CPU_CLOCK_STANDARD_SET(x) (((x) << CPU_CLOCK_STANDARD_LSB) & CPU_CLOCK_STANDARD_MASK)
#define CLOCK_GPIO_BT_CLK_OUT_EN_SET(x) (((x) << CLOCK_GPIO_BT_CLK_OUT_EN_LSB) & CLOCK_GPIO_BT_CLK_OUT_EN_MASK)
extern struct targetdef_s *targetdef;
#endif /* } */
#endif /*TARGET_REG_TABLE_H_*/

View File

@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
// <copyright file="utils_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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// Utility Macros & Functions common across OS.
// Author(s): ="Atheros"
//==============================================================================
#ifndef _HOST_UTILS_API_H_
#define _HOST_UTILS_API_H_
#ifdef __cplusplus
extern "C" {
#endif
/* unaligned little endian access */
#define LE_READ_2(p) \
((A_UINT16) \
((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8)))
#define LE_READ_4(p) \
((A_UINT32) \
((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \
(((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
#define WPA_GET_BE16(a) ((A_UINT16) (((a)[0] << 8) | (a)[1]))
#define WPA_PUT_BE16(a, val) \
do { \
(a)[0] = ((A_UINT16) (val)) >> 8; \
(a)[1] = ((A_UINT16) (val)) & 0xff; \
} while (0)
#define WPA_GET_LE16(a) ((A_UINT16) (((a)[1] << 8) | (a)[0]))
#define WPA_PUT_LE16(a, val) \
do { \
(a)[1] = ((A_UINT16) (val)) >> 8; \
(a)[0] = ((A_UINT16) (val)) & 0xff; \
} while (0)
#define WPA_GET_BE24(a) ((((A_UINT32) (a)[0]) << 16) | (((A_UINT32) (a)[1]) << 8) | \
((A_UINT32) (a)[2]))
#define WPA_PUT_BE24(a, val) \
do { \
(a)[0] = (A_UINT8) ((((A_UINT32) (val)) >> 16) & 0xff); \
(a)[1] = (A_UINT8) ((((A_UINT32) (val)) >> 8) & 0xff); \
(a)[2] = (A_UINT8) (((A_UINT32) (val)) & 0xff); \
} while (0)
#define WPA_GET_BE32(a) ((((A_UINT32) (a)[0]) << 24) | (((A_UINT32) (a)[1]) << 16) | \
(((A_UINT32) (a)[2]) << 8) | ((A_UINT32) (a)[3]))
#define WPA_PUT_BE32(a, val) \
do { \
(a)[0] = (A_UINT8) ((((A_UINT32) (val)) >> 24) & 0xff); \
(a)[1] = (A_UINT8) ((((A_UINT32) (val)) >> 16) & 0xff); \
(a)[2] = (A_UINT8) ((((A_UINT32) (val)) >> 8) & 0xff); \
(a)[3] = (A_UINT8) (((A_UINT32) (val)) & 0xff); \
} while (0)
#define WPA_GET_LE32(a) ((((A_UINT32) (a)[3]) << 24) | (((A_UINT32) (a)[2]) << 16) | \
(((A_UINT32) (a)[1]) << 8) | ((A_UINT32) (a)[0]))
#define WPA_PUT_LE32(a, val) \
do { \
(a)[3] = (A_UINT8) ((((A_UINT32) (val)) >> 24) & 0xff); \
(a)[2] = (A_UINT8) ((((A_UINT32) (val)) >> 16) & 0xff); \
(a)[1] = (A_UINT8) ((((A_UINT32) (val)) >> 8) & 0xff); \
(a)[0] = (A_UINT8) (((A_UINT32) (val)) & 0xff); \
} while (0)
#define WPA_OUI 0xf25000
static int __inline
iswscoui(const A_UINT8 *frm)
{
return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
}
static inline int is_zero_mac_addr(const A_UINT8 *addr)
{
return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _HOST_UTILS_API_H_ */

View File

@ -0,0 +1,137 @@
//------------------------------------------------------------------------------
// 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 for the host wlan module
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _HOST_WLAN_API_H_
#define _HOST_WLAN_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <a_osapi.h>
struct ieee80211_node_table;
struct ieee80211_frame;
struct ieee80211_common_ie {
A_UINT16 ie_chan;
A_UINT8 *ie_tstamp;
A_UINT8 *ie_ssid;
A_UINT8 *ie_rates;
A_UINT8 *ie_xrates;
A_UINT8 *ie_country;
A_UINT8 *ie_wpa;
A_UINT8 *ie_rsn;
A_UINT8 *ie_wmm;
A_UINT8 *ie_ath;
A_UINT16 ie_capInfo;
A_UINT16 ie_beaconInt;
A_UINT8 *ie_tim;
A_UINT8 *ie_chswitch;
A_UINT8 ie_erp;
A_UINT8 *ie_wsc;
A_UINT8 *ie_htcap;
A_UINT8 *ie_htop;
#ifdef WAPI_ENABLE
A_UINT8 *ie_wapi;
#endif
};
typedef struct bss {
A_UINT8 ni_macaddr[6];
A_UINT8 ni_snr;
A_INT16 ni_rssi;
struct bss *ni_list_next;
struct bss *ni_list_prev;
struct bss *ni_hash_next;
struct bss *ni_hash_prev;
struct ieee80211_common_ie ni_cie;
#ifdef P2P
void *p2p_dev;
#endif /* P2P */
A_UINT8 *ni_buf;
A_UINT16 ni_framelen;
A_UINT8 ni_frametype; /* frame type in ni_buf */
struct ieee80211_node_table *ni_table;
A_UINT32 ni_refcnt;
int ni_scangen;
A_UINT32 ni_tstamp;
A_UINT32 ni_actcnt;
#ifdef OS_ROAM_MANAGEMENT
A_UINT32 ni_si_gen;
#endif
} bss_t;
typedef void wlan_node_iter_func(void *arg, bss_t *);
bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size);
void wlan_node_free(bss_t *ni);
void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
const A_UINT8 *macaddr);
bss_t *wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr);
void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni);
A_STATUS wlan_node_buf_update(struct ieee80211_node_table *nt, bss_t *ni, A_UINT32 len);
void wlan_free_allnodes(struct ieee80211_node_table *nt);
void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
void *arg);
void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt);
void wlan_node_table_reset(struct ieee80211_node_table *nt);
void wlan_node_table_cleanup(struct ieee80211_node_table *nt);
A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen,
struct ieee80211_common_ie *cie);
A_UINT16 wlan_ieee2freq(int chan);
A_UINT32 wlan_freq2ieee(A_UINT16 freq);
void wlan_set_nodeage(struct ieee80211_node_table *nt, A_UINT32 nodeAge);
void
wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt);
bss_t *
wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID);
void
wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni);
bss_t *wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid);
bss_t *
wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp);
void wlan_node_update_timestamp(struct ieee80211_node_table *nt, bss_t *ni);
#ifdef __cplusplus
}
#endif
#endif /* _HOST_WLAN_API_H_ */

View File

@ -0,0 +1,565 @@
//------------------------------------------------------------------------------
// <copyright file="wmi_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 definitions for the Wireless Module Interface (WMI).
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef _WMI_API_H_
#define _WMI_API_H_
#ifdef __cplusplus
extern "C" {
#endif
/* WMI converts a dix frame with an ethernet payload (up to 1500 bytes)
* to an 802.3 frame (adds SNAP header) and adds on a WMI data header */
#define WMI_MAX_TX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR))
/* A normal WMI data frame */
#define WMI_MAX_NORMAL_RX_DATA_FRAME_LENGTH (1500 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR))
/* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */
#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH (3840 + sizeof(WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + sizeof(ATH_LLC_SNAP_HDR))
/*
* IP QoS Field definitions according to 802.1p
*/
#define BEST_EFFORT_PRI 0
#define BACKGROUND_PRI 1
#define EXCELLENT_EFFORT_PRI 3
#define CONTROLLED_LOAD_PRI 4
#define VIDEO_PRI 5
#define VOICE_PRI 6
#define NETWORK_CONTROL_PRI 7
#define MAX_NUM_PRI 8
#define UNDEFINED_PRI (0xff)
#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */
#define A_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
typedef enum {
ATHEROS_COMPLIANCE = 0x1,
}TSPEC_PARAM_COMPLIANCE;
struct wmi_t;
void *wmi_init(void *devt, int devid);
void wmi_qos_state_init(struct wmi_t *wmip);
void wmi_shutdown(struct wmi_t *wmip);
HTC_ENDPOINT_ID wmi_get_control_ep(struct wmi_t * wmip);
void wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid);
A_UINT16 wmi_get_mapped_qos_queue(struct wmi_t *, A_UINT8);
A_STATUS wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
A_STATUS wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_UINT32 flags , WMI_DATA_HDR_DATA_TYPE data_type,A_UINT8 metaVersion, void *pTxMetaS);
A_STATUS wmi_dot3_2_dix(void *osbuf);
A_STATUS wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf);
A_STATUS wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode);
A_STATUS wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
A_STATUS wmi_syncpoint(struct wmi_t *wmip);
A_STATUS wmi_syncpoint_reset(struct wmi_t *wmip);
A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 layer2Priority, A_BOOL wmmEnabled);
A_UINT8 wmi_determine_userPriority (A_UINT8 *pkt, A_UINT32 layer2Pri);
A_STATUS wmi_control_rx(struct wmi_t *wmip, void *osbuf);
void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg);
void wmi_free_allnodes(struct wmi_t *wmip);
bss_t *wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
void wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
typedef enum {
NO_SYNC_WMIFLAG = 0,
SYNC_BEFORE_WMIFLAG, /* transmit all queued data before cmd */
SYNC_AFTER_WMIFLAG, /* any new data waits until cmd execs */
SYNC_BOTH_WMIFLAG,
END_WMIFLAG /* end marker */
} WMI_SYNC_FLAG;
A_STATUS wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
WMI_SYNC_FLAG flag);
A_STATUS wmi_connect_cmd(struct wmi_t *wmip,
NETWORK_TYPE netType,
DOT11_AUTH_MODE dot11AuthMode,
AUTH_MODE authMode,
CRYPTO_TYPE pairwiseCrypto,
A_UINT8 pairwiseCryptoLen,
CRYPTO_TYPE groupCrypto,
A_UINT8 groupCryptoLen,
int ssidLength,
A_UCHAR *ssid,
A_UINT8 *bssid,
A_UINT16 channel,
A_UINT32 ctrl_flags);
A_STATUS wmi_set_div_param_cmd(struct wmi_t *wmip, A_UINT32 divIdleTime,
A_UINT8 antRssiThresh, A_UINT8 divEnable, A_UINT16 active_treshold_rate);
A_STATUS wmi_reconnect_cmd(struct wmi_t *wmip,
A_UINT8 *bssid,
A_UINT16 channel);
A_STATUS wmi_disconnect_cmd(struct wmi_t *wmip);
A_STATUS wmi_getrev_cmd(struct wmi_t *wmip);
A_STATUS wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
A_BOOL forceFgScan, A_BOOL isLegacy,
A_UINT32 homeDwellTime, A_UINT32 forceScanInterval,
A_INT8 numChan, A_UINT16 *channelList);
A_STATUS wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
A_UINT16 fg_end_sec, A_UINT16 bg_sec,
A_UINT16 minact_chdw_msec,
A_UINT16 maxact_chdw_msec, A_UINT16 pas_chdw_msec,
A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
A_UINT32 max_dfsch_act_time,
A_UINT16 maxact_scan_per_ssid);
A_STATUS wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask);
A_STATUS wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
A_UINT8 ssidLength, A_UCHAR *ssid);
A_STATUS wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons);
A_STATUS wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmisstime, A_UINT16 bmissbeacons);
A_STATUS wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
A_UINT8 ieLen, A_UINT8 *ieInfo);
A_STATUS wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode);
A_STATUS wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
A_UINT16 atim_windows, A_UINT16 timeout_value);
A_STATUS wmi_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time,
A_UINT32 ps_period, A_UINT8 sleep_period);
A_STATUS wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
A_UINT16 psPollNum, A_UINT16 dtimPolicy,
A_UINT16 wakup_tx_policy, A_UINT16 num_tx_to_wakeup,
A_UINT16 ps_fail_event_policy);
A_STATUS wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout);
A_STATUS wmi_sync_cmd(struct wmi_t *wmip, A_UINT8 syncNumber);
A_STATUS wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
A_STATUS wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 streamID);
A_STATUS wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8 subType, A_UINT16 rateMask);
A_STATUS wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_INT32 ctlRate);
A_STATUS wmi_get_bitrate_cmd(struct wmi_t *wmip);
A_INT8 wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate, A_INT8 *rate_idx);
A_STATUS wmi_get_regDomain_cmd(struct wmi_t *wmip);
A_STATUS wmi_get_channelList_cmd(struct wmi_t *wmip);
A_STATUS wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
WMI_PHY_MODE mode, A_INT8 numChan,
A_UINT16 *channelList);
A_STATUS wmi_set_snr_threshold_params(struct wmi_t *wmip,
WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
A_STATUS wmi_set_rssi_threshold_params(struct wmi_t *wmip,
WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
A_STATUS wmi_clr_rssi_snr(struct wmi_t *wmip);
A_STATUS wmi_set_lq_threshold_params(struct wmi_t *wmip,
WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd);
A_STATUS wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold);
A_STATUS wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status, A_UINT8 preamblePolicy);
A_STATUS wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 bitmask);
A_STATUS wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie,
A_UINT32 source);
A_STATUS wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
A_UINT32 valid);
A_STATUS wmi_get_stats_cmd(struct wmi_t *wmip);
A_STATUS wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex,
CRYPTO_TYPE keyType, A_UINT8 keyUsage,
A_UINT8 keyLength,A_UINT8 *keyRSC,
A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, A_UINT8 *mac,
WMI_SYNC_FLAG sync_flag);
A_STATUS wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk);
A_STATUS wmi_delete_krk_cmd(struct wmi_t *wmip);
A_STATUS wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex);
A_STATUS wmi_set_akmp_params_cmd(struct wmi_t *wmip,
WMI_SET_AKMP_PARAMS_CMD *akmpParams);
A_STATUS wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
A_STATUS wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
WMI_SET_PMKID_LIST_CMD *pmkInfo);
A_STATUS wmi_abort_scan_cmd(struct wmi_t *wmip);
A_STATUS wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM);
A_STATUS wmi_get_txPwr_cmd(struct wmi_t *wmip);
A_STATUS wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid);
A_STATUS wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex);
A_STATUS wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en);
A_STATUS wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
A_BOOL set);
A_STATUS wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT8 ac, A_UINT16 txop,
A_UINT8 eCWmin, A_UINT8 eCWmax,
A_UINT8 aifsn);
A_STATUS wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
A_UINT8 trafficClass, A_UINT8 maxRetries,
A_UINT8 enableNotify);
void wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid);
A_STATUS wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
A_STATUS wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType);
A_STATUS wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
A_UINT8 size);
A_STATUS wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
A_UINT8 size);
A_STATUS wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode);
A_STATUS wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
A_UINT8 frmType,
A_UINT8 *dstMacAddr,
A_UINT8 *bssid,
A_UINT16 optIEDataLen,
A_UINT8 *optIEData);
A_STATUS wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl);
A_STATUS wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize);
A_STATUS wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSpLen);
A_UINT8 convert_userPriority_to_trafficClass(A_UINT8 userPriority);
A_UINT8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
A_STATUS wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance);
#ifdef CONFIG_HOST_TCMD_SUPPORT
A_STATUS wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len);
#endif
A_STATUS wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status);
A_STATUS wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
A_STATUS wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd);
A_STATUS wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd);
A_STATUS wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *cmd);
A_STATUS wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd);
A_STATUS wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
WMI_SET_BTCOEX_A2DP_CONFIG_CMD* cmd);
A_STATUS wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd);
A_STATUS wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd);
A_STATUS wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd);
A_STATUS wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd);
A_STATUS wmi_get_btcoex_stats_cmd(struct wmi_t * wmip);
A_STATUS wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 *sgiMask, A_UINT8 sgiPERThreshold);
/*
* This function is used to configure the fix rates mask to the target.
*/
A_STATUS wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 *fixRatesMask);
A_STATUS wmi_get_ratemask_cmd(struct wmi_t *wmip);
A_STATUS wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
A_STATUS wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
A_STATUS wmi_set_qos_supp_cmd(struct wmi_t *wmip,A_UINT8 status);
A_STATUS wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
A_STATUS wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
A_STATUS wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode);
A_STATUS wmi_get_keepalive_configured(struct wmi_t *wmip);
A_UINT8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
A_STATUS wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval);
A_STATUS wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType,
A_UINT8 ieLen,A_UINT8 *ieInfo);
A_STATUS wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen);
A_INT32 wmi_get_rate(A_INT8 rateindex);
A_STATUS wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd);
/*Wake on Wireless WMI commands*/
A_STATUS wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
A_STATUS wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
A_STATUS wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
WMI_ADD_WOW_PATTERN_CMD *cmd, A_UINT8* pattern, A_UINT8* mask, A_UINT8 pattern_size);
A_STATUS wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
WMI_DEL_WOW_PATTERN_CMD *cmd);
A_STATUS wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status);
A_STATUS
wmi_set_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR* buffer);
A_STATUS
wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 *filter);
A_STATUS
wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 *filter);
A_STATUS
wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable);
bss_t *
wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID);
void
wmi_node_return (struct wmi_t *wmip, bss_t *bss);
void
wmi_node_update_timestamp(struct wmi_t *wmip, bss_t *bss);
void wmi_setup_node(struct wmi_t *wmip, bss_t *bss, const A_UINT8 *bssid);
bss_t *wmi_node_alloc(struct wmi_t *wmip, A_UINT8 len);
void
wmi_set_nodeage(struct wmi_t *wmip, A_UINT32 nodeAge);
#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
A_STATUS wmi_prof_cfg_cmd(struct wmi_t *wmip, A_UINT32 period, A_UINT32 nbins);
A_STATUS wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr);
A_STATUS wmi_prof_start_cmd(struct wmi_t *wmip);
A_STATUS wmi_prof_stop_cmd(struct wmi_t *wmip);
A_STATUS wmi_prof_count_get_cmd(struct wmi_t *wmip);
#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
#ifdef OS_ROAM_MANAGEMENT
void wmi_scan_indication (struct wmi_t *wmip);
#endif
A_STATUS
wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd);
bss_t *wmi_rm_current_bss (struct wmi_t *wmip, A_UINT8 *id);
A_STATUS wmi_add_current_bss (struct wmi_t *wmip, A_UINT8 *id, bss_t *bss);
/*
* AP mode
*/
A_STATUS
wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p);
A_STATUS
wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid);
A_STATUS
wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta);
A_STATUS
wmi_ap_set_dfs(struct wmi_t *wmip, A_UINT8 enable);
A_STATUS
wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy);
A_STATUS
wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *a);
A_UINT8
acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl);
A_STATUS
wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason);
A_STATUS
wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag);
A_STATUS
wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period);
A_STATUS
wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell);
A_STATUS
wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim);
A_STATUS
wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset);
A_STATUS
wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd);
A_STATUS
wmi_get_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd);
A_STATUS
wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width);
A_STATUS
wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz);
A_STATUS
wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray);
A_STATUS
wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid);
A_STATUS
wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink);
A_STATUS
wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask);
A_STATUS
wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion, A_BOOL rxDot11Hdr, A_BOOL defragOnHost);
A_STATUS
wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode);
A_STATUS
wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence);
A_STATUS
wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk);
A_STATUS
wmi_set_passphrase_cmd(struct wmi_t *wmip, WMI_SET_PASSPHRASE_CMD *cmd);
A_STATUS
wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd);
A_STATUS
wmi_assoc_req_enable_cmd(struct wmi_t *wmip, A_UINT8 enable);
A_STATUS
wmi_assoc_req_report_cmd (struct wmi_t *wmip, A_UINT8 host_accept, A_UINT8 host_reaspncode, A_UINT8 target_status, A_UINT8 *sta_mac_addr, A_UINT8 rspType);
#ifdef P2P
A_STATUS
wmi_p2p_discover(struct wmi_t *wmip, WMI_P2P_FIND_CMD *find_param);
A_STATUS
wmi_p2p_stop_find(struct wmi_t *wmip);
A_STATUS
wmi_p2p_cancel(struct wmi_t *wmip);
A_STATUS
wmi_p2p_listen(struct wmi_t *wmip, A_UINT32 timeout);
A_STATUS
wmi_p2p_go_neg_start(struct wmi_t *wmip, WMI_P2P_GO_NEG_START_CMD *go_param);
A_STATUS wmi_p2p_sdpd_tx_cmd(struct wmi_t *wmip, WMI_P2P_SDPD_TX_CMD *buf);
A_STATUS wmi_p2p_stop_sdpd(struct wmi_t *wmip);
A_STATUS wmi_p2p_go_neg_rsp_cmd(struct wmi_t *wmip, A_UINT8 status,
A_UINT8 go_intent, A_UINT32 wps_method, A_UINT16 listen_freq,
A_UINT8 *wpsbuf, A_UINT32 wpslen, A_UINT8 *p2pbuf, A_UINT32 p2plen,
A_UINT8 dialog_token, A_UINT8 persistent_grp);
A_STATUS
wmi_p2p_set_config(struct wmi_t *wmip, WMI_P2P_SET_CONFIG_CMD *config);
A_STATUS
wmi_wps_set_config(struct wmi_t *wmip, WMI_WPS_SET_CONFIG_CMD *wps_config);
A_STATUS wmi_p2p_grp_init_cmd(struct wmi_t *wmip, WMI_P2P_GRP_INIT_CMD *buf);
A_STATUS wmi_p2p_grp_done_cmd(struct wmi_t *wmip,
WMI_P2P_GRP_FORMATION_DONE_CMD *buf);
A_STATUS wmi_p2p_invite_cmd(struct wmi_t *wmip, WMI_P2P_INVITE_CMD *buf);
A_STATUS wmi_p2p_invite_req_rsp_cmd(struct wmi_t *wmip, A_UINT8 status,
A_INT8 is_go, A_UINT8 *grp_bssid, A_UINT8 *p2pbuf,
A_UINT8 p2plen, A_UINT8 dialog_token);
A_STATUS wmi_p2p_prov_disc_cmd(struct wmi_t *wmip,
WMI_P2P_PROV_DISC_REQ_CMD *buf);
A_STATUS wmi_p2p_set_cmd(struct wmi_t *wmip, WMI_P2P_SET_CMD *buf);
#endif /* P2P */
A_UINT16
wmi_ieee2freq (int chan);
A_UINT32
wmi_freq2ieee (A_UINT16 freq);
bss_t *
wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
A_UINT32 ssidLength,
A_UINT32 dot11AuthMode, A_UINT32 authMode,
A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp);
A_STATUS
wmi_radarDetected_cmd(struct wmi_t *wmip, A_INT16 chan_index, A_INT8 bang_radar);
A_STATUS
wmi_set_dfs_maxpulsedur_cmd(struct wmi_t *wmip, A_UINT32 value);
A_STATUS
wmi_set_dfs_minrssithresh_cmd(struct wmi_t *wmip, A_INT32 rssi);
A_STATUS
wmi_beacon2bssnode (struct wmi_t *wmip, A_UINT8 *datap, int len, A_UINT8 *bssid, A_UINT16 channel);
A_STATUS
wmi_set_tx_mac_rules_cmd (struct wmi_t *wmip, A_UINT32 rules);
A_STATUS
wmi_set_promiscuous_mode_cmd (struct wmi_t *wmip, A_BOOL bMode);
//WAC
A_STATUS wmi_wac_enable_cmd(struct wmi_t *wmip, WMI_WAC_ENABLE_CMD *param);
A_STATUS
wmi_wac_scan_reply_cmd(struct wmi_t *wmip, WAC_SUBCMD param);
A_STATUS
wmi_wac_ctrl_req_cmd(struct wmi_t *wmip, WMI_WAC_CTRL_REQ_CMD *param);
#ifdef CONFIG_WLAN_RFKILL
A_STATUS
wmi_get_rfkill_mode_cmd(struct wmi_t *wmip);
A_STATUS
wmi_set_rfkill_mode_cmd(struct wmi_t *wmip,WMI_RFKILL_MODE_CMD *pCmd);
#endif
A_STATUS
wmi_force_target_assert(struct wmi_t *wmip);
A_STATUS
wmi_ap_set_apsd(struct wmi_t *wmip, A_UINT8 enable);
A_STATUS
wmi_set_apsd_buffered_traffic_cmd(struct wmi_t *wmip, A_UINT16 aid, A_UINT16 bitmap, A_UINT32 flags);
#ifdef __cplusplus
}
#endif
#endif /* _WMI_API_H_ */

View File

@ -0,0 +1,46 @@
#------------------------------------------------------------------------------
# <copyright file="makefile" company="Atheros">
# Copyright (c) 2005-2007 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"
#==============================================================================
CC := $(ATH_CROSS_COMPILE_TYPE)gcc
KERNEL_SRC :=$(ATH_LINUXPATH)
ifndef CFLAGS
#CFLAGS = -MMD -O2 -Wall -g
CFLAGS = -Wall
endif
CFLAGS += -DCONFIG_CTRL_IFACE_UNIX -DCONFIG_CTRL_IFACE -DWAPI_ENABLE
all:
$(CC) $(CFLAGS) -I./ -I$(KERNEL_SRC)/include -I../../include -I../../../include -I../../wlan/include \
-I../../os/linux/include -I../../3rdparty/supplicant/opensrc_0_6_9/src/common \
-I../../os/linux/include -I../../3rdparty/supplicant/opensrc_0_6_9/src/utils wac.c -o wac
#wpa_ctrl.o: os_internal.o
# $(CC) $(CFLAGS) -I./ -I$(KERNEL_SRC)/include -I../../include -I../../../include -I../../wlan/include \
# -I../../os/linux/include -I../../3rdparty/supplicant/opensrc_0_6_9/src/utils \
# -c ../../3rdparty/supplicant/opensrc_0_6_9/src/common/wpa_ctrl.c
#
#os_internal.o:
# $(CC) $(CFLAGS) -I./ -I$(KERNEL_SRC)/include -I../../include -I../../../include -I../../wlan/include \
# -I../../os/linux/include -I../../3rdparty/supplicant/opensrc_0_6_9/src/utils \
# -c ../../3rdparty/supplicant/opensrc_0_6_9/src/utils/os_internal.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
//------------------------------------------------------------------------------
// Copyright (c) 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 __WAC_LIB_API_H__
#define __WAC_LIB_API_H__
#include "wac_defs.h"
/*
* Function to enable or disable the WAC feature. This is the entry point to WAC when the
* user pushed a button on the remote
* Input arguments:
* s - open file descriptor of socket
* enable - flag to enable/disable WAC. 1 = enable; 0 = disable
* for disablethe remaining arguments are don't cares
* period - time in milliseconds between consecutive scans when WAC is enabled
* scan_thres - number of scan retries before the STA gave up on looking for WAC AP
* rssi_thres - RSSI threshold the STA will check in beacon or probe response frames
* to qualify a WAC AP. This is absolute value of the signal strength in dBm
* Return value:
* 0 = success; -1 = failure
*
* Examples:
* To enable WAC: wac_enable(s, 1, 2000, 3, 25)
* - WAC enabled with 2-second interval between scans for up to 3 tries. RSSI threshold is -25dBm
* To disable WAC: wac_enable(s, 0, 0, 0, 0)
* - When the flag is disable, the rest of arguments are don't cares
*/
int wac_enable(int s, int enable, unsigned int period, unsigned int scan_thres, int rssi_thres);
/*
* Function for I/O Control Request for Samsung IE as specified version 1.2 protocol
* Input arguments:
* s - open file descriptor for socket
* req - request type takes the possible values:
* WAC_SET
* WAC_GET
* cmd - command takes the possible values:
* WAC_ADD
* WAC_DEL
* WAC_GET_STATUS
* frm - frame type takes the possible values:
* PRBREQ (for STA)
* PRBRSP (for AP)
* BEACON (for AP)
* ie - pointer to char string that contains the IE to set or get
* ret_val - indicates whether the control request is successful
* 0 = success; -1 = failure
* status - status code returned by STA that takes possible values:
* WAC_FAILED_NO_WAC_AP
* WAC_FAILED_LOW_RSSI
* WAC_FAILED_INVALID_PARAM
* WAC_FAILED_REJECTED
* WAC_SUCCESS
* WAC_PROCEED_FIRST_PHASE
* WAC_PROCEED_SECOND_PHASE
* WAC_DISABLED
* Examples:
* To insert an IE into the probe request frame:
* wac_control_request(WAC_SET, WAC_ADD, PRBREQ,
* "0x0012fb0100010101083132333435363730" val, status)
* To query the WAC status from STA:
* wac_control_request(WAC_GET, WAC_GET_STATUS, NULL, NULL, val, status)
*/
void wac_control_request( int s,
WAC_REQUEST_TYPE req,
WAC_COMMAND cmd,
WAC_FRAME_TYPE frm,
char *ie,
int *ret_val,
WAC_STATUS *status );
#endif

View File

@ -0,0 +1,40 @@
#
# Local Makefile includes for tool and kernel source paths
#
# Copyright 2004-2010 Atheros Communications, Inc.
#
# When creating a new build type, use the following template:
# ifeq ($(ATH_BUILD_TYPE),<platform name>)
# ATH_ARCH_CPU_TYPE := < cpu architecture >
# ATH_CROSS_COMPILE_TYPE := < cross compiler path >
# ATH_LINUXPATH := < kernel source path >
ATH_BUILD_TYPE := LOCAL_ARM_RK29
ATH_BUS_TYPE := SDIO
ATH_LINUXPATH := /home/ko/work/customer/yifang/trunk_exp
ATH_CROSS_COMPILE_TYPE := /home/ko/work/customer/yifang/kernel_rk29_v0.1/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
ATH_ARCH_CPU_TYPE := arm
$(info *************************)
$(info PLATFORM: $(ATH_BUILD_TYPE))
$(info BSP: $(ATH_BSP_TYPE))
$(info *************************)
# Some environment settings
ATH_BUILD_TYPE=$(ATH_BSP_TYPE)_ARM_NATIVEMMC
ATH_ANDROID_ENV := yes
ATH_SOFTMAC_FILE_USED := no
ATH_DEBUG_DRIVER := yes
ATH_HTC_RAW_INT_ENV :=yes
ATH_AR6K_OTA_TEST_MODE := no
# Some common variable
ATH_BUS_TYPE := SDIO
ATH_OS_SUB_TYPE := linux_2_6
ATH_BUS_SUBTYPE := linux_sdio
ATH_BUILD_3RDPARTY := no
ATH_CFG80211_ENV := no
ATH_BUILD_SYSTEM_TOOLS := no
ATH_AR6K_HCI_PAL := no
ATH_AR6K_DEBUG_ALLOC := no
ATH_BUILD_P2P :=no

View File

@ -0,0 +1,59 @@
// based on 1, change DVDD=0.85V, LPO measure time to 8ms, 1300ms reCal interval
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 02 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]009C
[H:A]C1 C1 17 02 02 00 01 30 48 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//#
//[H:S]0021
//[H:S]0004
//[H:A]09 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96

View File

@ -0,0 +1,2 @@
0569
000000000e20000050800000000158000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0915300d4915300d8915300dc91530098b0530064ce5300f8d2530008e7530008d253000cd2530098d95300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff051001010101ffffff50500101010180019800c8019800f4029800d0039800380498001404980024059800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000366100ad0581c206bd01e00800bd0a17641c0c0abd05815d080c0ce00800bd02dd03ed05815c080c0ce00800c60400ad05c1f802922b11819903c09920926b11e008000c021df0003681001c0e516d030c0720d074d241107911d0cd90b805a0cc11cabbb90160e6030c2a609034972a026062003801e2c1102203068d07cc8260e613102000fd061df072631122011072434fc805204290a044114acc882c0c1980a00407e805820c4b07e8079c7aa20c4b07ea12a2c3340c0b0cfc0c198191029911e008000c1972434ec805e8114acca82cd20c4ba0a00416aa0590fd20f24c4bcc4e820349f65878a1b1039805a20a034a9992990980aa01a0a831909821809901909831a7294a0c5a81bc04bd02e00800cd0aad0281be04e805c0b0744ace920c4b0c4dd09920924c4be008009c7a72434a860400ad020c4b81bf0492a0fe909d10924c4be0080060e613102000ad061df00c1a81bd04bd02e00800cd0a46ecff0c5a81bd04bd02e00800cd0a86e8ff0000368100305074bd0120407481c206ad04e00800922a11216d0390920516890ba18804b16e03c0200040349091f204a03311822992c02000b08810a08820a8028269923aaab20a49d2ca48579b08c20a4bc0c204161c08b24a4ae1d104524d01eae5f20e7fe20e803c29f7be4a1c0b424110d9111c0c1c0f1c0552c110fd05cd0580e6030c2e80d034d72e02806200bd05b20500c20500a802c0bb90a0bb11baaa924a3480e613102000420500d811403490520d01a03311ad04b20d0081c204cd05e00800a802b2a0fb3aaa920a4b0c12b09910924a4b1df00c021df0364100811e0621c0098808921207ece8ecc9e1b103b21206a21ef1b73a210c0a817c03d21ef0c1d603f16c03c80ce20f44a0bd11e0bd93d1d209e00800a252071df00000364100817f04916c03880892092880801466180acc79810d04a2a064e008001df0000000364100c02000c16c03e1940391d9032178030c0dd2628bf20902c02000f0ed83e2628cc02000d2628dc02000d2628e820c43b20c28d19d0210bb01d0bb10cc580cba0c53c600000c0a0c83c020000c1dd2628fc02000a2628ac02000b26289a209020c088cfa661a040c1ac60300662a05a2190026ca040c0a8607000c0af0ba01e1da03a2090ce0bb100c1ea0ae93e1f40230aa11e0aa10b0aa20b1fd03c02000a26bc1f209020c18f62f040c098604009209070c1a909a930c2af09911a09910d09920c02000d17f04926bc6d80de20c28d0d014661d0acc7e810d04a2a064e00800c020003262881df00036410081c305c1900920b074e19605d16e09e80ec02000d22d82b94ed92ec02000b90c30e6030c2a309034972a02306200e00800c02000fd0391250382a10082698000710030e6131020001df0

View File

@ -0,0 +1,68 @@
// Coex Configuration
#
[H:S]0017
[H:S]0022
[H:A]d1 d1 20 00 02 01 02 09 0c 00 24 0f 04 00 00 01
00 01 00 01 01 01 01 01 01 00 00 00 01 00 00 00
d2 d2
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 06 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]00B6
[H:A]C1 C1 17 02 06 00 01 30 55 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC 0B CC 0A 17 07 B2
5E 01 52 0A 60 09 05 06 14 4B 00 00 58 02 D0 07
00 41 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//#
//[H:S]0021
//[H:S]0004
//[H:A]09 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96

View File

@ -0,0 +1,68 @@
// Coex Configuration
#
[H:S]0017
[H:S]0022
[H:A]d1 d1 20 00 02 01 02 09 0c 00 24 0f 04 00 00 01
00 01 00 01 01 01 01 01 01 00 00 00 01 00 00 00
d2 d2
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 06 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]00B6
[H:A]C1 C1 17 02 06 00 01 30 55 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC 0B CC 0A 17 07 B2
5E 01 52 0A 60 09 05 06 14 4B 00 00 58 02 D0 07
00 41 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//#
//[H:S]0021
//[H:S]0004
//[H:A]09 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96

View File

@ -0,0 +1,68 @@
// Coex Configuration
#
[H:S]0017
[H:S]0022
[H:A]d1 d1 20 00 02 01 02 09 0c 00 24 0f 04 00 00 01
00 01 00 00 01 01 01 01 01 00 00 00 01 00 00 00
d2 d2
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 06 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]00B6
[H:A]C1 C1 17 02 06 00 01 30 55 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC 0B CC 0A 17 07 B2
5E 01 52 0A 60 09 05 06 14 4B 00 00 58 02 D0 07
00 41 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//#
//[H:S]0021
//[H:S]0004
//[H:A]09 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96

View File

@ -0,0 +1,2 @@
0569
000000000e20000050800000000158000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0915300d4915300d8915300dc91530098b0530064ce5300f8d2530008e7530008d253000cd2530098d95300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff051001010101ffffff50500101010180019800c8019800f4029800d0039800380498001404980024059800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000366100ad0581c206bd01e00800bd0a17641c0c0abd05815d080c0ce00800bd02dd03ed05815c080c0ce00800c60400ad05c1f802922b11819903c09920926b11e008000c021df0003681001c0e516d030c0720d074d241107911d0cd90b805a0cc11cabbb90160e6030c2a609034972a026062003801e2c1102203068d07cc8260e613102000fd061df072631122011072434fc805204290a044114acc882c0c1980a00407e805820c4b07e8079c7aa20c4b07ea12a2c3340c0b0cfc0c198191029911e008000c1972434ec805e8114acca82cd20c4ba0a00416aa0590fd20f24c4bcc4e820349f65878a1b1039805a20a034a9992990980aa01a0a831909821809901909831a7294a0c5a81bc04bd02e00800cd0aad0281be04e805c0b0744ace920c4b0c4dd09920924c4be008009c7a72434a860400ad020c4b81bf0492a0fe909d10924c4be0080060e613102000ad061df00c1a81bd04bd02e00800cd0a46ecff0c5a81bd04bd02e00800cd0a86e8ff0000368100305074bd0120407481c206ad04e00800922a11216d0390920516890ba18804b16e03c0200040349091f204a03311822992c02000b08810a08820a8028269923aaab20a49d2ca48579b08c20a4bc0c204161c08b24a4ae1d104524d01eae5f20e7fe20e803c29f7be4a1c0b424110d9111c0c1c0f1c0552c110fd05cd0580e6030c2e80d034d72e02806200bd05b20500c20500a802c0bb90a0bb11baaa924a3480e613102000420500d811403490520d01a03311ad04b20d0081c204cd05e00800a802b2a0fb3aaa920a4b0c12b09910924a4b1df00c021df0364100811e0621c0098808921207ece8ecc9e1b103b21206a21ef1b73a210c0a817c03d21ef0c1d603f16c03c80ce20f44a0bd11e0bd93d1d209e00800a252071df00000364100817f04916c03880892092880801466180acc79810d04a2a064e008001df0000000364100c02000c16c03e1940391d9032178030c0dd2628bf20902c02000f0ed83e2628cc02000d2628dc02000d2628e820c43b20c28d19d0210bb01d0bb10cc580cba0c53c600000c0a0c83c020000c1dd2628fc02000a2628ac02000b26289a209020c088cfa661a040c1ac60300662a05a2190026ca040c0a8607000c0af0ba01e1da03a2090ce0bb100c1ea0ae93e1f40230aa11e0aa10b0aa20b1fd03c02000a26bc1f209020c18f62f040c098604009209070c1a909a930c2af09911a09910d09920c02000d17f04926bc6d80de20c28d0d014661d0acc7e810d04a2a064e00800c020003262881df00036410081c305c1900920b074e19605d16e09e80ec02000d22d82b94ed92ec02000b90c30e6030c2a309034972a02306200e00800c02000fd0391250382a10082698000710030e6131020001df0

View File

@ -0,0 +1,65 @@
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 08 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]009C
[H:A]C1 C1 17 02 08 00 01 30 48 00 0E CC 33 26 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//#
//[H:S]0021
//[H:S]0004
//[H:A]09 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96
//Sniff Recovery
#
[H:S]003D
[H:S]0018
[H:A]A0 0F 00 00 00 08 00 00 0F 00 7D 04 E8 03 01 00
01 00 01 05 00 02 1F 01

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
-"PS_ASIC.pst"
This file contains radio, system, and firwmare configurabilities.
Details on how the ".pst" format and definitions can be found in the documents folder.
-"RamPatch.txt"
This file contains firmware fixes for known defects. Atheros will release patch files as needed.
Both files are required for the system to be operational.
- "ar3kbdaddr.pst"
This file contains the user configurable Bluetooth Address
Linux:
The files have to be copied to "\lib\firmware\" folder.
Windows CE.
The files have to be copied to "platform\<HardWare Name>\Files" folder.
Please refer the corresponding documents for the exacts steps to be followed.

View File

@ -0,0 +1,93 @@
// Coex Configuration
#
[H:S]0017
[H:S]0022
[H:A]d1 d1 20 00 02 01 02 09 0c 00 24 0f 04 00 00 01
00 01 00 01 01 01 01 01 01 00 00 00 01 00 00 00
d2 d2
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 08 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]00B6
[H:A]C1 C1 17 02 06 00 01 30 55 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC 0B CC 0A 17 07 B2
5E 01 52 0A 60 09 05 06 14 4B 00 00 58 02 D0 07
00 41 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//bit 7: sleep disable/enable, default to enable
//e.g. to disable sleep, clear bit 7:
//[H:A]08 00 00 00
#
[H:S]0021
[H:S]0004
[H:A]88 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96
//Sniff Recovery
#
[H:S]003D
[H:S]0018
[H:A]A0 0F 00 00 00 08 00 00 0F 00 7D 04 E8 03 01 00
01 00 01 05 00 02 1F 01
//BRM Config
#
[H:S]0026
[H:S]000C
[H:A]01 20 46 01 0F 02 28 14 01 28 68 01
//TLPM
//[79:64] - TLPM wakeup timeout in ms, default 10
//[127:96] - TLPM idle timeout in ms, default 1000
//e.g. to change the wakeup timeout to 5 and idle timeout to 2000
//[H:A]03 00 03 00 00 00 00 00 05 00 0A 00 D0 07 00 00
// E8 03 00 00 E8 03 00 00
#
[H:S]0023
[H:S]0018
[H:A]03 00 03 00 00 00 00 00 0A 00 0A 00 E8 03 00 00
E8 03 00 00 E8 03 00 00

View File

@ -0,0 +1,93 @@
// Coex Configuration
#
[H:S]0017
[H:S]0022
[H:A]d1 d1 20 00 02 01 02 09 0c 00 24 0f 04 00 00 01
00 01 00 01 01 01 01 01 01 00 00 00 01 00 00 00
d2 d2
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 08 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]00B6
[H:A]C1 C1 17 02 06 00 01 30 55 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC 0B CC 0A 17 07 B2
5E 01 52 0A 60 09 05 06 14 4B 00 00 58 02 D0 07
00 41 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//bit 7: sleep disable/enable, default to enable
//e.g. to disable sleep, clear bit 7:
//[H:A]08 00 00 00
#
[H:S]0021
[H:S]0004
[H:A]88 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96
//Sniff Recovery
#
[H:S]003D
[H:S]0018
[H:A]A0 0F 00 00 00 08 00 00 0F 00 7D 04 E8 03 01 00
01 00 01 05 00 02 1F 01
//BRM Config
#
[H:S]0026
[H:S]000C
[H:A]01 20 46 01 0F 02 28 14 01 28 68 01
//TLPM
//[79:64] - TLPM wakeup timeout in ms, default 10
//[127:96] - TLPM idle timeout in ms, default 1000
//e.g. to change the wakeup timeout to 5 and idle timeout to 2000
//[H:A]03 00 03 00 00 00 00 00 05 00 0A 00 D0 07 00 00
// E8 03 00 00 E8 03 00 00
#
[H:S]0023
[H:S]0018
[H:A]03 00 03 00 00 00 00 00 0A 00 0A 00 E8 03 00 00
E8 03 00 00 E8 03 00 00

View File

@ -0,0 +1,93 @@
// Coex Configuration
#
[H:S]0017
[H:S]0022
[H:A]d1 d1 20 00 02 01 02 09 0c 00 24 0f 04 00 00 01
00 01 00 00 01 01 01 01 01 00 00 00 01 00 00 00
d2 d2
// Radio table TAG
#
[H:S]012C
[H:S]0042
[H:A]B1 B1 12 00 08 00 01 30 06 00 02 00 00 20 02 00
04 00 0C 40 01 00 48 00 00 48 54 9A 02 00 00 08
02 00 48 00 89 EE 70 E6 38 00 D8 70 EF 52 02 00
00 40 00 00 08 00 31 00 00 00 04 00 10 00 00 00
B2 B2
// System config TAG
#
[H:S]0013
[H:S]00B6
[H:A]C1 C1 17 02 06 00 01 30 55 00 0E CC 33 06 01 08
64 96 14 05 FF FF 05 80 00 00 FF CC 00 CC 01 00
20 80 FF CC 02 CC 04 00 DF EC 43 F8 00 21 00 E0
FF CC 03 CC 06 00 80 F0 08 28 80 F4 0C 20 80 F8
0E 18 80 FC 14 10 80 00 18 08 80 04 16 00 FF CC
04 CC 01 00 1A 12 40 96 01 C0 28 00 00 00 C0 01
40 06 00 01 00 00 C8 00 00 F0 00 00 FF CC 0C CC
08 00 01 03 00 7E 08 08 00 7E 01 01 00 7E 01 03
00 7E 03 03 00 7E 61 63 00 7E 63 65 00 7E 6A 6C
00 7E FF CC 09 CC 00 C9 FF CC 0B CC 0A 17 07 B2
5E 01 52 0A 60 09 05 06 14 4B 00 00 58 02 D0 07
00 41 FF CC C2 C2
//Extern 32k + 24Mhz CPU
//bit 7: sleep disable/enable, default to enable
//e.g. to disable sleep, clear bit 7:
//[H:A]08 00 00 00
#
[H:S]0021
[H:S]0004
[H:A]88 00 00 00
//Bdaddr
//#
//[H:S]0001
//[H:S]0006
//[H:A]89 60 41 7f 03 00
//Audio
#
[H:S]0002
[H:S]0004
[H:A]23 08 01 33
//Audio
#
[H:S]0003
[H:S]0004
[H:A]dd e5 2e 00
//Audio
#
[H:S]0015
[H:S]0004
[H:A]12 00 00 00
//Audio
#
[H:S]0016
[H:S]0004
[H:A]00 00 a7 02
#
//PLC
[H:S]001F
[H:S]0008
[H:A]01 1A 06 14 50 B4 32 96
//Sniff Recovery
#
[H:S]003D
[H:S]0018
[H:A]A0 0F 00 00 00 08 00 00 0F 00 7D 04 E8 03 01 00
01 00 01 05 00 02 1F 01
//BRM Config
#
[H:S]0026
[H:S]000C
[H:A]01 20 46 01 0F 02 28 14 01 28 68 01
//TLPM
//[79:64] - TLPM wakeup timeout in ms, default 10
//[127:96] - TLPM idle timeout in ms, default 1000
//e.g. to change the wakeup timeout to 5 and idle timeout to 2000
//[H:A]03 00 03 00 00 00 00 00 05 00 0A 00 D0 07 00 00
// E8 03 00 00 E8 03 00 00
#
[H:S]0023
[H:S]0018
[H:A]03 00 03 00 00 00 00 00 0A 00 0A 00 E8 03 00 00
E8 03 00 00 E8 03 00 00

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,569 @@
//------------------------------------------------------------------------------
// 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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// AR3K configuration implementation
//
// Author(s): ="Atheros"
//==============================================================================
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#define ATH_MODULE_NAME misc
#include "a_debug.h"
#include "common_drv.h"
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
#include "export_hci_transport.h"
#else
#include "hci_transport_api.h"
#endif
#include "ar3kconfig.h"
#include "tlpm.h"
#define BAUD_CHANGE_COMMAND_STATUS_OFFSET 5
#define HCI_EVENT_RESP_TIMEOUTMS 3000
#define HCI_CMD_OPCODE_BYTE_LOW_OFFSET 0
#define HCI_CMD_OPCODE_BYTE_HI_OFFSET 1
#define HCI_EVENT_OPCODE_BYTE_LOW 3
#define HCI_EVENT_OPCODE_BYTE_HI 4
#define HCI_CMD_COMPLETE_EVENT_CODE 0xE
#define HCI_MAX_EVT_RECV_LENGTH 257
#define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET 5
A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig,
A_UINT8 *pBuffer,
int Length)
{
HTC_PACKET *pPacket = NULL;
A_STATUS status = A_OK;
do {
pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));
if (NULL == pPacket) {
status = A_NO_MEMORY;
break;
}
A_MEMZERO(pPacket,sizeof(HTC_PACKET));
SET_HTC_PACKET_INFO_TX(pPacket,
NULL,
pBuffer,
Length,
HCI_COMMAND_TYPE,
AR6K_CONTROL_PKT_TAG);
/* issue synchronously */
status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,TRUE);
} while (FALSE);
if (pPacket != NULL) {
A_FREE(pPacket);
}
return status;
}
static A_STATUS RecvHCIEvent(AR3K_CONFIG_INFO *pConfig,
A_UINT8 *pBuffer,
int *pLength)
{
A_STATUS status = A_OK;
HTC_PACKET *pRecvPacket = NULL;
do {
pRecvPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));
if (NULL == pRecvPacket) {
status = A_NO_MEMORY;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
break;
}
A_MEMZERO(pRecvPacket,sizeof(HTC_PACKET));
SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
pRecvPacket,
HCI_EVENT_RESP_TIMEOUTMS);
if (A_FAILED(status)) {
break;
}
*pLength = pRecvPacket->ActualLength;
} while (FALSE);
if (pRecvPacket != NULL) {
A_FREE(pRecvPacket);
}
return status;
}
A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
A_UINT8 *pHCICommand,
int CmdLength,
A_UINT8 **ppEventBuffer,
A_UINT8 **ppBufferToFree)
{
A_STATUS status = A_OK;
A_UINT8 *pBuffer = NULL;
A_UINT8 *pTemp;
int length;
A_BOOL commandComplete = FALSE;
A_UINT8 opCodeBytes[2];
do {
length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength);
length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
length += pConfig->pHCIProps->IOBlockPad;
pBuffer = (A_UINT8 *)A_MALLOC(length);
if (NULL == pBuffer) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
status = A_NO_MEMORY;
break;
}
/* get the opcodes to check the command complete event */
opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET];
opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET];
/* copy HCI command */
A_MEMCPY(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);
/* send command */
status = SendHCICommand(pConfig,
pBuffer + pConfig->pHCIProps->HeadRoom,
CmdLength);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status));
AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
break;
}
/* reuse buffer to capture command complete event */
A_MEMZERO(pBuffer,length);
status = RecvHCIEvent(pConfig,pBuffer,&length);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n"));
AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
break;
}
pTemp = pBuffer + pConfig->pHCIProps->HeadRoom;
if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) {
if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) &&
(pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) {
commandComplete = TRUE;
}
}
if (!commandComplete) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0]));
AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event");
status = A_ECOMM;
break;
}
if (ppEventBuffer != NULL) {
/* caller wants to look at the event */
*ppEventBuffer = pTemp;
if (ppBufferToFree == NULL) {
status = A_EINVAL;
break;
}
/* caller must free the buffer */
*ppBufferToFree = pBuffer;
pBuffer = NULL;
}
} while (FALSE);
if (pBuffer != NULL) {
A_FREE(pBuffer);
}
return status;
}
static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
{
A_STATUS status = A_OK;
A_UINT8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0};
A_UINT16 baudVal;
A_UINT8 *pEvent = NULL;
A_UINT8 *pBufferToFree = NULL;
do {
if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100);
hciBaudChangeCommand[3] = (A_UINT8)baudVal;
hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8);
status = SendHCICommandWaitCommandComplete(pConfig,
hciBaudChangeCommand,
sizeof(hciBaudChangeCommand),
&pEvent,
&pBufferToFree);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));
break;
}
if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("AR3K Config: Baud change command event status failed: %d \n",
pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET]));
status = A_ECOMM;
break;
}
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate));
}
if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) {
/* some versions of AR3K do not switch baud immediately, up to 300MS */
A_MDELAY(325);
}
if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) {
/* Tell target to change UART baud rate for AR6K */
status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("AR3K Config: failed to set scale and step values: %d \n", status));
break;
}
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));
}
} while (FALSE);
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
return status;
}
static A_STATUS AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig)
{
A_STATUS status;
A_CHAR exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00};
A_UINT8 *pEvent = NULL;
A_UINT8 *pBufferToFree = NULL;
status = SendHCICommandWaitCommandComplete(pConfig,
exitMinBootCmd,
sizeof(exitMinBootCmd),
&pEvent,
&pBufferToFree);
if (A_SUCCESS(status)) {
if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("AR3K Config: MinBoot exit command event status failed: %d \n",
pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET]));
status = A_ECOMM;
} else {
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
("AR3K Config: MinBoot Exit Command Complete (Success) \n"));
A_MDELAY(1);
}
} else {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n"));
}
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
return status;
}
static A_STATUS AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig)
{
A_STATUS status = A_OK;
A_UINT8 hciResetCommand[] = {0x03,0x0c,0x0};
A_UINT8 *pEvent = NULL;
A_UINT8 *pBufferToFree = NULL;
status = SendHCICommandWaitCommandComplete( pConfig,
hciResetCommand,
sizeof(hciResetCommand),
&pEvent,
&pBufferToFree );
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
}
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
return status;
}
static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
{
A_STATUS status;
/* AR3K vendor specific command for Host Wakeup Config */
A_CHAR hostWakeupConfig[] = {0x31,0xFC,0x18,
0x02,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,
TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
0x00,0x00,0x00,0x00,
TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms
0x00,0x00,0x00,0x00};
/* AR3K vendor specific command for Target Wakeup Config */
A_CHAR targetWakeupConfig[] = {0x31,0xFC,0x18,
0x04,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,
TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
0x00,0x00,0x00,0x00,
TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms
0x00,0x00,0x00,0x00};
/* AR3K vendor specific command for Host Wakeup Enable */
A_CHAR hostWakeupEnable[] = {0x31,0xFC,0x4,
0x01,0x00,0x00,0x00};
/* AR3K vendor specific command for Target Wakeup Enable */
A_CHAR targetWakeupEnable[] = {0x31,0xFC,0x4,
0x06,0x00,0x00,0x00};
/* AR3K vendor specific command for Sleep Enable */
A_CHAR sleepEnable[] = {0x4,0xFC,0x1,
0x1};
A_UINT8 *pEvent = NULL;
A_UINT8 *pBufferToFree = NULL;
if (0 != pConfig->IdleTimeout) {
A_UINT8 idle_lsb = pConfig->IdleTimeout & 0xFF;
A_UINT8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
}
if (0 != pConfig->WakeupTimeout) {
hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF);
}
status = SendHCICommandWaitCommandComplete(pConfig,
hostWakeupConfig,
sizeof(hostWakeupConfig),
&pEvent,
&pBufferToFree);
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));
return status;
}
pEvent = NULL;
pBufferToFree = NULL;
status = SendHCICommandWaitCommandComplete(pConfig,
targetWakeupConfig,
sizeof(targetWakeupConfig),
&pEvent,
&pBufferToFree);
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));
return status;
}
pEvent = NULL;
pBufferToFree = NULL;
status = SendHCICommandWaitCommandComplete(pConfig,
hostWakeupEnable,
sizeof(hostWakeupEnable),
&pEvent,
&pBufferToFree);
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));
return status;
}
pEvent = NULL;
pBufferToFree = NULL;
status = SendHCICommandWaitCommandComplete(pConfig,
targetWakeupEnable,
sizeof(targetWakeupEnable),
&pEvent,
&pBufferToFree);
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));
return status;
}
pEvent = NULL;
pBufferToFree = NULL;
status = SendHCICommandWaitCommandComplete(pConfig,
sleepEnable,
sizeof(sleepEnable),
&pEvent,
&pBufferToFree);
if (pBufferToFree != NULL) {
A_FREE(pBufferToFree);
}
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status));
return status;
}
A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
{
A_STATUS status = A_OK;
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
do {
if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
status = A_EINVAL;
break;
}
/* disable asynchronous recv while we issue commands and receive events synchronously */
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
if (A_FAILED(status)) {
break;
}
if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
status = AR3KExitMinBoot(pConfig);
if (A_FAILED(status)) {
break;
}
}
/* Load patching and PST file if available*/
if (A_OK != AthPSInitialize(pConfig)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
}
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("TLPM - PwrMgmtEnabled=%d, IdleTimeout=%d, WakeupTimeout=%d\n",
pConfig->PwrMgmtEnabled,
pConfig->IdleTimeout,
pConfig->WakeupTimeout));
/* Send HCI reset to make PS tags take effect*/
AR3KConfigureSendHCIReset(pConfig);
if (pConfig->PwrMgmtEnabled) {
/* the delay is required after the previous HCI reset before further
* HCI commands can be issued
*/
A_MDELAY(200);
AR3KEnableTLPM(pConfig);
}
if (pConfig->Flags &
(AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
status = AR3KConfigureHCIBaud(pConfig);
if (A_FAILED(status)) {
break;
}
}
/* re-enable asynchronous recv */
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
if (A_FAILED(status)) {
break;
}
} while (FALSE);
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
return status;
}
A_STATUS AR3KConfigureExit(void *config)
{
A_STATUS status = A_OK;
AR3K_CONFIG_INFO *pConfig = (AR3K_CONFIG_INFO *)config;
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
do {
if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
status = A_EINVAL;
break;
}
/* disable asynchronous recv while we issue commands and receive events synchronously */
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
if (A_FAILED(status)) {
break;
}
if (pConfig->Flags &
(AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
status = AR3KConfigureHCIBaud(pConfig);
if (A_FAILED(status)) {
break;
}
}
/* re-enable asynchronous recv */
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
if (A_FAILED(status)) {
break;
}
} while (FALSE);
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));
return status;
}

View File

@ -0,0 +1,694 @@
/*
* Copyright (c) 2004-2010 Atheros Communications Inc.
* All rights reserved.
*
* This file implements the Atheros PS and patch downloaded for HCI UART Transport driver.
* This file can be used for HCI SDIO transport implementation for AR6002 with HCI_TRANSPORT_SDIO
* defined.
*
*
* ar3kcpsconfig.c
*
*
*
* The software source and binaries included in this development package are
* licensed, not sold. You, or your company, received the package under one
* or more license agreements. The rights granted to you are specifically
* listed in these license agreement(s). All other rights remain with Atheros
* Communications, Inc., its subsidiaries, or the respective owner including
* those listed on the included copyright notices.. Distribution of any
* portion of this package must be in strict compliance with the license
* agreement(s) terms.
*
*
*
*/
#include "ar3kpsconfig.h"
#ifndef HCI_TRANSPORT_SDIO
#include "hci_ath.h"
#include "hci_uart.h"
#endif /* #ifndef HCI_TRANSPORT_SDIO */
#define MAX_FW_PATH_LEN 50
#define MAX_BDADDR_FORMAT_LENGTH 30
/*
* Structure used to send HCI packet, hci packet length and device info
* together as parameter to PSThread.
*/
typedef struct {
PSCmdPacket *HciCmdList;
A_UINT32 num_packets;
AR3K_CONFIG_INFO *dev;
}HciCommandListParam;
A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
A_UINT8 *pHCICommand,
int CmdLength,
A_UINT8 **ppEventBuffer,
A_UINT8 **ppBufferToFree);
void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int index);
A_UINT32 Rom_Version;
A_UINT32 Build_Version;
extern A_BOOL BDADDR;
extern A_UINT32 Patch_Count;
A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code);
A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig);
A_STATUS set_patch_ram(AR3K_CONFIG_INFO *pConfig,A_UCHAR *patch_loc,A_UINT8 len);
#ifndef HCI_TRANSPORT_SDIO
DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent);
DECLARE_WAIT_QUEUE_HEAD(HciEvent);
A_UCHAR *HciEventpacket;
rwlock_t syncLock;
wait_queue_t Eventwait;
int PSHciWritepacket(struct hci_dev*,A_UCHAR* Data, A_UINT32 len);
extern char *bdaddr;
#endif /* HCI_TRANSPORT_SDIO */
A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type);
int PSSendOps(void *arg);
#ifdef BT_PS_DEBUG
void Hci_log(A_UCHAR * log_string,A_UCHAR *data,A_UINT32 len)
{
int i;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string));
for (i = 0; i < len; i++) {
printk("0x%02x ", data[i]);
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n...................................\n"));
}
#else
#define Hci_log(string,data,len)
#endif /* BT_PS_DEBUG */
A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev)
{
A_STATUS status = A_OK;
if(hdev == NULL) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n"));
return A_ERROR;
}
#ifndef HCI_TRANSPORT_SDIO
DECLARE_WAITQUEUE(wait, current);
#endif /* HCI_TRANSPORT_SDIO */
#ifdef HCI_TRANSPORT_SDIO
status = PSSendOps((void*)hdev);
#else
if(InitPSState(hdev) == -1) {
return A_ERROR;
}
allow_signal(SIGKILL);
add_wait_queue(&PsCompleteEvent,&wait);
set_current_state(TASK_INTERRUPTIBLE);
if(!kernel_thread(PSSendOps,(void*)hdev,CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Kthread Failed\n"));
remove_wait_queue(&PsCompleteEvent,&wait);
return A_ERROR;
}
wait_event_interruptible(PsCompleteEvent,(PSTagMode == FALSE));
set_current_state(TASK_RUNNING);
remove_wait_queue(&PsCompleteEvent,&wait);
#endif /* HCI_TRANSPORT_SDIO */
return status;
}
int PSSendOps(void *arg)
{
int i;
int ps_index;
int status = 0;
PSCmdPacket *HciCmdList; /* List storing the commands */
const struct firmware* firmware;
A_UINT32 numCmds;
A_UINT8 *event;
A_UINT8 *bufferToFree;
struct hci_dev *device;
A_UCHAR *buffer;
A_UINT32 len;
A_UINT32 DevType;
A_UCHAR *PsFileName;
A_UCHAR *patchFileName;
A_UCHAR patch_loc[40];
A_UCHAR *path = NULL;
A_UCHAR *config_path = NULL;
A_UCHAR config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
AR3K_CONFIG_INFO *hdev = (AR3K_CONFIG_INFO*)arg;
struct device *firmwareDev = NULL;
A_UINT8 cFlags = 0;
A_UINT8 bit7 = 0;
status = 0;
HciCmdList = NULL;
#ifdef HCI_TRANSPORT_SDIO
device = hdev->pBtStackHCIDev;
firmwareDev = device->parent;
#else
device = hdev;
firmwareDev = &device->dev;
AthEnableSyncCommandOp(TRUE);
#endif /* HCI_TRANSPORT_SDIO */
/* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different.
*/
path =(A_UCHAR *)A_MALLOC(MAX_FW_PATH_LEN);
if(path == NULL) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN));
goto complete;
}
config_path = (A_UCHAR *) A_MALLOC(MAX_FW_PATH_LEN);
if(config_path == NULL) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN));
goto complete;
}
if(A_ERROR == getDeviceType(hdev,&DevType)) {
status = 1;
goto complete;
}
if(A_ERROR == ReadVersionInfo(hdev)) {
status = 1;
goto complete;
}
patchFileName = PATCH_FILE;
snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version);
if(DevType){
if(DevType == 0xdeadc0de){
PsFileName = PS_ASIC_FILE;
} else{
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version));
if((Rom_Version == 0x99999999) && (Build_Version == 1)){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n"));
patchFileName = NULL;
}
PsFileName = PS_FPGA_FILE;
}
}
else{
PsFileName = PS_ASIC_FILE;
}
snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,PsFileName);
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,config_path));
/* Read the PS file to a dynamically allocated buffer */
if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ ));
status = 1;
goto complete;
}
if(NULL == firmware || firmware->size == 0) {
status = 1;
goto complete;
}
buffer = (A_UCHAR *)A_MALLOC(firmware->size);
if(buffer != NULL) {
/* Copy the read file to a local Dynamic buffer */
memcpy(buffer,firmware->data,firmware->size);
len = firmware->size;
A_RELEASE_FIRMWARE(firmware);
/* Parse the PS buffer to a global variable */
status = AthDoParsePS(buffer,len);
A_FREE(buffer);
} else {
A_RELEASE_FIRMWARE(firmware);
}
/* Read the patch file to a dynamically allocated buffer */
if(patchFileName != NULL)
snprintf(config_path,
MAX_FW_PATH_LEN, "%s%s",path,patchFileName);
else {
status = 0;
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path));
if((patchFileName == NULL) || (A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ ));
/*
* It is not necessary that Patch file be available, continue with PS Operations if.
* failed.
*/
status = 0;
} else {
if(NULL == firmware || firmware->size == 0) {
status = 0;
} else {
buffer = (A_UCHAR *)A_MALLOC(firmware->size);
if(buffer != NULL) {
/* Copy the read file to a local Dynamic buffer */
memcpy(buffer,firmware->data,firmware->size);
len = firmware->size;
A_RELEASE_FIRMWARE(firmware);
/* parse and store the Patch file contents to a global variables */
patch_loc[0] = '\0';
status = AthDoParsePatch(buffer,len, patch_loc);
A_FREE(buffer);
} else {
A_RELEASE_FIRMWARE(firmware);
}
}
}
/* Create an HCI command list from the parsed PS and patch information */
AthCreateCommandList(&HciCmdList,&numCmds);
#define CONFIG_PLATFORM 0x21
#define CONFIG_TLPM 0x23
#define PLATFORM_CONFIG_BIT 0x01
#define TLPM_CONFIG_BIT 0x02
#define IDLE_TIMEOUT_OFFSET 12
#define WAKEUP_TIMEOUT_OFFSET 8
#define IDLE_TIMEOUT_DEFAULT_VAL 1000
#define WAKEUP_TIMEOUT_DEFAULT_VAL 10
hdev->IdleTimeout = IDLE_TIMEOUT_DEFAULT_VAL;
hdev->WakeupTimeout = WAKEUP_TIMEOUT_DEFAULT_VAL;
hdev->PwrMgmtEnabled = 0;
ps_index = 2; /* CRC + PS Reset */
if (Patch_Count)
ps_index += Patch_Count + 1; /* Patches + Enable patch Cmd */
for(i = ps_index; i <numCmds; i++) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Check PS ID %x\n", HciCmdList[i].Hcipacket[4]));
/* search for Platform config and TLPM tags */
if((HciCmdList[i].Hcipacket[4] == CONFIG_PLATFORM) &&
(HciCmdList[i].Hcipacket[5] == 0)) {
cFlags |= PLATFORM_CONFIG_BIT;
bit7 = (HciCmdList[i].Hcipacket[7]) & (1<<7);
if(bit7) {
hdev->PwrMgmtEnabled = 1;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("CONFIG PLATFORM present and Pwr Manage %x\n", hdev->PwrMgmtEnabled));
}
}
else if((HciCmdList[i].Hcipacket[4] == CONFIG_TLPM) &&
(HciCmdList[i].Hcipacket[5] == 0)) {
cFlags |= TLPM_CONFIG_BIT;
hdev->IdleTimeout = *((A_UINT32 *)&HciCmdList[i].Hcipacket[IDLE_TIMEOUT_OFFSET + 7]);
hdev->WakeupTimeout = *((A_UINT16 *)&HciCmdList[i].Hcipacket[WAKEUP_TIMEOUT_OFFSET + 7]);
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("hdev->idletimeout %d hdev->WakeupTimeout %d",hdev->IdleTimeout, hdev->WakeupTimeout));
}
}
/* Form the parameter for PSSendOps() API */
/*
* First Send the CRC packet,
* We have to continue with the PS operations only if the CRC packet has been replied with
* a Command complete event with status Error.
*/
if(SendHCICommandWaitCommandComplete
(hdev,
HciCmdList[0].Hcipacket,
HciCmdList[0].packetLen,
&event,
&bufferToFree) == A_OK) {
if(ReadPSEvent(event) == A_OK) { /* Exit if the status is success */
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
#ifndef HCI_TRANSPORT_SDIO
if(bdaddr && bdaddr[0] !='\0') {
write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING);
}
#endif
status = 1;
goto complete;
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
} else {
status = 0;
goto complete;
}
/* Set Patch location */
if(patch_loc[0] != '\0') {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Setting Patch Location %s\n", patch_loc));
set_patch_ram(hdev,patch_loc,sizeof(patch_loc));
}
for(i = 1; i <numCmds; i++) {
Hci_log("PS/Patch Write -->",HciCmdList[i].Hcipacket,HciCmdList[i].packetLen);
if(SendHCICommandWaitCommandComplete
(hdev,
HciCmdList[i].Hcipacket,
HciCmdList[i].packetLen,
&event,
&bufferToFree) == A_OK) {
if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
status = 1;
goto complete;
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
} else {
status = 0;
goto complete;
}
}
#ifdef HCI_TRANSPORT_SDIO
if(BDADDR == FALSE)
if(hdev->bdaddr[0] !=0x00 ||
hdev->bdaddr[1] !=0x00 ||
hdev->bdaddr[2] !=0x00 ||
hdev->bdaddr[3] !=0x00 ||
hdev->bdaddr[4] !=0x00 ||
hdev->bdaddr[5] !=0x00)
write_bdaddr(hdev,hdev->bdaddr,BDADDR_TYPE_HEX);
/* if Platform config is present and TLPM is not available
* write HCI command for TLPM with default timeout values */
if(bit7 && !(cFlags & TLPM_CONFIG_BIT)) {
A_UCHAR TLPMHciCmd[] = {0x0b, 0xfc, 0x1c, 0x01, 0x23, 0x00, 0x18,
0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0a, 0x00, 0x0a, 0x00, 0xe8, 0x03,
0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xe8,
0x03, 0x00, 0x00 };
int CmdLen = sizeof(TLPMHciCmd);
*((A_UINT32 *)&TLPMHciCmd[IDLE_TIMEOUT_OFFSET + 7]) = hdev->IdleTimeout;
*((A_UINT16 *)&TLPMHciCmd[WAKEUP_TIMEOUT_OFFSET + 7]) = hdev->WakeupTimeout;
if(SendHCICommandWaitCommandComplete
(hdev,
TLPMHciCmd,
CmdLen,
&event,
&bufferToFree) == A_OK) {
if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
status = 1;
goto complete;
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
} else {
status = 0;
goto complete;
}
}
#ifndef HCI_TRANSPORT_SDIO
if(bdaddr && bdaddr[0] != '\0') {
write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING);
} else
#endif /* HCI_TRANSPORT_SDIO */
/* Write BDADDR Read from OTP here */
#endif
{
/* Read Contents of BDADDR file if user has not provided any option */
snprintf(config_path,MAX_FW_PATH_LEN, "%s%s",path,BDADDR_FILE);
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR File Name %s\n", config_path));
if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ ));
goto complete;
}
if(NULL == firmware || firmware->size == 0) {
goto complete;
}
len = (firmware->size > MAX_BDADDR_FORMAT_LENGTH)? MAX_BDADDR_FORMAT_LENGTH: firmware->size;
memcpy(config_bdaddr, firmware->data,len);
config_bdaddr[len] = '\0';
write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING);
A_RELEASE_FIRMWARE(firmware);
}
complete:
#ifndef HCI_TRANSPORT_SDIO
AthEnableSyncCommandOp(FALSE);
PSTagMode = FALSE;
wake_up_interruptible(&PsCompleteEvent);
#endif /* HCI_TRANSPORT_SDIO */
if(NULL != HciCmdList) {
AthFreeCommandList(&HciCmdList,numCmds);
}
if(path) {
A_FREE(path);
}
if(config_path) {
A_FREE(config_path);
}
return status;
}
#ifndef HCI_TRANSPORT_SDIO
/*
* This API is used to send the HCI command to controller and return
* with a HCI Command Complete event.
* For HCI SDIO transport, this will be internally defined.
*/
A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
A_UINT8 *pHCICommand,
int CmdLength,
A_UINT8 **ppEventBuffer,
A_UINT8 **ppBufferToFree)
{
if(CmdLength == 0) {
return A_ERROR;
}
Hci_log("COM Write -->",pHCICommand,CmdLength);
PSAcked = FALSE;
if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) {
/* If the controller is not available, return Error */
return A_ERROR;
}
//add_timer(&psCmdTimer);
wait_event_interruptible(HciEvent,(PSAcked == TRUE));
if(NULL != HciEventpacket) {
*ppEventBuffer = HciEventpacket;
*ppBufferToFree = HciEventpacket;
} else {
/* Did not get an event from controller. return error */
*ppBufferToFree = NULL;
return A_ERROR;
}
return A_OK;
}
#endif /* HCI_TRANSPORT_SDIO */
A_STATUS ReadPSEvent(A_UCHAR* Data){
if(Data[4] == 0xFC && Data[5] == 0x00)
{
switch(Data[3]){
case 0x0B:
return A_OK;
break;
case 0x0C:
/* Change Baudrate */
return A_OK;
break;
case 0x04:
return A_OK;
break;
case 0x1E:
Rom_Version = Data[9];
Rom_Version = ((Rom_Version << 8) |Data[8]);
Rom_Version = ((Rom_Version << 8) |Data[7]);
Rom_Version = ((Rom_Version << 8) |Data[6]);
Build_Version = Data[13];
Build_Version = ((Build_Version << 8) |Data[12]);
Build_Version = ((Build_Version << 8) |Data[11]);
Build_Version = ((Build_Version << 8) |Data[10]);
return A_OK;
break;
}
}
return A_ERROR;
}
int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr)
{
unsigned char bdbyte[3];
unsigned char *str_byte = str_bdaddr;
int i,j;
unsigned char colon_present = 0;
if(NULL != strstr(str_bdaddr,":")) {
colon_present = 1;
}
bdbyte[2] = '\0';
for( i = 0,j = 5; i < 6; i++, j--) {
bdbyte[0] = str_byte[0];
bdbyte[1] = str_byte[1];
bdaddr[j] = A_STRTOL(bdbyte,NULL,16);
if(colon_present == 1) {
str_byte+=3;
} else {
str_byte+=2;
}
}
return 0;
}
A_STATUS set_patch_ram(AR3K_CONFIG_INFO *pConfig,A_UCHAR *patch_loc,A_UINT8 len)
{
A_UCHAR cmd[] = { 0x0B, 0xFC, 0x07, 0x0D, 0x00, 0x00, 0x00, /* Loc */0x00, 0x00, 0x00, 0x00 };
A_UCHAR i,j;
unsigned char loc_byte[3];
A_UINT8 *event;
A_UINT8 *bufferToFree = NULL;
A_STATUS result = A_ERROR;
A_UCHAR *loc_ptr = &cmd[7];
if(!patch_loc)
return result;
loc_byte[2] = '\0';
LoadHeader(cmd, 0x0D, 4, 0);
for( i = 0,j = 3; i < 4; i++, j--) {
loc_byte[0] = patch_loc[0];
loc_byte[1] = patch_loc[1];
loc_ptr[j] = A_STRTOL(loc_byte,NULL,16);
patch_loc+=2;
}
Hci_log("Patch Ram Write -->",cmd, sizeof(cmd));
if(A_OK == SendHCICommandWaitCommandComplete(pConfig,cmd,
sizeof(cmd),
&event,&bufferToFree)) {
result = ReadPSEvent(event);
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
return result;
}
A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type)
{
A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01,
0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
A_UINT8 *event;
A_UINT8 *bufferToFree = NULL;
A_STATUS result = A_ERROR;
int inc,outc;
if (type == BDADDR_TYPE_STRING)
str2ba(bdaddr,&bdaddr_cmd[7]);
else {
/* Bdaddr has to be sent as LAP first */
for(inc = 5 ,outc = 7; inc >=0; inc--, outc++)
bdaddr_cmd[outc] = bdaddr[inc];
}
Hci_log("BDADDR Write -->",bdaddr_cmd,sizeof(bdaddr_cmd));
if(A_OK == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
sizeof(bdaddr_cmd),
&event,&bufferToFree)) {
if(event[4] == 0xFC && event[5] == 0x00){
if(event[3] == 0x0B){
result = A_OK;
}
}
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
return result;
}
A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig)
{
A_UINT8 hciCommand[] = {0x1E,0xfc,0x00};
A_UINT8 *event;
A_UINT8 *bufferToFree = NULL;
A_STATUS result = A_ERROR;
Hci_log("Read Version -->",hciCommand,sizeof(hciCommand));
if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
result = ReadPSEvent(event);
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
return result;
}
A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code)
{
A_UINT8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
A_UINT8 *event;
A_UINT8 *bufferToFree = NULL;
A_UINT32 reg;
A_STATUS result = A_ERROR;
*code = 0;
hciCommand[3] = (A_UINT8)(FPGA_REGISTER & 0xFF);
hciCommand[4] = (A_UINT8)((FPGA_REGISTER >> 8) & 0xFF);
hciCommand[5] = (A_UINT8)((FPGA_REGISTER >> 16) & 0xFF);
hciCommand[6] = (A_UINT8)((FPGA_REGISTER >> 24) & 0xFF);
if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
if(event[4] == 0xFC && event[5] == 0x00){
switch(event[3]){
case 0x05:
reg = event[9];
reg = ((reg << 8) |event[8]);
reg = ((reg << 8) |event[7]);
reg = ((reg << 8) |event[6]);
*code = reg;
result = A_OK;
break;
case 0x06:
//Sleep(500);
break;
}
}
}
if(bufferToFree != NULL) {
A_FREE(bufferToFree);
}
return result;
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2004-2010 Atheros Communications Inc.
* All rights reserved.
*
* This file defines the symbols exported by Atheros PS and patch download module.
* define the constant HCI_TRANSPORT_SDIO if the module is being used for HCI SDIO transport.
* defined.
*
*
* ar3kcpsconfig.h
*
*
*
* The software source and binaries included in this development package are
* licensed, not sold. You, or your company, received the package under one
* or more license agreements. The rights granted to you are specifically
* listed in these license agreement(s). All other rights remain with Atheros
* Communications, Inc., its subsidiaries, or the respective owner including
* those listed on the included copyright notices.. Distribution of any
* portion of this package must be in strict compliance with the license
* agreement(s) terms.
*
*
*
*/
#ifndef __AR3KPSCONFIG_H
#define __AR3KPSCONFIG_H
/*
* Define the flag HCI_TRANSPORT_SDIO and undefine HCI_TRANSPORT_UART if the transport being used is SDIO.
*/
#undef HCI_TRANSPORT_UART
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/signal.h>
#include <linux/timer.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
#include <linux/firmware.h>
#include <linux/wait.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "ar3kpsparser.h"
#define FPGA_REGISTER 0x4FFC
#define BDADDR_TYPE_STRING 0
#define BDADDR_TYPE_HEX 1
#define CONFIG_PATH "ar3k"
#define PS_ASIC_FILE "PS_ASIC.pst"
#define PS_FPGA_FILE "PS_FPGA.pst"
#define PATCH_FILE "RamPatch.txt"
#define BDADDR_FILE "ar3kbdaddr.pst"
#define ROM_VER_AR3001_3_1_0 30000
#define ROM_VER_AR3001_3_1_1 30101
#ifndef HCI_TRANSPORT_SDIO
#define AR3K_CONFIG_INFO struct hci_dev
extern wait_queue_head_t HciEvent;
extern wait_queue_t Eventwait;
extern A_UCHAR *HciEventpacket;
#endif /* #ifndef HCI_TRANSPORT_SDIO */
A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
A_STATUS ReadPSEvent(A_UCHAR* Data);
#endif /* __AR3KPSCONFIG_H */

View File

@ -0,0 +1,989 @@
/*
* Copyright (c) 2004-2010 Atheros Communications Inc.
* All rights reserved.
*
* This file implements the Atheros PS and patch parser.
* It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands.
*
*
*
* ar3kpsparser.c
*
*
*
* The software source and binaries included in this development package are
* licensed, not sold. You, or your company, received the package under one
* or more license agreements. The rights granted to you are specifically
* listed in these license agreement(s). All other rights remain with Atheros
* Communications, Inc., its subsidiaries, or the respective owner including
* those listed on the included copyright notices.. Distribution of any
* portion of this package must be in strict compliance with the license
* agreement(s) terms.
*
*
*
*/
#include "ar3kpsparser.h"
#define BD_ADDR_SIZE 6
#define WRITE_PATCH 8
#define ENABLE_PATCH 11
#define PS_RESET 2
#define PS_WRITE 1
#define PS_VERIFY_CRC 9
#define CHANGE_BDADDR 15
#define HCI_COMMAND_HEADER 7
#define HCI_EVENT_SIZE 7
#define WRITE_PATCH_COMMAND_STATUS_OFFSET 5
#define PS_RAM_SIZE 2048
#define RAM_PS_REGION (1<<0)
#define RAM_PATCH_REGION (1<<1)
#define RAMPS_MAX_PS_DATA_PER_TAG 20000
#define MAX_RADIO_CFG_TABLE_SIZE 244
#define RAMPS_MAX_PS_TAGS_PER_FILE 50
#define PS_MAX_LEN 500
#define LINE_SIZE_MAX (PS_MAX_LEN *2)
/* Constant values used by parser */
#define BYTES_OF_PS_DATA_PER_LINE 16
#define RAMPS_MAX_PS_DATA_PER_TAG 20000
/* Number pf PS/Patch entries in an HCI packet */
#define MAX_BYTE_LENGTH 244
#define SKIP_BLANKS(str) while (*str == ' ') str++
#define MIN(x, y) (((x) <= (y))? (x):(y))
#define MAX(x, y) (((x) >= (y))? (x):(y))
#define UNUSED(x) (x=x)
#define IS_BETWEEN(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper)))
#define IS_DIGIT(c) (IS_BETWEEN((c), '0', '9'))
#define IS_HEX(c) (IS_BETWEEN((c), '0', '9') || IS_BETWEEN((c), 'a', 'f') || IS_BETWEEN((c), 'A', 'F'))
#define TO_LOWER(c) (IS_BETWEEN((c), 'A', 'Z') ? ((c) - 'A' + 'a') : (c))
#define IS_BLANK(c) ((c) == ' ')
#define CONV_DEC_DIGIT_TO_VALUE(c) ((c) - '0')
#define CONV_HEX_DIGIT_TO_VALUE(c) (IS_DIGIT(c) ? ((c) - '0') : (IS_BETWEEN((c), 'A', 'Z') ? ((c) - 'A' + 10) : ((c) - 'a' + 10)))
#define CONV_VALUE_TO_HEX(v) ((A_UINT8)( ((v & 0x0F) <= 9) ? ((v & 0x0F) + '0') : ((v & 0x0F) - 10 + 'A') ) )
enum MinBootFileFormatE
{
MB_FILEFORMAT_RADIOTBL,
MB_FILEFORMAT_PATCH,
MB_FILEFORMAT_COEXCONFIG
};
enum RamPsSection
{
RAM_PS_SECTION,
RAM_PATCH_SECTION,
RAM_DYN_MEM_SECTION
};
enum eType {
eHex,
edecimal
};
typedef struct tPsTagEntry
{
A_UINT32 TagId;
A_UINT32 TagLen;
A_UINT8 *TagData;
} tPsTagEntry, *tpPsTagEntry;
typedef struct tRamPatch
{
A_UINT16 Len;
A_UINT8 * Data;
} tRamPatch, *ptRamPatch;
typedef struct ST_PS_DATA_FORMAT {
enum eType eDataType;
A_BOOL bIsArray;
}ST_PS_DATA_FORMAT;
typedef struct ST_READ_STATUS {
unsigned uTagID;
unsigned uSection;
unsigned uLineCount;
unsigned uCharCount;
unsigned uByteCount;
}ST_READ_STATUS;
/* Stores the number of PS Tags */
static A_UINT32 Tag_Count = 0;
/* Stores the number of patch commands */
A_UINT32 Patch_Count = 0;
static A_UINT32 Total_tag_lenght = 0;
A_BOOL BDADDR = FALSE;
A_UINT32 StartTagId;
tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE];
tRamPatch RamPatch[MAX_NUM_PATCH_ENTRY];
A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat);
char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos);
char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos);
static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index);
/* Function to reads the next character from the input buffer */
char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos)
{
char Ch;
if(buffer == NULL || *pos >=len )
{
return '\0';
} else {
Ch = buffer[*pos];
(*pos)++;
return Ch;
}
}
/* PS parser helper function */
unsigned int uGetInputDataFormat(char* pCharLine, ST_PS_DATA_FORMAT *pstFormat)
{
if(pCharLine[0] != '[') {
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
return 0;
}
switch(pCharLine[1]) {
case 'H':
case 'h':
if(pCharLine[2]==':') {
if((pCharLine[3]== 'a') || (pCharLine[3]== 'A')) {
if(pCharLine[4] == ']') {
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 5;
return 0;
}
else {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A
return 1;
}
}
if((pCharLine[3]== 'S') || (pCharLine[3]== 's')) {
if(pCharLine[4] == ']') {
pstFormat->eDataType = eHex;
pstFormat->bIsArray = false;
pCharLine += 5;
return 0;
}
else {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n")); //[H:A
return 1;
}
}
else if(pCharLine[3] == ']') { //[H:]
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 4;
return 0;
}
else { //[H:
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n"));
return 1;
}
}
else if(pCharLine[2]==']') { //[H]
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 3;
return 0;
}
else { //[H
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format\n"));
return 1;
}
break;
case 'A':
case 'a':
if(pCharLine[2]==':') {
if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
if(pCharLine[4] == ']') {
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 5;
return 0;
}
else {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 1\n")); //[A:H
return 1;
}
}
else if(pCharLine[3]== ']') { //[A:]
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 4;
return 0;
}
else { //[A:
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 2\n"));
return 1;
}
}
else if(pCharLine[2]==']') { //[H]
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 3;
return 0;
}
else { //[H
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 3\n"));
return 1;
}
break;
case 'S':
case 's':
if(pCharLine[2]==':') {
if((pCharLine[3]== 'h') || (pCharLine[3]== 'H')) {
if(pCharLine[4] == ']') {
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 5;
return 0;
}
else {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 5\n")); //[A:H
return 1;
}
}
else if(pCharLine[3]== ']') { //[A:]
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 4;
return 0;
}
else { //[A:
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 6\n"));
return 1;
}
}
else if(pCharLine[2]==']') { //[H]
pstFormat->eDataType = eHex;
pstFormat->bIsArray = true;
pCharLine += 3;
return 0;
}
else { //[H
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 7\n"));
return 1;
}
break;
default:
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Illegal Data format 8\n"));
return 1;
}
}
unsigned int uReadDataInSection(char *pCharLine, ST_PS_DATA_FORMAT stPS_DataFormat)
{
char *pTokenPtr = pCharLine;
if(pTokenPtr[0] == '[') {
while(pTokenPtr[0] != ']' && pTokenPtr[0] != '\0') {
pTokenPtr++;
}
if(pTokenPtr[0] == '\0') {
return (0x0FFF);
}
pTokenPtr++;
}
if(stPS_DataFormat.eDataType == eHex) {
if(stPS_DataFormat.bIsArray == true) {
//Not implemented
return (0x0FFF);
}
else {
return (A_STRTOL(pTokenPtr, NULL, 16));
}
}
else {
//Not implemented
return (0x0FFF);
}
}
A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat)
{
char *Buffer;
char *pCharLine;
A_UINT8 TagCount;
A_UINT16 ByteCount;
A_UINT8 ParseSection=RAM_PS_SECTION;
A_UINT32 pos;
int uReadCount;
ST_PS_DATA_FORMAT stPS_DataFormat;
ST_READ_STATUS stReadStatus = {0, 0, 0,0};
pos = 0;
Buffer = NULL;
if (srcbuffer == NULL || srclen == 0)
{
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Could not open .\n"));
return A_ERROR;
}
TagCount = 0;
ByteCount = 0;
Buffer = A_MALLOC(LINE_SIZE_MAX + 1);
if(NULL == Buffer) {
return A_ERROR;
}
if (FileFormat == MB_FILEFORMAT_PATCH)
{
int LineRead = 0;
while((pCharLine = AthGetLine(Buffer, LINE_SIZE_MAX, srcbuffer,srclen,&pos)) != NULL)
{
SKIP_BLANKS(pCharLine);
// Comment line or empty line
if ((pCharLine[0] == '/') && (pCharLine[1] == '/'))
{
continue;
}
if ((pCharLine[0] == '#')) {
if (stReadStatus.uSection != 0)
{
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("error\n"));
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
else {
stReadStatus.uSection = 1;
continue;
}
}
if ((pCharLine[0] == '/') && (pCharLine[1] == '*'))
{
pCharLine+=2;
SKIP_BLANKS(pCharLine);
if(!strncmp(pCharLine,"PA",2)||!strncmp(pCharLine,"Pa",2)||!strncmp(pCharLine,"pa",2))
ParseSection=RAM_PATCH_SECTION;
if(!strncmp(pCharLine,"DY",2)||!strncmp(pCharLine,"Dy",2)||!strncmp(pCharLine,"dy",2))
ParseSection=RAM_DYN_MEM_SECTION;
if(!strncmp(pCharLine,"PS",2)||!strncmp(pCharLine,"Ps",2)||!strncmp(pCharLine,"ps",2))
ParseSection=RAM_PS_SECTION;
LineRead = 0;
stReadStatus.uSection = 0;
continue;
}
switch(ParseSection)
{
case RAM_PS_SECTION:
{
if (stReadStatus.uSection == 1) //TagID
{
SKIP_BLANKS(pCharLine);
if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail\n"));
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
//pCharLine +=5;
PsTagEntry[TagCount].TagId = uReadDataInSection(pCharLine, stPS_DataFormat);
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG ID %d \n",PsTagEntry[TagCount].TagId));
//AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag # %x\n", PsTagEntry[TagCount].TagId);
if (TagCount == 0)
{
StartTagId = PsTagEntry[TagCount].TagId;
}
stReadStatus.uSection = 2;
}
else if (stReadStatus.uSection == 2) //TagLength
{
if(uGetInputDataFormat(pCharLine, &stPS_DataFormat)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat fail \n"));
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
//pCharLine +=5;
ByteCount = uReadDataInSection(pCharLine, stPS_DataFormat);
//AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("tag length %x\n", ByteCount));
if (ByteCount > LINE_SIZE_MAX/2)
{
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
PsTagEntry[TagCount].TagLen = ByteCount;
PsTagEntry[TagCount].TagData = (A_UINT8*)A_MALLOC(ByteCount);
stReadStatus.uSection = 3;
stReadStatus.uLineCount = 0;
}
else if( stReadStatus.uSection == 3) { //Data
if(stReadStatus.uLineCount == 0) {
if(uGetInputDataFormat(pCharLine,&stPS_DataFormat)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("uGetInputDataFormat Fail\n"));
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
//pCharLine +=5;
}
SKIP_BLANKS(pCharLine);
stReadStatus.uCharCount = 0;
if(pCharLine[stReadStatus.uCharCount] == '[') {
while(pCharLine[stReadStatus.uCharCount] != ']' && pCharLine[stReadStatus.uCharCount] != '\0' ) {
stReadStatus.uCharCount++;
}
if(pCharLine[stReadStatus.uCharCount] == ']' ) {
stReadStatus.uCharCount++;
} else {
stReadStatus.uCharCount = 0;
}
}
uReadCount = (ByteCount > BYTES_OF_PS_DATA_PER_LINE)? BYTES_OF_PS_DATA_PER_LINE: ByteCount;
//AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" "));
if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) {
while(uReadCount > 0) {
PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] =
(A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount]) << 4)
| (A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount + 1]));
PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] =
(A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount + 3]) << 4)
| (A_UINT8)(CONV_HEX_DIGIT_TO_VALUE(pCharLine[stReadStatus.uCharCount + 4]));
stReadStatus.uCharCount += 6; // read two bytes, plus a space;
stReadStatus.uByteCount += 2;
uReadCount -= 2;
}
if(ByteCount > BYTES_OF_PS_DATA_PER_LINE) {
ByteCount -= BYTES_OF_PS_DATA_PER_LINE;
}
else {
ByteCount = 0;
}
}
else {
//to be implemented
}
stReadStatus.uLineCount++;
if(ByteCount == 0) {
stReadStatus.uSection = 0;
stReadStatus.uCharCount = 0;
stReadStatus.uLineCount = 0;
stReadStatus.uByteCount = 0;
}
else {
stReadStatus.uCharCount = 0;
}
if((stReadStatus.uSection == 0)&&(++TagCount == RAMPS_MAX_PS_TAGS_PER_FILE))
{
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n Buffer over flow PS File too big!!!"));
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
//Sleep (3000);
//exit(1);
}
}
}
break;
default:
{
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
break;
}
LineRead++;
}
Tag_Count = TagCount;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Number of Tags %d\n", Tag_Count));
}
if (TagCount > RAMPS_MAX_PS_TAGS_PER_FILE)
{
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_ERROR;
}
if(Buffer != NULL) {
A_FREE(Buffer);
}
return A_OK;
}
/********************/
A_STATUS GetNextTwoChar(A_UCHAR *srcbuffer,A_UINT32 len, A_UINT32 *pos, char * buffer)
{
unsigned char ch;
ch = AthReadChar(srcbuffer,len,pos);
if(ch != '\0' && IS_HEX(ch)) {
buffer[0] = ch;
} else
{
return A_ERROR;
}
ch = AthReadChar(srcbuffer,len,pos);
if(ch != '\0' && IS_HEX(ch)) {
buffer[1] = ch;
} else
{
return A_ERROR;
}
return A_OK;
}
#define PATCH_LOC_KEY "DA:"
#define PATCH_LOC_STRING_LEN 8
A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen, A_UCHAR *patch_loc)
{
char Byte[3];
char Line[MAX_BYTE_LENGTH + 1];
int ByteCount,ByteCount_Org;
int count;
int i,j,k;
int data;
A_UINT32 filepos;
Byte[2] = '\0';
j = 0;
filepos = 0;
Patch_Count = 0;
if(!patch_loc)
return A_ERROR;
while(NULL != AthGetLine(Line,MAX_BYTE_LENGTH,patchbuffer,patchlen,&filepos)) {
if(strlen(Line) <= 1) {
continue;
} else if (strstr(Line, PATCH_LOC_KEY) == Line) {
strncpy(patch_loc, &Line[sizeof(PATCH_LOC_KEY) -1],PATCH_LOC_STRING_LEN);
patch_loc[PATCH_LOC_STRING_LEN] = '\0';
continue;
} else if(IS_HEX(Line[0])){
break;
} else {
return A_ERROR;
}
}
ByteCount = A_STRTOL(Line, NULL, 16);
ByteCount_Org = ByteCount;
if(!ByteCount)
return A_ERROR;
while(ByteCount > MAX_BYTE_LENGTH){
/* Handle case when the number of patch buffer is more than the 20K */
if(MAX_NUM_PATCH_ENTRY == Patch_Count) {
for(i = 0; i < Patch_Count; i++) {
A_FREE(RamPatch[i].Data);
}
return A_ERROR;
}
RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH;
RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(MAX_BYTE_LENGTH);
Patch_Count ++;
ByteCount= ByteCount - MAX_BYTE_LENGTH;
}
RamPatch[Patch_Count].Len= (ByteCount & 0xFF);
if(ByteCount != 0) {
RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(ByteCount);
Patch_Count ++;
}
count = 0;
while(ByteCount_Org > MAX_BYTE_LENGTH){
for (i = 0,k=0; i < MAX_BYTE_LENGTH*2; i += 2,k++,count +=2) {
if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) {
return A_ERROR;
}
data = A_STRTOUL(&Byte[0], NULL, 16);
RamPatch[j].Data[k] = (data & 0xFF);
}
j++;
ByteCount_Org = ByteCount_Org - MAX_BYTE_LENGTH;
}
if(j == 0){
j++;
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Index [%d]\n",j));
for (k=0; k < ByteCount_Org; i += 2,k++,count+=2) {
if(GetNextTwoChar(patchbuffer,patchlen,&filepos,Byte) == A_ERROR) {
return A_ERROR;
}
data = A_STRTOUL(Byte, NULL, 16);
RamPatch[j].Data[k] = (data & 0xFF);
}
return A_OK;
}
/********************/
A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen)
{
A_STATUS status;
int i;
A_BOOL BDADDR_Present = A_ERROR;
Tag_Count = 0;
Total_tag_lenght = 0;
BDADDR = FALSE;
status = A_ERROR;
if(NULL != srcbuffer && srclen != 0)
{
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("File Open Operation Successful\n"));
status = AthParseFilesUnified(srcbuffer,srclen,MB_FILEFORMAT_PATCH);
}
if(Tag_Count == 0){
Total_tag_lenght = 10;
}
else{
for(i=0; i<Tag_Count; i++){
if(PsTagEntry[i].TagId == 1){
BDADDR_Present = A_OK;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is present in Patch File \r\n"));
}
if(PsTagEntry[i].TagLen % 2 == 1){
Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen + 1;
}
else{
Total_tag_lenght = Total_tag_lenght + PsTagEntry[i].TagLen;
}
}
}
if(Tag_Count > 0 && !BDADDR_Present){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is not present adding 10 extra bytes \r\n"));
Total_tag_lenght=Total_tag_lenght + 10;
}
Total_tag_lenght = Total_tag_lenght+ 10 + (Tag_Count*4);
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Total Length %d\n",Total_tag_lenght));
return status;
}
char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos)
{
int count;
static short flag;
char CharRead;
count = 0;
flag = A_ERROR;
do
{
CharRead = AthReadChar(srcbuffer,len,pos);
if( CharRead == '\0' ) {
buffer[count+1] = '\0';
if(count == 0) {
return NULL;
}
else {
return buffer;
}
}
if(CharRead == 13) {
} else if(CharRead == 10) {
buffer[count] ='\0';
flag = A_ERROR;
return buffer;
}else {
buffer[count++] = CharRead;
}
}
while(count < maxlen-1 && CharRead != '\0');
buffer[count] = '\0';
return buffer;
}
void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int index){
HCI_PS_Command[0]= 0x0B;
HCI_PS_Command[1]= 0xFC;
HCI_PS_Command[2]= length + 4;
HCI_PS_Command[3]= opcode;
HCI_PS_Command[4]= (index & 0xFF);
HCI_PS_Command[5]= ((index>>8) & 0xFF);
HCI_PS_Command[6]= length;
}
/////////////////////////
//
int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets)
{
A_UINT8 count;
A_UINT32 NumcmdEntry = 0;
A_UINT32 Crc = 0;
*numPackets = 0;
if(Patch_Count > 0)
Crc |= RAM_PATCH_REGION;
if(Tag_Count > 0)
Crc |= RAM_PS_REGION;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Thread Started CRC %x Patch Count %d Tag Count %d \n",Crc,Patch_Count,Tag_Count));
if(Patch_Count || Tag_Count ){
NumcmdEntry+=(2 + Patch_Count + Tag_Count); /* CRC Packet + PS Reset Packet + Patch List + PS List*/
if(Patch_Count > 0) {
NumcmdEntry++; /* Patch Enable Command */
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size %d \r\n",NumcmdEntry,(A_UINT32)sizeof(PSCmdPacket) * NumcmdEntry));
(*HciPacketList) = A_MALLOC(sizeof(PSCmdPacket) * NumcmdEntry);
if(NULL == *HciPacketList) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed \r\n"));
}
AthPSCreateHCICommand(PS_VERIFY_CRC,Crc,*HciPacketList,numPackets);
if(Patch_Count > 0){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Write Patch**** \r\n"));
AthPSCreateHCICommand(WRITE_PATCH,Patch_Count,*HciPacketList,numPackets);
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** Enable Patch**** \r\n"));
AthPSCreateHCICommand(ENABLE_PATCH,0,*HciPacketList,numPackets);
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Reset**** %d[0x%x] \r\n",PS_RAM_SIZE,PS_RAM_SIZE));
AthPSCreateHCICommand(PS_RESET,PS_RAM_SIZE,*HciPacketList,numPackets);
if(Tag_Count > 0){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("*** PS Write**** \r\n"));
AthPSCreateHCICommand(PS_WRITE,Tag_Count,*HciPacketList,numPackets);
}
}
if(!BDADDR){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR not present \r\n"));
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("PS Count %d Patch Count %d",Tag_Count, Patch_Count));
for(count = 0; count < Patch_Count; count++) {
A_FREE(RamPatch[Patch_Count].Data);
}
for(count = 0; count < Tag_Count; count++) {
A_FREE(PsTagEntry[count].TagData);
}
/*
* SDIO Transport uses synchronous mode of data transfer
* So, AthPSOperations() call returns only after receiving the
* command complete event.
*/
return *numPackets;
}
////////////////////////
/////////////
static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index)
{
A_UCHAR *HCI_PS_Command;
A_UINT32 Length;
int i,j;
switch(Opcode)
{
case WRITE_PATCH:
for(i=0;i< Param1;i++){
HCI_PS_Command = (A_UCHAR *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
if(HCI_PS_Command == NULL){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
return A_ERROR;
}
memset (HCI_PS_Command, 0, RamPatch[i].Len+HCI_COMMAND_HEADER);
LoadHeader(HCI_PS_Command,Opcode,RamPatch[i].Len,i);
for(j=0;j<RamPatch[i].Len;j++){
HCI_PS_Command[HCI_COMMAND_HEADER+j]=RamPatch[i].Data[j];
}
PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
PSPatchPacket[*index].packetLen = RamPatch[i].Len+HCI_COMMAND_HEADER;
(*index)++;
}
break;
case ENABLE_PATCH:
Length = 0;
i= 0;
HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
if(HCI_PS_Command == NULL){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
return A_ERROR;
}
memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
LoadHeader(HCI_PS_Command,Opcode,Length,i);
PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
(*index)++;
break;
case PS_RESET:
Length = 0x06;
i=0;
HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
if(HCI_PS_Command == NULL){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
return A_ERROR;
}
memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
LoadHeader(HCI_PS_Command,Opcode,Length,i);
HCI_PS_Command[7]= 0x00;
HCI_PS_Command[Length+HCI_COMMAND_HEADER -2]= (Param1 & 0xFF);
HCI_PS_Command[Length+HCI_COMMAND_HEADER -1]= ((Param1 >> 8) & 0xFF);
PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
(*index)++;
break;
case PS_WRITE:
for(i=0;i< Param1;i++){
if(PsTagEntry[i].TagId ==1)
BDADDR = TRUE;
HCI_PS_Command = (A_UCHAR *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
if(HCI_PS_Command == NULL){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
return A_ERROR;
}
memset (HCI_PS_Command, 0, PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
LoadHeader(HCI_PS_Command,Opcode,PsTagEntry[i].TagLen,PsTagEntry[i].TagId);
for(j=0;j<PsTagEntry[i].TagLen;j++){
HCI_PS_Command[HCI_COMMAND_HEADER+j]=PsTagEntry[i].TagData[j];
}
PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
PSPatchPacket[*index].packetLen = PsTagEntry[i].TagLen+HCI_COMMAND_HEADER;
(*index)++;
}
break;
case PS_VERIFY_CRC:
Length = 0x0;
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("VALUE of CRC:%d At index %d\r\n",Param1,*index));
HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
if(HCI_PS_Command == NULL){
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
return A_ERROR;
}
memset (HCI_PS_Command, 0, Length+HCI_COMMAND_HEADER);
LoadHeader(HCI_PS_Command,Opcode,Length,Param1);
PSPatchPacket[*index].Hcipacket = HCI_PS_Command;
PSPatchPacket[*index].packetLen = Length+HCI_COMMAND_HEADER;
(*index)++;
break;
case CHANGE_BDADDR:
break;
}
return A_OK;
}
A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets)
{
int i;
if(*HciPacketList == NULL) {
return A_ERROR;
}
for(i = 0; i < numPackets;i++) {
A_FREE((*HciPacketList)[i].Hcipacket);
}
A_FREE(*HciPacketList);
return A_OK;
}

View File

@ -0,0 +1,127 @@
//------------------------------------------------------------------------------
//
// 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 is the include file for Atheros PS and patch parser.
// It implements APIs to parse data buffer with patch and PS information and convert it to HCI commands.
//
#ifndef __AR3KPSPARSER_H
#define __AR3KPSPARSER_H
#include <linux/fs.h>
#include <linux/slab.h>
#include "athdefs.h"
#ifdef HCI_TRANSPORT_SDIO
#include "a_config.h"
#include "a_types.h"
#include "a_osapi.h"
#define ATH_MODULE_NAME misc
#include "a_debug.h"
#include "common_drv.h"
#include "hci_transport_api.h"
#include "ar3kconfig.h"
#else
#ifndef A_PRINTF
#define A_PRINTF(args...) printk(KERN_ALERT args)
#endif /* A_PRINTF */
#include "debug_linux.h"
/* Helper data type declaration */
#ifndef A_UINT32
#define A_UCHAR unsigned char
#define A_UINT32 unsigned long
#define A_UINT16 unsigned short
#define A_UINT8 unsigned char
#define A_BOOL unsigned char
#endif /* A_UINT32 */
#define ATH_DEBUG_ERR (1 << 0)
#define ATH_DEBUG_WARN (1 << 1)
#define ATH_DEBUG_INFO (1 << 2)
#define FALSE 0
#define TRUE 1
#ifndef A_MALLOC
#define A_MALLOC(size) kmalloc((size),GFP_KERNEL)
#endif /* A_MALLOC */
#ifndef A_FREE
#define A_FREE(addr) kfree((addr))
#endif /* A_MALLOC */
#endif /* HCI_TRANSPORT_UART */
/* String manipulation APIs */
#ifndef A_STRTOUL
#define A_STRTOUL simple_strtoul
#endif /* A_STRTOL */
#ifndef A_STRTOL
#define A_STRTOL simple_strtol
#endif /* A_STRTOL */
/* The maximum number of bytes possible in a patch entry */
#define MAX_PATCH_SIZE 30000
/* Maximum HCI packets that will be formed from the Patch file */
#define MAX_NUM_PATCH_ENTRY (MAX_PATCH_SIZE/MAX_BYTE_LENGTH) + 1
typedef struct PSCmdPacket
{
A_UCHAR *Hcipacket;
int packetLen;
} PSCmdPacket;
/* Parses a Patch information buffer and store it in global structure */
A_STATUS AthDoParsePatch(A_UCHAR *, A_UINT32, A_UCHAR*);
/* parses a PS information buffer and stores it in a global structure */
A_STATUS AthDoParsePS(A_UCHAR *, A_UINT32);
/*
* Uses the output of Both AthDoParsePS and AthDoParsePatch APIs to form HCI command array with
* all the PS and patch commands.
* The list will have the below mentioned commands in order.
* CRC command packet
* Download patch command(s)
* Enable patch Command
* PS Reset Command
* PS Tag Command(s)
*
*/
int AthCreateCommandList(PSCmdPacket **, A_UINT32 *);
/* Cleanup the dynamically allicated HCI command list */
A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets);
#endif /* __AR3KPSPARSER_H */

View File

@ -0,0 +1,882 @@
//------------------------------------------------------------------------------
// <copyright file="common_drv.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"
//==============================================================================
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#include "targaddrs.h"
#include "hif.h"
#include "htc_api.h"
#include "wmi.h"
#include "bmi.h"
#include "bmi_msg.h"
#include "common_drv.h"
#define ATH_MODULE_NAME misc
#include "a_debug.h"
#include "ar6000_diag.h"
#include "target_reg_table.h"
#include "host_reg_table.h"
static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL;
static A_MUTEX_T g_ModuleListLock;
static A_BOOL g_ModuleDebugInit = FALSE;
#ifdef DEBUG
ATH_DEBUG_INSTANTIATE_MODULE_VAR(misc,
"misc",
"Common and misc APIs",
ATH_DEBUG_MASK_DEFAULTS,
0,
NULL);
#endif
#define AR6001_LOCAL_COUNT_ADDRESS 0x0c014080
#define AR6002_LOCAL_COUNT_ADDRESS 0x00018080
#define AR6003_LOCAL_COUNT_ADDRESS 0x00018080
static A_UINT8 custDataAR6002[AR6002_CUST_DATA_SIZE];
static A_UINT8 custDataAR6003[AR6003_CUST_DATA_SIZE];
static A_UINT8 custDataMCKINLEY[MCKINLEY_CUST_DATA_SIZE];
/*
* Read from the AR6000 through its diagnostic window.
* No cooperation from the Target is required for this.
*/
A_STATUS
ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
{
return HIFDiagReadAccess(hifDevice, *address, data);
}
/*
* Write to the AR6000 through its diagnostic window.
* No cooperation from the Target is required for this.
*/
A_STATUS
ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
{
return HIFDiagWriteAccess(hifDevice, *address, *data);
}
A_STATUS
ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
A_UCHAR *data, A_UINT32 length)
{
A_UINT32 count;
A_STATUS status = A_OK;
for (count = 0; count < length; count += 4, address += 4) {
if ((status = HIFDiagReadAccess(hifDevice, address,
(A_UINT32 *)&data[count])) != A_OK)
{
break;
}
}
return status;
}
A_STATUS
ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
A_UCHAR *data, A_UINT32 length)
{
A_UINT32 count;
A_STATUS status = A_OK;
for (count = 0; count < length; count += 4, address += 4) {
if ((status = HIFDiagWriteAccess(hifDevice, address,
*((A_UINT32 *)&data[count]))) != A_OK)
{
break;
}
}
return status;
}
#ifdef HIF_MESSAGE_BASED
/* TODO : for message based interfaces there are no HOST registers. These are just
* stub functions for now */
A_STATUS
ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
{
/* TODO */
return A_ERROR;
}
void
ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs)
{
int i;
for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) {
targregs[i] = 0xffffffff;
}
}
#endif
/*
* Delay up to wait_msecs millisecs to allow Target to enter BMI phase,
* which is a good sign that it's alive and well. This is used after
* explicitly forcing the Target to reset.
*
* The wait_msecs time should be sufficiently long to cover any reasonable
* boot-time delay. For instance, AR6001 firmware allow one second for a
* low frequency crystal to settle before it calibrates the refclk frequency.
*
* TBD: Might want to add special handling for AR6K_OPTION_BMI_DISABLE.
*/
#if 0
static A_STATUS
_delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 TargetType)
{
A_INT32 actual_wait;
A_INT32 i;
A_UINT32 address;
actual_wait = 0;
/* Hardcode the address of LOCAL_COUNT_ADDRESS based on the target type */
if (TargetType == TARGET_TYPE_AR6002) {
address = AR6002_LOCAL_COUNT_ADDRESS;
} else if (TargetType == TARGET_TYPE_AR6003) {
address = AR6003_LOCAL_COUNT_ADDRESS;
} else {
A_ASSERT(0);
}
address += 0x10;
for (i=0; actual_wait < wait_msecs; i++) {
A_UINT32 data;
A_MDELAY(100);
actual_wait += 100;
data = 0;
if (ar6000_ReadRegDiag(hifDevice, &address, &data) != A_OK) {
return A_ERROR;
}
if (data != 0) {
/* No need to wait longer -- we have a BMI credit */
return A_OK;
}
}
return A_ERROR; /* timed out */
}
#endif
#define AR6001_RESET_CONTROL_ADDRESS 0x0C000000
#define AR6002_RESET_CONTROL_ADDRESS 0x00004000
#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
#define MCKINLEY_RESET_CONTROL_ADDRESS 0x00004000
#define AR6001_WLAN_RESET_CONTROL_ADDRESS 0x0C000000
#define AR6002_WLAN_RESET_CONTROL_ADDRESS 0x00004000
#define AR6003_WLAN_RESET_CONTROL_ADDRESS 0x00004000
#define MCKINLEY_WLAN_RESET_CONTROL_ADDRESS 0x00005000
/* reset device */
A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset)
{
A_STATUS status = A_OK;
A_UINT32 address = 0;
A_UINT32 data;
do {
// Workaround BEGIN
// address = RESET_CONTROL_ADDRESS;
if (coldReset) {
data = WLAN_RESET_CONTROL_COLD_RST_MASK;
/* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
if (TargetType == TARGET_TYPE_AR6002) {
address = AR6002_WLAN_RESET_CONTROL_ADDRESS;
} else if (TargetType == TARGET_TYPE_AR6003) {
address = AR6003_WLAN_RESET_CONTROL_ADDRESS;
} else if (TargetType == TARGET_TYPE_MCKINLEY) {
address = MCKINLEY_WLAN_RESET_CONTROL_ADDRESS;
} else {
A_ASSERT(0);
}
}
else {
data = RESET_CONTROL_MBOX_RST_MASK;
/* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
if (TargetType == TARGET_TYPE_AR6002) {
address = AR6002_RESET_CONTROL_ADDRESS;
} else if (TargetType == TARGET_TYPE_AR6003) {
address = AR6003_RESET_CONTROL_ADDRESS;
} else if (TargetType == TARGET_TYPE_MCKINLEY) {
address = MCKINLEY_RESET_CONTROL_ADDRESS;
} else {
A_ASSERT(0);
}
}
status = ar6000_WriteRegDiag(hifDevice, &address, &data);
if (A_FAILED(status)) {
break;
}
if (!waitForCompletion) {
break;
}
#if 0
/* Up to 2 second delay to allow things to settle down */
(void)_delay_until_target_alive(hifDevice, 2000, TargetType);
/*
* Read back the RESET CAUSE register to ensure that the cold reset
* went through.
*/
// address = RESET_CAUSE_ADDRESS;
/* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
if (TargetType == TARGET_TYPE_AR6002) {
address = 0x000040C0;
} else if (TargetType == TARGET_TYPE_AR6003) {
address = 0x000040C0;
} else {
A_ASSERT(0);
}
data = 0;
status = ar6000_ReadRegDiag(hifDevice, &address, &data);
if (A_FAILED(status)) {
break;
}
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
data &= RESET_CAUSE_LAST_MASK;
if (data != 2) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
}
#endif
// Workaroud END
} while (FALSE);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
}
return A_OK;
}
/* This should be called in BMI phase after firmware is downloaded */
void
ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
{
A_UINT32 eepHeaderAddr;
A_UINT8 AR6003CustDataShadow[AR6003_CUST_DATA_SIZE+4];
A_UINT8 MCKINLEYCustDataShadow[MCKINLEY_CUST_DATA_SIZE+4];
A_INT32 i;
if (BMIReadMemory(hifDevice,
HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_board_data),
(A_UCHAR *)&eepHeaderAddr,
4)!= A_OK)
{
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadMemory for reading board data address failed \n"));
return;
}
if (TargetType == TARGET_TYPE_MCKINLEY) {
eepHeaderAddr += 36; /* MCKINLEY customer data section offset is 37 */
for (i=0; i<MCKINLEY_CUST_DATA_SIZE+4; i+=4){
if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&MCKINLEYCustDataShadow[i])!= A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
return ;
}
eepHeaderAddr +=4;
}
memcpy(custDataMCKINLEY, MCKINLEYCustDataShadow+1, MCKINLEY_CUST_DATA_SIZE);
}
if (TargetType == TARGET_TYPE_AR6003) {
eepHeaderAddr += 36; /* AR6003 customer data section offset is 37 */
for (i=0; i<AR6003_CUST_DATA_SIZE+4; i+=4){
if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&AR6003CustDataShadow[i])!= A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
return ;
}
eepHeaderAddr +=4;
}
memcpy(custDataAR6003, AR6003CustDataShadow+1, AR6003_CUST_DATA_SIZE);
}
if (TargetType == TARGET_TYPE_AR6002) {
eepHeaderAddr += 64; /* AR6002 customer data sectioin offset is 64 */
for (i=0; i<AR6002_CUST_DATA_SIZE; i+=4){
if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&custDataAR6002[i])!= A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
return ;
}
eepHeaderAddr +=4;
}
}
return;
}
/* This is the function to call when need to use the cust data */
A_UINT8 *
ar6000_get_cust_data_buffer(A_UINT32 TargetType)
{
if (TargetType == TARGET_TYPE_MCKINLEY)
return custDataMCKINLEY;
if (TargetType == TARGET_TYPE_AR6003)
return custDataAR6003;
if (TargetType == TARGET_TYPE_AR6002)
return custDataAR6002;
return NULL;
}
#define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR600x_regdump.h */
#define REG_DUMP_COUNT_AR6002 60
#define REG_DUMP_COUNT_AR6003 60
#define REG_DUMP_COUNT_MCKINLEY 60
#define REGISTER_DUMP_LEN_MAX 60
#if REG_DUMP_COUNT_AR6001 > REGISTER_DUMP_LEN_MAX
#error "REG_DUMP_COUNT_AR6001 too large"
#endif
#if REG_DUMP_COUNT_AR6002 > REGISTER_DUMP_LEN_MAX
#error "REG_DUMP_COUNT_AR6002 too large"
#endif
#if REG_DUMP_COUNT_AR6003 > REGISTER_DUMP_LEN_MAX
#error "REG_DUMP_COUNT_AR6003 too large"
#endif
#if REG_DUMP_COUNT_MCKINLEY > REGISTER_DUMP_LEN_MAX
#error "REG_DUMP_COUNT_MCKINLEY too large"
#endif
void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
{
A_UINT32 address;
A_UINT32 regDumpArea = 0;
A_STATUS status;
A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
A_UINT32 regDumpCount = 0;
A_UINT32 i;
do {
/* the reg dump pointer is copied to the host interest area */
address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
address = TARG_VTOP(TargetType, address);
if (TargetType == TARGET_TYPE_AR6002) {
regDumpCount = REG_DUMP_COUNT_AR6002;
} else if (TargetType == TARGET_TYPE_AR6003) {
regDumpCount = REG_DUMP_COUNT_AR6003;
} else if (TargetType == TARGET_TYPE_MCKINLEY) {
regDumpCount = REG_DUMP_COUNT_MCKINLEY;
} else {
A_ASSERT(0);
}
/* read RAM location through diagnostic window */
status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
break;
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));
if (regDumpArea == 0) {
/* no reg dump */
break;
}
regDumpArea = TARG_VTOP(TargetType, regDumpArea);
/* fetch register dump data */
status = ar6000_ReadDataDiag(hifDevice,
regDumpArea,
(A_UCHAR *)&regDumpValues[0],
regDumpCount * (sizeof(A_UINT32)));
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
break;
}
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));
for (i = 0; i < regDumpCount; i++)
{
AR_DEBUG_PRINTF (ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i]));
#ifdef UNDER_CE
/*
* For Every logPrintf() Open the File so that in case of Crashes
* We will have until the Last Message Flushed on to the File
* So use logPrintf Sparingly..!!
*/
tgtassertPrintf (ATH_DEBUG_TRC," %d: 0x%8.8X \n",i, regDumpValues[i]);
#endif
}
} while (FALSE);
}
/* set HTC/Mbox operational parameters, this can only be called when the target is in the
* BMI phase */
A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
A_UINT32 TargetType,
A_UINT32 MboxIsrYieldValue,
A_UINT8 HtcControlBuffers)
{
A_STATUS status;
A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
do {
/* get the block sizes */
status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
blocksizes, sizeof(blocksizes));
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n"));
break;
}
/* note: we actually get the block size for mailbox 1, for SDIO the block
* size on mailbox 0 is artificially set to 1 */
/* must be a power of 2 */
A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0);
if (HtcControlBuffers != 0) {
/* set override for number of control buffers to use */
blocksizes[1] |= ((A_UINT32)HtcControlBuffers) << 16;
}
/* set the host interest area for the block size */
status = BMIWriteMemory(hifDevice,
HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz),
(A_UCHAR *)&blocksizes[1],
4);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n"));
break;
}
AR_DEBUG_PRINTF(ATH_LOG_INF,("Block Size Set: %d (target address:0x%X)\n",
blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz)));
if (MboxIsrYieldValue != 0) {
/* set the host interest area for the mbox ISR yield limit */
status = BMIWriteMemory(hifDevice,
HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit),
(A_UCHAR *)&MboxIsrYieldValue,
4);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n"));
break;
}
}
} while (FALSE);
return status;
}
static A_STATUS prepare_ar6002(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
{
A_STATUS status = A_OK;
/* placeholder */
return status;
}
static A_STATUS prepare_ar6003(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
{
A_STATUS status = A_OK;
/* placeholder */
return status;
}
static A_STATUS prepare_MCKINLEY(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
{
A_STATUS status = A_OK;
A_UINT32 value = 0;
/* force the setting to disable sleep for Bringup FIXME_MK */
value |= WLAN_SYSTEM_SLEEP_DISABLE_MASK;
status = BMIWriteMemory(hifDevice,
HOST_INTEREST_ITEM_ADDRESS(TARGET_TYPE_AR6002, hi_system_sleep_setting),
(A_UCHAR *)&value,
4);
return status;
}
/* this function assumes the caller has already initialized the BMI APIs */
A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
A_UINT32 TargetType,
A_UINT32 TargetVersion)
{
if (TargetType == TARGET_TYPE_AR6002) {
/* do any preparations for AR6002 devices */
return prepare_ar6002(hifDevice,TargetVersion);
} else if (TargetType == TARGET_TYPE_AR6003) {
return prepare_ar6003(hifDevice,TargetVersion);
} else if (TargetType == TARGET_TYPE_MCKINLEY) {
return prepare_MCKINLEY(hifDevice,TargetVersion);
}
return A_OK;
}
#if defined(CONFIG_AR6002_REV1_FORCE_HOST)
/*
* Call this function just before the call to BMIInit
* in order to force* AR6002 rev 1.x firmware to detect a Host.
* THIS IS FOR USE ONLY WITH AR6002 REV 1.x.
* TBDXXX: Remove this function when REV 1.x is desupported.
*/
A_STATUS
ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
{
A_INT32 i;
struct forceROM_s {
A_UINT32 addr;
A_UINT32 data;
};
struct forceROM_s *ForceROM;
A_INT32 szForceROM;
A_STATUS status = A_OK;
A_UINT32 address;
A_UINT32 data;
/* Force AR6002 REV1.x to recognize Host presence.
*
* Note: Use RAM at 0x52df80..0x52dfa0 with ROM Remap entry 0
* so that this workaround functions with AR6002.war1.sh. We
* could fold that entire workaround into this one, but it's not
* worth the effort at this point. This workaround cannot be
* merged into the other workaround because this must be done
* before BMI.
*/
static struct forceROM_s ForceROM_NEW[] = {
{0x52df80, 0x20f31c07},
{0x52df84, 0x92374420},
{0x52df88, 0x1d120c03},
{0x52df8c, 0xff8216f0},
{0x52df90, 0xf01d120c},
{0x52df94, 0x81004136},
{0x52df98, 0xbc9100bd},
{0x52df9c, 0x00bba100},
{0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */
{0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380},
{0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000},
{0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001},
{0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter */
{0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
};
address = 0x004ed4b0; /* REV1 target software ID is stored here */
status = ar6000_ReadRegDiag(hifDevice, &address, &data);
if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
return A_ERROR; /* Not AR6002 REV1 */
}
ForceROM = ForceROM_NEW;
szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);
ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize Host....\n"));
for (i = 0; i < szForceROM; i++)
{
if (ar6000_WriteRegDiag(hifDevice,
&ForceROM[i].addr,
&ForceROM[i].data) != A_OK)
{
ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
return A_ERROR;
}
}
A_MDELAY(1000);
return A_OK;
}
#endif /* CONFIG_AR6002_REV1_FORCE_HOST */
void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription)
{
A_CHAR stream[60];
A_CHAR byteOffsetStr[10];
A_UINT32 i;
A_UINT16 offset, count, byteOffset;
A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription);
count = 0;
offset = 0;
byteOffset = 0;
for(i = 0; i < length; i++) {
A_SPRINTF(stream + offset, "%2.2X ", buffer[i]);
count ++;
offset += 3;
if(count == 16) {
count = 0;
offset = 0;
A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset);
A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
A_MEMZERO(stream, 60);
byteOffset += 16;
}
}
if(offset != 0) {
A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset);
A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
}
A_PRINTF("<------------------------------------------------->\n");
}
void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
{
int i;
ATH_DEBUG_MASK_DESCRIPTION *pDesc;
if (pInfo == NULL) {
return;
}
pDesc = pInfo->pMaskDescriptions;
A_PRINTF("========================================================\n\n");
A_PRINTF("Module Debug Info => Name : %s \n", pInfo->ModuleName);
A_PRINTF(" => Descr. : %s \n", pInfo->ModuleDescription);
A_PRINTF("\n Current mask => 0x%8.8X \n", pInfo->CurrentMask);
A_PRINTF("\n Avail. Debug Masks :\n\n");
for (i = 0; i < pInfo->MaxDescriptions; i++,pDesc++) {
A_PRINTF(" => 0x%8.8X -- %s \n", pDesc->Mask, pDesc->Description);
}
if (0 == i) {
A_PRINTF(" => * none defined * \n");
}
A_PRINTF("\n Standard Debug Masks :\n\n");
/* print standard masks */
A_PRINTF(" => 0x%8.8X -- Errors \n", ATH_DEBUG_ERR);
A_PRINTF(" => 0x%8.8X -- Warnings \n", ATH_DEBUG_WARN);
A_PRINTF(" => 0x%8.8X -- Informational \n", ATH_DEBUG_INFO);
A_PRINTF(" => 0x%8.8X -- Tracing \n", ATH_DEBUG_TRC);
A_PRINTF("\n========================================================\n");
}
static ATH_DEBUG_MODULE_DBG_INFO *FindModule(A_CHAR *module_name)
{
ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
if (!g_ModuleDebugInit) {
return NULL;
}
while (pInfo != NULL) {
/* TODO: need to use something other than strlen */
if (A_MEMCMP(pInfo->ModuleName,module_name,strlen(module_name)) == 0) {
break;
}
pInfo = pInfo->pNext;
}
return pInfo;
}
void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
{
if (!g_ModuleDebugInit) {
return;
}
A_MUTEX_LOCK(&g_ModuleListLock);
if (!(pInfo->Flags & ATH_DEBUG_INFO_FLAGS_REGISTERED)) {
if (g_pModuleInfoHead == NULL) {
g_pModuleInfoHead = pInfo;
} else {
pInfo->pNext = g_pModuleInfoHead;
g_pModuleInfoHead = pInfo;
}
pInfo->Flags |= ATH_DEBUG_INFO_FLAGS_REGISTERED;
}
A_MUTEX_UNLOCK(&g_ModuleListLock);
}
void a_dump_module_debug_info_by_name(A_CHAR *module_name)
{
ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
if (!g_ModuleDebugInit) {
return;
}
if (A_MEMCMP(module_name,"all",3) == 0) {
/* dump all */
while (pInfo != NULL) {
a_dump_module_debug_info(pInfo);
pInfo = pInfo->pNext;
}
return;
}
pInfo = FindModule(module_name);
if (pInfo != NULL) {
a_dump_module_debug_info(pInfo);
}
}
A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask)
{
ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
if (NULL == pInfo) {
return A_ERROR;
}
*pMask = pInfo->CurrentMask;
return A_OK;
}
A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask)
{
ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
if (NULL == pInfo) {
return A_ERROR;
}
pInfo->CurrentMask = Mask;
A_PRINTF("Module %s, new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask);
return A_OK;
}
void a_module_debug_support_init(void)
{
if (g_ModuleDebugInit) {
return;
}
A_MUTEX_INIT(&g_ModuleListLock);
g_pModuleInfoHead = NULL;
g_ModuleDebugInit = TRUE;
A_REGISTER_MODULE_DEBUG_INFO(misc);
}
void a_module_debug_support_cleanup(void)
{
ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
ATH_DEBUG_MODULE_DBG_INFO *pCur;
if (!g_ModuleDebugInit) {
return;
}
g_ModuleDebugInit = FALSE;
A_MUTEX_LOCK(&g_ModuleListLock);
while (pInfo != NULL) {
pCur = pInfo;
pInfo = pInfo->pNext;
pCur->pNext = NULL;
/* clear registered flag */
pCur->Flags &= ~ATH_DEBUG_INFO_FLAGS_REGISTERED;
}
A_MUTEX_UNLOCK(&g_ModuleListLock);
A_MUTEX_DELETE(&g_ModuleListLock);
g_pModuleInfoHead = NULL;
}
/* can only be called during bmi init stage */
A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
A_UINT32 TargetType,
A_UINT32 Flags)
{
A_STATUS status = A_OK;
do {
if ((TargetType != TARGET_TYPE_AR6003) && (TargetType != TARGET_TYPE_MCKINLEY)) {
AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Target Type:%d, does not support HCI bridging! \n",
TargetType));
break;
}
/* set hci bridge flags */
status = BMIWriteMemory(hifDevice,
HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_bridge_flags),
(A_UCHAR *)&Flags,
4);
} while (FALSE);
return status;
}

Some files were not shown because too many files have changed in this diff Show More