mtk_wlan_driver_code_analyse

mtk_wlan_driver_code_analyse

暂定

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
————————————————
版权声明:本文为CSDN博主「qq_26956477」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_26956477/article/details/78303614

posted @   blankjyn  阅读(481)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示