/drivers/staging/ath6kl/os/linux/ar6000_drv.c
https://bitbucket.org/wisechild/galaxy-nexus · C · 6260 lines · 4727 code · 967 blank · 566 comment · 964 complexity · ec75dce87d28aa6f7e4b128a4c77e336 MD5 · raw file
Large files are truncated click here to view the full file
- //------------------------------------------------------------------------------
- // Copyright (c) 2004-2010 Atheros Communications Inc.
- // All rights reserved.
- //
- //
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- //
- //
- //
- // Author(s): ="Atheros"
- //------------------------------------------------------------------------------
- /*
- * This driver is a pseudo ethernet driver to access the Atheros AR6000
- * WLAN Device
- */
- #include "ar6000_drv.h"
- #include "cfg80211.h"
- #include "htc.h"
- #include "wmi_filter_linux.h"
- #include "epping_test.h"
- #include "wlan_config.h"
- #include "ar3kconfig.h"
- #include "ar6k_pal.h"
- #include "AR6002/addrs.h"
- /* LINUX_HACK_FUDGE_FACTOR -- this is used to provide a workaround for linux behavior. When
- * the meta data was added to the header it was found that linux did not correctly provide
- * enough headroom. However when more headroom was requested beyond what was truly needed
- * Linux gave the requested headroom. Therefore to get the necessary headroom from Linux
- * the driver requests more than is needed by the amount = LINUX_HACK_FUDGE_FACTOR */
- #define LINUX_HACK_FUDGE_FACTOR 16
- #define BDATA_BDADDR_OFFSET 28
- u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- #ifdef DEBUG
- #define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0)
- #define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1)
- #define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2)
- #define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3)
- #define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4)
- #define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5)
- #define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6)
- static struct ath_debug_mask_description driver_debug_desc[] = {
- { ATH_DEBUG_DBG_LOG , "Target Debug Logs"},
- { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"},
- { ATH_DEBUG_WLAN_SCAN , "WLAN scan"},
- { ATH_DEBUG_WLAN_TX , "WLAN Tx"},
- { ATH_DEBUG_WLAN_RX , "WLAN Rx"},
- { ATH_DEBUG_HTC_RAW , "HTC Raw IF tracing"},
- { ATH_DEBUG_HCI_BRIDGE , "HCI Bridge Setup"},
- { ATH_DEBUG_HCI_RECV , "HCI Recv tracing"},
- { ATH_DEBUG_HCI_DUMP , "HCI Packet dumps"},
- };
- ATH_DEBUG_INSTANTIATE_MODULE_VAR(driver,
- "driver",
- "Linux Driver Interface",
- ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_WLAN_SCAN |
- ATH_DEBUG_HCI_BRIDGE,
- ATH_DEBUG_DESCRIPTION_COUNT(driver_debug_desc),
- driver_debug_desc);
- #endif
- #define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && mac[4]==0 && mac[5]==0)
- #define IS_MAC_BCAST(mac) (*mac==0xff)
- #define DESCRIPTION "Driver to access the Atheros AR600x Device, version " __stringify(__VER_MAJOR_) "." __stringify(__VER_MINOR_) "." __stringify(__VER_PATCH_) "." __stringify(__BUILD_NUMBER_)
- MODULE_AUTHOR("Atheros Communications, Inc.");
- MODULE_DESCRIPTION(DESCRIPTION);
- MODULE_LICENSE("Dual BSD/GPL");
- #ifndef REORG_APTC_HEURISTICS
- #undef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- #endif /* REORG_APTC_HEURISTICS */
- #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- #define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */
- #define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */
- #define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */
- typedef struct aptc_traffic_record {
- bool timerScheduled;
- struct timeval samplingTS;
- unsigned long bytesReceived;
- unsigned long bytesTransmitted;
- } APTC_TRAFFIC_RECORD;
- A_TIMER aptcTimer;
- APTC_TRAFFIC_RECORD aptcTR;
- #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- #ifdef EXPORT_HCI_BRIDGE_INTERFACE
- // callbacks registered by HCI transport driver
- struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL };
- #endif
- unsigned int processDot11Hdr = 0;
- char ifname[IFNAMSIZ] = {0,};
- int wlaninitmode = WLAN_INIT_MODE_DEFAULT;
- static bool bypasswmi;
- unsigned int debuglevel = 0;
- int tspecCompliance = ATHEROS_COMPLIANCE;
- unsigned int busspeedlow = 0;
- unsigned int onebitmode = 0;
- unsigned int skipflash = 0;
- unsigned int wmitimeout = 2;
- unsigned int wlanNodeCaching = 1;
- unsigned int enableuartprint = ENABLEUARTPRINT_DEFAULT;
- unsigned int logWmiRawMsgs = 0;
- unsigned int enabletimerwar = 0;
- unsigned int num_device = 1;
- unsigned int regscanmode;
- unsigned int fwmode = 1;
- unsigned int mbox_yield_limit = 99;
- unsigned int enablerssicompensation = 0;
- int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF;
- int allow_trace_signal = 0;
- #ifdef CONFIG_HOST_TCMD_SUPPORT
- unsigned int testmode =0;
- #endif
- unsigned int irqprocmode = HIF_DEVICE_IRQ_SYNC_ONLY;//HIF_DEVICE_IRQ_ASYNC_SYNC;
- unsigned int panic_on_assert = 1;
- unsigned int nohifscattersupport = NOHIFSCATTERSUPPORT_DEFAULT;
- unsigned int setuphci = SETUPHCI_DEFAULT;
- unsigned int loghci = 0;
- unsigned int setupbtdev = SETUPBTDEV_DEFAULT;
- #ifndef EXPORT_HCI_BRIDGE_INTERFACE
- unsigned int ar3khcibaud = AR3KHCIBAUD_DEFAULT;
- unsigned int hciuartscale = HCIUARTSCALE_DEFAULT;
- unsigned int hciuartstep = HCIUARTSTEP_DEFAULT;
- #endif
- unsigned int csumOffload=0;
- unsigned int csumOffloadTest=0;
- unsigned int eppingtest=0;
- unsigned int mac_addr_method;
- unsigned int firmware_bridge;
- module_param_string(ifname, ifname, sizeof(ifname), 0644);
- module_param(wlaninitmode, int, 0644);
- module_param(bypasswmi, bool, 0644);
- module_param(debuglevel, uint, 0644);
- module_param(tspecCompliance, int, 0644);
- module_param(onebitmode, uint, 0644);
- module_param(busspeedlow, uint, 0644);
- module_param(skipflash, uint, 0644);
- module_param(wmitimeout, uint, 0644);
- module_param(wlanNodeCaching, uint, 0644);
- module_param(logWmiRawMsgs, uint, 0644);
- module_param(enableuartprint, uint, 0644);
- module_param(enabletimerwar, uint, 0644);
- module_param(fwmode, uint, 0644);
- module_param(mbox_yield_limit, uint, 0644);
- module_param(reduce_credit_dribble, int, 0644);
- module_param(allow_trace_signal, int, 0644);
- module_param(enablerssicompensation, uint, 0644);
- module_param(processDot11Hdr, uint, 0644);
- module_param(csumOffload, uint, 0644);
- #ifdef CONFIG_HOST_TCMD_SUPPORT
- module_param(testmode, uint, 0644);
- #endif
- module_param(irqprocmode, uint, 0644);
- module_param(nohifscattersupport, uint, 0644);
- module_param(panic_on_assert, uint, 0644);
- module_param(setuphci, uint, 0644);
- module_param(loghci, uint, 0644);
- module_param(setupbtdev, uint, 0644);
- #ifndef EXPORT_HCI_BRIDGE_INTERFACE
- module_param(ar3khcibaud, uint, 0644);
- module_param(hciuartscale, uint, 0644);
- module_param(hciuartstep, uint, 0644);
- #endif
- module_param(eppingtest, uint, 0644);
- /* in 2.6.10 and later this is now a pointer to a uint */
- unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX;
- #define mboxnum &_mboxnum
- #ifdef DEBUG
- u32 g_dbg_flags = DBG_DEFAULTS;
- unsigned int debugflags = 0;
- int debugdriver = 0;
- unsigned int debughtc = 0;
- unsigned int debugbmi = 0;
- unsigned int debughif = 0;
- unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0};
- unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0};
- unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0};
- unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0};
- module_param(debugflags, uint, 0644);
- module_param(debugdriver, int, 0644);
- module_param(debughtc, uint, 0644);
- module_param(debugbmi, uint, 0644);
- module_param(debughif, uint, 0644);
- module_param_array(txcreditsavailable, uint, mboxnum, 0644);
- module_param_array(txcreditsconsumed, uint, mboxnum, 0644);
- module_param_array(txcreditintrenable, uint, mboxnum, 0644);
- module_param_array(txcreditintrenableaggregate, uint, mboxnum, 0644);
- #endif /* DEBUG */
- unsigned int resetok = 1;
- unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0};
- unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0};
- unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0};
- unsigned int hifBusRequestNumMax = 40;
- unsigned int war23838_disabled = 0;
- #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- unsigned int enableAPTCHeuristics = 1;
- #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- module_param_array(tx_attempt, uint, mboxnum, 0644);
- module_param_array(tx_post, uint, mboxnum, 0644);
- module_param_array(tx_complete, uint, mboxnum, 0644);
- module_param(hifBusRequestNumMax, uint, 0644);
- module_param(war23838_disabled, uint, 0644);
- module_param(resetok, uint, 0644);
- #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- module_param(enableAPTCHeuristics, uint, 0644);
- #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- #ifdef BLOCK_TX_PATH_FLAG
- int blocktx = 0;
- module_param(blocktx, int, 0644);
- #endif /* BLOCK_TX_PATH_FLAG */
- typedef struct user_rssi_compensation_t {
- u16 customerID;
- union {
- u16 a_enable;
- u16 bg_enable;
- u16 enable;
- };
- s16 bg_param_a;
- s16 bg_param_b;
- s16 a_param_a;
- s16 a_param_b;
- u32 reserved;
- } USER_RSSI_CPENSATION;
- static USER_RSSI_CPENSATION rssi_compensation_param;
- static s16 rssi_compensation_table[96];
- int reconnect_flag = 0;
- static ar6k_pal_config_t ar6k_pal_config_g;
- /* Function declarations */
- static int ar6000_init_module(void);
- static void ar6000_cleanup_module(void);
- int ar6000_init(struct net_device *dev);
- static int ar6000_open(struct net_device *dev);
- static int ar6000_close(struct net_device *dev);
- static void ar6000_init_control_info(struct ar6_softc *ar);
- static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
- void ar6000_destroy(struct net_device *dev, unsigned int unregister);
- static void ar6000_detect_error(unsigned long ptr);
- static void ar6000_set_multicast_list(struct net_device *dev);
- static struct net_device_stats *ar6000_get_stats(struct net_device *dev);
- static void disconnect_timer_handler(unsigned long ptr);
- void read_rssi_compensation_param(struct ar6_softc *ar);
- /*
- * HTC service connection handlers
- */
- static int ar6000_avail_ev(void *context, void *hif_handle);
- static int ar6000_unavail_ev(void *context, void *hif_handle);
- int ar6000_configure_target(struct ar6_softc *ar);
- static void ar6000_target_failure(void *Instance, int Status);
- static void ar6000_rx(void *Context, struct htc_packet *pPacket);
- static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
- static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets);
- static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket);
- static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num);
- static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf);
- //static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf);
- static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length);
- static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count);
- static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar);
- static ssize_t
- ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count);
- static ssize_t
- ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count);
- static int
- ar6000_sysfs_bmi_init(struct ar6_softc *ar);
- void ar6k_cleanup_hci_pal(struct ar6_softc *ar);
- static void
- ar6000_sysfs_bmi_deinit(struct ar6_softc *ar);
- int
- ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode);
- /*
- * Static variables
- */
- struct net_device *ar6000_devices[MAX_AR6000];
- static int is_netdev_registered;
- DECLARE_WAIT_QUEUE_HEAD(arEvent);
- static void ar6000_cookie_init(struct ar6_softc *ar);
- static void ar6000_cookie_cleanup(struct ar6_softc *ar);
- static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie);
- static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar);
- static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl);
- #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
- struct net_device *arApNetDev;
- #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
- static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM];
- #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
- (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))
- static struct net_device_ops ar6000_netdev_ops = {
- .ndo_init = NULL,
- .ndo_open = ar6000_open,
- .ndo_stop = ar6000_close,
- .ndo_get_stats = ar6000_get_stats,
- .ndo_start_xmit = ar6000_data_tx,
- .ndo_set_multicast_list = ar6000_set_multicast_list,
- };
- /* Debug log support */
- /*
- * Flag to govern whether the debug logs should be parsed in the kernel
- * or reported to the application.
- */
- #define REPORT_DEBUG_LOGS_TO_APP
- int
- ar6000_set_host_app_area(struct ar6_softc *ar)
- {
- u32 address, data;
- struct host_app_area_s host_app_area;
- /* Fetch the address of the host_app_area_s instance in the host interest area */
- address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest));
- if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) {
- return A_ERROR;
- }
- address = TARG_VTOP(ar->arTargetType, data);
- host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
- if (ar6000_WriteDataDiag(ar->arHifDevice, address,
- (u8 *)&host_app_area,
- sizeof(struct host_app_area_s)) != 0)
- {
- return A_ERROR;
- }
- return 0;
- }
- u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar)
- {
- u32 param;
- u32 address;
- int status;
- address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr));
- if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
- (u8 *)¶m, 4)) != 0)
- {
- param = 0;
- }
- return param;
- }
- /*
- * The dbglog module has been initialized. Its ok to access the relevant
- * data stuctures over the diagnostic window.
- */
- void
- ar6000_dbglog_init_done(struct ar6_softc *ar)
- {
- ar->dbglog_init_done = true;
- }
- u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit)
- {
- s32 *buffer;
- u32 count;
- u32 numargs;
- u32 length;
- u32 fraglen;
- count = fraglen = 0;
- buffer = (s32 *)datap;
- length = (limit >> 2);
- if (len <= limit) {
- fraglen = len;
- } else {
- while (count < length) {
- numargs = DBGLOG_GET_NUMARGS(buffer[count]);
- fraglen = (count << 2);
- count += numargs + 1;
- }
- }
- return fraglen;
- }
- void
- dbglog_parse_debug_logs(s8 *datap, u32 len)
- {
- s32 *buffer;
- u32 count;
- u32 timestamp;
- u32 debugid;
- u32 moduleid;
- u32 numargs;
- u32 length;
- count = 0;
- buffer = (s32 *)datap;
- length = (len >> 2);
- while (count < length) {
- debugid = DBGLOG_GET_DBGID(buffer[count]);
- moduleid = DBGLOG_GET_MODULEID(buffer[count]);
- numargs = DBGLOG_GET_NUMARGS(buffer[count]);
- timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]);
- switch (numargs) {
- case 0:
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d)\n", moduleid, debugid, timestamp));
- break;
- case 1:
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x\n", moduleid, debugid,
- timestamp, buffer[count+1]));
- break;
- case 2:
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid,
- timestamp, buffer[count+1], buffer[count+2]));
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid args: %d\n", numargs));
- }
- count += numargs + 1;
- }
- }
- int
- ar6000_dbglog_get_debug_logs(struct ar6_softc *ar)
- {
- u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */
- u32 address;
- u32 length;
- u32 dropped;
- u32 firstbuf;
- u32 debug_hdr_ptr;
- if (!ar->dbglog_init_done) return A_ERROR;
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- if (ar->dbgLogFetchInProgress) {
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- return A_EBUSY;
- }
- /* block out others */
- ar->dbgLogFetchInProgress = true;
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar);
- printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr);
- /* Get the contents of the ring buffer */
- if (debug_hdr_ptr) {
- address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr);
- length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */;
- A_MEMZERO(data, sizeof(data));
- ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length);
- address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */);
- firstbuf = address;
- dropped = data[1]; /* dropped */
- length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
- A_MEMZERO(data, sizeof(data));
- ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length);
- do {
- address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/);
- length = data[3]; /* length */
- if ((length) && (length <= data[2] /* bufsize*/)) {
- /* Rewind the index if it is about to overrun the buffer */
- if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
- ar->log_cnt = 0;
- }
- if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
- (u8 *)&ar->log_buffer[ar->log_cnt], length))
- {
- break;
- }
- ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length);
- ar->log_cnt += length;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n",
- data[3], data[2]));
- }
- address = TARG_VTOP(ar->arTargetType, data[0] /* next */);
- length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
- A_MEMZERO(data, sizeof(data));
- if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
- (u8 *)&data, length))
- {
- break;
- }
- } while (address != firstbuf);
- }
- ar->dbgLogFetchInProgress = false;
- return 0;
- }
- void
- ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
- s8 *buffer, u32 length)
- {
- #ifdef REPORT_DEBUG_LOGS_TO_APP
- #define MAX_WIRELESS_EVENT_SIZE 252
- /*
- * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages.
- * There seems to be a limitation on the length of message that could be
- * transmitted to the user app via this mechanism.
- */
- u32 send, sent;
- sent = 0;
- send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
- MAX_WIRELESS_EVENT_SIZE);
- while (send) {
- sent += send;
- send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
- MAX_WIRELESS_EVENT_SIZE);
- }
- #else
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Dropped logs: 0x%x\nDebug info length: %d\n",
- dropped, length));
- /* Interpret the debug logs */
- dbglog_parse_debug_logs((s8 *)buffer, length);
- #endif /* REPORT_DEBUG_LOGS_TO_APP */
- }
- static int __init
- ar6000_init_module(void)
- {
- static int probed = 0;
- int r;
- OSDRV_CALLBACKS osdrvCallbacks;
- a_module_debug_support_init();
- #ifdef DEBUG
- /* check for debug mask overrides */
- if (debughtc != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(htc,debughtc);
- }
- if (debugbmi != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(bmi,debugbmi);
- }
- if (debughif != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(hif,debughif);
- }
- if (debugdriver != 0) {
- ATH_DEBUG_SET_DEBUG_MASK(driver,debugdriver);
- }
- #endif
- A_REGISTER_MODULE_DEBUG_INFO(driver);
- A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks));
- osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev;
- osdrvCallbacks.deviceRemovedHandler = ar6000_unavail_ev;
- #ifdef CONFIG_PM
- osdrvCallbacks.deviceSuspendHandler = ar6000_suspend_ev;
- osdrvCallbacks.deviceResumeHandler = ar6000_resume_ev;
- osdrvCallbacks.devicePowerChangeHandler = ar6000_power_change_ev;
- #endif
- #ifdef DEBUG
- /* Set the debug flags if specified at load time */
- if(debugflags != 0)
- {
- g_dbg_flags = debugflags;
- }
- #endif
- if (probed) {
- return -ENODEV;
- }
- probed++;
- #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD));
- #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- r = HIFInit(&osdrvCallbacks);
- if (r)
- return r;
- return 0;
- }
- static void __exit
- ar6000_cleanup_module(void)
- {
- int i = 0;
- struct net_device *ar6000_netdev;
- #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- /* Delete the Adaptive Power Control timer */
- if (timer_pending(&aptcTimer)) {
- del_timer_sync(&aptcTimer);
- }
- #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- for (i=0; i < MAX_AR6000; i++) {
- if (ar6000_devices[i] != NULL) {
- ar6000_netdev = ar6000_devices[i];
- ar6000_devices[i] = NULL;
- ar6000_destroy(ar6000_netdev, 1);
- }
- }
- HIFShutDownDevice(NULL);
- a_module_debug_support_cleanup();
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_cleanup: success\n"));
- }
- #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
- void
- aptcTimerHandler(unsigned long arg)
- {
- u32 numbytes;
- u32 throughput;
- struct ar6_softc *ar;
- int status;
- ar = (struct ar6_softc *)arg;
- A_ASSERT(ar != NULL);
- A_ASSERT(!timer_pending(&aptcTimer));
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- /* Get the number of bytes transferred */
- numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
- aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
- /* Calculate and decide based on throughput thresholds */
- throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
- if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
- /* Enable Sleep and delete the timer */
- A_ASSERT(ar->arWmiReady == true);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- A_ASSERT(status == 0);
- aptcTR.timerScheduled = false;
- } else {
- A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
- }
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- }
- #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
- static void
- ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num)
- {
- void * osbuf;
- while(num) {
- if((osbuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE))) {
- A_NETBUF_ENQUEUE(q, osbuf);
- } else {
- break;
- }
- num--;
- }
- if(num) {
- A_PRINTF("%s(), allocation of netbuf failed", __func__);
- }
- }
- static struct bin_attribute bmi_attr = {
- .attr = {.name = "bmi", .mode = 0600},
- .read = ar6000_sysfs_bmi_read,
- .write = ar6000_sysfs_bmi_write,
- };
- static ssize_t
- ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count)
- {
- int index;
- struct ar6_softc *ar;
- struct hif_device_os_device_info *osDevInfo;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count));
- for (index=0; index < MAX_AR6000; index++) {
- ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
- osDevInfo = &ar->osDevInfo;
- if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
- break;
- }
- }
- if (index == MAX_AR6000) return 0;
- if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) {
- return 0;
- }
- return count;
- }
- static ssize_t
- ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buf, loff_t pos, size_t count)
- {
- int index;
- struct ar6_softc *ar;
- struct hif_device_os_device_info *osDevInfo;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count));
- for (index=0; index < MAX_AR6000; index++) {
- ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
- osDevInfo = &ar->osDevInfo;
- if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
- break;
- }
- }
- if (index == MAX_AR6000) return 0;
- if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) {
- return 0;
- }
- return count;
- }
- static int
- ar6000_sysfs_bmi_init(struct ar6_softc *ar)
- {
- int status;
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n"));
- A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info));
- /* Get the underlying OS device */
- status = HIFConfigureDevice(ar->arHifDevice,
- HIF_DEVICE_GET_OS_DEVICE,
- &ar->osDevInfo,
- sizeof(struct hif_device_os_device_info));
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n"));
- return A_ERROR;
- }
- /* Create a bmi entry in the sysfs filesystem */
- if ((sysfs_create_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr)) < 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to create entry for bmi in sysfs filesystem\n"));
- return A_ERROR;
- }
- return 0;
- }
- static void
- ar6000_sysfs_bmi_deinit(struct ar6_softc *ar)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n"));
- sysfs_remove_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &bmi_attr);
- }
- #define bmifn(fn) do { \
- if ((fn) < 0) { \
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \
- return A_ERROR; \
- } \
- } while(0)
- #ifdef SOFTMAC_FILE_USED
- #define AR6002_MAC_ADDRESS_OFFSET 0x0A
- #define AR6003_MAC_ADDRESS_OFFSET 0x16
- static
- void calculate_crc(u32 TargetType, u8 *eeprom_data)
- {
- u16 *ptr_crc;
- u16 *ptr16_eeprom;
- u16 checksum;
- u32 i;
- u32 eeprom_size;
- if (TargetType == TARGET_TYPE_AR6001)
- {
- eeprom_size = 512;
- ptr_crc = (u16 *)eeprom_data;
- }
- else if (TargetType == TARGET_TYPE_AR6003)
- {
- eeprom_size = 1024;
- ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
- }
- else
- {
- eeprom_size = 768;
- ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
- }
- // Clear the crc
- *ptr_crc = 0;
- // Recalculate new CRC
- checksum = 0;
- ptr16_eeprom = (u16 *)eeprom_data;
- for (i = 0;i < eeprom_size; i += 2)
- {
- checksum = checksum ^ (*ptr16_eeprom);
- ptr16_eeprom++;
- }
- checksum = 0xFFFF ^ checksum;
- *ptr_crc = checksum;
- }
- static void
- ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size)
- {
- const char *source = "random generated";
- const struct firmware *softmac_entry;
- u8 *ptr_mac;
- switch (ar->arTargetType) {
- case TARGET_TYPE_AR6002:
- ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET);
- break;
- case TARGET_TYPE_AR6003:
- ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET);
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n"));
- return;
- }
- printk(KERN_DEBUG "MAC from EEPROM %pM\n", ptr_mac);
- /* create a random MAC in case we cannot read file from system */
- ptr_mac[0] = 0;
- ptr_mac[1] = 0x03;
- ptr_mac[2] = 0x7F;
- ptr_mac[3] = random32() & 0xff;
- ptr_mac[4] = random32() & 0xff;
- ptr_mac[5] = random32() & 0xff;
- if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0)
- {
- char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1);
- if (macbuf) {
- unsigned int softmac[6];
- memcpy(macbuf, softmac_entry->data, softmac_entry->size);
- macbuf[softmac_entry->size] = '\0';
- if (sscanf(macbuf, "%02x:%02x:%02x:%02x:%02x:%02x",
- &softmac[0], &softmac[1], &softmac[2],
- &softmac[3], &softmac[4], &softmac[5])==6) {
- int i;
- for (i=0; i<6; ++i) {
- ptr_mac[i] = softmac[i] & 0xff;
- }
- source = "softmac file";
- }
- kfree(macbuf);
- }
- A_RELEASE_FIRMWARE(softmac_entry);
- }
- printk(KERN_DEBUG "MAC from %s %pM\n", source, ptr_mac);
- calculate_crc(ar->arTargetType, eeprom_data);
- }
- #endif /* SOFTMAC_FILE_USED */
- static int
- ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed)
- {
- int status;
- const char *filename;
- const struct firmware *fw_entry;
- u32 fw_entry_size;
- u8 **buf;
- size_t *buf_len;
- switch (file) {
- case AR6K_OTP_FILE:
- buf = &ar->fw_otp;
- buf_len = &ar->fw_otp_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_OTP_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_OTP_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_OTP_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- break;
- case AR6K_FIRMWARE_FILE:
- buf = &ar->fw;
- buf_len = &ar->fw_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
-
- if (eppingtest) {
- bypasswmi = true;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_EPPING_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_EPPING_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_EPPING_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("eppingtest : unsupported firmware revision: %d\n",
- ar->arVersion.target_ver));
- return A_ERROR;
- }
- compressed = false;
- }
-
- #ifdef CONFIG_HOST_TCMD_SUPPORT
- if(testmode) {
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_TCMD_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- compressed = false;
- }
- #endif
- #ifdef HTC_RAW_INTERFACE
- if (!eppingtest && bypasswmi) {
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_ART_FIRMWARE_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_ART_FIRMWARE_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- compressed = false;
- }
- #endif
- break;
- case AR6K_PATCH_FILE:
- buf = &ar->fw_patch;
- buf_len = &ar->fw_patch_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_PATCH_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_PATCH_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_PATCH_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- break;
- case AR6K_BOARD_DATA_FILE:
- buf = &ar->fw_data;
- buf_len = &ar->fw_data_len;
- if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
- filename = AR6003_REV1_BOARD_DATA_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- filename = AR6003_REV2_BOARD_DATA_FILE;
- } else if (ar->arVersion.target_ver == AR6003_REV3_VERSION) {
- filename = AR6003_REV3_BOARD_DATA_FILE;
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
- return A_ERROR;
- }
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown file type: %d\n", file));
- return A_ERROR;
- }
- if (*buf == NULL) {
- if ((A_REQUEST_FIRMWARE(&fw_entry, filename, ((struct device *)ar->osDevInfo.pOSDevice))) != 0) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to get %s\n", filename));
- return A_ENOENT;
- }
- *buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- *buf_len = fw_entry->size;
- A_RELEASE_FIRMWARE(fw_entry);
- }
- #ifdef SOFTMAC_FILE_USED
- if (file==AR6K_BOARD_DATA_FILE && *buf_len) {
- ar6000_softmac_update(ar, *buf, *buf_len);
- }
- #endif
- fw_entry_size = *buf_len;
- /* Load extended board data for AR6003 */
- if ((file==AR6K_BOARD_DATA_FILE) && *buf) {
- u32 board_ext_address;
- u32 board_ext_data_size;
- u32 board_data_size;
- board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0));
- board_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_DATA_SZ : \
- (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0));
-
- /* Determine where in Target RAM to write Board Data */
- bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address));
- /* check whether the target has allocated memory for extended board data and file contains extended board data */
- if ((board_ext_address) && (*buf_len == (board_data_size + board_ext_data_size))) {
- u32 param;
- status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(*buf + board_data_size), board_ext_data_size);
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
- return A_ERROR;
- }
- /* Record the fact that extended board Data IS initialized */
- param = (board_ext_data_size << 16) | 1;
- bmifn(BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_config),
- (unsigned char *)¶m, 4));
- }
- fw_entry_size = board_data_size;
- }
- if (compressed) {
- status = BMIFastDownload(ar->arHifDevice, address, *buf, fw_entry_size);
- } else {
- status = BMIWriteMemory(ar->arHifDevice, address, *buf, fw_entry_size);
- }
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
- return A_ERROR;
- }
- return 0;
- }
- int
- ar6000_update_bdaddr(struct ar6_softc *ar)
- {
- if (setupbtdev != 0) {
- u32 address;
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n"));
- return A_ERROR;
- }
- if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n", ar->bdaddr[0],
- ar->bdaddr[1], ar->bdaddr[2], ar->bdaddr[3],
- ar->bdaddr[4], ar->bdaddr[5]));
- }
- return 0;
- }
- int
- ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n"));
- if (mode == WLAN_INIT_MODE_UDEV) {
- char version[16];
- const struct firmware *fw_entry;
- /* Get config using udev through a script in user space */
- sprintf(version, "%2.2x", ar->arVersion.target_ver);
- if ((A_REQUEST_FIRMWARE(&fw_entry, version, ((struct device *)ar->osDevInfo.pOSDevice))) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get configuration for target version: %s\n", version));
- return A_ERROR;
- }
- A_RELEASE_FIRMWARE(fw_entry);
- } else {
- /* The config is contained within the driver itself */
- int status;
- u32 param, options, sleep, address;
- /* Temporarily disable system sleep */
- address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m));
- options = param;
- param |= AR6K_OPTION_SLEEP_DISABLE;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m));
- sleep = param;
- param |= WLAN_SYSTEM_SLEEP_DISABLE_SET(1);
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("old options: %d, old sleep: %d\n", options, sleep));
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* Program analog PLL register */
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, ANALOG_INTF_BASE_ADDRESS + 0x284, 0xF9104001));
- /* Run at 80/88MHz by default */
- param = CPU_CLOCK_STANDARD_SET(1);
- } else {
- /* Run at 40/44MHz by default */
- param = CPU_CLOCK_STANDARD_SET(0);
- }
- address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- param = 0;
- if (ar->arTargetType == TARGET_TYPE_AR6002) {
- bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4));
- }
- /* LPO_CAL.ENABLE = 1 if no external clk is detected */
- if (param != 1) {
- address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
- param = LPO_CAL_ENABLE_SET(1);
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
- /* Venus2.0: Lower SDIO pad drive strength,
- * temporary WAR to avoid SDIO CRC error */
- if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6K: Temporary WAR to avoid SDIO CRC error\n"));
- param = 0x20;
- address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
- #ifdef FORCE_INTERNAL_CLOCK
- /* Ignore external clock, if any, and force use of internal clock */
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* hi_ext_clk_detected = 0 */
- param = 0;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)¶m, 4));
- /* CLOCK_CONTROL &= ~LF_CLK32 */
- address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m));
- param &= (~CLOCK_CONTROL_LF_CLK32_SET(1));
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
- #endif /* FORCE_INTERNAL_CLOCK */
- /* Transfer Board Data from Target EEPROM to Target RAM */
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* Determine where in Target RAM to write Board Data */
- bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4));
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address));
- /* Write EEPROM data to Target RAM */
- if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) {
- return A_ERROR;
- }
- /* Record the fact that Board Data IS initialized */
- param = 1;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)¶m, 4));
- /* Transfer One time Programmable data */
- AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver);
- if (ar->arVersion.target_ver == AR6003_REV3_VERSION)
- address = 0x1234;
- status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true);
- if (status == 0) {
- /* Execute the OTP code */
- param = 0;
- AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver);
- bmifn(BMIExecute(ar->arHifDevice, address, ¶m));
- } else if (status != A_ENOENT) {
- return A_ERROR;
- }
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Programming of board data for chip %d not supported\n", ar->arTargetType));
- return A_ERROR;
- }
- /* Download Target firmware */
- AR6K_APP_LOAD_ADDRESS(address, ar->arVersion.target_ver);
- if (ar->arVersion.target_ver == AR6003_REV3_VERSION)
- address = 0x1234;
- if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) {
- return A_ERROR;
- }
- /* Set starting address for firmware */
- AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver);
- bmifn(BMISetAppStart(ar->arHifDevice, address));
- if(ar->arTargetType == TARGET_TYPE_AR6003) {
- AR6K_DATASET_PATCH_ADDRESS(address, ar->arVersion.target_ver);
- if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE,
- address, false)) != 0)
- return A_ERROR;
- param = address;
- bmifn(BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head),
- (unsigned char *)¶m, 4));
- }
- /* Restore system sleep */
- address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, sleep));
- address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
- param = options | 0x20;
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- if (ar->arTargetType == TARGET_TYPE_AR6003) {
- /* Configure GPIO AR6003 UART */
- #ifndef CONFIG_AR600x_DEBUG_UART_TX_PIN
- #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
- #endif
- param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)¶m, 4));
- #if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23)
- {
- address = GPIO_BASE_ADDRESS + CLOCK_GPIO_ADDRESS;
- bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m));
- param |= CLOCK_GPIO_BT_CLK_OUT_EN_SET(1);
- bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param));
- }
- #endif
- /* Configure GPIO for BT Reset */
- #ifdef ATH6KL_CONFIG_GPIO_BT_RESET
- #define CONFIG_AR600x_BT_RESET_PIN 0x16
- param = CONFIG_AR600x_BT_RESET_PIN;
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)¶m, 4));
- #endif /* ATH6KL_CONFIG_GPIO_BT_RESET */
- /* Configure UART flow control polarity */
- #ifndef CONFIG_ATH6KL_BT_UART_FC_POLARITY
- #define CONFIG_ATH6KL_BT_UART_FC_POLARITY 0
- #endif
- #if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1)
- if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
- param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2);
- bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)¶m, 4));
- }
- #endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */
- }
- #ifdef HTC_RAW_INTERFACE
- if (!eppingtest && bypasswmi) {
- /* Don't run BMIDone for ART mode and force resetok=0 */
- resetok = 0;
- msleep(1000);
- }
- #endif /* HTC_RAW_INTERFACE */
- }
- return 0;
- }
- int
- ar6000_configure_target(struct ar6_softc *ar)
- {
- u32 param;
- if (enableuartprint) {
- param = 1;
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
- (u8 *)¶m,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Serial console prints enabled\n"));
- }
- /* Tell target which HTC version it is used*/
- param = HTC_PROTOCOL_VERSION;
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest),
- (u8 *)¶m,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n"));
- return A_ERROR;
- }
- #ifdef CONFIG_HOST_TCMD_SUPPORT
- if(testmode) {
- ar->arTargetMode = AR6000_TCMD_MODE;
- }else {
- ar->arTargetMode = AR6000_WLAN_MODE;
- }
- #endif
- if (enabletimerwar) {
- u32 param;
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)¶m,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n"));
- return A_ERROR;
- }
- param |= HI_OPTION_TIMER_WAR;
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)¶m,
- 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Timer WAR enabled\n"));
- }
- /* set the firmware mode to STA/IBSS/AP */
- {
- u32 param;
- if (BMIReadMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)¶m,
- 4)!= 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n"));
- return A_ERROR;
- }
- param |= (num_device << HI_OPTION_NUM_DEV_SHIFT);
- param |= (fwmode << HI_OPTION_FW_MODE_SHIFT);
- param |= (mac_addr_method << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
- param |= (firmware_bridge << HI_OPTION_FW_BRIDGE_SHIFT);
- if (BMIWriteMemory(ar->arHifDevice,
- HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
- (u8 *)¶m,
- 4) != 0)
- {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n"));
- return A_ERROR;
- }
- AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n"));…