⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmi.c

📁 Linux下SDIO设备的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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 module implements the hardware independent layer of the * Wireless Module Interface (WMI) protocol. * */#include "../include/athdefs.h"#include "../include/athtypes.h"#include "../include/osapi.h"#include "../include/htc.h"#include "../include/wmi.h"#include "../include/ieee80211.h"#include "../include/ieee80211_node.h"#include "../include/wlan_api.h"#include "../include/wmi_api.h"#include "../include/dset_api.h"#include "../include/gpio_api.h"#include "../include/wmi_host.h"#include "../include/athdrv.h"#include "../include/ar6000_api.h"#ifdef DEBUGint wmi_debug = 0;#define WMI_DEBUG_PRINTF(args...)        if (wmi_debug) printk(args);#define WMI_DEBUG_PRINTF2(args...)       if (wmi_debug > 1) printk(args);#else#define WMI_DEBUG_PRINTF(args...)#define WMI_DEBUG_PRINTF2(args...)#endifstatic A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                        int len);static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                        int len);static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                       int len);static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);static A_STATUS wmi_sync_point(struct wmi_t *wmip);static A_STATUS wmi_create_pstream_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,                                          int len);static A_STATUS wmi_delete_pstream_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,                                          int len);static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,                                         int len);static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                       int len);static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                             int len);static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);#if CONFIG_HOST_DSET_SUPPORTstatic A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);#endif /* CONFIG_HOST_DSET_SUPPORT */static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap,                                     int len);static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                      int len);static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap,                                      int len);#if CONFIG_HOST_GPIO_SUPPORTstatic A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);#endif /* CONFIG_HOST_GPIO_SUPPORT */static const A_INT32 wmi_rateTable[] = {    1000,    2000,    5500,    11000,    6000,    9000,    12000,    18000,    24000,    36000,    48000,    54000,    0};#define MODE_A_SUPPORT_RATE_START       4#define MODE_A_SUPPORT_RATE_STOP        11#define MODE_GONLY_SUPPORT_RATE_START   MODE_A_SUPPORT_RATE_START#define MODE_GONLY_SUPPORT_RATE_STOP    MODE_A_SUPPORT_RATE_STOP#define MODE_B_SUPPORT_RATE_START       0#define MODE_B_SUPPORT_RATE_STOP        3/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */const A_UINT8 up_to_ac[]= {                WMM_AC_BE,                WMM_AC_BK,                WMM_AC_BK,                WMM_AC_BE,                WMM_AC_VI,                WMM_AC_VI,                WMM_AC_VO,                WMM_AC_VO,            };void *wmi_init(void *devt){    struct wmi_t *wmip;    A_UINT8 i;    wmip = A_MALLOC(sizeof(struct wmi_t));    if (wmip == NULL) {        return (NULL);    }    A_MEMZERO(wmip, sizeof(*wmip));    wmip->wmi_devt = devt;    wlan_node_table_init(wmip, &wmip->wmi_scan_table);    for (i = UPLINK_TRAFFIC; i < BIDIR_TRAFFIC; i++) {        wmip->wmi_pstreamCmdInProgress[i][WMM_AC_BE] = FALSE;        wmip->wmi_pstreamCmdInProgress[i][WMM_AC_BK] = FALSE;        wmip->wmi_pstreamCmdInProgress[i][WMM_AC_VI] = FALSE;        wmip->wmi_pstreamCmdInProgress[i][WMM_AC_VO] = FALSE;    }    wmip->wmi_cpstreamCmdInProgress = FALSE;    wmi_qos_state_init(wmip);    wmip->wmi_powerMode = REC_POWER;    wmip->wmi_phyMode = WMI_11G_MODE;    return (wmip);}voidwmi_qos_state_init(struct wmi_t *wmip){    A_UINT8 i;    if (wmip == NULL) {        return;    }    /* Initialize QoS States */    wmip->wmi_numQoSStream = 0;    for (i = 0; i < WMI_MAX_NUM_PRI_STREAMS; i++) {        wmip->wmi_priority[i].inUse = 0;        wmip->wmi_priority[i].mbox = WMI_BEST_EFFORT_MBOX;    }    for (i = 0; i < WMM_NUM_AC; i++) {        wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][i] = WMI_NOT_MAPPED;        wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][i] = WMI_NOT_MAPPED;    }    wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][WMM_AC_BE] = WMI_BEST_EFFORT_MBOX;    wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][WMM_AC_BE] = WMI_BEST_EFFORT_MBOX;    for (i = 0; i < WMI_MBOX_COUNT; i++) {        wmip->wmi_mboxMap[UPLINK_TRAFFIC][i].trafficClass = WMM_AC_BE;        wmip->wmi_mboxMap[UPLINK_TRAFFIC][i].priorityNum = WMI_NOT_MAPPED;        wmip->wmi_mboxMap[DNLINK_TRAFFIC][i].trafficClass = WMM_AC_BE;        wmip->wmi_mboxMap[DNLINK_TRAFFIC][i].priorityNum = WMI_NOT_MAPPED;    }    wmip->wmi_olderPriRxMbox = WMI_HIGH_PRIORITY_MBOX;    wmip->wmi_newerPriRxMbox = WMI_LOW_PRIORITY_MBOX;    ar6000_set_numdataendpts(wmip->wmi_devt, 1);}voidwmi_shutdown(struct wmi_t *wmip){    if (wmip != NULL) {        wlan_node_table_cleanup(&wmip->wmi_scan_table);        A_FREE(wmip);    }}/* *  performs DIX to 802.3 encapsulation for transmit packets. *  uses passed in buffer.  Returns buffer or NULL if failed. *  Assumes the entire DIX header is contigous and that there is *  enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. */A_STATUSwmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf){    A_UINT8          *datap;    A_UINT16         typeorlen;    ATH_MAC_HDR      macHdr;    ATH_LLC_SNAP_HDR *llcHdr;    A_ASSERT(osbuf != NULL);    if (a_netbuf_headroom(osbuf) <        (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))    {        return A_NO_MEMORY;    }    datap = a_netbuf_to_data(osbuf);    typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);    if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {        /*         * packet is already in 802.3 format - return success         */        WMI_DEBUG_PRINTF("packet already 802.3\n");        return (A_OK);    }    /*     * Save mac fields and length to be inserted later     */    A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);    A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);    macHdr.typeOrLen = A_CPU2BE16(a_netbuf_to_len(osbuf) - sizeof(ATH_MAC_HDR) +                                  sizeof(ATH_LLC_SNAP_HDR));    /*     * Make room for LLC+SNAP headers     */    if (a_netbuf_push(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {        return A_NO_MEMORY;    }    datap = a_netbuf_to_data(osbuf);    A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));    llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));    llcHdr->dsap      = 0xAA;    llcHdr->ssap      = 0xAA;    llcHdr->cntl      = 0x03;    llcHdr->orgCode[0] = 0x0;    llcHdr->orgCode[1] = 0x0;    llcHdr->orgCode[2] = 0x0;    llcHdr->etherType = typeorlen;    return (A_OK);}/* * Adds a WMI data header * Assumes there is enough room in the buffer to add header. */A_STATUSwmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType){    WMI_DATA_HDR     *dtHdr;    A_ASSERT(osbuf != NULL);    if (a_netbuf_push(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {        return A_NO_MEMORY;    }    dtHdr = (WMI_DATA_HDR *)a_netbuf_to_data(osbuf);    dtHdr->info = msgType;    dtHdr->rssi = 0;    return (A_OK);}A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir){    A_UINT8         *datap;    A_UINT8         trafficClass, userPriority = 0;    ATH_LLC_SNAP_HDR *llcHdr;    A_UINT16        ipType = IP_ETHERTYPE;    WMI_DATA_HDR     *dtHdr;    WMI_CREATE_PSTREAM_CMD  cmd;    A_ASSERT(osbuf != NULL);    A_ASSERT(dir == DNLINK_TRAFFIC || dir == UPLINK_TRAFFIC);    datap = a_netbuf_to_data(osbuf);    llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) +                                  sizeof(ATH_MAC_HDR));    if (llcHdr->etherType == htons(ipType)) {        /* Extract the endpoint info from the TOS field in the IP header */        userPriority = ar6000_iptos_to_userPriority(((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR));        trafficClass = convert_userPriority_to_trafficClass(userPriority);    } else {        trafficClass = WMM_AC_BE;    }    dtHdr = (WMI_DATA_HDR *)datap;    if(dir==UPLINK_TRAFFIC)        dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT;  /* lower 3-bits are 802.1d priority */    /* Implicitly determine whether a create_pstream_cmd is needed for this trafficClass */    if (!((trafficClass == WMM_AC_BE) || (wmip->wmi_trafficClassMap[dir][trafficClass] != WMI_NOT_MAPPED))) {        A_UINT8 reqMbox;        /*         * If the data pkt is tagged with a priority that doesn't have a MBOX created,         * we must first call create_pstream_cmd         * Originally, assume traffic goes to BE MBox,         * until the driver receives the reply from the create_pstream cmd         */        wmip->wmi_trafficClassMap[dir][trafficClass] = WMI_BEST_EFFORT_MBOX;        if (dir == DNLINK_TRAFFIC) {            /* determine which mailbox to use */            reqMbox = wmip->wmi_olderPriRxMbox;        } else {            reqMbox = WMI_BEST_EFFORT_MBOX;        }        A_MEMZERO(&cmd, sizeof(cmd));        cmd.trafficClass = trafficClass;        cmd.rxQueueNum = reqMbox;        cmd.userPriority = userPriority;        cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;        if (wmi_create_pstream_cmd(wmip, &cmd) != A_OK) {            wmip->wmi_trafficClassMap[dir][trafficClass] = WMI_NOT_MAPPED;            trafficClass = WMM_AC_BE;        }    }    return trafficClass;}HTC_ENDPOINT_IDwmi_get_endpoint(struct wmi_t *wmip, A_UINT8 trafficClass){    WMI_DEBUG_PRINTF2("1 pkt of traffic class(%d) to mbox(%d)\n",                      trafficClass, wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][trafficClass]);    return wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][trafficClass];}/* *  performs 802.3 to DIX encapsulation for received packets. *  Assumes the entire 802.3 header is contigous. */A_STATUSwmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf){    A_UINT8          *datap;    ATH_MAC_HDR      macHdr;    ATH_LLC_SNAP_HDR *llcHdr;    A_ASSERT(osbuf != NULL);    datap = a_netbuf_to_data(osbuf);    A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR));    llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));    macHdr.typeOrLen = llcHdr->etherType;    if (a_netbuf_pull(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {        return A_NO_MEMORY;    }    datap = a_netbuf_to_data(osbuf);    A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));    return (A_OK);}/* * Removes a WMI data header */A_STATUSwmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf){    A_ASSERT(osbuf != NULL);    return (a_netbuf_pull(osbuf, sizeof(WMI_DATA_HDR)));}voidwmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg){    wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);}/* * WMI Extended Event received from Target. */A_STATUSwmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf){    WMIX_CMD_HDR *cmd;    A_UINT16 id;    A_UINT8 *datap;    A_UINT32 len;    A_STATUS status = A_OK;    if (a_netbuf_to_len(osbuf) < sizeof(WMIX_CMD_HDR)) {        WMI_DEBUG_PRINTF("wmi extended event rx: bad packet\n");        wmip->wmi_stats.cmd_len_err++;        a_netbuf_free(osbuf);        return A_ERROR;    }    cmd = (WMIX_CMD_HDR *)a_netbuf_to_data(osbuf);    id = cmd->commandId;    if (a_netbuf_pull(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {        WMI_DEBUG_PRINTF("wmi extended event rx: bad packet\n");        wmip->wmi_stats.cmd_len_err++;        a_netbuf_free(osbuf);        return A_ERROR;    }    datap = a_netbuf_to_data(osbuf);    len = a_netbuf_to_len(osbuf);    switch (id) {    case (WMIX_DSETOPENREQ_EVENTID):        status = wmi_dset_open_req_rx(wmip, datap, len);        break;#if CONFIG_HOST_DSET_SUPPORT    case (WMIX_DSETCLOSE_EVENTID):        status = wmi_dset_close_rx(wmip, datap, len);        break;    case (WMIX_DSETDATAREQ_EVENTID):        status = wmi_dset_data_req_rx(wmip, datap, len);        break;#endif /* CONFIG_HOST_DSET_SUPPORT */#if CONFIG_HOST_GPIO_SUPPORT    case (WMIX_GPIO_INTR_EVENTID):        wmi_gpio_intr_rx(wmip, datap, len);        break;    case (WMIX_GPIO_DATA_EVENTID):        wmi_gpio_data_rx(wmip, datap, len);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -