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

📄 wmi.c

📁 Atheros Communications AR6001 WLAN Driver for SDIO installation Read Me March 26,2007 (based on
💻 C
📖 第 1 页 / 共 5 页
字号:
        wmi_gpio_data_rx(wmip, datap, len);
        break;
    case (WMIX_GPIO_ACK_EVENTID):
        wmi_gpio_ack_rx(wmip, datap, len);
        break;
#endif /* CONFIG_HOST_GPIO_SUPPORT */
    default:
        WMI_DEBUG_PRINTF(ATH_LOG_ERR,
			             "Host received unknown extended reply/event with id 0x%x\n",
                         id);
        wmip->wmi_stats.cmd_id_err++;
        status = A_ERROR;
        break;
    }

    return status;
}

/*
 * Control Path
 */
A_STATUS
wmi_control_rx(struct wmi_t *wmip, void *osbuf)
{
    WMI_CMD_HDR *cmd;
    A_UINT16 id;
    A_UINT8 *datap;
    A_UINT32 len;
    A_STATUS status = A_OK;

    AR_DEBUG_ASSERT(osbuf != NULL);
    if (a_netbuf_to_len(osbuf) < sizeof(WMI_CMD_HDR)) {
        WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi event rx: bad packet\n");
        wmip->wmi_stats.cmd_len_err++;
        return A_ERROR;
    }

    cmd = (WMI_CMD_HDR *)a_netbuf_to_data(osbuf);
    id = cmd->commandId;

    if (a_netbuf_pull(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
        WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi 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 (WMI_CREATE_PSTREAM_CMDID):
        status = wmi_create_pstream_reply_rx(wmip, datap, len);
        break;
    case (WMI_DELETE_PSTREAM_CMDID):
        status = wmi_delete_pstream_reply_rx(wmip, datap, len);
        break;
    case (WMI_GET_BITRATE_CMDID):
        status = wmi_bitrate_reply_rx(wmip, datap, len);
        break;
    case (WMI_GET_CHANNEL_LIST_CMDID):
        status = wmi_channelList_reply_rx(wmip, datap, len);
        break;
    case (WMI_GET_TX_PWR_CMDID):
        status = wmi_txPwr_reply_rx(wmip, datap, len);
        break;
    case (WMI_READY_EVENTID):
        status = wmi_ready_event_rx(wmip, datap, len);
        break;
    case (WMI_CONNECT_EVENTID):
        status = wmi_connect_event_rx(wmip, datap, len);
        break;
    case (WMI_DISCONNECT_EVENTID):
        status = wmi_disconnect_event_rx(wmip, datap, len);
        break;
    case (WMI_TKIP_MICERR_EVENTID):
        status = wmi_tkip_micerr_event_rx(wmip, datap, len);
        break;
    case (WMI_BSSINFO_EVENTID):
        status = wmi_bssInfo_event_rx(wmip, datap, len);
        break;
    case (WMI_REGDOMAIN_EVENTID):
        status = wmi_regDomain_event_rx(wmip, datap, len);
        break;
    case (WMI_PSTREAM_TIMEOUT_EVENTID):
        status = wmi_pstream_timeout_event_rx(wmip, datap, len);
        break;
    case (WMI_NEIGHBOR_REPORT_EVENTID):
        status = wmi_neighborReport_event_rx(wmip, datap, len);
        break;
    case (WMI_SCAN_COMPLETE_EVENTID):
        status = wmi_scanComplete_rx(wmip, datap, len);
        break;
    case (WMI_CMDERROR_EVENTID):
        status = wmi_errorEvent_rx(wmip, datap, len);
        break;
    case (WMI_REPORT_STATISTICS_EVENTID):
        status = wmi_statsEvent_rx(wmip, datap, len);
        break;
    case (WMI_RSSI_THRESHOLD_EVENTID):
        status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
        break;
    case (WMI_ERROR_REPORT_EVENTID):
        status = wmi_reportErrorEvent_rx(wmip, datap, len);
        break;
    case (WMI_OPT_RX_FRAME_EVENTID):
        status = wmi_opt_frame_event_rx(wmip, datap, len);
        break;
    case (WMI_EXTENSION_EVENTID):
        status = wmi_control_rx_xtnd(wmip, osbuf);
        break;
#ifndef AR6K_FIRMWARE_1_0
    case (WMI_REPORT_ROAM_TBL_EVENTID):
        status = wmi_roam_tbl_event_rx(wmip, datap, len);
        break;
    case (WMI_CAC_EVENTID):
        status = wmi_cac_event_rx(wmip, datap, len);
        break;
    case (WMI_REPORT_ROAM_DATA_EVENTID):
        status = wmi_road_data_event_rx(wmip, datap, len);
        break;
#endif 
   default:
        WMI_DEBUG_PRINTF(ATH_LOG_ERR,"Host received unknown reply/event with id 0x%x\n",
                         id);
        wmip->wmi_stats.cmd_id_err++;
        status = A_ERROR;
        break;
    }


    return status;
}

static A_STATUS
wmi_create_pstream_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) 
{
    WMI_CRE_PRIORITY_STREAM_REPLY *reply;
    A_INT8 priNum = 0, i;
    A_UINT8 dir;

    if (len < sizeof(WMI_CRE_PRIORITY_STREAM_REPLY)) {
        WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi: create pstream reply too short (%d)!!\n", len);
        return A_EINVAL;
    }

    reply = (WMI_CRE_PRIORITY_STREAM_REPLY *)datap;
    WMI_DEBUG_PRINTF(ATH_LOG_ERR,"wmi: create pstream reply: status = %d, tx mbox = %d\n", reply->status, reply->txQueueNumber);

    dir = reply->trafficDirection;
    if (dir == BIDIR_TRAFFIC) {
        wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][reply->trafficClass] = FALSE;
        wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][reply->trafficClass] = FALSE;
    } else {
        wmip->wmi_pstreamCmdInProgress[dir][reply->trafficClass] = FALSE;
    }
    wmip->wmi_cpstreamCmdInProgress = FALSE;

    if (reply->status == A_FAILED_CREATE_REMOVE_PSTREAM_FIRST) {
        /* do nothing */
        return A_OK;
    }

    if (reply->status == A_SUCCEEDED) {
        if (reply->trafficDirection == DNLINK_TRAFFIC ||
            reply->trafficDirection == BIDIR_TRAFFIC) {
            wmip->wmi_olderPriRxMbox = wmip->wmi_newerPriRxMbox;
            wmip->wmi_newerPriRxMbox = reply->rxQueueNumber;
            wmip->wmi_mboxMap[DNLINK_TRAFFIC][reply->rxQueueNumber].trafficClass = reply->trafficClass;
            wmip->wmi_mboxMap[DNLINK_TRAFFIC][reply->rxQueueNumber].priorityNum = 0;
            wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][reply->trafficClass] = reply->rxQueueNumber;
        }

        if (reply->trafficDirection == UPLINK_TRAFFIC ||
            reply->trafficDirection == BIDIR_TRAFFIC) {
            wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][reply->trafficClass] = reply->txQueueNumber;
            wmip->wmi_numQoSStream++;
            for (i = 0; i < WMI_MAX_NUM_PRI_STREAMS; i++) {
                if (!wmip->wmi_priority[i].inUse) {
                    priNum = i;
                    wmip->wmi_priority[i].inUse = 1;
                    wmip->wmi_priority[i].mbox = reply->txQueueNumber;
                    break;
                }
            }
            wmip->wmi_mboxMap[UPLINK_TRAFFIC][reply->txQueueNumber].trafficClass = reply->trafficClass;
            wmip->wmi_mboxMap[UPLINK_TRAFFIC][reply->txQueueNumber].priorityNum = priNum;
            ar6000_set_numdataendpts(wmip->wmi_devt, wmip->wmi_numQoSStream+1);
        }
    }

    return reply->status;
}

static A_STATUS
wmi_delete_pstream_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_DEL_PRIORITY_STREAM_REPLY *reply;
    A_UINT8 dir;

    if (len < sizeof(WMI_DEL_PRIORITY_STREAM_REPLY)) {
        return A_EINVAL;
    }

    reply = (WMI_DEL_PRIORITY_STREAM_REPLY *)datap;
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: delete pstream reply: status = %d, rx mbox = %d\n", reply->status, reply->rxQueueNumber);

    dir = reply->trafficDirection;
    if (dir == BIDIR_TRAFFIC) {
        wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][reply->trafficClass] = FALSE;
        wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][reply->trafficClass] = FALSE;
    } else {
        wmip->wmi_pstreamCmdInProgress[dir][reply->trafficClass] = FALSE;
    }

    if (reply->status == A_OK) {
        /* update internal states for Rx Path */
        if (reply->trafficDirection == DNLINK_TRAFFIC || reply->trafficDirection == BIDIR_TRAFFIC) {
            A_UINT8 qNum = reply->rxQueueNumber;
            A_UINT8 class = wmip->wmi_mboxMap[DNLINK_TRAFFIC][qNum].trafficClass;
            wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][class] = WMI_NOT_MAPPED;
            wmip->wmi_mboxMap[DNLINK_TRAFFIC][qNum].priorityNum = WMI_NOT_MAPPED;
            wmip->wmi_mboxMap[DNLINK_TRAFFIC][qNum].trafficClass = WMM_AC_BE;
            if (wmip->wmi_newerPriRxMbox == qNum) {
                wmip->wmi_newerPriRxMbox = wmip->wmi_olderPriRxMbox;
                wmip->wmi_olderPriRxMbox = qNum;
            }
        }
    }

    return reply->status;
}

static A_STATUS
wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;

    if (len < sizeof(WMI_READY_EVENT)) {
        return A_EINVAL;
    }
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: ready event\n");
    wmip->wmi_ready = TRUE;
    ar6000_ready_event(wmip->wmi_devt, ev->macaddr, ev->phyCapability);

    return A_OK;
}

static A_STATUS
wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_CONNECT_EVENT *ev;

    if (len < sizeof(WMI_CONNECT_EVENT)) {
        return A_EINVAL;
    }
    ev = (WMI_CONNECT_EVENT *)datap;
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: connected event at freq %d ", ev->channel);
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
                     ev->bssid[0], ev->bssid[1], ev->bssid[2],
                     ev->bssid[3], ev->bssid[4], ev->bssid[5]);

    A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);

#ifndef AR6K_FIRMWARE_1_0
    ar6000_connect_event(wmip->wmi_devt, ev->channel, ev->bssid,
                         ev->listenInterval, ev->assocReqLen, ev->assocRespLen,
                         ev->assocInfo, ev->beaconIeLen);
#else
	    ar6000_connect_event(wmip->wmi_devt, ev->channel, ev->bssid,
                         ev->listenInterval, ev->assocReqLen, ev->assocRespLen,
                         ev->assocInfo, 0);
#endif
    return A_OK;
}

static A_STATUS
wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_REG_DOMAIN_EVENT *ev;

    if (len < sizeof(*ev)) {
        return A_EINVAL;
    }
    ev = (WMI_REG_DOMAIN_EVENT *)datap;

    ar6000_regDomain_event(wmip->wmi_devt, ev->regDomain);

    return A_OK;
}

static A_STATUS
wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_NEIGHBOR_REPORT_EVENT *ev;
    int numAps;

    if (len < sizeof(*ev)) {
        return A_EINVAL;
    }
    ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
    numAps = ev->numberOfAps;

    if (len < (A_INT32)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
        return A_EINVAL;
    }

    ar6000_neighborReport_event(wmip->wmi_devt, numAps, ev->neighbor);

    return A_OK;
}

static A_STATUS
wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_DISCONNECT_EVENT *ev;

    if (len < sizeof(WMI_DISCONNECT_EVENT)) {
        return A_EINVAL;
    }
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: disconnected event\n");

    ev = (WMI_DISCONNECT_EVENT *)datap;

    A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));

    ar6000_disconnect_event(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
                            ev->assocRespLen, ev->assocInfo);

    return A_OK;
}

static A_STATUS
wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    WMI_TKIP_MICERR_EVENT *ev;

    if (len < sizeof(*ev)) {
        return A_EINVAL;
    }
    WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: tkip micerr event\n");

    ev = (WMI_TKIP_MICERR_EVENT *)datap;
    ar6000_tkip_micerr_event(wmip->wmi_devt, ev->keyid, ev->ismcast);

    return A_OK;
}

static A_STATUS
wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    bss_t *bss;
    WMI_BSS_INFO_HDR *bih;
    A_UINT8 *buf;

    if (len <= sizeof(WMI_BSS_INFO_HDR)) {
        return A_EINVAL;
    }

    bih = (WMI_BSS_INFO_HDR *)datap;
    buf = datap + sizeof(WMI_BSS_INFO_HDR);
    len -= sizeof(WMI_BSS_INFO_HDR);

    WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi: bssInfo event %2.2x:%2.2x\n",
                      bih->bssid[4], bih->bssid[5]);

    bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
    if (bss != NULL) {
        /*
         * Free up the node.  Not the most efficient process given
         * we are about to allocate a new node but it is simple and should be
         * adequate.
         */
        wlan_node_ret_n_remove(&wmip->wmi_scan_table, bss);
    }

    bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
    if (bss == NULL) {
        return A_NO_MEMORY;
    }

    bss->ni_rssi        = bih->rssi;
    AR_DEBUG_ASSERT(bss->ni_buf != NULL);
    A_MEMCPY(bss->ni_buf, buf, len);

    if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
        wlan_node_free(bss);
        return A_EINVAL;
    }

    /*
     * Update the frequency in ie_chan, overwriting of channel number
     * which is done in wlan_parse_beacon
     */
    bss->ni_cie.ie_chan = bih->channel;
    wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);

    return A_OK;
}

static A_STATUS
wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
{
    bss_t *bss;
    WMI_OPT_RX_INFO_HDR *bih;
    A_UINT8 *buf;

    if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
        return A_EINVAL;
    }

    bih = (WMI_OPT_RX_INFO_HDR *)datap;
    buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
    len -= sizeof(WMI_OPT_RX_INFO_HDR);

    WMI_DEBUG_PRINTF(ATH_LOG_INF, 
                     "wmi: opt frame event %2.2x:%2.2x\n",
                      bih->bssid[4], bih->bssid[5]);

    bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
    if (bss != NULL) {
        /*
         * Free up the node.  Not the most efficient process given
         * we are about to allocate a new node but it is simple and should be
         * adequate.
         */
        wlan_node_ret_n_remove(&wmip->wmi_scan_table, bss);
    }

    bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
    if (bss == NULL) {
        return A_NO_MEMORY;
    }
    
    bss->ni_rssi        = bih->rssi;

⌨️ 快捷键说明

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