📄 wmi.c
字号:
//------------------------------------------------------------------------------
// <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 + -