mtk_wlan_driver_code_analyse

来源:互联网 发布:vmware安装ubuntu教程 编辑:程序博客网 时间:2024/06/02 05:55


                    mtk_wlan_driver_code_analyse


                                                                             --------------Hank


http://www.rfc-editor.org/materials/abbrev.expansion.txt 




1.    kernel-3.18\drivers\misc\mediatek\connectivity\wlan\gen2\os\linux\gl_init.c


mtk_wcn_wlan_gen2_init-> initWlan();


initWlan(); ---------------wifi driver start !


#if DBG  //defult closed; you can open it when you want to debug wifi log .


kalInitIOBuffer(); ----SDIO buf  alloc




procInitFs(); ---dbglevel_ops(debug module and debug level)
          --- proc_txdone_ops ("ARP", "DNS", "TCP", "UDP", "EAPOL", "DHCP", "ICMP")
          --- auto_per_ops  (Performance Configure)
          --- country_ops// diff country support diff channel
 
重点关注一下国家码country_ops,此信息跟选择的工作频段 TX power 等有关。


Two Special country code:
COUNTRY_CODE_FF    enable open for all channel for Certification
COUNTRY_CODE_FE    disable open for all channel for Certification
static ssize_t procCountryWrite(struct file *file, const char __user *buffer,size_t count, loff_t *data);
 wlanoidSetCountryCode WLAN_STATUS wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter,
              IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen)
 pucCountry = pvSetBuffer; 
 prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup = prAdapter->rWifiVar.rConnSettings.u2CountryCode;
(set country code complete)


     *  For example: 2.4GHz, 1~13, 20MHz ==> regulation class = 81
     *               2.4GHz, 1~13, SCA   ==> regulation class = 83
     *               2.4GHz, 1~13, SCB   ==> regulation class = 84


Force to re-search
rlmDomainSendCmd(prAdapter, TRUE); 
    1 .rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid);
    2. rlmDomainSendPwrLimitCmd(prAdapter);
    3. rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid);


    rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid);
rlmDomainGetDomainInfo(prAdapter); 
//defined three mothed to get country code:
1. by given table idx 2. by customized  3. by country code


    rlmDomainSendPwrLimitCmd(prAdapter); //TX power limit
WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0],&prCmd->u2CountryCode); // Corresponding country TX power limit allocation
MAX_TX_POWER                    63
MIN_TX_POWER                    -64


rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); //default table information
rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); // configuration table information




    rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid); //Set passive scan channel info to chip




createWirelessDevice();
/* <1.1> Create wireless_dev */
    prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
/* <1.2> Create wiphy */
prWiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T));
/* <1.3> configure wireless_dev & wiphy */
...
/* <1.4> wowlan support */
prWiphy->wowlan = &mtk_wlan_wowlan_support;
    /* <1.5> Use wireless extension to replace IOCTL */
prWiphy->wext = &wext_handler_def;


/* <2> allocate and register net_device */
prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE,
                   ether_setup, CFG_MAX_TXQ_NUM);
prNetDev->netdev_ops = &wlan_netdev_ops;
/* <2.1> co-relate with wireless_dev bi-directionally */
prNetDev->ieee80211_ptr = prWdev;
    prWdev->netdev = prNetDev;
/* <2.2> co-relate net device & device tree */
SET_NETDEV_DEV(prNetDev, wiphy_dev(prWiphy));
/* <2.3> register net_device */
register_netdev(prWdev->netdev)









createWirelessDevice  -> /* <1.2> Create wiphy */
                    phy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T));  Start 
static struct cfg80211_ops mtk_wlan_ops = {
    .suspend = mtk_cfg80211_suspend,
    .resume    = mtk_cfg80211_resume,
    .change_virtual_intf = mtk_cfg80211_change_iface,
//wlanoidSetInfrastructureMode   1. Infrastructure Client (Non-AP STA) = AP + STA  2. Ad-Hoc IBSS = STA+ STA
    .add_key = mtk_cfg80211_add_key,
    // mtk_cfg80211_add_key -> wlanoidSetAddKey -> _wlanoidSetAddKey (wlan_oid.c) 
    According to the different prNewKey-> u4KeyLength, select the encryption method. 
    /* rKey.u4KeyIndex |= BIT(31);//Enable BIT 31 will make tx use bc key id,should use pairwise key id 0 */
    .get_key = mtk_cfg80211_get_key,
    .del_key = mtk_cfg80211_del_key,
    .set_default_key = mtk_cfg80211_set_default_key,
    .set_default_mgmt_key = mtk_cfg80211_set_default_mgmt_key,
    .get_station = mtk_cfg80211_get_station,  
    //This routine is responsible for getting station information such as RSSI
    /* 1. check BSSID */
    UNEQUAL_MAC_ADDR(arBssid, mac)
    /* 2. fill TX rate */
    wlanoidQueryLinkSpeed
    /* 3. fill RSSI */
    wlanoidQueryRssi   
    Contradictory point:
    rRssi = (PARAM_RSSI) prAdapter->rLinkQuality.cRssi;    /* ranged from (-128 ~ 30) in unit of dBm */
    #define PARAM_WHQL_RSSI_MAX_DBM                 (-10)
#define PARAM_WHQL_RSSI_MIN_DBM                 (-200)
    
    /* 4. Fill Tx OK and Tx Bad */
    wlanoidQueryStatisticsPL
.change_station = mtk_cfg80211_change_station,
    .add_station = mtk_cfg80211_add_station,
    .del_station = mtk_cfg80211_del_station,
    .scan = mtk_cfg80211_scan,
    #define CFG_SCAN_SSID_MAX_NUM                   (4)
#define CFG_SCAN_SSID_MATCH_MAX_NUM             (16)
#if CFG_MULTI_SSID_SCAN
wlanoidSetBssidListScanAdv
wlanoidGetChannelInfo(prAdapter, prScanRequest->puPartialScanReq);// get channel list
aisFsmScanRequestAdv(prAdapter, ucSsidNum, rSsid, pucIe, u4IeLength);
{//遍历赋值ssid,此方法多次使用,请以适当的场景赋值为准
            for (i = 0; i < ucSsidNum; i++) {
                COPY_SSID(prAisFsmInfo->arScanSSID[i].aucSsid,
                      prAisFsmInfo->arScanSSID[i].u4SsidLen,
                      prSsid[i].aucSsid, prSsid[i].u4SsidLen);
}


/* start online scan */
wlanClearScanningResult(prAdapter);
aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN);
{
case AIS_STATE_ONLINE_SCAN:
1、//ssid 赋值(各种扫描方式宏控辅助)
COPY_SSID(prAisFsmInfo->rRoamingSSID.aucSsid,prAisFsmInfo->rRoamingSSID.u4SsidLen,prConnSettings->aucSSID,prConnSettings->ucSSIDLen); 
2、//channel 获取
}


#else
wlanoidSetBssidListScanExt
// The difference between the two cases is: last case did not achieve aisFsmScanRequestAdv(fun :LIST_SCAN) function.
#endif
    .connect = mtk_cfg80211_connect,
1.    wlanoidSetInfrastructureMode 
    {
        /* Verify the new infrastructure mode. */基础架构BSS 网络
    if (eOpMode >= NET_TYPE_NUM) {
        DBGLOG(OID, TRACE, "Invalid mode value %d\n", eOpMode);
        return WLAN_STATUS_INVALID_DATA;
    }


    /* check if possible to switch to AdHoc mode */独立架构BSS网络
    if (eOpMode == NET_TYPE_IBSS || eOpMode == NET_TYPE_DEDICATED_IBSS) {
        if (cnmAisIbssIsPermitted(prAdapter) == FALSE) {
            DBGLOG(OID, TRACE, "Mode value %d unallowed\n", eOpMode);
            return WLAN_STATUS_FAILURE;
        }
}
2.    AKM(Authentication and Key Management) 初始化(auth_type  开放系统认证 & 共享密钥认证) & 加密方式
3.    wlanoidSetAuthMode 
note:prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_INFRA 
NET_TYPE_INFRA,        /*!< Try to join an Infrastructure, do periodic SCAN for joining. */
specific AKM(Authentication and Key Management)
 
4.    wlanoidSetEncryptionStatus //加密方式
5.    wlanoidSetAddWep会走wlanoidSetAddKey(); WEP 加密单独处理,前面讨论的都是WPA/WAP2 
6.    前面都是认证,加密的过程最后一步就是connect。
prConnSettings = &prAdapter->rWifiVar.rConnSettings;
    /* Set Connection Request Issued Flag */
    if (fgIsValidSsid)
        prConnSettings->fgIsConnReqIssued = TRUE;
    else {
        prConnSettings->eReConnectLevel = RECONNECT_LEVEL_USER_SET;
        prConnSettings->fgIsConnReqIssued = FALSE;
    }
疑问点:
prConnSettings = &prAdapter->rWifiVar.rConnSettings;
mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF);
{
/* to wake up main service thread */
        GLUE_SET_EVENT(prAdapter->prGlueInfo);
}
此过程prConnSettings  并未赋值给prAdapter ! mboxSendMsg 意义何在?
    .disconnect = mtk_cfg80211_disconnect,
    .join_ibss = mtk_cfg80211_join_ibss,
    {
    /* set channel */
1.    u4ChnlFreq = nicChannelNum2Freq(channel->hw_value);//返回channel 频率
2.    wlanoidSetFrequency -> 得出2.4G 频段还是5G 频段 prAdapter->rWifiVar.rConnSettings.eAdHocBand = *pu4FreqInKHz < 5000000 ? BAND_2G4 : BAND_5G;
/* set SSID */
3.    wlanoidSetSsid
}
    .leave_ibss = mtk_cfg80211_leave_ibss,
    .set_power_mgmt = mtk_cfg80211_set_power_mgmt,
    {
1.    wlanoidSet802dot11PowerSaveProfile
2.    status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE);
wlanSendSetQueryCmd -> CMD_ID_POWER_SAVE_MODE 


}
    .set_pmksa = mtk_cfg80211_set_pmksa,
    理论知识:
根据前述内容可知,PMK是密钥派生的源,如果认证前,STA没有PMK,它将首先利用图3-47右图所示的802.1X协商步骤以获取PMK(当然,对于SOHO环境中所使用的PSK而言,则不存在这种情况)。由于802.1X协商步骤涉及多次帧交换,故其所花费时间往往较长。在这种情况下,STA缓存这个得来不易的PMK信息就可消除以后再次进行802.1X协商步骤的必要,从而大大提升整个认证的速度。
根据802.11规范,PMK缓存信息的名称叫PMKSA(PMK Security Association),它包括AP的MAC地址、PMK的生命周期(lifetime),以及PMKID(PMK IDentifier,用于标示这个PMKSA,其值由PMK、AP的MAC地址、STA的MAC地址等信息用Hash计算得来)。
当STA和AP进行关联(或重关联)时:
STA首先根据AP的MAC地址判断自己是否有缓存了的PMKSA,如果有则把PMKID放在RSNE中然后通过Association/Reassociation Request发送给AP。
AP根据这个PMKID再判断自己是否也保持了对应的PMKSA。如果是,双方立即进入4-Way Handshake过程,从而避免802.1X协商步骤。
wlanoidSetPmkid();
rsnSearchPmkidEntry ();
{
Nomal case:
    /* Search for desired BSSID */
    for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) {
        if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, pucBssid, MAC_ADDR_LEN))
            break;
    }


    /* If desired BSSID is found, then set the PMKID */
    if (i < prAisSpecBssInfo->u4PmkidCacheCount) {
        *pu4EntryIndex = i;


        return TRUE;
    }
Except case:
/* No entry found for the specified BSSID, so add one entry */
            if (prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE - 1) {
                j = prAisSpecBssInfo->u4PmkidCacheCount;
                kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID,
                       prPmkid->arBSSIDInfo[i].arBSSID, sizeof(PARAM_MAC_ADDRESS));
                prAisSpecBssInfo->u4PmkidCacheCount++;
            }
}


    .del_pmksa = mtk_cfg80211_del_pmksa,
    .flush_pmksa = mtk_cfg80211_flush_pmksa,
wlanoidSetPmkid();
    .assoc = mtk_cfg80211_assoc,
    wlanQueryInformation
    {
    wlanoidQueryBssid // This routine is called to query the current BSSID.
}
1.    check BSSID
UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid) 
/* The macro to check if two MAC addresses are not equal */
2.    wlanoidSetBssid  
//This routine will initiate the join procedure to attempt to associate with the specified BSSID
    /* Action Frame TX/RX */
    .remain_on_channel = mtk_cfg80211_remain_on_channel,
    /*This routine is responsible for requesting to stay on a specified channel*/
    


    .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, 
.mgmt_tx = mtk_cfg80211_mgmt_tx,
// This routine is responsible for requesting to send a management fram
1.    Init
prMsgTxReq->fgNoneCckRate = FALSE;
prMsgTxReq->fgIsWaitRsp = TRUE;
prMsgTxReq->prMgmtMsduInfo = prMgmtFrame;
prMsgTxReq->u8Cookie = *cookie;
prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX;
2.    xSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF);


/* .mgmt_tx_cancel_wait        = mtk_cfg80211_mgmt_tx_cancel_wait, */
    .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register,
    switch (frame_type)
    {
    case MAC_FRAME_PROBE_REQ:
            if (reg) {
                prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ;
                DBGLOG(REQ, LOUD, "Open packet filer probe request\n");
            } else {
                prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ;
                DBGLOG(REQ, LOUD, "Close packet filer probe request\n");
            }
            break;
        case MAC_FRAME_ACTION:
            if (reg) {
                prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME;
                DBGLOG(REQ, LOUD, "Open packet filer action frame.\n");
            } else {
                prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME;
                DBGLOG(REQ, LOUD, "Close packet filer action frame.\n");
            }
            break;
        default:
            DBGLOG(REQ, TRACE, "Ask frog to add code for mgmt:%x\n", frame_type);
            break;
    }


#ifdef CONFIG_NL80211_TESTMODE
    .testmode_cmd = mtk_cfg80211_testmode_cmd,
#endif 
#if (CFG_SUPPORT_TDLS == 1)//EEE802.11z TDLS  //palease reviewer protocol
    .tdls_mgmt = TdlsexCfg80211TdlsMgmt,
    /* send the TDLS action data frame */
    TdlsexMgmtCtrl
    /* init */
    switch (prMgmtTxInfo->ucActionCode) 
    /* send the TDLS data frame */
{
/* record disconnect history */
if (prMgmtTxInfo->ucActionCode == TDLS_FRM_ACTION_TEARDOWN) {
            /* record disconnect history */
            TdlsLinkHistoryRecord(prGlueInfo, TRUE, prMgmtTxInfo->aucPeer,
                          TRUE, prMgmtTxInfo->u2StatusCode, NULL);
        }
}
return TdlsDataFrameSend(prAdapter,
                 prStaRec,
                 prMgmtTxInfo->aucPeer,
                 prMgmtTxInfo->ucActionCode,
                 prMgmtTxInfo->ucDialogToken,
                 prMgmtTxInfo->u2StatusCode,
                 (UINT_8 *) prMgmtTxInfo->aucSecBuf, prMgmtTxInfo->u4SecBufLen);
    
    .tdls_oper = TdlsexCfg80211TdlsOper,
    /* sanity check */
    /* init */
    /*
       enum nl80211_tdls_operation {
       NL80211_TDLS_DISCOVERY_REQ,
       NL80211_TDLS_SETUP,
       NL80211_TDLS_TEARDOWN,
       NL80211_TDLS_ENABLE_LINK,
       NL80211_TDLS_DISABLE_LINK,
       };
*/
switch (oper)
/* enable or disable TDLS link */
TdlsexLinkCtrl


#endif /* CFG_SUPPORT_TDLS */
#if 1    /* Remove schedule_scan because we need more verification for NLO */
    .sched_scan_start = mtk_cfg80211_sched_scan_start,
    /* This routine is responsible for handling sched_scan start/stop request*/
    wlanoidSetStartSchedScan //This routine is called to request starting of schedule scan
    { scnFsmSchedScanRequest}
    .sched_scan_stop = mtk_cfg80211_sched_scan_stop,
#endif
}; 


createWirelessDevice  -> /* <1.2> Create wiphy */
                    phy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T));   End 




createWirelessDevice  -> /* <1.3> configure wireless_dev & wiphy */   Start


#define CFG_MULTI_SSID_SCAN            1
#define CFG_SCAN_SSID_MAX_NUM                   (10)
#define CFG_SCAN_SSID_MATCH_MAX_NUM             (16)


prWiphy->max_sched_scan_ssids    = CFG_SCAN_SSID_MAX_NUM;
prWiphy->max_match_sets        = CFG_SCAN_SSID_MATCH_MAX_NUM;
prWiphy->max_sched_scan_ie_len    = CFG_CFG80211_IE_BUF_LEN;


prWiphy->max_remain_on_channel_duration = 5000;//每个channel 保持的时间
prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes;//工作模式VLAN adhoc 等
{
NL80211_IFTYPE_ADHOC
NL80211_IFTYPE_STATION
NL80211_IFTYPE_AP
NL80211_IFTYPE_AP_VLAN
NL80211_IFTYPE_P2P_CLIENT
NL80211_IFTYPE_P2P_GO
}


prWiphy->vendor_commands = mtk_wlan_vendor_ops;
Commands:
.subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST
.subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE
.subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
.subcmd = GSCAN_SUBCMD_SET_CONFIG
.subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
.subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
.subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
.subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
.subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
.subcmd = GSCAN_SUBCMD_SET_HOTLIST
.subcmd = RTT_SUBCMD_GETCAPABILITY
.subcmd = LSTATS_SUBCMD_GET_INFO
.subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
.subcmd = WIFI_OFFLOAD_START_MKEEP_ALIVE
.subcmd = WIFI_OFFLOAD_STOP_MKEEP_ALIVE


{
.doit = mtk_cfg80211_vendor_get_channel_list
.doit = mtk_cfg80211_vendor_set_country_code
#if CFG_SUPPORT_GSCN
.doit = mtk_cfg80211_vendor_get_gscan_capabilities
.doit = mtk_cfg80211_vendor_set_config
{
PARAM_WIFI_GSCAN_BUCKET_SPEC buckets[GSCAN_MAX_BUCKETS];
UINT_32 bucket;        /* bucket index, 0 based */
WIFI_BAND band;        /* when UNSPECIFIED, use channel list */
UINT_32 period;        /* desired period, in millisecond; if this is too */
UINT_8 report_events;
UINT_32 max_period; /* if max_period is non zero or different than period, then this bucket is
            * an exponential backoff bucket and the scan period will grow exponentially
            * as per formula: actual_period(N) = period * (base ^ (N/step_count))
            * to a maximum period of max_period */
UINT_32 step_count; /* for exponential back off bucket, number of scans to perform for a given period */
UINT_32 num_channels;
            /* channels to scan; these may include DFS channels
            * Note that a given channel may appear in multiple buckets */
PARAM_WIFI_GSCAN_CHANNEL_SPEC channels[GSCAN_MAX_CHANNELS];
}
.doit = mtk_cfg80211_vendor_set_scan_config
.doit = mtk_cfg80211_vendor_enable_scan
.doit = mtk_cfg80211_vendor_enable_full_scan_results
.doit = mtk_cfg80211_vendor_get_gscan_result
#endif
.doit = mtk_cfg80211_vendor_set_significant_change
typedef struct _PARAM_WIFI_SIGNIFICANT_CHANGE {
    UINT_16 rssi_sample_size;    /* number of samples for averaging RSSI */
    UINT_16 lost_ap_sample_size;    /* number of samples to confirm AP loss */
    UINT_16 min_breaching;    /* number of APs breaching threshold */
    UINT_16 num_ap;        /* max 64 */
    PARAM_AP_THRESHOLD ap[MAX_SIGNIFICANT_CHANGE_APS];
} PARAM_WIFI_SIGNIFICANT_CHANGE, *P_PARAM_WIFI_SIGNIFICANT_CHANGE;
typedef struct _PARAM_AP_THRESHOLD {
    mac_addr bssid;        /* AP BSSID */
    wifi_rssi low;        /* low threshold */
    wifi_rssi high;        /* high threshold */
    wifi_channel channel;    /* channel hint */
} PARAM_AP_THRESHOLD, *P_PARAM_AP_THRESHOLD;
.doit = mtk_cfg80211_vendor_set_hotlist
.doit = mtk_cfg80211_vendor_get_rtt_capabilities
/* RTT Capabilities */
typedef struct _PARAM_WIFI_RTT_CAPABILITIES {
    UINT_8 rtt_one_sided_supported;  /* if 1-sided rtt data collection is supported */
    UINT_8 rtt_ftm_supported;        /* if ftm rtt data collection is supported */
    UINT_8 lci_support;              /* if initiator supports LCI request. Applies to 2-sided RTT */
    UINT_8 lcr_support;              /* if initiator supports LCR request. Applies to 2-sided RTT */
    UINT_8 preamble_support;         /* bit mask indicates what preamble is supported by initiator */
    UINT_8 bw_support;               /* bit mask indicates what BW is supported by initiator */
} PARAM_WIFI_RTT_CAPABILITIES, *P_PARAM_WIFI_RTT_CAPABILITIES;
.doit = mtk_cfg80211_vendor_llstats_get_info
/* Link Layer Statistics */
    pRadioStat->radio = 10;
    pRadioStat->on_time = 11;
    pRadioStat->tx_time = 12;
    pRadioStat->num_channels = 4;
    return -1; /* not support LLS now*/
.doit = mtk_cfg80211_vendor_set_rssi_monitoring
/* RSSI Monitoring */
wlanoidRssiMonitor
{
#define PARAM_WHQL_RSSI_MAX_DBM                 (-10)
    if (rRssi.enable) {
        if (rRssi.max_rssi_value > PARAM_WHQL_RSSI_MAX_DBM)
            rRssi.max_rssi_value = PARAM_WHQL_RSSI_MAX_DBM;
        if (rRssi.min_rssi_value < -120)
            rRssi.min_rssi_value = -120;
    } else {
        rRssi.max_rssi_value = 0;
        rRssi.min_rssi_value = 0;
    }
}
.doit = mtk_cfg80211_vendor_packet_keep_alive_start
/* Packet Keep Alive */
prPkt->enable = TRUE; /*start packet keep alive*/
wlanoidPacketKeepAlive
wlanSendSetQueryCmd(prAdapter,
               CMD_ID_WFC_KEEP_ALIVE,
               TRUE,
               FALSE,
               TRUE,
               nicCmdEventSetCommon,
               nicOidCmdTimeoutCommon,
               sizeof(PARAM_PACKET_KEEPALIVE_T), (PUINT_8)prPacket, NULL, 0);
.doit = mtk_cfg80211_vendor_packet_keep_alive_stop
prPkt->enable = FALSE;  /*stop packet keep alive*/
.doit = mtk_cfg80211_vendor_set_band
    if (setBand == QCA_SETBAND_5G)
        band = BAND_5G;
    else if (setBand == QCA_SETBAND_2G)
        band = BAND_2G4;
    else
        band = BAND_NULL;
.doit = mtk_cfg80211_vendor_set_roaming_policy


wlanoidSetDrvRoamingPolicy


}


prWiphy->vendor_events = mtk_wlan_vendor_events;
{
.subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS
.subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND
.subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE
.subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS
.subcmd = RTT_EVENT_COMPLETE
.subcmd = GSCAN_EVENT_COMPLETE_SCAN
.subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST
.subcmd = WIFI_EVENT_RSSI_MONITOR
}




createWirelessDevice  -> /* <1.3> configure wireless_dev & wiphy */   End
/* <2> allocate and register net_device */   Start
#define NIC_INF_NAME    "wlan%d"
prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE,
                   ether_setup, CFG_MAX_TXQ_NUM);


static const struct net_device_ops wlan_netdev_ops = {// 网络设备
    .ndo_open = wlanOpen,
    netif_tx_start_all_queues(prDev);
    netif_tx_start_all_queues使能传输队列调度


    .ndo_stop = wlanStop,
    cfg80211_scan_done(prScanRequest, TRUE);
    netif_tx_stop_all_queues(prDev);


    .ndo_set_rx_mode = wlanSetMulticastList,
    gPrDev = prDev;
    schedule_delayed_work(&workq, 0);


    .ndo_get_stats = wlanGetStats,
    prGlueInfo->rNetDevStats.tx_errors = 0;
    prGlueInfo->rNetDevStats.rx_errors = 0;
    /* prGlueInfo->rNetDevStats.rx_bytes   = 0; */
    /* prGlueInfo->rNetDevStats.tx_bytes   = 0; */
    prGlueInfo->rNetDevStats.rx_errors = 0;
    prGlueInfo->rNetDevStats.multicast = 0;
    return &prGlueInfo->rNetDevStats;


    .ndo_do_ioctl = wlanDoIOCTL,
    .ndo_start_xmit = wlanHardStartXmit,
    //数据包发送
    BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket)
    {
This function is called to identify 802.1x and Bluetooth-over-Wi-Fi security frames, and queued into command queue for strict ordering due to 802.1x frames before add-key OIDs are not to be encrypted


kalQoSFrameClassifierAndPacketInfo//这种在线功能是通过Wi-Fi提取一些包信息,包括用户优先级,包长度,目的地址,802.1x和BT。


prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone;// This function is called when 802.1x or Bluetooth-over-Wi-Fi security frames has been sent to firmware


prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout;


}
    .ndo_init = wlanInit,
    wlanSetMulticastListWorkQueue
    {
    wlanoidSetCurrentPacketFilter // This routine is called to set Packet Filter
    {
    wlanoidSetPacketFilter
    
    /* Note:
        If PARAM_PACKET_FILTER_ALL_MULTICAST is set in PacketFilter,
        Firmware will pass multicast frame.
        Else if PARAM_PACKET_FILTER_MULTICAST is set in PacketFilter,
        Firmware will pass some multicast frame in multicast table.
        Else firmware will drop all multicast frame.
    */
    if (fgIsUnderSuspend)
        u4PacketFilter &= ~(PARAM_PACKET_FILTER_MULTICAST | PARAM_PACKET_FILTER_ALL_MULTICAST);
    
    wlanSendSetQueryCmd;


    }
    wlanoidSetMulticastList;
    /* The data must be a multiple of the Ethernet address size. */
    /* Verify if we can support so many multicast addresses. */
    /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 &&
     * pvSetBuffer == NULL to clear exist Multicast List.
     */
    wlanSendSetQueryCmd (CMD_ID_MAC_MCAST_ADDR);
    }
    wlanSchedScanStoppedWorkQueue;
    cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo));


    .ndo_uninit = wlanUninit,
    .ndo_select_queue = wlanSelectQueue,
};




/* <2> allocate and register net_device */   End


ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO);  


概述:probe主要工作如下:
glBusInit
wlanWakeLockInit
load firmware
glLoadNvram
wlanAdapterStart ---重点
tx_thread
wlanoidQueryCurrentAddr
wlanNetRegister
wlanRegisterNotifier
procCreateFsEntry




static INT_32 wlanProbe(PVOID pvData)
    enum ENUM_PROBE_FAIL_REASON {
        BUS_INIT_FAIL,
        NET_CREATE_FAIL,
        BUS_SET_IRQ_FAIL,
        ADAPTER_START_FAIL,
        NET_REGISTER_FAIL,
        PROC_INIT_FAIL,
        FAIL_MET_INIT_PROCFS,
        FAIL_REASON_NUM
    } eFailReason;


/* 4 <1> Initialize the IO port of the interface */
bRet = glBusInit(pvData);


wlanDebugTC4Init(); ----- I don`t know !!!!


/* 4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) */


prWdev = wlanNetCreate(pvData);


{
/* 4 <3.1> Create net device */
#define NIC_INF_NAME    "wlan%d"
alloc_netdev_mq   
/* 4 <3.1.1> Initialize net device varaiables */
prGlueInfo->prDevHandler->netdev_ops = &wlan_netdev_ops;
wlanMonWorkHandler //netif_tx_start_all_queues(prDev);


/* initialize timer for OID timeout checker */
kalOsTimerInitialize(prGlueInfo, kalTimeoutHandler);// command timeout call-back function
/* 4 <4> Create Adapter structure */
prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo);


}
/* 4 <4> Setup IRQ */
/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 */
//static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} };
prWlandevInfo = &arWlanDevInfo[i4DevIdx];


/* Init wakelock */
wlanWakeLockInit(prGlueInfo);
//    KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rIntrWakeLock, "WLAN interrupt");
//    KAL_WAKE_LOCK_INIT(NULL, &prGlueInfo->rTimeoutWakeLock, "WLAN timeout");


/* 4 <5> Start Device */
/* before start adapter, we need to open and load firmware */
MT6630
#define CFG_FW_LOAD_ADDRESS                     0x00091400
#define CFG_FW_START_ADDRESS                    0x00091400
MT6797
#define CFG_FW_LOAD_ADDRESS                     0x000a2800
#define CFG_FW_START_ADDRESS                    0x000a2800
prRegInfo->u4StartAddress = CFG_FW_START_ADDRESS;
prRegInfo->u4LoadAddress = CFG_FW_LOAD_ADDRESS;




/* Load NVRAM content to REG_INFO_T */
glLoadNvram(prGlueInfo, prRegInfo);
{ /* load MAC Address */
/* load country code */
/* cast to wide characters */
/* load default normal TX power */
/* load feature flags */
/* load EFUSE overriding part */
/* load band edge tx power control */
/* load regulation subbands */
/* load rssiPathCompensation */
If 1
/* load full NVRAM */
}


kalFirmwareImageMapping(prGlueInfo, &prFwBuffer, &u4FwSize)


{
/* <1> Open firmware */
kalFirmwareOpen(prGlueInfo){
filp = filp_open(aucFilePath, O_RDONLY, 0); // aucFilePath = "/vendor/firmware/" CFG_FW_FILENAME "_"
}
/* <2> Query firmare size */
kalFirmwareSize(prGlueInfo, &u4FwSize);
/* <3> Use vmalloc for allocating large memory trunk */
prFwBuffer = vmalloc(ALIGN_4(u4FwSize));
/* <4> Load image binary into buffer */
kalFirmwareLoad(prGlueInfo, prFwBuffer, 0, &u4FwSize)
/* <5> write back info */
}


wlanAdapterStart(prAdapter, prRegInfo, prFwBuffer, u4FwSize)
{
// Initialize the adapter. The sequence is:
*        1. Disable interrupt
*        2. Read adapter configuration from EEPROM and registry, verify chip ID.
*        3. Create NIC Tx/Rx resource.
*        4. Initialize the chip
*        5. Initialize the protocol
*        6. Enable Interrupt
/* 4 <1> Initialize the Adapter */
nicInitializeAdapter(prAdapter);{
nicVerifyChipID;
nicSDIOInit; //For SDIO enhance mode, set the max rx len and tx status
}
/* init wake lock before interrupt enable and tx thread */
KAL_WAKE_LOCK_INIT(prAdapter, &prAdapter->rTxThreadWakeLock, "WLAN TX THREAD");
/* 4 <2> Initialize System Service (MGMT Memory pool and STA_REC) */
nicInitSystemService(prAdapter);{
    /* <1> Initialize MGMT Memory pool and STA_REC */
    cnmMemInit(prAdapter);
    cnmStaRecInit(prAdapter);
    cmdBufInitialize(prAdapter);


    /* <2> Mailbox Initialization */
    mboxInitialize(prAdapter);


    /* <3> Timer Initialization */
    cnmTimerInitialize(prAdapter);
}
/* 4 <3> Initialize Tx */
nicTxInitialize(prAdapter);
wlanDefTxPowerCfg(prAdapter);
/* 4 <4> Initialize Rx */
nicRxInitialize(prAdapter);
开始下载firmware,通过头文件判断是分离下载还是整体下载。
/* 1. disable interrupt, download is done by polling mode only */
nicDisableInterrupt(prAdapter);
/* 2. Initialize Tx Resource to fw download state */
nicTxInitResetResource(prAdapter);
/* 3. FW download here */
u4FwLoadAddr = prRegInfo->u4LoadAddress;
/* 3a. parse file header for decision of divided firmware download or not */
prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile;
/* 3b. engage divided firmware downloading */
wlanImageSectionDownload;
wlanImageSectionDownloadAggregated;
/* 4. send Wi-Fi Start command */
wlanConfigWifiFunc(prAdapter, TRUE, prRegInfo->u4StartAddress);
/* 4 <5> check Wi-Fi FW asserts ready bit */
if (u4Value & WCIR_WLAN_READY)


#if CFG_SUPPORT_NVRAM
wlanLoadManufactureData
{
/* 1. Version Check */
/* 2. Load TX power gain parameters if valid */
/* 3. Check if needs to support 5GHz */
/* 4. Send EFUSE data */
/* 5. Get 16-bits Country Code and Bandwidth */
/* 6. Set domain and channel information to chip */
/* 7. Set band edge tx power if available */
/* 8. set 5G band edge tx power if available (add for 6625) */
/* 9. set RSSI compensation */
/* 10. notify FW Band Support 5G */
}
#endif
}


prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread");  重点!


用一个标志位来触发事件:
ret = wait_event_interruptible(prGlueInfo->waitq, (prGlueInfo->ulFlag != 0)); 


ulFlag :
         * sleep on waitqueue if no events occurred. Event contain (1) GLUE_FLAG_INT
         * (2) GLUE_FLAG_OID (3) GLUE_FLAG_TXREQ (4) GLUE_FLAG_HALT


/* Handle Interrupt */


wlanIST(prGlueInfo->prAdapter);
{
WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter)  // The function used to read interrupt status and then invoking dispatching procedure for the appropriate functions corresponding to specific interrupt bits
VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) //Read interrupt status from hardware


WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus) // Process each of the interrupt status consequently
static INT_EVENT_MAP_T arIntEventMapTable[] = {
    {WHISR_ABNORMAL_INT, INT_EVENT_ABNORMAL},
    {WHISR_D2H_SW_INT, INT_EVENT_SW_INT},
    {WHISR_TX_DONE_INT, INT_EVENT_TX},
    {(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT), INT_EVENT_RX}
};
}
/* Handle Packet Tx */


wlanEnqueueTxPacket // This function is called to enqueue a single TX packet into CORE  加到一个队列等待发送呗。
wlanGetTxPendingFrameCount > 0 //This function is called to report currently pending TX frames count . (command packets are not included)
wlanTxPendingPackets // this function sends pending MSDU_INFO_T to MT6620  


以上部分可以查看协议帧汇聚部分内容。




最后,/* exit while loop, tx thread is closed so we flush all pending packets */
kalFlushPendingTxPackets(prGlueInfo); 、this routine is used to flush pending TX packets in glue layer
kalClearSecurityFrames(prGlueInfo);、、This routine is used to clear all pending security frames
wlanReleasePendingOid(prGlueInfo->prAdapter, 0);、、 This function will search the CMD Queue to look for the pending OID and compelete it immediately when system request a reset.


回到probe 主函数,
先设置一下wifi  task 的优先级到最高。


/* set MAC address */
wlanoidQueryCurrentAddr 、、This routine is called to query the MAC address the NIC is currently using.


ether_addr_copy(prGlueInfo->prDevHandler->dev_addr, MacAddr.sa_data);
ether_addr_copy(prGlueInfo->prDevHandler->perm_addr,prGlueInfo->prDevHandler->dev_addr);
以上是copy MAC 地址。


/* card is ready */
/* 4 <3> Register the card */
wlanNetRegister(prWdev); 、、Register the device to the kernel and return the index.
/* 4 <5> Register Notifier callback */ 注册回调函数


procCreateFsEntry(prGlueInfo); 、、注册调试节点信息


&mcr_ops  、、用于读取MCR寄存器到用户空间的PROC功能,在u4McrOffset中指定MCR的偏移量。
以下俩个节点需要打开CFG_SUPPORT_DEBUG_FS 这个宏。
&roam_ops
&country_ops


再回到probe,


if (i4Status == WLAN_STATUS_SUCCESS) {
        wlanCfgSetSwCtrl(prGlueInfo->prAdapter);
        wlanCfgSetChip(prGlueInfo->prAdapter);
        wlanCfgSetCountryCode(prGlueInfo->prAdapter);
        /* Init performance monitor structure */
        kalPerMonInit(prGlueInfo);
        {
        kalPerMonHandler
        /*Calculate current throughput*/这里计算当前吞吐量
        
}
#if CFG_SUPPORT_AGPS_ASSIST
        kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, 0);// 这个函数跟AGPS相关
#endif
        DBGLOG(INIT, LOUD, "wlanProbe: probe success\n");


以上probe success 
最后还有个:
switch (eFailReason) 
{判断 probe fail 的原因}


到此整个probe函数分析完成了。






我们再回到Module Entry Point initWlan();


#if (CFG_CHIP_RESET_SUPPORT)
    glResetInit();
#endif


分析glResetInit();
/* 1. Register reset callback */
glResetCallback
{
case WMTRSTMSG_RESET_START:
wifi_reset_start();
{
if (powered == 1) {
netdev = dev_get_by_name(&init_net, ifname); }
 else {
        /* WIFI is off before whole chip reset, do nothing */
    }
}
}
/* 2. Initialize reset work */
mtk_wifi_reset-> wifi_reset_end // Receiving RESET_END/RESET_END_FAIL message

原创粉丝点击