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

📄 wmi.c

📁 Atheros Communications AR6001 WLAN Driver for SDIO installation Read Me March 26,2007 (based on
💻 C
📖 第 1 页 / 共 5 页
字号:
//------------------------------------------------------------------------------
// <copyright file="wmi.c" company="Atheros">
//    Copyright (c) 2006 Microsoft Corporation.  All rights reserved.
//    Copyright (c) 2006 Atheros Corporation.  All rights reserved.
//
//    The use and distribution terms for this software are covered by the
//    Microsoft Limited Permissive License (Ms-LPL) 
//    http://www.microsoft.com/resources/sharedsource/licensingbasics/limitedpermissivelicense.mspx 
//    which can be found in the file MS-LPL.txt at the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by
//    the terms of this license.
//
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
//    Windows CE Wifi Driver for AR-6000
// </summary>
//------------------------------------------------------------------------------
//==============================================================================
// This module implements the hardware independent layer of the
// Wireless Module Interface (WMI) protocol.
//
// Author(s): ="Atheros"
//==============================================================================


#include <athdefs.h>
#include <athtypes.h>
#include <osapi.h>
#include "htc.h"
#include <ieee80211.h>
#include <ieee80211_node.h>
#include <wlan_api.h>
#include <wmi_api.h>
#include "dset_api.h"
#include "gpio_api.h"
#include "wmi_host.h"
#include "athdrv.h"
#include <ar6000_api.h>

static 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_SUPPORT
static 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_roam_tbl_event_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_road_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
#if CONFIG_HOST_GPIO_SUPPORT
static 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};

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);

    return (wmip);
}

void
wmi_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);
}

void
wmi_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_STATUS
wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
{
    A_UINT8          *datap;
    A_UINT16         typeorlen;
    ATH_MAC_HDR      macHdr;
    ATH_LLC_SNAP_HDR *llcHdr;

    AR_DEBUG_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(ATH_LOG_INF,"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_UINT16)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_STATUS
wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType)
{
    WMI_DATA_HDR     *dtHdr;

    AR_DEBUG_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);
#ifndef AR6K_FIRMWARE_1_0
    dtHdr->rssi = 0;
#else
    dtHdr->reserved1 = 0;
#endif
    WMI_DATA_HDR_SET_MSG_TYPE( dtHdr, msgType );
    return (A_OK);
}

A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT32 ndisUserPriority)
{
    A_UINT8         *datap;
    A_UINT8         trafficClass;
    ATH_LLC_SNAP_HDR *llcHdr;
    A_UINT16        ipType = IP_ETHERTYPE;
    WMI_CREATE_PSTREAM_CMD cmd;

    AR_DEBUG_ASSERT(osbuf != NULL);
    AR_DEBUG_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 */
        trafficClass = ar6000_trafficclass(((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),ndisUserPriority);
    } else {
        trafficClass = ar6000_trafficclass(NULL,ndisUserPriority);
    }

    /* 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;
        }

        cmd.trafficClass = trafficClass;
        cmd.rxQueueNum = reqMbox;
        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_ID
wmi_get_endpoint(struct wmi_t *wmip, A_UINT8 trafficClass)
{
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"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_STATUS
wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf)
{
    A_UINT8          *datap;
    ATH_MAC_HDR      macHdr;
    ATH_LLC_SNAP_HDR *llcHdr;

    AR_DEBUG_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_STATUS
wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
{
    AR_DEBUG_ASSERT(osbuf != NULL);

    return (a_netbuf_pull(osbuf, sizeof(WMI_DATA_HDR)));
}

void
wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
{
    wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
}

void 
wmi_free_allnodes(struct wmi_t *wmip)
{
	wlan_free_allnodes(&wmip->wmi_scan_table);
}

bss_t *
wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr) 
{
	bss_t *ni=NULL;
	ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
	return ni;
}

/*
 * WMI Extended Event received from Target.
 */
A_STATUS
wmi_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(ATH_LOG_ERR, "wmi extended event rx: bad packet\n");
        wmip->wmi_stats.cmd_len_err++;
        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(ATH_LOG_ERR, "wmi extended event rx: bad packet\n");
        wmip->wmi_stats.cmd_len_err++;
        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):

⌨️ 快捷键说明

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