--- drivers/pnp/Kconfig | 2 drivers/pnp/core.c | 4 drivers/pnp/driver.c | 2 drivers/sdio/function/wlan/Makefile | 4 drivers/sdio/function/wlan/ar6000/Makefile | 29 drivers/sdio/function/wlan/ar6000/ar6000/ar6000_drv.c | 5862 ++++++++++ drivers/sdio/function/wlan/ar6000/ar6000/ar6000_drv.h | 133 drivers/sdio/function/wlan/ar6000/bmi/Makefile | 1 drivers/sdio/function/wlan/ar6000/bmi/bmi.c | 473 drivers/sdio/function/wlan/ar6000/bmi/bmi_internal.h | 31 drivers/sdio/function/wlan/ar6000/hif/Makefile | 2 drivers/sdio/function/wlan/ar6000/hif/cf/Makefile | 11 drivers/sdio/function/wlan/ar6000/hif/cf/ar6000_cs.c | 1001 + drivers/sdio/function/wlan/ar6000/hif/cf/ar6000_cs.h | 110 drivers/sdio/function/wlan/ar6000/hif/cf/ar6000_cs_internal.h | 62 drivers/sdio/function/wlan/ar6000/hif/cf/hif.c | 390 drivers/sdio/function/wlan/ar6000/hif/cf/hif_internal.h | 78 drivers/sdio/function/wlan/ar6000/hif/hif.c | 664 + drivers/sdio/function/wlan/ar6000/hif/hif_internal.h | 85 drivers/sdio/function/wlan/ar6000/htc/Makefile | 5 drivers/sdio/function/wlan/ar6000/htc/htc.c | 441 drivers/sdio/function/wlan/ar6000/htc/htc_events.c | 1056 + drivers/sdio/function/wlan/ar6000/htc/htc_internal.h | 464 drivers/sdio/function/wlan/ar6000/htc/htc_recv.c | 211 drivers/sdio/function/wlan/ar6000/htc/htc_send.c | 395 drivers/sdio/function/wlan/ar6000/htc/htc_utils.c | 375 drivers/sdio/function/wlan/ar6000/include/AR6000_bmi.h | 136 drivers/sdio/function/wlan/ar6000/include/AR6000_gpio.h | 39 drivers/sdio/function/wlan/ar6000/include/AR6000_version.h | 46 drivers/sdio/function/wlan/ar6000/include/app/dset.h | 77 drivers/sdio/function/wlan/ar6000/include/ar6000_api.h | 84 drivers/sdio/function/wlan/ar6000/include/athdefs.h | 82 drivers/sdio/function/wlan/ar6000/include/athdrv.h | 598 + drivers/sdio/function/wlan/ar6000/include/athtypes.h | 43 drivers/sdio/function/wlan/ar6000/include/bmi.h | 76 drivers/sdio/function/wlan/ar6000/include/dset_api.h | 49 drivers/sdio/function/wlan/ar6000/include/gpio_api.h | 64 drivers/sdio/function/wlan/ar6000/include/hif.h | 207 drivers/sdio/function/wlan/ar6000/include/host_version.h | 48 drivers/sdio/function/wlan/ar6000/include/htc.h | 120 drivers/sdio/function/wlan/ar6000/include/hw/mbox_host_reg.h | 416 drivers/sdio/function/wlan/ar6000/include/hw/mbox_reg.h | 550 drivers/sdio/function/wlan/ar6000/include/hw/mc_reg.h | 1129 + drivers/sdio/function/wlan/ar6000/include/hw/rtc_reg.h | 1204 ++ drivers/sdio/function/wlan/ar6000/include/ieee80211.h | 333 drivers/sdio/function/wlan/ar6000/include/ieee80211_ioctl.h | 120 drivers/sdio/function/wlan/ar6000/include/ieee80211_node.h | 74 drivers/sdio/function/wlan/ar6000/include/osapi.h | 63 drivers/sdio/function/wlan/ar6000/include/osapi_linux.h | 167 drivers/sdio/function/wlan/ar6000/include/queue.h | 552 drivers/sdio/function/wlan/ar6000/include/wlan_api.h | 90 drivers/sdio/function/wlan/ar6000/include/wmi.h | 1150 + drivers/sdio/function/wlan/ar6000/include/wmi_api.h | 173 drivers/sdio/function/wlan/ar6000/include/wmi_host.h | 75 drivers/sdio/function/wlan/ar6000/include/wmix.h | 197 drivers/sdio/function/wlan/ar6000/wlan/Makefile | 2 drivers/sdio/function/wlan/ar6000/wlan/wlan_node.c | 285 drivers/sdio/function/wlan/ar6000/wlan/wlan_recv_beacon.c | 169 drivers/sdio/function/wlan/ar6000/wlan/wlan_utils.c | 56 drivers/sdio/function/wlan/ar6000/wmi/wmi.c | 2881 ++++ 60 files changed, 23239 insertions(+), 7 deletions(-) Index: linux-2.6.22/drivers/sdio/function/wlan/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/Makefile 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,4 @@ +# +# SDIO wlan ar600 card function driver +# +obj-$(CONFIG_SDIO_AR6000_WLAN) += ar6000/ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/Makefile 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,29 @@ +# +# AR6K Kernel Module makefile. +# +REV ?= 2 + + +EXTRA_CFLAGS += -DLINUX -DDEBUG -D__KERNEL__ -DHTC_RAW_INTERFACE \ + -DSEND_EVENT_TO_APP#\ + -DMULTIPLE_FRAMES_PER_INTERRUPT -DAR6000REV$(REV) \ + -DBLOCK_TX_PATH_FLAG \ + +EXTRA_CFLAGS += -DKERNEL_2_6 + +obj-dir := /bmi /htc /hif + +obj-$(CONFIG_SDIO_AR6000_WLAN) += ar6000.o +ar6000-objs += htc/htc.o \ + htc/htc_send.o \ + htc/htc_recv.o \ + htc/htc_utils.o \ + htc/htc_events.o \ + bmi/bmi.o \ + hif/hif.o \ + ar6000/ar6000_drv.o \ + wmi/wmi.o \ + wlan/wlan_node.o \ + wlan/wlan_recv_beacon.o \ + wlan/wlan_utils.o + Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/bmi.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/bmi.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * BMI declarations and prototypes + */ + +#ifndef _BMI_H_ +#define _BMI_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Header files */ +#include "../include/athdefs.h" +#include "../include/athtypes.h" +#include "../include/hif.h" +#include "../include/osapi.h" + +void +BMIInit(void); + +A_STATUS +BMIDone(HIF_DEVICE *device); + +A_STATUS +BMIGetTargetId(HIF_DEVICE *device, A_UINT32 *id); + +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); + +#ifdef __cplusplus +} +#endif + +#endif /* _BMI_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/ar6000/ar6000_drv.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/ar6000/ar6000_drv.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the definitions for the AR6000 linux driver. + * + */ + +#ifndef _AR6000_H_ +#define _AR6000_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_AR6000 1 +#define AR6000_MAX_RX_BUFFERS 16 +#define AR6000_BUFFER_SIZE 1552 +#define AR6000_DATA_OFFSET 64 +#define AR6000_TX_TIMEOUT 10 +#define AR6000_ETH_ADDR_LEN 6 +#define AR6000_MAX_ENDPOINTS 4 +#define MAX_NODE_NUM 15 +#define MAX_COOKIE_NUM 150 + +struct ar_wep_key { + A_UINT8 arKeyIndex; + A_UINT8 arKeyLen; + A_UINT8 arKey[64]; +} ; + +struct ar_node_mapping { + A_UINT8 macAddress[6]; + A_UINT8 epId; + A_UINT8 txPending; +}; + +struct ar_cookie { + A_UINT32 arc_bp[2]; /* Must be first field */ + struct ar_cookie *arc_list_next; +}; + +typedef struct ar6_softc { + struct net_device *arNetDev; /* net_device pointer */ + void *arWmi; + int arTxPending[AR6000_MAX_ENDPOINTS]; + int arTotalTxDataPending; + A_UINT8 arNumDataEndPts; + A_BOOL arWmiEnabled; + A_BOOL arWmiReady; + A_BOOL arConnected; + void *arHtcTarget; + void *arHifDevice; + spinlock_t arLock; + struct semaphore arSem; + int arRxBuffers[AR6000_MAX_ENDPOINTS]; + int arSsidLen; + u_char arSsid[32]; + A_UINT8 arNetworkType; + A_UINT8 arDot11AuthMode; + A_UINT8 arAuthMode; + A_UINT8 arPairwiseCrypto; + A_UINT8 arPairwiseCryptoLen; + A_UINT8 arGroupCrypto; + A_UINT8 arGroupCryptoLen; + A_UINT8 arDefTxKeyIndex; + struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1]; + A_UINT8 arBssid[6]; + A_UINT8 arReqBssid[6]; + A_UINT16 arChannelHint; + A_UINT16 arBssChannel; + A_UINT16 arListenInterval; + struct ar6000_version arVersion; + A_INT8 arRssi; + A_UINT8 arTxPwr; + A_BOOL arTxPwrSet; + A_INT32 arBitRate; + struct net_device_stats arNetStats; + struct iw_statistics arIwStats; + A_INT8 arNumChannels; + A_UINT16 arChannelList[32]; + A_UINT32 arRegCode; + A_BOOL statsUpdatePending; + TARGET_STATS arTargetStats; + A_INT8 arMaxRetries; + A_UINT8 arPhyCapability; + AR6000_WLAN_STATE arWlanState; + struct ar_node_mapping arNodeMap[MAX_NODE_NUM]; + A_UINT8 arIbssPsEnable; + A_UINT8 arNodeNum; + A_UINT8 arNexEpId; + struct ar_cookie *arCookieList; + A_BOOL arConnectPending; +} AR_SOFTC_T; + +struct ar_giwscan_param { + char *current_ev; + char *end_buf; + A_BOOL firstPass; +}; + +#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++) + +#define AR6000_SPIN_LOCK(lock, param) do { \ + if (irqs_disabled()) { \ + AR_DEBUG_PRINTF("IRQs disabled:AR6000_LOCK\n"); \ + } \ + spin_lock_bh(lock); \ +} while (0) + +#define AR6000_SPIN_UNLOCK(lock, param) do { \ + if (irqs_disabled()) { \ + AR_DEBUG_PRINTF("IRQs disabled: AR6000_UNLOCK\n"); \ + } \ + spin_unlock_bh(lock); \ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* _AR6000_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ar6000_api.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ar6000_api.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the API to access the OS dependent atheros host driver + * by the WMI or WLAN generic modules. + * + */ + +#ifndef _AR6000_API_H_ +#define _AR6000_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ar6_softc; + +void ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap); +A_UINT8 ar6000_iptos_to_userPriority(A_UINT8 *pkt); +A_STATUS ar6000_control_tx(void *devt, void *osbuf, int endPt); +void ar6000_connect_event(struct ar6_softc *ar, A_UINT16 channel, + A_UINT8 *bssid, A_UINT16 listenInterval, + A_UINT8 beaconIeLen, A_UINT8 assocReqLen, + A_UINT8 assocRespLen,A_UINT8 *assocInfo); +void ar6000_disconnect_event(struct ar6_softc *ar, A_UINT8 reason, + A_UINT8 *bssid, A_UINT8 assocRespLen, + A_UINT8 *assocInfo); +void ar6000_tkip_micerr_event(struct ar6_softc *ar, A_UINT8 keyid, + A_BOOL ismcast); +void ar6000_bitrate_rx(void *devt, A_INT32 rateKbps); +void ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList); +void ar6000_regDomain_event(struct ar6_softc *ar, A_UINT32 regCode); +void ar6000_txPwr_rx(void *devt, A_UINT8 txPwr); +void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, + WMI_NEIGHBOR_INFO *info); +void ar6000_set_numdataendpts(struct ar6_softc *ar, A_UINT32 num); +void ar6000_scanComplete_event(struct ar6_softc *ar); +void ar6000_targetStats_event(struct ar6_softc *ar, WMI_TARGET_STATS *pStats); +void ar6000_rssiThreshold_event(struct ar6_softc *, WMI_RSSI_THRESHOLD_VAL); +void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal); +void ar6000_cac_event(struct ar6_softc *ar, A_UINT8 ac, A_UINT8 cac_indication, + A_UINT8 statusCode, A_UINT8 *tspecSuggestion); + +void +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl); + +void +ar6000_roam_data_event(struct ar6_softc **ar, WMI_TARGET_ROAM_DATA *p); + +void ar6000_dset_open_req(void *devt, + A_UINT32 id, + A_UINT32 targ_handle, + A_UINT32 targ_reply_fn, + A_UINT32 targ_reply_arg); +void ar6000_dset_close(void *devt, A_UINT32 access_cookie); +void ar6000_dset_data_req(void *devt, + A_UINT32 access_cookie, + A_UINT32 offset, + A_UINT32 length, + A_UINT32 targ_buf, + A_UINT32 targ_reply_fn, + A_UINT32 targ_reply_arg); + +void ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values); +void ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value); +void ar6000_gpio_ack_rx(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _AR6000_API_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/athdrv.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/athdrv.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the definitions for the AR6000 linux driver. + * + */ + +#ifndef _ATHDRV_H_ +#define _ATHDRV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * There are two types of ioctl's here: Standard ioctls and + * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed + * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The + * arguments for every XIOCTL starts with a 32-bit command word + * that is used to select which extended ioctl is in use. After + * the command word are command-specific arguments. + */ + +/* Linux standard Wireless Extensions, private ioctl interfaces */ +#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) +#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1) +#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+2) +#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+3) +#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+4) +#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+5) +#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+6) +#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+6) +#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+7) +#define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+8) +//#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10) +#define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+9) + + + +/* ====WMI Ioctls==== */ +/* + * + * Many ioctls simply provide WMI services to application code: + * an application makes such an ioctl call with a set of arguments + * that are packaged into the corresponding WMI message, and sent + * to the Target. + */ + +#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+10) +/* + * arguments: + * ar6000_version *revision + */ + +#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+11) +/* + * arguments: + * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h) + * uses: WMI_SET_POWER_MODE_CMDID + */ + +#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+12) +/* + * arguments: + * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h) + * uses: WMI_SET_SCAN_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+13) +/* + * arguments: + * UINT32 listenInterval + * uses: WMI_SET_LISTEN_INT_CMDID + */ + +#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+14) +/* + * arguments: + * WMI_BSS_FILTER filter (see include/wmi.h) + * uses: WMI_SET_BSS_FILTER_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) +/* + * arguments: + * WMI_CHANNEL_PARAMS_CMD chParams + * uses: WMI_SET_CHANNEL_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) +/* + * arguments: + * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h) + * uses: WMI_SETPROBED_SSID_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) +/* + * arguments: + * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h) + * uses: WMI_SET_POWER_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) +/* + * arguments: + * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h) + * uses: WMI_ADD_BAD_AP_CMDID + */ + +#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) +/* + * arguments: + * ar6000_queuereq queueRequest (see below) + */ + +#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) +/* + * arguments: + * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h) + * uses: WMI_CREATE_PSTREAM_CMDID + */ + +#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) +/* + * arguments: + * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h) + * uses: WMI_DELETE_PSTREAM_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_LINKTHRESHOLD (SIOCIWFIRSTPRIV+23) +/* + * arguments: + * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) + * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24) +/* + * arguments: + * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h) + * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID + */ + +#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) +/* + * arguments: + * TARGET_STATS *targetStats (see below) + * uses: WMI_GET_STATISTICS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) +/* + * arguments: + * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd + * uses: WMI_SET_ASSOC_INFO_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) +/* + * arguments: + * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h) + * uses: WMI_SET_ACCESS_PARAMS_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) +/* + * arguments: + * UINT32 beaconMissTime + * uses: WMI_SET_BMISS_TIME_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) +/* + * arguments: + * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h) + * uses: WMI_SET_DISC_TIMEOUT_CMDID + */ + +#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) +/* + * arguments: + * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd + * uses: WMI_SET_IBSS_PM_CAPS_CMDID + */ + +/* + * There is a very small space available for driver-private + * wireless ioctls. In order to circumvent this limitation, + * we multiplex a bunch of ioctls (XIOCTLs) on top of a + * single AR6000_IOCTL_EXTENDED ioctl. + */ +#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31) + + +/* ====BMI Extended Ioctls==== */ + +#define AR6000_XIOCTL_BMI_DONE 1 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_DONE) + * uses: BMI_DONE + */ + +#define AR6000_XIOCTL_BMI_READ_MEMORY 2 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY) + * UINT32 address + * UINT32 length + * } + * char results[length] + * } + * uses: BMI_READ_MEMORY + */ + +#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY) + * UINT32 address + * UINT32 length + * char data[length] + * uses: BMI_WRITE_MEMORY + */ + +#define AR6000_XIOCTL_BMI_EXECUTE 4 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE) + * UINT32 TargetAddress + * UINT32 parameter + * uses: BMI_EXECUTE + */ + +#define AR6000_XIOCTL_BMI_SET_APP_START 5 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START) + * UINT32 TargetAddress + * uses: BMI_SET_APP_START + */ + +#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER) + * UINT32 TargetAddress, 32-bit aligned + * } + * UINT32 result + * } + * uses: BMI_READ_SOC_REGISTER + */ + +#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 +/* + * arguments: + * struct { + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER) + * UINT32 TargetAddress, 32-bit aligned + * UINT32 newValue + * } + * uses: BMI_WRITE_SOC_REGISTER + */ + +#define AR6000_XIOCTL_BMI_TEST 8 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_BMI_TEST) + * UINT32 address + * UINT32 length + * UINT32 count + */ + + + +/* ====DataSet Extended Ioctls==== */ + +#define AR6000_XIOCTL_WMI_DSET_WAIT_REQ 9 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_DSET_WAIT_REQ) + */ + +#define AR6000_XIOCTL_WMI_DSET_OPEN_REPLY 10 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_DSET_OPEN_REPLY) + * dset_open_reply_t (see host/include/app/dset.h) + * uses: WMIX_DSETOPEN_REPLY_CMDID + */ + +#define AR6000_XIOCTL_WMI_DSET_DATA_REPLY 11 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_WMI_DSET_DATA_REPLY) + * dset_data_reply_t (see host/include/app/dset.h) + * uses: WMIX_DSETDATA_REPLY_CMDID + */ + +#define AR6000_XIOCTL_FORCE_TARGET_RESET 12 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET) + */ + + +#ifdef HTC_RAW_INTERFACE +/* HTC Raw Interface Ioctls */ +#define AR6000_XIOCTL_HTC_RAW_OPEN 13 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN) + */ + +#define AR6000_XIOCTL_HTC_RAW_CLOSE 14 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE) + */ + +#define AR6000_XIOCTL_HTC_RAW_READ 15 +/* + * arguments: + * union { + * struct { + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ) + * UINT32 mailboxID + * UINT32 length + * } + * results[length] + * } + */ + +#define AR6000_XIOCTL_HTC_RAW_WRITE 16 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE) + * UINT32 mailboxID + * UINT32 length + * char buffer[length] + */ +#endif /* HTC_RAW_INTERFACE */ + +#define AR6000_XIOCTL_CHECK_TARGET_READY 17 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY) + */ + + + +/* ====GPIO (General Purpose I/O) Extended Ioctls==== */ + +#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET) + * ar6000_gpio_output_set_cmd_s (see below) + * uses: WMIX_GPIO_OUTPUT_SET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INPUT_GET 19 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET) + * uses: WMIX_GPIO_INPUT_GET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_REGISTER_SET 20 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET) + * ar6000_gpio_register_cmd_s (see below) + * uses: WMIX_GPIO_REGISTER_SET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_REGISTER_GET 21 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET) + * ar6000_gpio_register_cmd_s (see below) + * uses: WMIX_GPIO_REGISTER_GET_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INTR_ACK 22 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK) + * ar6000_cpio_intr_ack_cmd_s (see below) + * uses: WMIX_GPIO_INTR_ACK_CMDID + */ + +#define AR6000_XIOCTL_GPIO_INTR_WAIT 23 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT) + */ + + + +/* ====more wireless commands==== */ + +#define AR6000_XIOCTL_SET_ADHOC_BSSID 24 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID) + * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h) + */ + +#define AR6000_XIOCTL_SET_OPT_MODE 25 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE) + * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h) + * uses: WMI_SET_OPT_MODE_CMDID + */ + +#define AR6000_XIOCTL_OPT_SEND_FRAME 26 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME) + * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h) + * uses: WMI_OPT_TX_FRAME_CMDID + */ + +#define AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL 27 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL) + * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h) + * uses: WMI_SET_BEACON_INT_CMDID + */ + + +#define IEEE80211_IOCTL_SETAUTHALG 28 + + +#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE) + * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h) + * uses: WMI_SET_VOICE_PKT_SIZE_CMDID + */ + + +#define AR6000_XIOCTL_SET_MAX_SP 30 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP) + * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h) + * uses: WMI_SET_MAX_SP_LEN_CMDID + */ + +#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 + +#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 + +#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS) + * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h) + * WMI_SET_POWERSAVE_TIMERS_CMDID + */ + +#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 +/* + * arguments: + * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE) + */ + +#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 +typedef enum { + WLAN_DISABLED, + WLAN_ENABLED +} AR6000_WLAN_STATE; +/* + * arguments: + * enable/disable + */ + +#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 + +/* used by AR6000_IOCTL_WMI_GETREV */ +struct ar6000_version { + A_UINT32 host_ver; + A_UINT32 target_ver; +}; + +/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */ +struct ar6000_queuereq{ + A_UINT8 trafficDirection; + A_UINT8 trafficClass; + A_INT8 queueNumber; +}; + +/* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */ +typedef struct targetStats_t { + A_UINT64 tx_packets; + A_UINT64 tx_bytes; + A_UINT64 tx_unicast_pkts; + A_UINT64 tx_unicast_bytes; + A_UINT64 tx_multicast_pkts; + A_UINT64 tx_multicast_bytes; + A_UINT64 tx_broadcast_pkts; + A_UINT64 tx_broadcast_bytes; + A_UINT64 tx_rts_success_cnt; + A_UINT64 tx_packet_per_ac[4]; + + A_UINT64 tx_errors; + A_UINT64 tx_failed_cnt; + A_UINT64 tx_retry_cnt; + A_UINT64 tx_rts_fail_cnt; + A_UINT64 rx_packets; + A_UINT64 rx_bytes; + A_UINT64 rx_unicast_pkts; + A_UINT64 rx_unicast_bytes; + A_UINT64 rx_multicast_pkts; + A_UINT64 rx_multicast_bytes; + A_UINT64 rx_broadcast_pkts; + A_UINT64 rx_broadcast_bytes; + A_UINT64 rx_fragment_pkt; + + A_UINT64 rx_errors; + A_UINT64 rx_crcerr; + A_UINT64 rx_key_cache_miss; + A_UINT64 rx_decrypt_err; + A_UINT64 rx_duplicate_frames; + + A_UINT64 tkip_local_mic_failure; + A_UINT64 tkip_counter_measures_invoked; + A_UINT64 tkip_replays; + A_UINT64 tkip_format_errors; + A_UINT64 ccmp_format_errors; + A_UINT64 ccmp_replays; + + A_UINT64 power_save_failure_cnt; + A_INT16 noise_floor_calibation; + + A_UINT64 cs_bmiss_cnt; + A_UINT64 cs_lowRssi_cnt; + A_UINT64 cs_connect_cnt; + A_UINT64 cs_disconnect_cnt; + A_UINT8 cs_aveBeacon_rssi; + A_UINT8 cs_lastRoam_msec; +}TARGET_STATS; + +/* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */ +struct ar6000_gpio_output_set_cmd_s { + A_UINT32 set_mask; + A_UINT32 clear_mask; + A_UINT32 enable_mask; + A_UINT32 disable_mask; +}; + +/* + * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET + */ +struct ar6000_gpio_register_cmd_s { + A_UINT32 gpioreg_id; + A_UINT32 value; +}; + +/* used by AR6000_XIOCTL_GPIO_INTR_ACK */ +struct ar6000_gpio_intr_ack_cmd_s { + A_UINT32 ack_mask; +}; + +/* used by AR6000_XIOCTL_GPIO_INTR_WAIT */ +struct ar6000_gpio_intr_wait_cmd_s { + A_UINT32 intr_mask; + A_UINT32 input_values; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ATHDRV_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/athtypes.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/athtypes.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright 2003-2006 Atheros Communications, Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * 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. + * + */ + +#ifndef _ATHTYPES_LINUX_H_ +#define _ATHTYPES_LINUX_H_ + +#ifdef __KERNEL__ +#include +#endif + +typedef int8_t A_INT8; +typedef int16_t A_INT16; +typedef int32_t A_INT32; +typedef int64_t A_INT64; + +typedef u_int8_t A_UINT8; +typedef u_int16_t A_UINT16; +typedef u_int32_t A_UINT32; +typedef u_int64_t A_UINT64; + +typedef int A_BOOL; +typedef char A_CHAR; +typedef unsigned char A_UCHAR; + +#endif /* _ATHTYPES_LINUX_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ieee80211.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ieee80211.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,333 @@ +/*- + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting + * Copyright 2006 ATheros Communications, Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * */ +#ifndef _NET80211_IEEE80211_H_ +#define _NET80211_IEEE80211_H_ + +/* + * 802.11 protocol definitions. + */ + +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ +/* is 802.11 address multicast/broadcast? */ +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) +#define IEEE80211_ADDR_EQ(addr1, addr2) \ + (A_MEMCMP(addr1, addr2, IEEE80211_ADDR_LEN) == 0) + +#define IEEE80211_KEYBUF_SIZE 16 +#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */ + +/* + * NB: these values are ordered carefully; there are lots of + * of implications in any reordering. In particular beware + * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY. + */ +#define IEEE80211_CIPHER_WEP 0 +#define IEEE80211_CIPHER_TKIP 1 +#define IEEE80211_CIPHER_AES_OCB 2 +#define IEEE80211_CIPHER_AES_CCM 3 +#define IEEE80211_CIPHER_CKIP 5 +#define IEEE80211_CIPHER_CCKM_KRK 6 +#define IEEE80211_CIPHER_NONE 7 /* pseudo value */ + +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1) + +#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \ + (((len) == 5) || ((len) == 13) || ((len) == 16)) + +/* + * generic definitions for IEEE 802.11 frames + */ +struct ieee80211_frame { + A_UINT8 i_fc[2]; + A_UINT8 i_dur[2]; + A_UINT8 i_addr1[IEEE80211_ADDR_LEN]; + A_UINT8 i_addr2[IEEE80211_ADDR_LEN]; + A_UINT8 i_addr3[IEEE80211_ADDR_LEN]; + A_UINT8 i_seq[2]; + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ + /* see below */ +} __ATTRIB_PACK; + +#define IEEE80211_FC0_VERSION_MASK 0x03 +#define IEEE80211_FC0_VERSION_SHIFT 0 +#define IEEE80211_FC0_VERSION_0 0x00 +#define IEEE80211_FC0_TYPE_MASK 0x0c +#define IEEE80211_FC0_TYPE_SHIFT 2 +#define IEEE80211_FC0_TYPE_MGT 0x00 +#define IEEE80211_FC0_TYPE_CTL 0x04 +#define IEEE80211_FC0_TYPE_DATA 0x08 + +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4 +/* for TYPE_MGT */ +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 +/* for TYPE_CTL */ +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 +/* for TYPE_DATA (bit combination) */ +#define IEEE80211_FC0_SUBTYPE_DATA 0x00 +#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10 +#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20 +#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 +#define IEEE80211_FC0_SUBTYPE_CFACK 0x50 +#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60 +#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80 +#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0 + +#define IEEE80211_FC1_DIR_MASK 0x03 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ + +#define IEEE80211_FC1_MORE_FRAG 0x04 +#define IEEE80211_FC1_RETRY 0x08 +#define IEEE80211_FC1_PWR_MGT 0x10 +#define IEEE80211_FC1_MORE_DATA 0x20 +#define IEEE80211_FC1_WEP 0x40 +#define IEEE80211_FC1_ORDER 0x80 + +#define IEEE80211_SEQ_FRAG_MASK 0x000f +#define IEEE80211_SEQ_FRAG_SHIFT 0 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0 +#define IEEE80211_SEQ_SEQ_SHIFT 4 + +#define IEEE80211_NWID_LEN 32 + +/* + * 802.11 rate set. + */ +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */ +#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */ + +#define WMM_NUM_AC 4 /* 4 AC categories */ + +#define WMM_PARAM_ACI_M 0x60 /* Mask for ACI field */ +#define WMM_PARAM_ACI_S 5 /* Shift for ACI field */ +#define WMM_PARAM_ACM_M 0x10 /* Mask for ACM bit */ +#define WMM_PARAM_ACM_S 4 /* Shift for ACM bit */ +#define WMM_PARAM_AIFSN_M 0x0f /* Mask for aifsn field */ +#define WMM_PARAM_LOGCWMIN_M 0x0f /* Mask for CwMin field (in log) */ +#define WMM_PARAM_LOGCWMAX_M 0xf0 /* Mask for CwMax field (in log) */ +#define WMM_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */ + +#define WMM_AC_TO_TID(_ac) ( \ + ((_ac) == WMM_AC_VO) ? 6 : \ + ((_ac) == WMM_AC_VI) ? 5 : \ + ((_ac) == WMM_AC_BK) ? 1 : \ + 0) + +#define TID_TO_WMM_AC(_tid) ( \ + ((_tid) < 1) ? WMM_AC_BE : \ + ((_tid) < 3) ? WMM_AC_BK : \ + ((_tid) < 6) ? WMM_AC_VI : \ + WMM_AC_VO) +/* + * Management information element payloads. + */ + +enum { + IEEE80211_ELEMID_SSID = 0, + IEEE80211_ELEMID_RATES = 1, + IEEE80211_ELEMID_FHPARMS = 2, + IEEE80211_ELEMID_DSPARMS = 3, + IEEE80211_ELEMID_CFPARMS = 4, + IEEE80211_ELEMID_TIM = 5, + IEEE80211_ELEMID_IBSSPARMS = 6, + IEEE80211_ELEMID_COUNTRY = 7, + IEEE80211_ELEMID_CHALLENGE = 16, + /* 17-31 reserved for challenge text extension */ + IEEE80211_ELEMID_PWRCNSTR = 32, + IEEE80211_ELEMID_PWRCAP = 33, + IEEE80211_ELEMID_TPCREQ = 34, + IEEE80211_ELEMID_TPCREP = 35, + IEEE80211_ELEMID_SUPPCHAN = 36, + IEEE80211_ELEMID_CHANSWITCH = 37, + IEEE80211_ELEMID_MEASREQ = 38, + IEEE80211_ELEMID_MEASREP = 39, + IEEE80211_ELEMID_QUIET = 40, + IEEE80211_ELEMID_IBSSDFS = 41, + IEEE80211_ELEMID_ERP = 42, + IEEE80211_ELEMID_RSN = 48, + IEEE80211_ELEMID_XRATES = 50, + IEEE80211_ELEMID_TPC = 150, + IEEE80211_ELEMID_CCKM = 156, + IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ +}; + +#define ATH_OUI 0x7f0300 /* Atheros OUI */ +#define ATH_OUI_TYPE 0x01 +#define ATH_OUI_SUBTYPE 0x01 +#define ATH_OUI_VERSION 0x00 + +#define WPA_OUI 0xf25000 +#define WPA_OUI_TYPE 0x01 +#define WPA_VERSION 1 /* current supported version */ + +#define WPA_CSE_NULL 0x00 +#define WPA_CSE_WEP40 0x01 +#define WPA_CSE_TKIP 0x02 +#define WPA_CSE_CCMP 0x04 +#define WPA_CSE_WEP104 0x05 + +#define WPA_ASE_NONE 0x00 +#define WPA_ASE_8021X_UNSPEC 0x01 +#define WPA_ASE_8021X_PSK 0x02 + +#define RSN_OUI 0xac0f00 +#define RSN_VERSION 1 /* current supported version */ + +#define RSN_CSE_NULL 0x00 +#define RSN_CSE_WEP40 0x01 +#define RSN_CSE_TKIP 0x02 +#define RSN_CSE_WRAP 0x03 +#define RSN_CSE_CCMP 0x04 +#define RSN_CSE_WEP104 0x05 + +#define RSN_ASE_NONE 0x00 +#define RSN_ASE_8021X_UNSPEC 0x01 +#define RSN_ASE_8021X_PSK 0x02 + +#define RSN_CAP_PREAUTH 0x01 + +#define WMM_OUI 0xf25000 +#define WMM_OUI_TYPE 0x02 +#define WMM_INFO_OUI_SUBTYPE 0x00 +#define WMM_PARAM_OUI_SUBTYPE 0x01 +#define WMM_VERSION 1 + +/* WMM stream classes */ +#define WMM_NUM_AC 4 +#define WMM_AC_BE 0 /* best effort */ +#define WMM_AC_BK 1 /* background */ +#define WMM_AC_VI 2 /* video */ +#define WMM_AC_VO 3 /* voice */ + +/* TSPEC related */ +#define ACTION_CATEGORY_CODE_TSPEC 17 +#define ACTION_CODE_TSPEC_ADDTS 0 +#define ACTION_CODE_TSPEC_ADDTS_RESP 1 +#define ACTION_CODE_TSPEC_DELTS 2 + +typedef enum { + TSPEC_STATUS_CODE_ADMISSION_ACCEPTED = 0, + TSPEC_STATUS_CODE_ADDTS_INVALID_PARAMS = 0x1, + TSPEC_STATUS_CODE_ADDTS_REQUEST_REFUSED = 0x3, + TSPEC_STATUS_CODE_UNSPECIFIED_QOS_RELATED_FAILURE = 0xC8, + TSPEC_STATUS_CODE_REQUESTED_REFUSED_POLICY_CONFIGURATION = 0xC9, + TSPEC_STATUS_CODE_INSUFFCIENT_BANDWIDTH = 0xCA, + TSPEC_STATUS_CODE_INVALID_PARAMS = 0xCB, + TSPEC_STATUS_CODE_DELTS_SENT = 0x30, + TSPEC_STATUS_CODE_DELTS_RECV = 0x31, +} TSPEC_STATUS_CODE; + +/* + * WMM/802.11e Tspec Element + */ +typedef struct wmm_tspec_ie_t { + A_UINT8 elementId; + A_UINT8 len; + A_UINT8 oui[3]; + A_UINT8 ouiType; + A_UINT8 ouiSubType; + A_UINT8 version; + A_UINT16 tsInfo_info; + A_UINT8 tsInfo_reserved; + A_UINT16 nominalMSDU; + A_UINT16 maxMSDU; + A_UINT32 minServiceInt; + A_UINT32 maxServiceInt; + A_UINT32 inactivityInt; + A_UINT32 suspensionInt; + A_UINT32 serviceStartTime; + A_UINT32 minDataRate; + A_UINT32 meanDataRate; + A_UINT32 peakDataRate; + A_UINT32 maxBurstSize; + A_UINT32 delayBound; + A_UINT32 minPhyRate; + A_UINT16 sba; + A_UINT16 mediumTime; +} __ATTRIB_PACK WMM_TSPEC_IE; + + +/* + * BEACON management packets + * + * octet timestamp[8] + * octet beacon interval[2] + * octet capability information[2] + * information element + * octet elemid + * octet length + * octet information[length] + */ + +#define IEEE80211_BEACON_INTERVAL(beacon) \ + ((beacon)[8] | ((beacon)[9] << 8)) +#define IEEE80211_BEACON_CAPABILITY(beacon) \ + ((beacon)[10] | ((beacon)[11] << 8)) + +#define IEEE80211_CAPINFO_ESS 0x0001 +#define IEEE80211_CAPINFO_IBSS 0x0002 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 +#define IEEE80211_CAPINFO_PRIVACY 0x0010 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 +#define IEEE80211_CAPINFO_PBCC 0x0040 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 +/* bits 8-9 are reserved */ +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 +#define IEEE80211_CAPINFO_APSD 0x0800 +/* bit 12 is reserved */ +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 +/* bits 14-15 are reserved */ + +/* + * Authentication Modes + */ + +enum ieee80211_authmode { + IEEE80211_AUTH_NONE = 0, + IEEE80211_AUTH_OPEN = 1, + IEEE80211_AUTH_SHARED = 2, + IEEE80211_AUTH_8021X = 3, + IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */ + /* NB: these are used only for ioctls */ + IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x */ + IEEE80211_AUTH_WPA_PSK = 6, /* WPA/RSN w/ PSK */ + IEEE80211_AUTH_WPA_CCKM = 7, /* WPA/RSN IE w/ CCKM */ +}; + +#endif /* _NET80211_IEEE80211_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ieee80211_ioctl.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ieee80211_ioctl.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * Portions Copyright (c) 2001 Atsushi Onoe, 2002-2005 Sam Leffler, Errno Consulting + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the definitions for the AR6000 linux driver. + * + */ + +#ifndef _IEEE80211_IOCTL_H_ +#define _IEEE80211_IOCTL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Extracted from the MADWIFI net80211/ieee80211_ioctl.h + */ + +/* + * WPA/RSN get/set key request. Specify the key/cipher + * type and whether the key is to be used for sending and/or + * receiving. The key index should be set only when working + * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). + * Otherwise a unicast/pairwise key is specified by the bssid + * (on a station) or mac address (on an ap). They key length + * must include any MIC key data; otherwise it should be no + more than IEEE80211_KEYBUF_SIZE. + */ +struct ieee80211req_key { + u_int8_t ik_type; /* key/cipher type */ + u_int8_t ik_pad; + u_int16_t ik_keyix; /* key index */ + u_int8_t ik_keylen; /* key length in bytes */ + u_int8_t ik_flags; +#define IEEE80211_KEY_XMIT 0x01 +#define IEEE80211_KEY_RECV 0x02 +#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */ + u_int8_t ik_macaddr[IEEE80211_ADDR_LEN]; + u_int64_t ik_keyrsc; /* key receive sequence counter */ + u_int64_t ik_keytsc; /* key transmit sequence counter */ + u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; +}; +/* + * Delete a key either by index or address. Set the index + * to IEEE80211_KEYIX_NONE when deleting a unicast key. + */ +struct ieee80211req_del_key { + u_int8_t idk_keyix; /* key index */ + u_int8_t idk_macaddr[IEEE80211_ADDR_LEN]; +}; +/* + * MLME state manipulation request. IEEE80211_MLME_ASSOC + * only makes sense when operating as a station. The other + * requests can be used when operating as a station or an + * ap (to effect a station). + */ +struct ieee80211req_mlme { + u_int8_t im_op; /* operation to perform */ +#define IEEE80211_MLME_ASSOC 1 /* associate station */ +#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */ +#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */ +#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */ +#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */ + u_int16_t im_reason; /* 802.11 reason code */ + u_int8_t im_macaddr[IEEE80211_ADDR_LEN]; +}; + +struct ieee80211req_addpmkid { + u_int8_t pi_bssid[IEEE80211_ADDR_LEN]; + u_int8_t pi_enable; + u_int8_t pi_pmkid[16]; +}; + +#define AUTH_ALG_OPEN_SYSTEM 0x01 +#define AUTH_ALG_SHARED_KEY 0x02 +#define AUTH_ALG_LEAP 0x04 + +struct ieee80211req_authalg { + u_int8_t auth_alg; +}; + +enum { + IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */ + IEEE80211_PARAM_MCASTCIPHER = 5, + IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */ + IEEE80211_PARAM_UCASTCIPHER = 8, + IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */ + IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */ + IEEE80211_PARAM_ROAMING = 12, /* roaming mode */ + IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */ + IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */ + IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */ +}; + +/* + * Values for IEEE80211_PARAM_WPA + */ +#define WPA_MODE_WPA1 1 +#define WPA_MODE_WPA2 2 +#define WPA_MODE_AUTO 3 +#define WPA_MODE_NONE 4 + +#ifdef __cplusplus +} +#endif + +#endif /* _IEEE80211_IOCTL_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ieee80211_node.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/ieee80211_node.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001 Atsushi Onoe + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting + * Copyright 2006 ATheros Communications, Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + */ +#ifndef _IEEE80211_NODE_H_ +#define _IEEE80211_NODE_H_ + +/* + * Node locking definitions. + */ +#define IEEE80211_NODE_LOCK_INIT(_nt) A_MUTEX_INIT(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_DESTROY(_nt) +#define IEEE80211_NODE_LOCK(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_BH(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK_BH(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_ASSERT(_nt) + +/* + * Node reference counting definitions. + * + * ieee80211_node_initref initialize the reference count to 1 + * ieee80211_node_incref add a reference + * ieee80211_node_decref remove a reference + * ieee80211_node_dectestref remove a reference and return 1 if this + * is the last reference, otherwise 0 + * ieee80211_node_refcnt reference count for printing (only) + */ +#define ieee80211_node_initref(_ni) ((_ni)->ni_refcnt = 1) +#define ieee80211_node_incref(_ni) ((_ni)->ni_refcnt++) +#define ieee80211_node_decref(_ni) ((_ni)->ni_refcnt--) +#define ieee80211_node_dectestref(_ni) (((_ni)->ni_refcnt--) == 0) +#define ieee80211_node_refcnt(_ni) ((_ni)->ni_refcnt) + +#define IEEE80211_NODE_HASHSIZE 32 +/* simple hash is enough for variation of macaddr */ +#define IEEE80211_NODE_HASH(addr) \ + (((const A_UINT8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \ + IEEE80211_NODE_HASHSIZE) + +/* + * Table of ieee80211_node instances. Each ieee80211com + * has at least one for holding the scan candidates. + * When operating as an access point or in ibss mode there + * is a second table for associated stations or neighbors. + */ +struct ieee80211_node_table { + void *nt_wmip; /* back reference */ + A_MUTEX_T nt_nodelock; /* on node table */ + struct bss *nt_node_first; /* information of all nodes */ + struct bss *nt_node_last; /* information of all nodes */ + struct bss *nt_hash[IEEE80211_NODE_HASHSIZE]; + const char *nt_name; /* for debugging */ + A_UINT32 nt_scangen; /* gen# for timeout scan */ + A_TIMER nt_inact_timer; +}; + +#define WLAN_NODE_INACT_TIMEOUT_MSEC 10000 + +#endif /* _IEEE80211_NODE_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/osapi_linux.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/osapi_linux.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,167 @@ +/* + * Copyright 2003-2006 Atheros Communications, Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * 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. + * + */ + +#ifndef _OSAPI_LINUX_H_ +#define _OSAPI_LINUX_H_ + +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include +#endif +#include +#include +#include +#ifdef KERNEL_2_4 +#include +#include +#endif + +/* + * Endianes macros + */ +#define A_BE2CPU8(x) ntohb(x) +#define A_BE2CPU16(x) ntohs(x) +#define A_BE2CPU32(x) ntohl(x) + +#define A_LE2CPU8(x) (x) +#define A_LE2CPU16(x) (x) +#define A_LE2CPU32(x) (x) + +#define A_CPU2BE8(x) htonb(x) +#define A_CPU2BE16(x) htons(x) +#define A_CPU2BE32(x) htonl(x) + +#define A_MEMCPY(dst, src, len) memcpy((A_UINT8 *)(dst), (src), (len)) +#define A_MEMZERO(addr, len) memset(addr, 0, len) +#define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len)) +#define A_MALLOC(size) kmalloc((size), GFP_KERNEL) +#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) +#define A_FREE(addr) kfree(addr) +#define A_PRINTF(args...) printk(args) + +/* Mutual Exclusion */ +typedef spinlock_t A_MUTEX_T; +#define A_MUTEX_INIT(mutex) spin_lock_init(mutex) +#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex) +#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex) + +/* + * Timer Functions + */ +#define A_MDELAY(msecs) mdelay(msecs) +typedef struct timer_list A_TIMER; + +#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \ + init_timer(pTimer); \ + (pTimer)->function = (pFunction); \ + (pTimer)->data = (unsigned long)(pArg); \ +} while (0) + +/* + * Start a Timer that elapses after 'periodMSec' milli-seconds + * Support is provided for a one-shot timer. The 'repeatFlag' is + * ignored. + */ +#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \ + if (repeatFlag) { \ + printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \ + panic("Timer Repeat"); \ + } \ + mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \ +} while (0) + +/* + * Cancel the Timer. + */ +#define A_UNTIMEOUT(pTimer) do { \ + del_timer((pTimer)); \ +} while (0) + +#define A_DELETE_TIMER(pTimer) do { \ +} while (0) + +/* + * Wait Queue related functions + */ +typedef wait_queue_head_t A_WAITQUEUE_HEAD; +#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head) +#ifdef mvlcee31_2_4_20_omap2420_gsm_gprs +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif /* wait_event_interruptible_timeout */ + +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ + wait_event_interruptible_timeout(head, condition, timeout); \ +} while (0) +#else +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ + wait_event_interruptible_timeout(head, condition, timeout); \ +} while (0) +#endif /* mvlcee31_2_4_20-omap2420_gsm_gprs */ + +#define A_WAKE_UP(head) wake_up(head) + +#ifdef DEBUG +#define A_ASSERT(expr) \ + if (!(expr)) { \ + printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \ + panic(#expr); \ + } + +#else +#define A_ASSERT(expr) +#endif /* DEBUG */ + +#endif /* _OSAPI_LINUX_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/wmi_host.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/include/wmi_host.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains local definitios for the wmi host module. + * + */ + +#ifndef _WMI_HOST_H_ +#define _WMI_HOST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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 + +struct wmi_stats { + A_UINT32 cmd_len_err; + A_UINT32 cmd_id_err; +}; + +struct wmi_priority_state { + A_UINT8 inUse; + A_UINT8 mbox; +}; + +struct wmi_mbox_state { + A_UINT8 trafficClass; + A_INT8 priorityNum; +}; + +struct wmi_t { + A_BOOL wmi_ready; + A_BOOL wmi_numQoSStream; + struct wmi_priority_state wmi_priority[WMI_MAX_NUM_PRI_STREAMS]; + struct wmi_mbox_state wmi_mboxMap[2][WMI_MBOX_COUNT]; + A_INT8 wmi_trafficClassMap[2][WMM_NUM_AC]; + A_UINT8 wmi_olderPriRxMbox; + A_UINT8 wmi_newerPriRxMbox; + void *wmi_devt; + struct wmi_stats wmi_stats; + struct ieee80211_node_table wmi_scan_table; + A_BOOL wmi_pstreamCmdInProgress[2][WMM_NUM_AC]; + A_BOOL wmi_cpstreamCmdInProgress; + A_UINT8 wmi_bssid[ATH_MAC_LEN]; + A_UINT8 wmi_powerMode; + A_UINT8 wmi_phyMode; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _WMI_HOST_H_ */ Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/bmi/bmi_internal.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/bmi/bmi_internal.h 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + */ +#include "../include/athdefs.h" +#include "../include/athtypes.h" +#include "../include/osapi.h" +#include "../include/hw/mbox_host_reg.h" +#include "../include/AR6000_bmi.h" + +#define BMI_COMMUNICATION_TIMEOUT 100000 + +A_STATUS +bmiBufferSend(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length); + +A_STATUS +bmiBufferReceive(HIF_DEVICE *device, + A_UCHAR *buffer, + A_UINT32 length); Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/hif/hif.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/hif/hif.c 2007-12-03 19:42:50.000000000 +0100 @@ -0,0 +1,664 @@ +/* + * Copyright (c) 2004-2005 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the routines handling the interaction with the SDIO + * driver + */ +#include "hif_internal.h" + +/* ------ Static Variables ------ */ + +/* ------ Global Variable Declarations ------- */ +SD_PNP_INFO Ids[] = { + { + .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0xB, + .SDIO_ManufacturerCode = MANUFACTURER_CODE, + .SDIO_FunctionClass = FUNCTION_CLASS, + .SDIO_FunctionNo = 1 + }, + { + .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0xA, + .SDIO_ManufacturerCode = MANUFACTURER_CODE, + .SDIO_FunctionClass = FUNCTION_CLASS, + .SDIO_FunctionNo = 1 + }, + { + .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0x9, + .SDIO_ManufacturerCode = MANUFACTURER_CODE, + .SDIO_FunctionClass = FUNCTION_CLASS, + .SDIO_FunctionNo = 1 + }, + { + .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0x8, + .SDIO_ManufacturerCode = MANUFACTURER_CODE, + .SDIO_FunctionClass = FUNCTION_CLASS, + .SDIO_FunctionNo = 1 + }, + { + } //list is null termintaed +}; + +TARGET_FUNCTION_CONTEXT FunctionContext = { + .function.Version = CT_SDIO_STACK_VERSION_CODE, + .function.pName = "sdio_wlan", + .function.MaxDevices = 1, + .function.NumDevices = 0, + .function.pIds = Ids, + .function.pProbe = hifDeviceInserted, + .function.pRemove = hifDeviceRemoved, + .function.pSuspend = NULL, + .function.pResume = NULL, + .function.pWake = NULL, + .function.pContext = &FunctionContext, +}; + +HIF_DEVICE hifDevice[HIF_MAX_DEVICES]; +HTC_CALLBACKS htcCallbacks; +BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; +OS_CRITICALSECTION lock; +extern A_UINT32 onebitmode; +extern A_UINT32 busspeedlow; +extern A_UINT32 debughif; + +#ifdef DEBUG +#define ATH_DEBUG_ERROR 1 +#define ATH_DEBUG_WARN 2 +#define ATH_DEBUG_TRACE 3 +#define _AR_DEBUG_PRINTX_ARG(arg...) arg +#define AR_DEBUG_PRINTF(lvl, args)\ + {if (lvl <= debughif)\ + A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\ + } +#else +#define AR_DEBUG_PRINTF(lvl, args) +#endif + +/* ------ Functions ------ */ +void +HIFRegisterCallbacks(HTC_CALLBACKS *callbacks) +{ + SDIO_STATUS status; + DBG_ASSERT(callbacks != NULL); + + /* Store the callback and event handlers */ + htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler; + htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler; + htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler; + htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler; + htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler; + htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler; + htcCallbacks.dsrHandler = callbacks->dsrHandler; + + CriticalSectionInit(&lock); + + /* Register with bus driver core */ + status = SDIO_RegisterFunction(&FunctionContext.function); + DBG_ASSERT(SDIO_SUCCESS(status)); +} + +A_STATUS +HIFReadWrite(HIF_DEVICE *device, + A_UINT32 address, + A_UCHAR *buffer, + A_UINT32 length, + HIF_REQUEST *request, + void *context) +{ + A_UINT8 rw; + A_UINT8 mode; + A_UINT8 funcNo; + A_UINT8 opcode; + A_UINT16 count; + SDREQUEST *sdrequest; + SDIO_STATUS status; + DBG_ASSERT(device != NULL); + DBG_ASSERT(device->handle != NULL); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); + sdrequest = hifAllocateDeviceRequest(device->handle); + if (sdrequest == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate bus request\n")); + return A_ERROR; + } + + sdrequest->pDataBuffer = buffer; + if (request->emode == HIF_SYNCHRONOUS) { + sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS; + sdrequest->pCompleteContext = NULL; + sdrequest->pCompletion = NULL; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n")); + } else if (request->emode == HIF_ASYNCHRONOUS) { + sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS | + SDREQ_FLAGS_TRANS_ASYNC; + sdrequest->pCompleteContext = context; + sdrequest->pCompletion = hifRWCompletionHandler; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Asynchronous\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid execution mode: %d\n", request->emode)); + return A_ERROR; + } + + if (request->type == HIF_EXTENDED_IO) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n")); + sdrequest->Command = CMD53; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid command type: %d\n", request->type)); + return A_ERROR; + } + + if (request->dmode == HIF_BLOCK_BASIS) { + mode = CMD53_BLOCK_BASIS; + sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE; + sdrequest->BlockCount = length / HIF_MBOX_BLOCK_SIZE; + count = sdrequest->BlockCount; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("Block mode (BlockLen: %d, BlockCount: %d)\n", + sdrequest->BlockLen, sdrequest->BlockCount)); + } else if (request->dmode == HIF_BYTE_BASIS) { + mode = CMD53_BYTE_BASIS; + sdrequest->BlockLen = length; + sdrequest->BlockCount = 1; + count = sdrequest->BlockLen; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("Byte mode (BlockLen: %d, BlockCount: %d)\n", + sdrequest->BlockLen, sdrequest->BlockCount)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid data mode: %d\n", request->dmode)); + return A_ERROR; + } + + if ((address >= HIF_MBOX_START_ADDR(0)) && + (address <= HIF_MBOX_END_ADDR(3))) + { + /* + * Mailbox write. Adjust the address so that the last byte + * falls on the EOM address. + */ + address += (HIF_MBOX_WIDTH - length); + } + + if (request->direction == HIF_WRITE) { + rw = CMD53_WRITE; + sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n")); + } else if (request->direction == HIF_READ) { + rw = CMD53_READ; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid direction: %d\n", request->direction)); + return A_ERROR; + } + + if (request->amode == HIF_FIXED_ADDRESS) { + opcode = CMD53_FIXED_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n")); + } else if (request->amode == HIF_INCREMENTAL_ADDRESS) { + opcode = CMD53_INCR_ADDRESS; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Incremental\n")); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid address mode: %d\n", request->amode)); + return A_ERROR; + } + + funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Function number: %d\n", funcNo)); + SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo, + mode, opcode, address, count); + + /* Send the command out */ + status = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); + if (status == SDIO_STATUS_PENDING) { + DBG_ASSERT(request->emode == HIF_ASYNCHRONOUS); + return A_OK; + } else if (status == SDIO_STATUS_SUCCESS) { + DBG_ASSERT(request->emode == HIF_SYNCHRONOUS); + hifFreeDeviceRequest(sdrequest); + return A_OK; + } + + return A_ERROR; +} + +A_STATUS +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, + void *config, A_UINT32 configLen) +{ + A_UINT32 count; + + switch(opcode) { + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: + ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; + ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; + ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; + ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; + break; + + case HIF_DEVICE_GET_MBOX_ADDR: + for (count = 0; count < 4; count ++) { + ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); + } + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Invalid configuration opcode: %d\n", opcode)); + return A_ERROR; + } + + return A_OK; +} + +void +HIFShutDownDevice(HIF_DEVICE *device) +{ + A_UINT8 data; + A_UINT32 count; + SDIO_STATUS status; + SDCONFIG_BUS_MODE_DATA busSettings; + SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; + + if (device != NULL) { + DBG_ASSERT(device->handle != NULL); + + /* Remove the allocated current if any */ + status = SDLIB_IssueConfig(device->handle, + SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0); + DBG_ASSERT(SDIO_SUCCESS(status)); + + /* Disable the card */ + fData.EnableFlags = SDCONFIG_DISABLE_FUNC; + fData.TimeOut = 1; + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ENABLE_DISABLE, + &fData, sizeof(fData)); + DBG_ASSERT(SDIO_SUCCESS(status)); + + /* Perform a soft I/O reset */ + data = SDIO_IO_RESET; + status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG, + &data, 1, 1); + DBG_ASSERT(SDIO_SUCCESS(status)); + + /* + * WAR - Codetelligence driver does not seem to shutdown correctly in 1 + * bit mode. By default it configures the HC in the 4 bit. Its later in + * our driver that we switch to 1 bit mode. If we try to shutdown, the + * driver hangs so we revert to 4 bit mode, to be transparent to the + * underlying bus driver. + */ + if (onebitmode) { + ZERO_OBJECT(busSettings); + busSettings.BusModeFlags = + device->handle->pHcd->CardProperties.BusMode; + SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, + SDCONFIG_BUS_WIDTH_4_BIT); + + /* Issue config request to change the bus width to 4 bit */ + status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL, + &busSettings, + sizeof(SDCONFIG_BUS_MODE_DATA)); + DBG_ASSERT(SDIO_SUCCESS(status)); + } + + /* Free the bus requests */ + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { + SDDeviceFreeRequest(device->handle, busRequest[count].request); + busRequest[count].free = FALSE; + } + } else { + /* Unregister with bus driver core */ + status = SDIO_UnregisterFunction(&FunctionContext.function); + DBG_ASSERT(SDIO_SUCCESS(status)); + } +} + +void +hifRWCompletionHandler(SDREQUEST *request) +{ + A_STATUS status; + void *context; + + if (SDIO_SUCCESS(request->Status)) { + status = A_OK; + } else { + status = A_ERROR; + } + context = (void *)request->pCompleteContext; + + htcCallbacks.rwCompletionHandler(context, status); + DBG_ASSERT(status == A_OK); + + hifFreeDeviceRequest(request); +} + +void +hifIRQHandler(void *context) +{ + A_STATUS status; + HIF_DEVICE *device; + + device = (HIF_DEVICE *)context; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); + status = htcCallbacks.dsrHandler(device); + DBG_ASSERT(status == A_OK); +} + +BOOL +hifDeviceInserted(SDFUNCTION *function, SDDEVICE *handle) +{ + BOOL enabled; + A_UINT8 data; + A_UINT32 count; + HIF_DEVICE *device; + SDIO_STATUS status; + A_UINT16 maxBlocks; + A_UINT16 maxBlockSize; + SDCONFIG_BUS_MODE_DATA busSettings; + SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; + TARGET_FUNCTION_CONTEXT *functionContext; + SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent; + DBG_ASSERT(function != NULL); + DBG_ASSERT(handle != NULL); + + device = addHifDevice(handle); + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); + functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext; + + /* + * Issue commands to get the manufacturer ID and stuff and compare it + * against the rev Id derived from the ID registered during the + * initialization process. Report the device only in the case there + * is a match. In the case od SDIO, the bus driver has already queried + * these details so we just need to use their data structures to get the + * relevant values. Infact, the driver has already matched it against + * the Ids that we registered with it so we dont need to the step here. + */ + + /* Configure the SDIO Bus Width */ + if (onebitmode) { + data = SDIO_BUS_WIDTH_1_BIT; + status = SDLIB_IssueCMD52(handle, 0, SDIO_BUS_IF_REG, &data, 1, 1); + if (!SDIO_SUCCESS(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Unable to set the bus width to 1 bit\n")); + return FALSE; + } + } + + /* Get current bus flags */ + ZERO_OBJECT(busSettings); + busSettings.BusModeFlags = handle->pHcd->CardProperties.BusMode; + if (onebitmode) { + SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, + SDCONFIG_BUS_WIDTH_1_BIT); + } + busSettings.ClockRate = (busspeedlow ? SDIO_CLOCK_FREQUENCY_REDUCED : + SDIO_CLOCK_FREQUENCY_DEFAULT); + + /* Issue config request to override clock rate */ + status = SDLIB_IssueConfig(handle, SDCONFIG_BUS_MODE_CTRL, &busSettings, + sizeof(SDCONFIG_BUS_MODE_DATA)); + if (!SDIO_SUCCESS(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Unable to configure the host clock\n")); + return FALSE; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("Configured clock: %d, Maximum clock: %d\n", + busSettings.ActualClockRate, + SDDEVICE_GET_MAX_CLOCK(handle))); + } + + /* + * Check if the target supports block mode. This result of this check + * can be used to implement the HIFReadWrite API. + */ + if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)) { + /* Limit block size to operational block limit or card function + capability */ + maxBlockSize = min(SDDEVICE_GET_OPER_BLOCK_LEN(handle), + SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)); + + /* check if the card support multi-block transfers */ + if (!(SDDEVICE_GET_SDIOCARD_CAPS(handle) & SDIO_CAPS_MULTI_BLOCK)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Byte basis only\n")); + + /* Limit block size to max byte basis */ + maxBlockSize = min(maxBlockSize, + (A_UINT16)SDIO_MAX_LENGTH_BYTE_BASIS); + maxBlocks = 1; + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Multi-block capable\n")); + maxBlocks = SDDEVICE_GET_OPER_BLOCKS(handle); + status = SDLIB_SetFunctionBlockSize(handle, HIF_MBOX_BLOCK_SIZE); + if (!SDIO_SUCCESS(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Failed to set block size. Err:%d\n", status)); + return FALSE; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("Bytes Per Block: %d bytes, Block Count:%d \n", + maxBlockSize, maxBlocks)); + } else { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Function does not support Block Mode!\n")); + return FALSE; + } + + /* Allocate the slot current */ + status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent); + if (SDIO_SUCCESS(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n", + slotCurrent.SlotCurrent)); + status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT, + &slotCurrent, sizeof(slotCurrent)); + if (!SDIO_SUCCESS(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Failed to allocate slot current %d\n", status)); + return FALSE; + } + } + + /* Enable the dragon function */ + count = 0; + enabled = FALSE; + fData.TimeOut = 1; + fData.EnableFlags = SDCONFIG_ENABLE_FUNC; + while ((count++ < SDWLAN_ENABLE_DISABLE_TIMEOUT) && !enabled) + { + /* Enable dragon */ + status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ENABLE_DISABLE, + &fData, sizeof(fData)); + if (!SDIO_SUCCESS(status)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("Attempting to enable the card again\n")); + continue; + } + + /* Mark the status as enabled */ + enabled = TRUE; + } + + /* Check if we were succesful in enabling the target */ + if (!enabled) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, + ("Failed to communicate with the target\n")); + return FALSE; + } + + /* Allocate the bus requests to be used later */ + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { + if ((busRequest[count].request = SDDeviceAllocRequest(handle)) == NULL){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate memory\n")); + /* TODO: Free the memory that has already been allocated */ + return FALSE; + } + busRequest[count].free = TRUE; + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("busRequest[%d].request = 0x%p, busRequest[%d].free = %d\n", count, busRequest[count].request, count, busRequest[count].free)); + } + + /* + * Adding a wait of around a second before we issue the very first + * command to dragon. During the process of loading/unloading the + * driver repeatedly it was observed that we get a data timeout + * while accessing function 1 registers in the chip. The theory at + * this point is that some initialization delay in dragon is + * causing the SDIO state in dragon core to be not ready even after + * the ready bit indicates that function 1 is ready. Accomodating + * for this behavior by adding some delay in the driver before it + * issues the first command after switching on dragon. Need to + * investigate this a bit more - TODO + */ +// A_MDELAY(1000); + + /* Inform HTC */ + if ((htcCallbacks.deviceInsertedHandler(device)) != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n")); + return FALSE; + } + + return TRUE; +} + +void +HIFAckInterrupt(HIF_DEVICE *device) +{ + SDIO_STATUS status; + DBG_ASSERT(device != NULL); + DBG_ASSERT(device->handle != NULL); + + /* Acknowledge our function IRQ */ + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ, + NULL, 0); + DBG_ASSERT(SDIO_SUCCESS(status)); +} + +void +HIFUnMaskInterrupt(HIF_DEVICE *device) +{ + SDIO_STATUS status; + + DBG_ASSERT(device != NULL); + DBG_ASSERT(device->handle != NULL); + + /* Register the IRQ Handler */ + SDDEVICE_SET_IRQ_HANDLER(device->handle, hifIRQHandler, device); + + /* Unmask our function IRQ */ + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ, + NULL, 0); + DBG_ASSERT(SDIO_SUCCESS(status)); +} + +void HIFMaskInterrupt(HIF_DEVICE *device) +{ + SDIO_STATUS status; + DBG_ASSERT(device != NULL); + DBG_ASSERT(device->handle != NULL); + + /* Mask our function IRQ */ + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ, + NULL, 0); + DBG_ASSERT(SDIO_SUCCESS(status)); + + /* Unregister the IRQ Handler */ + SDDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL); +} + +SDREQUEST * +hifAllocateDeviceRequest(SDDEVICE *device) +{ + SDREQUEST *request; + A_UINT32 count; + DBG_ASSERT(device != NULL); + + /* Acquire lock */ + CriticalSectionAcquire(&lock); + request = NULL; + for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("busRequest[%d].request = 0x%p, busRequest[%d].free = %d\n", count, busRequest[count].request, count, busRequest[count].free)); + if (busRequest[count].free) { + request = busRequest[count].request; + busRequest[count].free = FALSE; + break; + } + } + /* Release lock */ + CriticalSectionRelease(&lock); + + return request; +} + +void +hifFreeDeviceRequest(SDREQUEST *request) +{ + A_UINT32 count; + DBG_ASSERT(request != NULL); + + /* Acquire lock */ + CriticalSectionAcquire(&lock); + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { + if (busRequest[count].request == request) { + busRequest[count].free = TRUE; + break; + } + } + /* Release lock */ + CriticalSectionRelease(&lock); +} + +void +hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle) +{ + A_STATUS status; + HIF_DEVICE *device; + DBG_ASSERT(function != NULL); + DBG_ASSERT(handle != NULL); + + device = getHifDevice(handle); + status = htcCallbacks.deviceRemovedHandler(device); + delHifDevice(handle); + DBG_ASSERT(status == A_OK); +} + +HIF_DEVICE * +addHifDevice(SDDEVICE *handle) +{ + DBG_ASSERT(handle != NULL); + hifDevice[0].handle = handle; + return &hifDevice[0]; +} + +HIF_DEVICE * +getHifDevice(SDDEVICE *handle) +{ + DBG_ASSERT(handle != NULL); + return &hifDevice[0]; +} + +void +delHifDevice(SDDEVICE *handle) +{ + DBG_ASSERT(handle != NULL); + hifDevice[0].handle = NULL; +} Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/htc/htc.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/htc/htc.c 2007-12-03 21:16:59.000000000 +0100 @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the HTC APIs that are exposed to higher layers. + */ + +#include "htc_internal.h" + +/* ------ Global Variable Declarations ------- */ +HTC_TARGET *AtherosTargetList[HIF_MAX_DEVICES]; +HTC_GLOBAL_EVENT_TABLE AtherosEventTable; +A_MUTEX_T creditCS, counterCS, instanceCS; +A_WAITQUEUE_HEAD htcEvent; + +#ifdef DEBUG +extern A_UINT32 debughtc; +extern A_UINT32 txcreditsavailable[HTC_MAILBOX_NUM_MAX]; +extern A_UINT32 txcreditsconsumed[HTC_MAILBOX_NUM_MAX]; +extern A_UINT32 txcreditintrenable[HTC_MAILBOX_NUM_MAX]; +extern A_UINT32 txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX]; +#endif + +extern int tx_attempt[HTC_MAILBOX_NUM_MAX]; /* Num of attempts to add */ +extern int tx_post[HTC_MAILBOX_NUM_MAX]; /* Num of attemps succeded */ +extern int tx_complete[HTC_MAILBOX_NUM_MAX]; /* Num of tx complete */ + +/* Initializes the HTC module */ +A_STATUS +HTCInit(void) +{ + HTC_CALLBACKS htcCallbacks; + static A_BOOL HTCInitialized = FALSE; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Enter\n")); + if (HTCInitialized) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n")); + return A_OK; + } + + A_MEMZERO(&AtherosEventTable, sizeof(HTC_GLOBAL_EVENT_TABLE)); + A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS)); + A_INIT_WAITQUEUE_HEAD(&htcEvent); + + htcCallbacks.deviceInsertedHandler = htcTargetInsertedHandler; + htcCallbacks.deviceRemovedHandler = htcTargetRemovedHandler; + htcCallbacks.rwCompletionHandler = htcRWCompletionHandler; +#ifdef CF + htcCallbacks.deviceInterruptEnabler = htcInterruptEnabler; + htcCallbacks.deviceInterruptDisabler = htcInterruptDisabler; +#endif /* CF */ + + htcCallbacks.dsrHandler = htcDSRHandler; + HIFRegisterCallbacks(&htcCallbacks); + HTCInitialized = TRUE; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n")); + return A_OK; +} + +/* Enables Dragon interrupts */ +A_STATUS +HTCStart(HTC_TARGET *target) +{ + A_STATUS status; + A_UINT32 address; + HIF_REQUEST request; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); + + /* Unmask the host controller interrupts */ + HIFUnMaskInterrupt(target->device); + + /* Enable all the interrupts except for the dragon interrupt */ + target->table.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | + INT_STATUS_ENABLE_CPU_SET(0x01) | + INT_STATUS_ENABLE_COUNTER_SET(0x01) | + INT_STATUS_ENABLE_MBOX_DATA_SET(0x0F); + + /* Set up the CPU Interrupt Status Register */ + target->table.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00); + + /* Set up the Error Interrupt Status Register */ + target->table.error_status_enable = + ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) | + ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01); + + /* Set up the Counter Interrupt Status Register */ + target->table.counter_int_status_enable = + COUNTER_INT_STATUS_ENABLE_BIT_SET(0xFF); + + /* Write to the register */ + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.int_status_enable, 4, &request, NULL); + if (status != A_OK) { + /* Can't write it for some reason */ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to enable INT_STATUS_ENABLE | CPU_INT_STATUS_ENABLE | ERROR_STATUS_ENABLE | COUNTER_INT_STATUS_ENABLE, err: %d\n", status)); + HTCStop(target); + return status; + } + +#ifdef DEBUG + txcreditintrenable[ENDPOINT1] += 1; + txcreditintrenable[ENDPOINT2] += 1; + txcreditintrenable[ENDPOINT3] += 1; + txcreditintrenable[ENDPOINT4] += 1; + txcreditintrenableaggregate[ENDPOINT1] += 1; + txcreditintrenableaggregate[ENDPOINT2] += 1; + txcreditintrenableaggregate[ENDPOINT3] += 1; + txcreditintrenableaggregate[ENDPOINT4] += 1; +#endif /* DEBUG */ + + /* Wait on a timed semaphore that will get signalled once the block + size negotiation with the target has completed. Furthermore, we have + to do it only once during the lifetime of the target detection */ + if (!target->ready) { + int i; + + for (i = 0; i < 5; i++) { + mdelay(100); + } + AR_DEBUG_PRINTF(ATH_DEBUG_INF, + ("Waiting for the block size negotiation to finish\n")); + wait_event_interruptible_timeout(htcEvent, + (target->ready == TRUE), 60 * HZ); +#if 0 + A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(htcEvent, (target->ready == TRUE), + HTC_TARGET_RESPONSE_TIMEOUT); +#endif + if (target->ready) { + status = A_OK; + } else { + status = A_ERROR; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Failed to negotiate the block sizes\n")); + HTCStop(target); + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); + return status; +} + +/* + * Provides an interface for the higher layer module to register for + * different events supported by the HTC module + */ +A_STATUS +HTCEventReg(HTC_TARGET *target, HTC_ENDPOINT_ID endPointId, + HTC_EVENT_ID eventId, HTC_EVENT_HANDLER eventHandler, + void *param) +{ + /* + * Add the event handler against the specified event and store it in + * the event table + */ + A_STATUS status; + HTC_ENDPOINT *endPoint; + HTC_EVENT_INFO eventInfo; + HTC_DATA_REQUEST_QUEUE *sendQueue, *recvQueue; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("HTCEventReg: Enter (eventId: 0x%x, endPointId: %d)\n", + eventId, endPointId)); + + if (eventHandler) { + if ((status = addToEventTable(target, endPointId, eventId, + eventHandler, param)) != A_OK) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Could not add the event 0x%x to the event table\n", eventId)); + return status; + } + } + + switch(eventId) { + case HTC_TARGET_AVAILABLE: + if (eventHandler != NULL) { + /* + * Dispatch a Target Available event for all the targets + * present. Iterate through the global list of targets but + * currently we shall simply look for the first instance + */ + target = AtherosTargetList[0]; + if (target != NULL) { + FRAME_EVENT(eventInfo, (A_UCHAR *)target->device, + sizeof(HIF_DEVICE *), sizeof(HIF_DEVICE *), + A_OK, NULL); + dispatchEvent(target, ENDPOINT_UNUSED, eventId, &eventInfo); + } + } else { + /* Initiate a shut down procedure */ + } + break; + + case HTC_TARGET_UNAVAILABLE: + break; + + case HTC_BUFFER_RECEIVED: + if (eventHandler == NULL) { + /* Flush the queue before unregistering the event handler */ + endPoint = &target->endPoint[endPointId]; + recvQueue = &endPoint->recvQueue; + flushMboxQueue(endPoint, recvQueue, HTC_BUFFER_RECEIVED); + } + break; + + case HTC_SKB_RECEIVED: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("skb not handled currently\n")); + break; + + case HTC_BUFFER_SENT: + if (eventHandler == NULL) { + /* Flush the queue before unregistering the event handler */ + endPoint = &target->endPoint[endPointId]; + sendQueue = &endPoint->sendQueue; + flushMboxQueue(endPoint, sendQueue, HTC_BUFFER_SENT); + } + break; + + case HTC_SKB_SENT: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("skb not handled currently\n")); + break; + + case HTC_DATA_AVAILABLE: + /* + * Dispatch a data available event with the length. We are + * not handling this specific case currently because registering + * for HTC_DATA_AVAILABLE event is a part of the discipline + * that is imposed before one starts using HTC + */ + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Unknown Event ID: 0x%x\n", eventId)); + return A_EINVAL; + } + + /* Check if its a call for registering the event or unregistering it */ + if (eventHandler == NULL) { + if ((status = removeFromEventTable(target, endPointId, + eventId)) != A_OK) + { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Could not remove the event 0x%x from the event table\n", eventId)); + return status; + } + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCEventReg: Exit\n")); + return A_OK; +} + +/* + * Commit an address to either WINDOW_WRITE_ADDR_REG or to + * WINDOW_READ_ADDR_REG. We write the least significan byte (LSB) + * last, since it triggers the read/write. + */ +static void +_WRITE_WINDOW_ADDR(HTC_TARGET *target, A_UINT32 whichreg, A_UINT32 value) +{ + A_UINT32 window_addr; + HIF_REQUEST request; + A_STATUS status; + A_UINT32 address; + + window_addr = value; + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + + address = getRegAddr(whichreg, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address+1, + (A_UCHAR *)&window_addr+1, 3, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + + status = HIFReadWrite(target->device, address, + (A_UCHAR *)&window_addr, 1, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); +} + +void +HTCStop(HTC_TARGET *target) +{ + A_UINT32 count; + A_STATUS status; + A_UINT32 address; + HIF_REQUEST request; + A_UINT32 window_data; + HTC_ENDPOINT *endPoint; + HTC_REG_REQUEST_LIST *regList; + HTC_REG_REQUEST_ELEMENT *element; + HTC_DATA_REQUEST_QUEUE *sendQueue; + HTC_DATA_REQUEST_QUEUE *recvQueue; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStop: Enter")); + + /* Disable all the dragon interrupts */ + target->table.int_status_enable = 0; + target->table.cpu_int_status_enable = 0; + target->table.error_status_enable = 0; + target->table.counter_int_status_enable = 0; + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.int_status_enable, 4, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + + /* Disable the host controller interrupts */ + HIFMaskInterrupt(target->device); + + /* Flush all the queues and return the buffers to their owner */ + for (count = ENDPOINT1; count <= ENDPOINT4; count ++) { + endPoint = &target->endPoint[count]; + + /* Decrement the number of credits consumed */ + if (endPoint->txCreditsConsumed) { + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, + HIF_SYNCHRONOUS, HIF_BYTE_BASIS, + HIF_FIXED_ADDRESS); + address = getRegAddr(TX_CREDIT_COUNTER_DECREMENT_REG, count); + status = HIFReadWrite(target->device, address, + endPoint->txCreditsAvailable, + endPoint->txCreditsConsumed, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + } + + SET_TX_CREDITS_AVAILABLE(endPoint, 0); + SET_TX_CREDITS_CONSUMED(endPoint, 0); + +#ifdef DEBUG + txcreditsavailable[count] = GET_TX_CREDITS_AVAILABLE(endPoint); + txcreditsconsumed[count] = GET_TX_CREDITS_CONSUMED(endPoint); +#endif + + endPoint->txCreditsIntrEnable = FALSE; + endPoint->rxLengthPending = 0; + endPoint->enabled = FALSE; + + /* Flush the Pending Receive Queue */ + AR_DEBUG_PRINTF(ATH_DEBUG_INF, + ("Flushing the recv queue & returning the buffers\n")); + + recvQueue = &endPoint->recvQueue; + flushMboxQueue(endPoint, recvQueue, HTC_BUFFER_RECEIVED); + + /* Flush the Pending Send Queue */ + AR_DEBUG_PRINTF(ATH_DEBUG_INF, + ("Flushing the send queue & returning the buffers\n")); + sendQueue = &endPoint->sendQueue; + flushMboxQueue(endPoint, sendQueue, HTC_BUFFER_SENT); + } + + /* Clear the tx counters */ + memset(tx_attempt, 0, sizeof(tx_attempt)); + memset(tx_post, 0, sizeof(tx_post)); + memset(tx_complete, 0, sizeof(tx_complete)); + + /* Attempting a force reset of the target */ + window_data = RESET_CONTROL_COLD_RST_MASK; + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + address = getRegAddr(WINDOW_DATA_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_data, + 4, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + + _WRITE_WINDOW_ADDR(target, WINDOW_WRITE_ADDR_REG, RESET_CONTROL_ADDRESS); + + /* + * Read back the RESET CAUSE register to ensure that the cold reset + * went through. + */ + A_MDELAY(2000); /* 2 second delay to allow dragon to settle down */ + _WRITE_WINDOW_ADDR(target, WINDOW_READ_ADDR_REG, RESET_CAUSE_ADDRESS); + + window_data = 0; + HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + address = getRegAddr(WINDOW_DATA_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_data, + 4, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + + AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("window data: %d\n", window_data)); + window_data &= RESET_CAUSE_LAST_MASK; + + if (window_data != 2) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to cold reset the target\n")); + } + + /* + * Ensure that all the pending asynchronous register read/writes have + * been finished. + */ + regList = &target->regList; + for (count = 0; count < HTC_REG_REQUEST_LIST_SIZE; count ++) { + element = ®List->element[count]; + AR_DEBUG_ASSERT(IS_ELEMENT_FREE(element)); + } + + /* Initialize the shadow copy of the target register table */ + A_MEMZERO(&target->table, sizeof(HTC_REGISTER_TABLE)); + target->ready = FALSE; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStop: Exit")); +} + + +void +HTCShutDown(HTC_TARGET *target) +{ + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCShutDown: Enter\n")); + + if (target != NULL) { + HIFShutDownDevice(target->device); + delTargetInstance(target); + A_MEMZERO(target, sizeof(HTC_TARGET)); + A_FREE(target); + } else { + HIFShutDownDevice(NULL); + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCShutDown: Exit\n")); +} Index: linux-2.6.22/drivers/sdio/function/wlan/ar6000/htc/htc_events.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.22/drivers/sdio/function/wlan/ar6000/htc/htc_events.c 2007-11-29 20:54:57.000000000 +0100 @@ -0,0 +1,1056 @@ +/* + * Copyright (c) 2004-2006 Atheros Communications Inc. + * + * Wireless Network driver for Atheros AR6001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * This file contains the routines handling the different events and callbacks + * from the hardware interface layer. + */ + +#include "htc_internal.h" + +/* ------ Global Variable Declarations ------- */ +extern A_MUTEX_T instanceCS, counterCS, creditCS; +extern A_WAITQUEUE_HEAD htcEvent; + +#ifdef DEBUG +extern A_UINT32 debughtc; +extern A_UINT32 txcreditsavailable[HTC_MAILBOX_NUM_MAX]; +extern A_UINT32 txcreditsconsumed[HTC_MAILBOX_NUM_MAX]; +extern A_UINT32 txcreditintrenable[HTC_MAILBOX_NUM_MAX]; +extern A_UINT32 txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX]; +#endif + +extern A_UINT32 tx_complete[HTC_MAILBOX_NUM_MAX]; /* Num of tx complete */ + +/* ------ Static Variables ------ */ + + +/* ------ Functions ------ */ +#ifdef CF +A_STATUS htcInterruptEnabler(HIF_DEVICE *device) { + + A_STATUS status; + A_UINT32 address; + HIF_REQUEST request; + HTC_TARGET *target; + + target = getTargetInstance(device); + AR_DEBUG_ASSERT(target != NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("htcInterruptEnabler Enter target: 0x%p\n", target)); + + target->table.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | + INT_STATUS_ENABLE_CPU_SET(0x01) | + INT_STATUS_ENABLE_COUNTER_SET(0x01) | + INT_STATUS_ENABLE_MBOX_DATA_SET(0x0F); + /* Reenable Dragon Interrupts */ + + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); + address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.int_status_enable, 1, + &request, NULL); + + AR_DEBUG_ASSERT(status == A_OK); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("htcInterruptEnabler Exit\n")); + + return A_OK; +} +#endif /* CF */ + + +A_STATUS +htcRWCompletionHandler(void *context, + A_STATUS status) +{ + HTC_QUEUE_ELEMENT *element; + + element = (HTC_QUEUE_ELEMENT *)context; + AR_DEBUG_ASSERT(element != NULL); + + return(element->completionCB(element, status)); +} + +A_STATUS +htcTxCompletionCB(HTC_DATA_REQUEST_ELEMENT *element, + A_STATUS status) +{ + HTC_TARGET *target; + HTC_ENDPOINT_ID endPointId; + HTC_ENDPOINT *endPoint; + HTC_EVENT_INFO eventInfo; + HTC_MBOX_BUFFER *mboxBuffer; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, + ("htcTxCompletionCB - Enter\n")); + + /* Get the context */ + mboxBuffer = GET_MBOX_BUFFER(element); + AR_DEBUG_ASSERT(mboxBuffer != NULL); + endPoint = mboxBuffer->endPoint; + AR_DEBUG_ASSERT(endPoint != NULL); + target = endPoint->target; + AR_DEBUG_ASSERT(target != NULL); + endPointId = GET_ENDPOINT_ID(endPoint); + + AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_SEND, + ("mboxBuffer: 0x%p, buffer: 0x%p, endPoint(%d): 0x%p, target: 0x%p\n", mboxBuffer, mboxBuffer->buffer, endPointId, endPoint, target)); + + /* Return the buffer to the user if the transmission was not successful */ + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR | ATH_DEBUG_SEND, + ("Frame transmission failed\n")); + AR_DEBUG_PRINTF(ATH_DEBUG_ERR | ATH_DEBUG_SEND, + ("EndPoint: %d, Tx credits available: %d\n", + endPointId, GET_TX_CREDITS_AVAILABLE(endPoint))); + /* + * In the failure case it is possible that while queueing of the + * request itself it returned an error status in which case we + * would have dispatched an event and freed the element there + * itself. Ideally if it failed to queue the request then it + * should not generate a callback but we are being a little + * conservative. + */ + if (!(IS_ELEMENT_FREE(element))) { + mboxBuffer->buffer += HTC_HEADER_LEN; + FRAME_EVENT(eventInfo, mboxBuffer->buffer, + mboxBuffer->bufferLength, mboxBuffer->actualLength, + A_ECANCELED, mboxBuffer->cookie); + RECYCLE_DATA_REQUEST_ELEMENT(element); + dispatchEvent(target, endPointId, HTC_BUFFER_SENT, &eventInfo); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, + ("htcTxCompletionCB - Exit\n")); + } + return A_OK; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_SEND, + ("Frame transmission complete\n")); + + /* + * The user should see the actual length and buffer length + * to be the same. In case of block mode, we use the actual length + * parameter to reflect the total number of bytes transmitted after + * padding. + */ + mboxBuffer->actualLength = mboxBuffer->bufferLength; + mboxBuffer->buffer += HTC_HEADER_LEN; + + /* + * Return the transmit buffer to the user through the HTC_BUFFER_SENT + * event indicating that the frame was transmitted successfully. + */ + FRAME_EVENT(eventInfo, mboxBuffer->buffer, mboxBuffer->bufferLength, + mboxBuffer->actualLength, A_OK, mboxBuffer->cookie); + RECYCLE_DATA_REQUEST_ELEMENT(element); + + tx_complete[endPointId] += 1; + + dispatchEvent(target, endPointId, HTC_BUFFER_SENT, &eventInfo); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, + ("htcTxCompletionCB - Exit\n")); + + return A_OK; +} + +A_STATUS +htcBlkSzNegCompletionCB(HTC_DATA_REQUEST_ELEMENT *element, + A_STATUS status) +{ + HTC_TARGET *target; + HTC_ENDPOINT *endPoint; + HIF_REQUEST request; + HTC_MBOX_BUFFER *mboxBuffer; + HTC_REG_REQUEST_ELEMENT *regElement; + A_UINT32 address; + + /* Get the context */ + mboxBuffer = GET_MBOX_BUFFER(element); + AR_DEBUG_ASSERT(mboxBuffer != NULL); + endPoint = mboxBuffer->endPoint; + AR_DEBUG_ASSERT(endPoint != NULL); + target = endPoint->target; + AR_DEBUG_ASSERT(target != NULL); + + /* Recycle the request element */ + RECYCLE_DATA_REQUEST_ELEMENT(element); + element->completionCB = htcTxCompletionCB; + + if (status == A_OK) { + /* Mark the state to be ready */ + endPoint->enabled = TRUE; + + /* Set the state of the target as ready */ + if (target->endPoint[ENDPOINT1].enabled && + target->endPoint[ENDPOINT2].enabled && + target->endPoint[ENDPOINT3].enabled && + target->endPoint[ENDPOINT4].enabled ) + { + /* Send the INT_WLAN interrupt to the target */ + target->table.int_wlan = 1; + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, + HIF_ASYNCHRONOUS, HIF_BYTE_BASIS, + HIF_FIXED_ADDRESS); + address = getRegAddr(INT_WLAN_REG, ENDPOINT_UNUSED); + regElement = allocateRegRequestElement(target); + AR_DEBUG_ASSERT(regElement != NULL); + FILL_REG_BUFFER(regElement, &target->table.int_wlan, 1, + INT_WLAN_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.int_wlan, + 1, &request, regElement); +#ifndef HTC_SYNC + AR_DEBUG_ASSERT(status == A_OK); +#else + AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); + if(status == A_OK) { + regElement->completionCB(regElement, status); + } +#endif + } + } + + return A_OK; +} + +A_STATUS +htcRxCompletionCB(HTC_DATA_REQUEST_ELEMENT *element, + A_STATUS status) +{ + HTC_TARGET *target; + HTC_ENDPOINT *endPoint; + HTC_EVENT_INFO eventInfo; + HTC_ENDPOINT_ID endPointId; + HTC_MBOX_BUFFER *mboxBuffer; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_SEND, + ("htcRxCompletionCB - Enter\n")); + + /* Get the context */ + mboxBuffer = GET_MBOX_BUFFER(element); + AR_DEBUG_ASSERT(mboxBuffer != NULL); + endPoint = mboxBuffer->endPoint; + AR_DEBUG_ASSERT(endPoint != NULL); + target = endPoint->target; + AR_DEBUG_ASSERT(target != NULL); + endPointId = GET_ENDPOINT_ID(endPoint); + + AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_RECV, + ("mboxBuffer: 0x%p, buffer: 0x%p, endPoint(%d): 0x%p, target: 0x%p\n", mboxBuffer, mboxBuffer->buffer, endPointId, endPoint, target)); + + /* Return the buffer to the user if the reception was not successful */ + if (status != A_OK) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR | ATH_DEBUG_RECV, + ("Frame reception failed\n")); + /* + * In the failure case it is possible that while queueing of the + * request itself it returned an error status in which case we + * would have dispatched an event and freed the element there + * itself. Ideally if it failed to queue the request then it + * should not generate a callback but we are being a little + * conservative. + */ + if (!(IS_ELEMENT_FREE(element))) { + mboxBuffer->actualLength = 0; + mboxBuffer->buffer += HTC_HEADER_LEN; + FRAME_EVENT(eventInfo, mboxBuffer->buffer, + mboxBuffer->bufferLength, mboxBuffer->actualLength, + A_ECANCELED, mboxBuffer->cookie); + RECYCLE_DATA_REQUEST_ELEMENT(element); + dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED, &eventInfo); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_RECV, + ("htcRxCompletionCB - Exit\n")); + } + return A_OK; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_RECV, + ("Frame reception complete\n")); + + AR_DEBUG_PRINTBUF(mboxBuffer->buffer, mboxBuffer->actualLength); + + /* + * Advance the pointer by the size of HTC header and pass the payload + * pointer to the upper layer. + */ + mboxBuffer->actualLength = ((mboxBuffer->buffer[0] << 0) | + (mboxBuffer->buffer[1] << 8)); + mboxBuffer->buffer += HTC_HEADER_LEN; + + /* + * Frame the HTC_BUFFER_RECEIVED to the upper layer indicating that the + * packet has been succesfully received. + */ + FRAME_EVENT(eventInfo, mboxBuffer->buffer, mboxBuffer->bufferLength, + mboxBuffer->actualLength, A_OK, mboxBuffer->cookie); + + /* Recycle the bufferElement structure */ + RECYCLE_DATA_REQUEST_ELEMENT(element); + + /* Dispatch the event */ + dispatchEvent(target, endPointId, HTC_BUFFER_RECEIVED, &eventInfo); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_RECV, + ("htcRxCompletion - Exit\n")); + + return A_OK; +} + +A_STATUS +htcRegCompletionCB(HTC_REG_REQUEST_ELEMENT *element, + A_STATUS status) +{ + A_STATUS ret; + HTC_TARGET *target; + HTC_ENDPOINT *endPoint; + HTC_REG_BUFFER *regBuffer; + A_UINT8 txCreditsConsumed; + A_UINT8 txCreditsAvailable; + HTC_ENDPOINT_ID endPointId; + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC | ATH_DEBUG_RECV | ATH_DEBUG_SEND, + ("htcRegCompletion - Enter\n")); + AR_DEBUG_ASSERT(status == A_OK); + + /* Get the context */ + AR_DEBUG_ASSERT(element != NULL); + regBuffer = GET_REG_BUFFER(element); + AR_DEBUG_ASSERT(regBuffer != NULL); + target = regBuffer->target; + AR_DEBUG_ASSERT(target != NULL); + + /* Identify the register and the operation responsible for the callback */ + ret = A_OK; + switch(regBuffer->base) { + case TX_CREDIT_COUNTER_DECREMENT_REG: + AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("TX_CREDIT_COUNTER_DECREMENT_REG\n")); + endPointId = regBuffer->offset; + endPoint = &target->endPoint[endPointId]; + + AR_DEBUG_PRINTF(ATH_DEBUG_SYNC, + ("Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__)); + A_MUTEX_LOCK(&creditCS); + + /* Calculate the number of credits available */ + AR_DEBUG_ASSERT(GET_TX_CREDITS_CONSUMED(endPoint) == regBuffer->length); + AR_DEBUG_ASSERT(regBuffer->buffer[0] >= + GET_TX_CREDITS_CONSUMED(endPoint)); + SET_TX_CREDITS_AVAILABLE(endPoint, regBuffer->buffer[0] - + GET_TX_CREDITS_CONSUMED(endPoint)); + SET_TX_CREDITS_CONSUMED(endPoint, 0); + txCreditsAvailable = GET_TX_CREDITS_AVAILABLE(endPoint); + txCreditsConsumed = GET_TX_CREDITS_CONSUMED(endPoint); + AR_DEBUG_PRINTF(ATH_DEBUG_SYNC, + ("Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__)); + A_MUTEX_UNLOCK(&creditCS); + + AR_DEBUG_PRINTF(ATH_DEBUG_INF | ATH_DEBUG_SEND, + ("Pulling %d tx credits from the target\n", + txCreditsAvailable)); + +#ifdef DEBUG + txcreditsavailable[endPointId] = txCreditsAvailable; + txcreditsconsumed[endPointId] = txCreditsConsumed; +#endif /* DEBUG */ + + if (txCreditsAvailable) { + htcSendFrame(endPoint); + } else { + /* + * Enable the Tx credit counter interrupt so that we can get the + * credits posted by the target. + */ + htcEnableCreditCounterInterrupt(target, endPointId); + +#ifdef DEBUG + txcreditintrenable[endPointId] += 1; + txcreditintrenableaggregate[endPointId] += 1; +#endif /* DEBUG */ + } + break; + + case TX_CREDIT_COUNTER_RESET_REG: + AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("TX_CREDIT_COUNTER_RESET_REG\n")); + endPointId = regBuffer->offset; + + /* + * Enable the Tx credit counter interrupt so that we can get the + * credits posted by the target. + */ + htcEnableCreditCounterInterrupt(target, endPointId); + +#ifdef DEBUG + txcreditintrenable[endPointId] += 1; + txcreditintrenableaggregate[endPointId] += 1; +#endif /* DEBUG */ + break; + + case COUNTER_INT_STATUS_ENABLE_REG: + AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("COUNTER_INT_STATUS_ENABLE: 0x%x\n", + target->table.counter_int_status_enable)); + break; + + case COUNTER_INT_STATUS_DISABLE_REG: + AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("COUNTER_INT_STATUS_DISABLE:0x%x\n", + target->table.counter_int_status_enable)); + HIFAckInterrupt(target->device); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcDSRHandler - ACK\n")); + break; + + case INT_WLAN_REG: + AR_DEBUG_PRINTF(ATH_DEBUG_INF, ("INT_WLAN: 0x%x\n", + target->table.int_wlan)); + target->table.int_wlan = 0; + + /* Mark the target state as ready and signal the waiting sem */ + target->ready = TRUE; + A_WAKE_UP(&htcEvent); + break; + + case INT_STATUS_ENABLE_REG: + AR_DEBUG_PRINTF(ATH_DEBUG_INF,("INT_STATUS_ENABLE: 0x%x\n", + target->table.int_status_enable)); + break; + + default: + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, + ("Invalid register address: %d\n", regBuffer->base)); + } + + /* Free the register request structure */ + freeRegRequestElement(element); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcRegCompletion - Exit\n")); + + return ret; +} + + +A_STATUS +htcTargetInsertedHandler(HIF_DEVICE *device) +{ + HTC_TARGET *target; + HTC_ENDPOINT *endPoint; + A_UINT8 count1, count2; + HTC_EVENT_INFO eventInfo; + HTC_REG_BUFFER *regBuffer; + HTC_QUEUE_ELEMENT *element; + HTC_MBOX_BUFFER *mboxBuffer; + HTC_REG_REQUEST_LIST *regList; + HTC_DATA_REQUEST_QUEUE *sendQueue, *recvQueue; + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX]; + A_UINT32 blockSize[HTC_MAILBOX_NUM_MAX]; +#ifdef CF + HIF_REQUEST request; + A_STATUS status; + A_UINT32 address; +#endif /* CF */ + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Enter\n")); + + /* Initialize the locks */ + A_MUTEX_INIT(&instanceCS); + A_MUTEX_INIT(&creditCS); + A_MUTEX_INIT(&counterCS); + + /* Allocate target memory */ + if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); + return A_ERROR; + } + A_MEMZERO(target, sizeof(HTC_TARGET)); + target->device = device; + target->ready = FALSE; + + /* Initialize the endpoints, mbox queues, event table */ + for (count1 = ENDPOINT1; count1 <= ENDPOINT4; count1 ++) { + endPoint = &target->endPoint[count1]; + AR_DEBUG_PRINTF(ATH_DEBUG_INF, + ("endPoint[%d]: %p\n", count1, endPoint)); + A_MEMZERO(endPoint->txCreditsAvailable, HTC_TX_CREDITS_NUM_MAX); + endPoint->txCreditsConsumed = 0; + endPoint->txCreditsIntrEnable = FALSE; + endPoint->rxLengthPending = 0; + endPoint->target = target; + endPoint->enabled = FALSE; + for (count2 = 0; count2sendQueue; + sendQueue->head = sendQueue->size = 0; + element = &sendQueue->element[count2]; + A_MEMZERO(element, sizeof(HTC_DATA_REQUEST_ELEMENT)); + element->buffer.free = TRUE; + element->completionCB = htcTxCompletionCB; + mboxBuffer = GET_MBOX_BUFFER(element); + mboxBuffer->endPoint = endPoint; + + /* Receive Queue */ + recvQueue = &endPoint->recvQueue; + recvQueue->head = recvQueue->size = 0; + element = &recvQueue->element[count2]; + A_MEMZERO(element, sizeof(HTC_DATA_REQUEST_ELEMENT)); + element->buffer.free = TRUE; + element->completionCB = htcRxCompletionCB; + mboxBuffer = GET_MBOX_BUFFER(element); + mboxBuffer->endPoint = endPoint; + } + A_MEMZERO(&target->endPoint[count1].eventTable, + sizeof(HTC_ENDPOINT_EVENT_TABLE)); + } + + /* Populate the block size for each of the end points */ + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, + &blockSize, sizeof(blockSize)); + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, + &mboxAddress, sizeof(mboxAddress)); + for (count1 = ENDPOINT1; count1 <= ENDPOINT4; count1 ++) { + endPoint = &target->endPoint[count1]; + endPoint->blockSize = blockSize[count1]; + endPoint->address = mboxAddress[count1]; + } + + /* Initialize the shadow copy of the target register table */ + A_MEMZERO(&target->table, sizeof(HTC_REGISTER_TABLE)); + + /* Initialize the register request list */ + regList = &target->regList; + for (count1 = 0; count1 < HTC_REG_REQUEST_LIST_SIZE; count1 ++) { + element = ®List->element[count1]; + A_MEMZERO(element, sizeof(HTC_REG_REQUEST_ELEMENT)); + element->buffer.free = TRUE; + element->completionCB = htcRegCompletionCB; + regBuffer = GET_REG_BUFFER(element); + regBuffer->target = target; + } + + /* Add the target instance to the global list */ + addTargetInstance(target); +#ifdef CF + /* Disable all the dragon interrupts */ + target->table.int_status_enable = 0; + target->table.cpu_int_status_enable = 0; + target->table.error_status_enable = 0; + target->table.counter_int_status_enable = 0; + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.int_status_enable, 4, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); +#endif /* CF */ + + /* + * Frame a TARGET_AVAILABLE event and send it to the host. Return the + * HIF_DEVICE handle as a parameter with the event. + */ + FRAME_EVENT(eventInfo, (A_UCHAR *)device, sizeof(HIF_DEVICE *), + sizeof(HIF_DEVICE *), A_OK, NULL); + dispatchEvent(target, ENDPOINT_UNUSED, HTC_TARGET_AVAILABLE, &eventInfo); + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Exit\n")); + + return A_OK; +} + +A_STATUS +htcTargetRemovedHandler(HIF_DEVICE *device) +{ + HTC_TARGET *target; + HTC_EVENT_INFO eventInfo; + + /* Get the target instance bound to this device */ + target = getTargetInstance(device); + + if (target != NULL) { + /* Frame a TARGET_UNAVAILABLE event and send it to the host */ + FRAME_EVENT(eventInfo, NULL, 0, 0, A_OK, NULL); + dispatchEvent(target, ENDPOINT_UNUSED, HTC_TARGET_UNAVAILABLE, + &eventInfo); + } + + return A_OK; +} + + +#ifdef CF +A_STATUS +htcInterruptDisabler(HIF_DEVICE *device,A_BOOL *callDsr) +{ + A_STATUS status; + A_UINT32 address; + HTC_TARGET *target; + HIF_REQUEST request; + + target = getTargetInstance(device); + AR_DEBUG_ASSERT(target != NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("htcInterruptDisabler Enter target: 0x%p\n", target)); + + HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); + address = getRegAddr(INT_STATUS_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.host_int_status, 1, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + + /* Handle Suprise removal of CF card. Upon removal of the card the + * host_int_status reads 0xFF + */ + if (target->table.host_int_status == 0xFF) { + *callDsr=FALSE; + return A_OK; + } + + if ((target->table.int_status_enable & target->table.host_int_status) == 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("htcInterruptDisabler: MisRouted / Spurious interrupt : 0x%p\n", target)); + *callDsr=FALSE; + } else { + /* + * Disable the interrupts from Dragon. + * We do the interrupt servicing in the bottom half and reenable the + * Dragon interrupts at the end of the bottom-half + */ + + target->table.int_status_enable = 0; + HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); + address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.int_status_enable, 1, &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + *callDsr=TRUE; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcInterruptDisabler: Exit\n")); + return A_OK; +} +#endif /* CF */ + +A_STATUS +htcDSRHandler(HIF_DEVICE *device) +{ + A_STATUS status; + A_UINT32 address; + HTC_TARGET *target; + HIF_REQUEST request; + A_UCHAR host_int_status; + + target = getTargetInstance(device); + AR_DEBUG_ASSERT(target != NULL); + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, + ("htcDsrHandler: Enter (target: 0x%p\n", target)); + + /* + * 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); + */ + HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, + HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); + address = getRegAddr(INT_STATUS_REG, ENDPOINT_UNUSED); + status = HIFReadWrite(target->device, address, + &target->table.host_int_status, 28, + &request, NULL); + AR_DEBUG_ASSERT(status == A_OK); + +#ifdef DEBUG + dumpRegisters(target); +#endif /* DEBUG */ +#ifdef CF + /* Update only those registers that are enabled */ + /* This is not required as we have already checked for spurious interrupt + * in htcInterruptDisabler + */ + + host_int_status = target->table.host_int_status; +#else + /* Update only those registers that are enabled */ + host_int_status = target->table.host_int_status & + target->table.int_status_enable; +#endif /* CF */ + + AR_DEBUG_ASSERT(host_int_status); + AR_DEBUG_PRINTF(ATH_DEBUG_INF, + ("Valid interrupt source(s) in INT_STATUS: 0x%x\n", +