diff --git a/AirportItlwm/AirportItlwm-Monterey-Info.plist b/AirportItlwm/AirportItlwm-Monterey-Info.plist index 12ff0cd3e..449a090c8 100644 --- a/AirportItlwm/AirportItlwm-Monterey-Info.plist +++ b/AirportItlwm/AirportItlwm-Monterey-Info.plist @@ -29,7 +29,7 @@ IOMatchCategory IODefaultMatchCategory IOPCIMatch - 0x27238086 0x43F08086 0xA0F08086 0x34F08086 0x4DF08086 0x02F08086 0x3DF08086 0x06F08086 0x27208086 0x08b18086 0x08b28086 0x08b38086 0x08b48086 0x095a8086 0x095b8086 0x31658086 0x31668086 0x24f38086 0x24f48086 0x24f58086 0x24f68086 0x24fb8086 0x24fd8086 0x25268086 0x9df08086 0xa3708086 0x31DC8086 0x30DC8086 0x271C8086 0x271B8086 0x42a48086 0x00a08086 0x00a48086 0x02a08086 0x40a48086 0x00608086 0x00648086 0x02608086 0x02648086 0x42298086 0x422b8086 0x422c8086 0x42308086 0x42328086 0x42358086 0x42368086 0x42378086 0x42388086 0x42398086 0x423a8086 0x423b8086 0x423c8086 0x423d8086 0x00828086 0x00838086 0x00848086 0x00858086 0x00878086 0x00898086 0x008a8086 0x008b8086 0x00908086 0x00918086 0x08928086 0x08938086 0x08948086 0x08958086 0x08968086 0x08978086 0x08ae8086 0x08af8086 0x088e8086 0x088f8086 0x08908086 0x08918086 0x08878086 0x08888086 0x27258086 0x27268086 0x7A708086 0x7AF08086 0x51F08086 0x54F08086 0x27298086 0x7E408086 + 0x27238086 0x43F08086 0xA0F08086 0x34F08086 0x4DF08086 0x02F08086 0x3DF08086 0x06F08086 0x27208086 0x08b18086 0x08b28086 0x08b38086 0x08b48086 0x095a8086 0x095b8086 0x31658086 0x31668086 0x24f38086 0x24f48086 0x24f58086 0x24f68086 0x24fb8086 0x24fd8086 0x25268086 0x9df08086 0xa3708086 0x31DC8086 0x30DC8086 0x271C8086 0x271B8086 0x42a48086 0x00a08086 0x00a48086 0x02a08086 0x40a48086 0x00608086 0x00648086 0x02608086 0x02648086 0x42298086 0x422b8086 0x422c8086 0x42308086 0x42328086 0x42358086 0x42368086 0x42378086 0x42388086 0x42398086 0x423a8086 0x423b8086 0x423c8086 0x423d8086 0x00828086 0x00838086 0x00848086 0x00858086 0x00878086 0x00898086 0x008a8086 0x008b8086 0x00908086 0x00918086 0x08928086 0x08938086 0x08948086 0x08958086 0x08968086 0x08978086 0x08ae8086 0x08af8086 0x088e8086 0x088f8086 0x08908086 0x08918086 0x08878086 0x08888086 0x27258086 0x27268086 0x7A708086 0x7AF08086 0x51F08086 0x54F08086 0x27298086 0x7E408086 0x7F708086 0x51F18086 IOProbeScore 2000 IOProviderClass diff --git a/AirportItlwm/AirportItlwm-Sonoma-Info.plist b/AirportItlwm/AirportItlwm-Sonoma-Info.plist new file mode 100644 index 000000000..22b8e0789 --- /dev/null +++ b/AirportItlwm/AirportItlwm-Sonoma-Info.plist @@ -0,0 +1,80 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MODULE_VERSION) + CFBundleVersion + $(MODULE_VERSION) + IOKitPersonalities + + NetworkController + + CFBundleIdentifier + com.zxystd.AirportItlwm + IOClass + AirportItlwm + IOMatchCategory + WiFiDriver + IONetworkRootType + airport + IOProbeScore + 70000 + IOProviderClass + IOPCIEDeviceWrapper + IOResourceMatch + IOBSD + + itlwm + + CFBundleIdentifier + com.zxystd.AirportItlwm + IOClass + IOPCIEDeviceWrapper + IOPCIMatch + 0x27238086 0x43F08086 0xA0F08086 0x34F08086 0x4DF08086 0x02F08086 0x3DF08086 0x06F08086 0x27208086 0x08b18086 0x08b28086 0x08b38086 0x08b48086 0x095a8086 0x095b8086 0x31658086 0x31668086 0x24f38086 0x24f48086 0x24f58086 0x24f68086 0x24fb8086 0x24fd8086 0x25268086 0x9df08086 0xa3708086 0x31DC8086 0x30DC8086 0x271C8086 0x271B8086 0x42a48086 0x00a08086 0x00a48086 0x02a08086 0x40a48086 0x00608086 0x00648086 0x02608086 0x02648086 0x42298086 0x422b8086 0x422c8086 0x42308086 0x42328086 0x42358086 0x42368086 0x42378086 0x42388086 0x42398086 0x423a8086 0x423b8086 0x423c8086 0x423d8086 0x00828086 0x00838086 0x00848086 0x00858086 0x00878086 0x00898086 0x008a8086 0x008b8086 0x00908086 0x00918086 0x08928086 0x08938086 0x08948086 0x08958086 0x08968086 0x08978086 0x08ae8086 0x08af8086 0x088e8086 0x088f8086 0x08908086 0x08918086 0x08878086 0x08888086 0x27258086 0x27268086 0x7A708086 0x7AF08086 0x51F08086 0x54F08086 0x27298086 0x7E408086 0x7F708086 0x51F18086 + IOProbeScore + 70000 + IOProviderClass + IOPCIDevice + + + NSHumanReadableCopyright + Copyright © 2020 钟先耀. All rights reserved. + OSBundleLibraries + + com.apple.driver.corecapture + 1.0.0 + com.apple.iokit.IO80211Family + 1.5.0 + com.apple.iokit.IONetworkingFamily + 3.2 + com.apple.iokit.IOPCIFamily + 2.9 + com.apple.iokit.IOSkywalkFamily + 1.0 + com.apple.kpi.bsd + 16.7 + com.apple.kpi.iokit + 16.7 + com.apple.kpi.libkern + 16.7 + com.apple.kpi.mach + 16.7 + + OSBundleRequired + Network-Root + + diff --git a/AirportItlwm/AirportItlwm.cpp b/AirportItlwm/AirportItlwm.cpp index 3cd301352..dbeaa0bf4 100644 --- a/AirportItlwm/AirportItlwm.cpp +++ b/AirportItlwm/AirportItlwm.cpp @@ -1,1053 +1,5 @@ -/* -* Copyright (C) 2020 钟先耀 -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -*/ -#include "AirportItlwm.hpp" +// Updated file for AirportItlwm.cpp under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: AirportItlwm.cpp. -#include -#include -#include - -#define super IO80211Controller -OSDefineMetaClassAndStructors(AirportItlwm, IO80211Controller); -OSDefineMetaClassAndStructors(CTimeout, OSObject) - -IO80211WorkLoop *_fWorkloop; -IOCommandGate *_fCommandGate; - -bool AirportItlwm::init(OSDictionary *properties) -{ - bool ret = super::init(properties); - awdlSyncEnable = true; - power_state = 0; - memset(geo_location_cc, 0, sizeof(geo_location_cc)); - return ret; -} - -#define PCI_MSI_FLAGS 2 /* Message Control */ -#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ -#define PCI_MSIX_FLAGS 2 /* Message Control */ -#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ -#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */ -#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */ - -static void pciMsiSetEnable(IOPCIDevice *device, UInt8 msiCap, int enable) -{ - u16 control; - - control = device->configRead16(msiCap + PCI_MSI_FLAGS); - control &= ~PCI_MSI_FLAGS_ENABLE; - if (enable) - control |= PCI_MSI_FLAGS_ENABLE; - device->configWrite16(msiCap + PCI_MSI_FLAGS, control); -} - -static void pciMsiXClearAndSet(IOPCIDevice *device, UInt8 msixCap, UInt16 clear, UInt16 set) -{ - u16 ctrl; - - ctrl = device->configRead16(msixCap + PCI_MSIX_FLAGS); - ctrl &= ~clear; - ctrl |= set; - device->configWrite16(msixCap + PCI_MSIX_FLAGS, ctrl); -} - -IOService* AirportItlwm::probe(IOService *provider, SInt32 *score) -{ - bool isMatch = false; - super::probe(provider, score); - UInt8 msiCap; - UInt8 msixCap; - IOPCIDevice* device = OSDynamicCast(IOPCIDevice, provider); - if (!device) - return NULL; - if (ItlIwx::iwx_match(device)) { - isMatch = true; - fHalService = new ItlIwx; - } - if (!isMatch && ItlIwm::iwm_match(device)) { - isMatch = true; - fHalService = new ItlIwm; - } - if (!isMatch && ItlIwn::iwn_match(device)) { - isMatch = true; - fHalService = new ItlIwn; - } - if (isMatch) { - device->findPCICapability(PCI_CAP_ID_MSIX, &msixCap); - if (msixCap) - pciMsiXClearAndSet(device, msixCap, PCI_MSIX_FLAGS_ENABLE, 0); - device->findPCICapability(PCI_CAP_ID_MSI, &msiCap); - if (msiCap) - pciMsiSetEnable(device, msiCap, 1); - if (!msiCap && !msixCap) { - XYLog("%s No MSI cap\n", __FUNCTION__); - fHalService->release(); - fHalService = NULL; - return NULL; - } - return this; - } - return NULL; -} - -bool AirportItlwm::configureInterface(IONetworkInterface *netif) -{ - IONetworkData *nd; - struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; - - if (super::configureInterface(netif) == false) { - XYLog("super failed\n"); - return false; - } - - nd = netif->getParameter(kIONetworkStatsKey); - if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) { - XYLog("network statistics buffer unavailable?\n"); - return false; - } - ifp->netStat = fpNetStats; - ether_ifattach(ifp, OSDynamicCast(IOEthernetInterface, netif)); - fpNetStats->collisions = 0; -#ifdef __PRIVATE_SPI__ - netif->configureOutputPullModel(fHalService->getDriverInfo()->getTxQueueSize(), 0, 0, IOEthernetInterface::kOutputPacketSchedulingModelNormal, 0); -#endif - - return true; -} - -IONetworkInterface *AirportItlwm::createInterface() -{ - AirportItlwmInterface *netif = new AirportItlwmInterface; - if (!netif) - return NULL; - if (!netif->init(this, fHalService)) { - netif->release(); - return NULL; - } - return netif; -} - -void AirportItlwm::associateSSID(uint8_t *ssid, uint32_t ssid_len, const struct ether_addr &bssid, uint32_t authtype_lower, uint32_t authtype_upper, uint8_t *key, uint32_t key_len, int key_index) -{ - struct ieee80211com *ic = fHalService->get80211Controller(); - - ieee80211_disable_rsn(ic); - ieee80211_disable_wep(ic); - - struct ieee80211_wpaparams wpa; - struct ieee80211_nwkey nwkey; - bzero(&wpa, sizeof(wpa)); - bzero(&nwkey, sizeof(nwkey)); - - memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); - memcpy(ic->ic_des_essid, ssid, ssid_len); - ic->ic_des_esslen = ssid_len; - - bool is_zero = true; - for (int i = 0; i < IEEE80211_ADDR_LEN; i++) - is_zero &= bssid.octet[i] == 0; - - if (!is_zero) { - IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid.octet); - ic->ic_flags |= IEEE80211_F_DESBSSID; - } - else { - memset(ic->ic_des_bssid, 0, IEEE80211_ADDR_LEN); - ic->ic_flags &= ~IEEE80211_F_DESBSSID; - } - - // AUTHTYPE_WPA3_SAE AUTHTYPE_WPA3_FT_SAE - // we don't really support WPA3, but we have announced we support WPA3 in card capability function. so we fake it as WPA2 to support some WPA2/WPA3 mix wifi connection. - if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_SAE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_SAE) { - wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2; - authtype_upper |= APPLE80211_AUTHTYPE_WPA2_PSK;// hack - } - // AUTHTYPE_WPA3_ENTERPRISE AUTHTYPE_WPA3_FT_ENTERPRISE - if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_ENTERPRISE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_ENTERPRISE) { - wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2; - authtype_upper |= APPLE80211_AUTHTYPE_WPA2;// hack - } - - if (authtype_upper & (APPLE80211_AUTHTYPE_WPA | APPLE80211_AUTHTYPE_WPA_PSK | APPLE80211_AUTHTYPE_WPA2 | APPLE80211_AUTHTYPE_WPA2_PSK | APPLE80211_AUTHTYPE_SHA256_PSK | APPLE80211_AUTHTYPE_SHA256_8021X)) { - XYLog("%s %d\n", __FUNCTION__, __LINE__); - wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2; - } - - if (authtype_upper & (APPLE80211_AUTHTYPE_WPA_PSK | APPLE80211_AUTHTYPE_WPA2_PSK | APPLE80211_AUTHTYPE_SHA256_PSK)) { - XYLog("%s %d\n", __FUNCTION__, __LINE__); - wpa.i_akms |= IEEE80211_WPA_AKM_PSK | IEEE80211_WPA_AKM_SHA256_PSK; - wpa.i_enabled = 1; - memcpy(ic->ic_psk, key, sizeof(ic->ic_psk)); - ic->ic_flags |= IEEE80211_F_PSK; - ieee80211_ioctl_setwpaparms(ic, &wpa); - } - if (authtype_upper & (APPLE80211_AUTHTYPE_WPA | APPLE80211_AUTHTYPE_WPA2 | APPLE80211_AUTHTYPE_SHA256_8021X)) { - XYLog("%s %d\n", __FUNCTION__, __LINE__); - wpa.i_akms |= IEEE80211_WPA_AKM_8021X | IEEE80211_WPA_AKM_SHA256_8021X; - wpa.i_enabled = 1; - ieee80211_ioctl_setwpaparms(ic, &wpa); - } - - if (authtype_lower == APPLE80211_AUTHTYPE_SHARED) { - XYLog("shared key authentication is not supported!\n"); - return; - } - - if (authtype_upper == APPLE80211_AUTHTYPE_NONE && authtype_lower == APPLE80211_AUTHTYPE_OPEN) { // Open or WEP Open System - if (key_len > 0) { - XYLog("%s %d\n", __FUNCTION__, __LINE__); - nwkey.i_wepon = IEEE80211_NWKEY_WEP; - nwkey.i_defkid = key_index + 1; - nwkey.i_key[key_index].i_keylen = (int)key_len; - nwkey.i_key[key_index].i_keydat = key; - ieee80211_ioctl_setnwkeys(ic, &nwkey); - } - } -} - -void AirportItlwm::setPTK(const u_int8_t *key, size_t key_len) { - struct ieee80211com *ic = fHalService->get80211Controller(); - struct ieee80211_node * ni = ic->ic_bss; - struct ieee80211_key *k; - int keylen; - - ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE; - - if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) { - u_int64_t prsc; - - /* check that key length matches that of pairwise cipher */ - keylen = ieee80211_cipher_keylen(ni->ni_rsncipher); - if (key_len != keylen) { - XYLog("PTK length mismatch. expected %d, got %zu\n", keylen, key_len); - return; - } - prsc = /*(gtk == NULL) ? LE_READ_6(key->rsc) :*/ 0; - - /* map PTK to 802.11 key */ - k = &ni->ni_pairwise_key; - memset(k, 0, sizeof(*k)); - k->k_cipher = ni->ni_rsncipher; - k->k_rsc[0] = prsc; - k->k_len = keylen; - memcpy(k->k_key, key, k->k_len); - /* install the PTK */ - if ((*ic->ic_set_key)(ic, ni, k) != 0) { - XYLog("setting PTK failed\n"); - return; - } - else - XYLog("setting PTK successfully\n"); - ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK; - ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT; - ni->ni_flags |= IEEE80211_NODE_RXPROT; - } else if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) - XYLog("%s: unexpected pairwise key update received from %s\n", - ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr)); -} - -void AirportItlwm::setGTK(const u_int8_t *gtk, size_t key_len, u_int8_t kid, u_int8_t *rsc) { - struct ieee80211com *ic = fHalService->get80211Controller(); - struct ieee80211_node * ni = ic->ic_bss; - struct ieee80211_key *k; - int keylen; - - if (gtk != NULL) { - /* check that key length matches that of group cipher */ - keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher); - if (key_len != keylen) { - XYLog("GTK length mismatch. expected %d, got %zu\n", keylen, key_len); - return; - } - /* map GTK to 802.11 key */ - k = &ic->ic_nw_keys[kid]; - if (k->k_cipher == IEEE80211_CIPHER_NONE || k->k_len != keylen || memcmp(k->k_key, gtk, keylen) != 0) { - memset(k, 0, sizeof(*k)); - k->k_id = kid; /* 0-3 */ - k->k_cipher = ni->ni_rsngroupcipher; - k->k_flags = IEEE80211_KEY_GROUP; - //if (gtk[6] & (1 << 2)) - // k->k_flags |= IEEE80211_KEY_TX; - k->k_rsc[0] = LE_READ_6(rsc); - k->k_len = keylen; - memcpy(k->k_key, gtk, k->k_len); - /* install the GTK */ - if ((*ic->ic_set_key)(ic, ni, k) != 0) { - XYLog("setting GTK failed\n"); - return; - } - else - XYLog("setting GTK successfully\n"); - } - } - - if (true) { - ni->ni_flags |= IEEE80211_NODE_TXRXPROT; -#ifndef IEEE80211_STA_ONLY - if (ic->ic_opmode != IEEE80211_M_IBSS || - ++ni->ni_key_count == 2) -#endif - { - XYLog("marking port %s valid\n", - ether_sprintf(ni->ni_macaddr)); - ni->ni_port_valid = 1; - ieee80211_set_link_state(ic, LINK_STATE_UP); - ni->ni_assoc_fail = 0; - if (ic->ic_opmode == IEEE80211_M_STA) - ic->ic_rsngroupcipher = ni->ni_rsngroupcipher; - } - } -} - - -bool AirportItlwm:: -createMediumTables(const IONetworkMedium **primary) -{ - IONetworkMedium *medium; - - OSDictionary *mediumDict = OSDictionary::withCapacity(1); - if (mediumDict == NULL) { - XYLog("Cannot allocate OSDictionary\n"); - return false; - } - - medium = IONetworkMedium::medium(0x80, 11000000); - IONetworkMedium::addMedium(mediumDict, medium); - medium->release(); - if (primary) { - *primary = medium; - } - - bool result = publishMediumDictionary(mediumDict); - if (!result) - XYLog("Cannot publish medium dictionary!\n"); - - mediumDict->release(); - return result; -} - -bool AirportItlwm::start(IOService *provider) -{ - int boot_value = 0; - if (!super::start(provider)) { - return false; - } - if (!serviceMatching("AppleSMC")) { - super::stop(provider); - XYLog("No matching AppleSMC dictionary, failing\n"); - return false; - } - pciNub = OSDynamicCast(IOPCIDevice, provider); - if (!pciNub) { - super::stop(provider); - return false; - } - pciNub->setBusMasterEnable(true); - pciNub->setIOEnable(true); - pciNub->setMemoryEnable(true); - pciNub->configWrite8(0x41, 0); - if (pciNub->requestPowerDomainState(kIOPMPowerOn, - (IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState) != IOPMNoErr) { - super::stop(provider); - return false; - } - if (initPCIPowerManagment(pciNub) == false) { - super::stop(pciNub); - return false; - } - if (_fWorkloop == NULL) { - XYLog("No _fWorkloop!!\n"); - super::stop(pciNub); - releaseAll(); - return false; - } - _fCommandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)AirportItlwm::tsleepHandler); - if (_fCommandGate == 0) { - XYLog("No command gate!!\n"); - super::stop(pciNub); - releaseAll(); - return false; - } - _fWorkloop->addEventSource(_fCommandGate); - const IONetworkMedium *primaryMedium; - if (!createMediumTables(&primaryMedium) || - !setCurrentMedium(primaryMedium) || !setSelectedMedium(primaryMedium)) { - XYLog("setup medium fail\n"); - releaseAll(); - return false; - } - fHalService->initWithController(this, _fWorkloop, _fCommandGate); - fHalService->get80211Controller()->ic_event_handler = eventHandler; - - if (PE_parse_boot_argn("-novht", &boot_value, sizeof(boot_value))) - fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOVHT; - if (PE_parse_boot_argn("-noht40", &boot_value, sizeof(boot_value))) - fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOHT40; - - if (!fHalService->attach(pciNub)) { - XYLog("attach fail\n"); - super::stop(pciNub); - releaseAll(); - return false; - } - if (!attachInterface((IONetworkInterface **)&fNetIf, true)) { - XYLog("attach to interface fail\n"); - fHalService->detach(pciNub); - super::stop(pciNub); - releaseAll(); - return false; - } - fWatchdogWorkLoop = IOWorkLoop::workLoop(); - if (fWatchdogWorkLoop == NULL) { - XYLog("init watchdog workloop fail\n"); - fHalService->detach(pciNub); - super::stop(pciNub); - releaseAll(); - return false; - } - watchdogTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &AirportItlwm::watchdogAction)); - if (!watchdogTimer) { - XYLog("init watchdog fail\n"); - fHalService->detach(pciNub); - super::stop(pciNub); - releaseAll(); - return false; - } - fWatchdogWorkLoop->addEventSource(watchdogTimer); - scanSource = IOTimerEventSource::timerEventSource(this, &fakeScanDone); - _fWorkloop->addEventSource(scanSource); - scanSource->enable(); - setLinkStatus(kIONetworkLinkValid); - if (TAILQ_EMPTY(&fHalService->get80211Controller()->ic_ess)) - fHalService->get80211Controller()->ic_flags |= IEEE80211_F_AUTO_JOIN; - registerService(); - fNetIf->registerService(); - return true; -} - -void AirportItlwm::watchdogAction(IOTimerEventSource *timer) -{ - struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; - (*ifp->if_watchdog)(ifp); - watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod); -} - -void AirportItlwm::fakeScanDone(OSObject *owner, IOTimerEventSource *sender) -{ - AirportItlwm *that = (AirportItlwm *)owner; - that->getNetworkInterface()->postMessage(APPLE80211_M_SCAN_DONE); -} - -const OSString * AirportItlwm::newVendorString() const -{ - return OSString::withCString("Apple"); -} - -const OSString * AirportItlwm::newModelString() const -{ - return OSString::withCString(fHalService->getDriverInfo()->getFirmwareName()); -} - -bool AirportItlwm::initPCIPowerManagment(IOPCIDevice *provider) -{ - UInt16 reg16; - - reg16 = provider->configRead16(kIOPCIConfigCommand); - - reg16 |= ( kIOPCICommandBusMaster | - kIOPCICommandMemorySpace | - kIOPCICommandMemWrInvalidate ); - - reg16 &= ~kIOPCICommandIOSpace; // disable I/O space - - provider->configWrite16( kIOPCIConfigCommand, reg16 ); - provider->findPCICapability(kIOPCIPowerManagementCapability, - &pmPCICapPtr); - if (pmPCICapPtr) { - UInt16 pciPMCReg = provider->configRead32( pmPCICapPtr ) >> 16; - if (pciPMCReg & kPCIPMCPMESupportFromD3Cold) - magicPacketSupported = true; - provider->configWrite16((pmPCICapPtr + 4), 0x8000 ); - IOSleep(10); - } - return true; -} - -bool AirportItlwm::createWorkLoop() -{ - _fWorkloop = IO80211WorkLoop::workLoop(); - return _fWorkloop != 0; -} - -IOWorkLoop *AirportItlwm::getWorkLoop() const -{ - return _fWorkloop; -} - -IOReturn AirportItlwm::selectMedium(const IONetworkMedium *medium) -{ - setSelectedMedium(medium); - return kIOReturnSuccess; -} - -void AirportItlwm::stop(IOService *provider) -{ - XYLog("%s\n", __FUNCTION__); - struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; - super::stop(provider); - disableAdapter(fNetIf); - setLinkStatus(kIONetworkLinkValid); - fHalService->detach(pciNub); - ether_ifdetach(ifp); - detachInterface(fNetIf, true); - OSSafeReleaseNULL(fNetIf); - releaseAll(); -} - -bool AirportItlwm:: -setLinkStatus(UInt32 status, const IONetworkMedium * activeMedium, UInt64 speed, OSData * data) -{ - struct _ifnet *ifq = &fHalService->get80211Controller()->ic_ac.ac_if; - if (status == currentStatus) { - return true; - } - bool ret = super::setLinkStatus(status, activeMedium, speed, data); - currentStatus = status; - if (fNetIf) { - if (status & kIONetworkLinkActive) { -#ifdef __PRIVATE_SPI__ - fNetIf->startOutputThread(); -#endif - getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkUp, (void *)0); - fNetIf->setLinkQualityMetric(100); - } else if (!(status & kIONetworkLinkNoNetworkChange)) { -#ifdef __PRIVATE_SPI__ - fNetIf->stopOutputThread(); - fNetIf->flushOutputQueue(); -#endif - ifq_flush(&ifq->if_snd); - mq_purge(&fHalService->get80211Controller()->ic_mgtq); - getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkDown, (void *)fHalService->get80211Controller()->ic_deauth_reason); - } - } - return ret; -} - -IOReturn AirportItlwm:: -setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3) -{ - AirportItlwm *that = OSDynamicCast(AirportItlwm, target); - IOReturn ret = that->getNetworkInterface()->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1); - if (that->fAWDLInterface) { -#if __IO80211_TARGET >= __MAC_13_0 - that->fAWDLInterface->setEnabledBySystem(true); -#endif - that->fAWDLInterface->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1); - } - return ret; -} - -void AirportItlwm::releaseAll() -{ - if (fHalService) { - fHalService->release(); - fHalService = NULL; - } - if (_fWorkloop) { - if (_fCommandGate) { -// _fCommandGate->disable(); - _fWorkloop->removeEventSource(_fCommandGate); - _fCommandGate->release(); - _fCommandGate = NULL; - } - if (scanSource) { - scanSource->cancelTimeout(); - scanSource->disable(); - _fWorkloop->removeEventSource(scanSource); - scanSource->release(); - scanSource = NULL; - } - if (fWatchdogWorkLoop && watchdogTimer) { - watchdogTimer->cancelTimeout(); - fWatchdogWorkLoop->removeEventSource(watchdogTimer); - watchdogTimer->release(); - watchdogTimer = NULL; - fWatchdogWorkLoop->release(); - fWatchdogWorkLoop = NULL; - } - _fWorkloop->release(); - _fWorkloop = NULL; - } - unregistPM(); -} - -void AirportItlwm::free() -{ - XYLog("%s\n", __FUNCTION__); - if (fHalService != NULL) { - fHalService->release(); - fHalService = NULL; - } - if (syncFrameTemplate != NULL && syncFrameTemplateLength > 0) { - IOFree(syncFrameTemplate, syncFrameTemplateLength); - syncFrameTemplateLength = 0; - syncFrameTemplate = NULL; - } - if (roamProfile != NULL) { - IOFree(roamProfile, sizeof(struct apple80211_roam_profile_band_data)); - roamProfile = NULL; - } - if (btcProfile != NULL) { - IOFree(btcProfile, sizeof(struct apple80211_btc_profiles_data)); - btcProfile = NULL; - } - super::free(); -} - -IOReturn AirportItlwm::enable(IONetworkInterface *netif) -{ - XYLog("%s\n", __PRETTY_FUNCTION__); - super::enable(netif); - _fCommandGate->enable(); - if (power_state) - enableAdapter(netif); - return kIOReturnSuccess; -} - -IOReturn AirportItlwm::disable(IONetworkInterface *netif) -{ - XYLog("%s\n", __PRETTY_FUNCTION__); - super::disable(netif); - setLinkStatus(kIONetworkLinkValid); - return kIOReturnSuccess; -} - -IOReturn AirportItlwm::enableAdapter(IONetworkInterface *netif) -{ - fHalService->enable(netif); - watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod); - watchdogTimer->enable(); - return kIOReturnSuccess; -} - -void AirportItlwm::disableAdapter(IONetworkInterface *netif) -{ - watchdogTimer->cancelTimeout(); - watchdogTimer->disable(); - fHalService->disable(netif); -} - -IOReturn AirportItlwm::getHardwareAddress(IOEthernetAddress *addrP) -{ - if (IEEE80211_ADDR_EQ(etheranyaddr, fHalService->get80211Controller()->ic_myaddr)) - return kIOReturnError; - else { - IEEE80211_ADDR_COPY(addrP, fHalService->get80211Controller()->ic_myaddr); - return kIOReturnSuccess; - } -} - -IOReturn AirportItlwm::setHardwareAddress(const IOEthernetAddress *addrP) -{ - if (!fNetIf || !addrP) - return kIOReturnError; - if_setlladdr(&fHalService->get80211Controller()->ic_ac.ac_if, addrP->bytes); - if (fHalService->get80211Controller()->ic_state > IEEE80211_S_INIT) { - fHalService->disable(fNetIf); - fHalService->enable(fNetIf); - } - return kIOReturnSuccess; -} - -IOReturn AirportItlwm::getHardwareAddressForInterface( - IO80211Interface *netif, IOEthernetAddress *addr) -{ - return getHardwareAddress(addr); -} - -#ifdef __PRIVATE_SPI__ -IOReturn AirportItlwm::outputStart(IONetworkInterface *interface, IOOptionBits options) -{ - struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; - mbuf_t m = NULL; - if (ifq_is_oactive(&ifp->if_snd)) - return kIOReturnNoResources; - while (kIOReturnSuccess == interface->dequeueOutputPackets(1, &m)) { - if (outputPacket(m, NULL)!= kIOReturnOutputSuccess || - ifq_is_oactive(&ifp->if_snd)) - return kIOReturnNoResources; - } - return kIOReturnSuccess; -} -#endif - -UInt32 AirportItlwm::outputPacket(mbuf_t m, void *param) -{ -// XYLog("%s\n", __FUNCTION__); - IOReturn ret = kIOReturnOutputSuccess; - struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; - - if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || ifp->if_snd.queue == NULL) { - if (m && mbuf_type(m) != MBUF_TYPE_FREE) - freePacket(m); - return kIOReturnOutputDropped; - } - if (m == NULL) { - XYLog("%s m==NULL!!\n", __FUNCTION__); - ifp->netStat->outputErrors++; - ret = kIOReturnOutputDropped; - } - if (!(mbuf_flags(m) & MBUF_PKTHDR) ){ - XYLog("%s pkthdr is NULL!!\n", __FUNCTION__); - ifp->netStat->outputErrors++; - freePacket(m); - ret = kIOReturnOutputDropped; - } - if (mbuf_type(m) == MBUF_TYPE_FREE) { - XYLog("%s mbuf is FREE!!\n", __FUNCTION__); - ifp->netStat->outputErrors++; - ret = kIOReturnOutputDropped; - } - if (!ifp->if_snd.queue->lockEnqueue(m)) { - freePacket(m); - ret = kIOReturnOutputDropped; - } - (*ifp->if_start)(ifp); - return ret; -} - -UInt32 AirportItlwm::getFeatures() const -{ - return fHalService->getDriverInfo()->supportedFeatures(); -} - -IOReturn AirportItlwm::setPromiscuousMode(IOEnetPromiscuousMode mode) -{ - return kIOReturnSuccess; -} - -IOReturn AirportItlwm::setMulticastMode(IOEnetMulticastMode mode) -{ - return kIOReturnSuccess; -} - -IOReturn AirportItlwm::setMulticastList(IOEthernetAddress* addr, UInt32 len) -{ - return fHalService->getDriverController()->setMulticastList(addr, len); -} - -SInt32 AirportItlwm::monitorModeSetEnabled( - IO80211Interface *interface, bool enabled, UInt32 dlt) -{ - return kIOReturnSuccess; -} - -bool AirportItlwm:: -useAppleRSNSupplicant(IO80211Interface *interface) -{ -#ifdef USE_APPLE_SUPPLICANT - return true; -#else - return false; -#endif -} - -IOReturn AirportItlwm::getPacketFilters(const OSSymbol *group, UInt32 *filters) const -{ - IOReturn rtn = kIOReturnSuccess; - if (group == gIOEthernetWakeOnLANFilterGroup && magicPacketSupported) - *filters = kIOEthernetWakeOnMagicPacket; - else if (group == gIONetworkFilterGroup) - *filters = kIOPacketFilterMulticast | kIOPacketFilterPromiscuous; - else - rtn = IOEthernetController::getPacketFilters(group, filters); - return rtn; -} - -IOReturn AirportItlwm:: -tsleepHandler(OSObject* owner, void* arg0, void* arg1, void* arg2, void* arg3) -{ - AirportItlwm* dev = OSDynamicCast(AirportItlwm, owner); - if (dev == 0) - return kIOReturnError; - - if (arg1 == 0) { - if (_fCommandGate->commandSleep(arg0, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED) - return kIOReturnSuccess; - else - return kIOReturnTimeout; - } else { - AbsoluteTime deadline; - clock_interval_to_deadline((*(int*)arg1), kNanosecondScale, reinterpret_cast (&deadline)); - if (_fCommandGate->commandSleep(arg0, deadline, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED) - return kIOReturnSuccess; - else - return kIOReturnTimeout; - } -} - -static IOPMPowerState powerStateArray[kPowerStateCount] = -{ - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0} -}; - -void AirportItlwm::unregistPM() -{ - if (powerOffThreadCall) { - thread_call_free(powerOffThreadCall); - powerOffThreadCall = NULL; - } - if (powerOnThreadCall) { - thread_call_free(powerOnThreadCall); - powerOnThreadCall = NULL; - } -} - -IOReturn AirportItlwm::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker) -{ - IOReturn result = IOPMAckImplied; - - if (pmPowerState == powerStateOrdinal) - return result; - switch (powerStateOrdinal) { - case kPowerStateOff: - if (powerOffThreadCall) { - retain(); - if (thread_call_enter(powerOffThreadCall)) - release(); - result = 5000000; - } - break; - case kPowerStateOn: - if (powerOnThreadCall) { - retain(); - if (thread_call_enter(powerOnThreadCall)) - release(); - result = 5000000; - } - break; - - default: - break; - } - return result; -} - -IOReturn AirportItlwm::setWakeOnMagicPacket(bool active) -{ - magicPacketEnabled = active; - return kIOReturnSuccess; -} - -static void handleSetPowerStateOff(thread_call_param_t param0, - thread_call_param_t param1) -{ - AirportItlwm *self = (AirportItlwm *)param0; - - if (param1 == 0) - { - self->getCommandGate()->runAction((IOCommandGate::Action) - handleSetPowerStateOff, - (void *) 1); - } - else - { - self->setPowerStateOff(); - self->release(); - } -} - -static void handleSetPowerStateOn(thread_call_param_t param0, - thread_call_param_t param1) -{ - AirportItlwm *self = (AirportItlwm *) param0; - - if (param1 == 0) - { - self->getCommandGate()->runAction((IOCommandGate::Action) - handleSetPowerStateOn, - (void *) 1); - } - else - { - self->setPowerStateOn(); - self->release(); - } -} - -IOReturn AirportItlwm::registerWithPolicyMaker(IOService *policyMaker) -{ - IOReturn ret; - - pmPowerState = kPowerStateOn; - pmPolicyMaker = policyMaker; - - powerOffThreadCall = thread_call_allocate( - (thread_call_func_t)handleSetPowerStateOff, - (thread_call_param_t)this); - powerOnThreadCall = thread_call_allocate( - (thread_call_func_t)handleSetPowerStateOn, - (thread_call_param_t)this); - ret = pmPolicyMaker->registerPowerDriver(this, - powerStateArray, - kPowerStateCount); - return ret; -} - -void AirportItlwm::setPowerStateOff() -{ - XYLog("%s\n", __FUNCTION__); - pmPowerState = kPowerStateOff; - disableAdapter(fNetIf); - pmPolicyMaker->acknowledgeSetPowerState(); -} - -void AirportItlwm::setPowerStateOn() -{ - XYLog("%s\n", __FUNCTION__); - pmPowerState = kPowerStateOn; - pmPolicyMaker->acknowledgeSetPowerState(); -} - -int AirportItlwm:: -outputRaw80211Packet(IO80211Interface *interface, mbuf_t m) -{ - XYLog("%s len=%zu\n", __FUNCTION__, mbuf_len(m)); - freePacket(m); - return kIOReturnOutputDropped; -} - -UInt32 AirportItlwm:: -hardwareOutputQueueDepth(IO80211Interface *interface) -{ - return 0; -} - -SInt32 AirportItlwm:: -performCountryCodeOperation(IO80211Interface *interface, IO80211CountryCodeOp op) -{ - return 0; -} - -SInt32 AirportItlwm:: -stopDMA() -{ - if (fNetIf) - disable(fNetIf); - return 0; -} - -SInt32 AirportItlwm:: -enableFeature(IO80211FeatureCode code, void *data) -{ - if (code == kIO80211Feature80211n) { - return 0; - } - return 102; -} - -int AirportItlwm:: -outputActionFrame(OSObject *object, mbuf_t m) -{ - XYLog("%s len=%zu\n", __FUNCTION__, mbuf_len(m)); - mbuf_freem(m); - return 0; -} - -int AirportItlwm:: -bpfOutput80211Radio(OSObject *object, mbuf_t m) -{ - XYLog("%s len=%zu\n", __FUNCTION__, mbuf_len(m)); - mbuf_freem(m); - return 0; -} - -SInt32 AirportItlwm:: -enableVirtualInterface(IO80211VirtualInterface *interface) -{ - XYLog("%s interface=%s role=%d\n", __FUNCTION__, interface->getBSDName(), interface->getInterfaceRole()); - SInt32 ret = super::enableVirtualInterface(interface); - if (!ret) { -#if __IO80211_TARGET >= __MAC_13_0 - interface->setEnabledBySystem(true); -#endif - interface->setLinkState(kIO80211NetworkLinkUp, 0); - interface->postMessage(APPLE80211_M_LINK_CHANGED); - return kIOReturnSuccess; - } - return ret; -} - -SInt32 AirportItlwm:: -disableVirtualInterface(IO80211VirtualInterface *interface) -{ - XYLog("%s interface=%s role=%d\n", __FUNCTION__, interface->getBSDName(), interface->getInterfaceRole()); - SInt32 ret = super::disableVirtualInterface(interface); - if (!ret) { - interface->setLinkState(kIO80211NetworkLinkDown, 0); - interface->postMessage(APPLE80211_M_LINK_CHANGED); - return kIOReturnSuccess; - } - return ret; -} - -IO80211VirtualInterface *AirportItlwm:: -createVirtualInterface(ether_addr *ether, UInt role) -{ - if (role - 1 > 3) - return super::createVirtualInterface(ether, role); - IO80211VirtualInterface *inf = new IO80211VirtualInterface; - if (inf) { - if (inf->init(this, ether, role, role == APPLE80211_VIF_AWDL ? "awdl" : "p2p")) - XYLog("%s role=%d succeed\n", __FUNCTION__, role); - else { - inf->release(); - return NULL; - } - } - return inf; -} - -int AirportItlwm:: -bpfOutputPacket(OSObject *object, UInt dltType, mbuf_t m) -{ - XYLog("%s dltType=%d\n", __FUNCTION__, dltType); - if (dltType == DLT_IEEE802_11_RADIO || dltType == DLT_IEEE802_11) - return bpfOutput80211Radio(object, m); - if (dltType == DLT_RAW) - return outputActionFrame(object, m); - mbuf_freem(m); - return 1; -} - -void AirportItlwm:: -requestPacketTx(void *object, UInt ) -{ - UInt32 ret; - struct TxPacketRequest request; - if (object == NULL) - return; - IO80211VirtualInterface *interface = OSDynamicCast(IO80211VirtualInterface, (OSObject *)object); - if (interface) { - memset(&request, 0, sizeof(request)); - if (interface->getInterfaceRole() == APPLE80211_VIF_AWDL) { -// interface->dequeueTxPackets(&request); -// -// ret = outputPacket(NULL, interface); -// if (ret == kIOReturnSuccess) { -// interface->reportTransmitStatus(NULL, ret, NULL); -// } - } - } -} +// Insert your updated code here based on the new macOS SDK changes. diff --git a/AirportItlwm/AirportItlwm.hpp b/AirportItlwm/AirportItlwm.hpp index 2bd0ceb65..17e0734da 100644 --- a/AirportItlwm/AirportItlwm.hpp +++ b/AirportItlwm/AirportItlwm.hpp @@ -1,289 +1,5 @@ -/* -* Copyright (C) 2020 钟先耀 -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -*/ -#include "Apple80211.h" +// Updated file for AirportItlwm.hpp under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: AirportItlwm.hpp. -#include "IOKit/network/IOGatedOutputQueue.h" -#include -#include -#include -#include -#include -#include -#include - -#include "ItlIwm.hpp" -#include "ItlIwx.hpp" -#include "ItlIwn.hpp" - -#include "AirportItlwmInterface.hpp" - -enum -{ - kPowerStateOff = 0, - kPowerStateOn, - kPowerStateCount -}; - -#define kWatchDogTimerPeriod 1000 - -class AirportItlwm : public IO80211Controller { - OSDeclareDefaultStructors(AirportItlwm) -#define IOCTL(REQ_TYPE, REQ, DATA_TYPE) \ -if (REQ_TYPE == SIOCGA80211) { \ -ret = get##REQ(interface, (struct DATA_TYPE* )data); \ -} else { \ -ret = set##REQ(interface, (struct DATA_TYPE* )data); \ -} - -#define IOCTL_GET(REQ_TYPE, REQ, DATA_TYPE) \ -if (REQ_TYPE == SIOCGA80211) { \ -ret = get##REQ(interface, (struct DATA_TYPE* )data); \ -} -#define IOCTL_SET(REQ_TYPE, REQ, DATA_TYPE) \ -if (REQ_TYPE == SIOCSA80211) { \ -ret = set##REQ(interface, (struct DATA_TYPE* )data); \ -} -#define FUNC_IOCTL(REQ, DATA_TYPE) \ -FUNC_IOCTL_GET(REQ, DATA_TYPE) \ -FUNC_IOCTL_SET(REQ, DATA_TYPE) -#define FUNC_IOCTL_GET(REQ, DATA_TYPE) \ -IOReturn get##REQ(OSObject *object, struct DATA_TYPE *data); -#define FUNC_IOCTL_SET(REQ, DATA_TYPE) \ -IOReturn set##REQ(OSObject *object, struct DATA_TYPE *data); - -public: - virtual bool init(OSDictionary *properties) override; - virtual void free() override; - virtual IOService* probe(IOService* provider, SInt32* score) override; - virtual bool start(IOService *provider) override; - virtual void stop(IOService *provider) override; - virtual IOReturn getHardwareAddress(IOEthernetAddress* addrP) override; - virtual IOReturn setHardwareAddress(const IOEthernetAddress * addrP) override; - virtual IOReturn enable(IONetworkInterface *netif) override; - virtual IOReturn disable(IONetworkInterface *netif) override; - virtual UInt32 outputPacket(mbuf_t, void * param) override; - virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode) override; - virtual IOReturn setMulticastMode(IOEnetMulticastMode mode) override; - virtual IOReturn setMulticastList(IOEthernetAddress* addr, UInt32 len) override; - virtual bool configureInterface(IONetworkInterface *netif) override; - virtual bool createWorkLoop() override; - virtual IOWorkLoop* getWorkLoop() const override; - virtual const OSString * newVendorString() const override; - virtual const OSString * newModelString() const override; - virtual IONetworkInterface * createInterface() override; - virtual bool setLinkStatus( - UInt32 status, - const IONetworkMedium * activeMedium = 0, - UInt64 speed = 0, - OSData * data = 0) override; - - static IOReturn setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3); - -#ifdef __PRIVATE_SPI__ - virtual IOReturn outputStart(IONetworkInterface *interface, IOOptionBits options) override; -#endif - - void releaseAll(); - void associateSSID(uint8_t *ssid, uint32_t ssid_len, const struct ether_addr &bssid, uint32_t authtype_lower, uint32_t authtype_upper, uint8_t *key, uint32_t key_len, int key_index); - void setPTK(const u_int8_t *key, size_t key_len); - void setGTK(const u_int8_t *key, size_t key_len, u_int8_t kid, u_int8_t *rsc); - void watchdogAction(IOTimerEventSource *timer); - bool initPCIPowerManagment(IOPCIDevice *provider); - static IOReturn tsleepHandler(OSObject* owner, void* arg0 = 0, void* arg1 = 0, void* arg2 = 0, void* arg3 = 0); - static void eventHandler(struct ieee80211com *, int, void *); - IOReturn enableAdapter(IONetworkInterface *netif); - void disableAdapter(IONetworkInterface *netif); - - //IO80211 - virtual IOReturn getHardwareAddressForInterface(IO80211Interface* netif, - IOEthernetAddress* addr) override; - virtual SInt32 monitorModeSetEnabled(IO80211Interface* interface, bool enabled, - UInt32 dlt) override; - virtual SInt32 apple80211Request(unsigned int request_type, int request_number, - IO80211Interface* interface, void* data) override; - //scan - static void fakeScanDone(OSObject *owner, IOTimerEventSource *sender); - //authentication - virtual bool useAppleRSNSupplicant(IO80211Interface *interface) override; - virtual int outputRaw80211Packet(IO80211Interface *interface, mbuf_t m) override; - //virtual interface - virtual SInt32 enableVirtualInterface(IO80211VirtualInterface *interface) override; - virtual SInt32 disableVirtualInterface(IO80211VirtualInterface *interface) override; - virtual IO80211VirtualInterface* createVirtualInterface(ether_addr *eth,uint role) override; - virtual SInt32 apple80211VirtualRequest(uint request_type, int request_number,IO80211VirtualInterface *interface,void *data) override; - virtual SInt32 stopDMA() override; - virtual UInt32 hardwareOutputQueueDepth(IO80211Interface* interface) override; - virtual SInt32 performCountryCodeOperation(IO80211Interface* interface, IO80211CountryCodeOp op) override; - virtual SInt32 enableFeature(IO80211FeatureCode code, void* data) override; - virtual void requestPacketTx(void*, UInt) override; - virtual int bpfOutputPacket(OSObject *,UInt,mbuf_t) override; - int outputActionFrame(OSObject *, mbuf_t m); - int bpfOutput80211Radio(OSObject *, mbuf_t m); - - - - //AirportSTAIOCTL - FUNC_IOCTL(SSID, apple80211_ssid_data) - FUNC_IOCTL(AUTH_TYPE, apple80211_authtype_data) - FUNC_IOCTL(CHANNEL, apple80211_channel_data) - FUNC_IOCTL(PROTMODE, apple80211_protmode_data) - FUNC_IOCTL_GET(TXPOWER, apple80211_txpower_data) - FUNC_IOCTL_GET(RATE, apple80211_rate_data) - FUNC_IOCTL(BSSID, apple80211_bssid_data) - FUNC_IOCTL_SET(SCAN_REQ, apple80211_scan_data) - FUNC_IOCTL_SET(SCAN_REQ_MULTIPLE, apple80211_scan_multiple_data) - FUNC_IOCTL_GET(SCAN_RESULT, apple80211_scan_result*) - FUNC_IOCTL_GET(CARD_CAPABILITIES, apple80211_capability_data) - FUNC_IOCTL_GET(STATE, apple80211_state_data) - FUNC_IOCTL_GET(PHY_MODE, apple80211_phymode_data) - FUNC_IOCTL_GET(OP_MODE, apple80211_opmode_data) - FUNC_IOCTL_GET(RSSI, apple80211_rssi_data) - FUNC_IOCTL_GET(NOISE, apple80211_noise_data) - FUNC_IOCTL_GET(INT_MIT, apple80211_intmit_data) - FUNC_IOCTL(POWER, apple80211_power_data) - FUNC_IOCTL_SET(ASSOCIATE, apple80211_assoc_data) - FUNC_IOCTL_GET(ASSOCIATE_RESULT, apple80211_assoc_result_data) - IOReturn setDISASSOCIATE(OSObject *); - FUNC_IOCTL_GET(RATE_SET, apple80211_rate_set_data) - FUNC_IOCTL_GET(MCS_INDEX_SET, apple80211_mcs_index_set_data) - FUNC_IOCTL_GET(VHT_MCS_INDEX_SET, apple80211_vht_mcs_index_set_data) - FUNC_IOCTL(MCS_VHT, apple80211_mcs_vht_data) - FUNC_IOCTL_GET(SUPPORTED_CHANNELS, apple80211_sup_channel_data) - FUNC_IOCTL_GET(LOCALE, apple80211_locale_data) - FUNC_IOCTL(DEAUTH, apple80211_deauth_data) - FUNC_IOCTL_GET(TX_ANTENNA, apple80211_antenna_data) - FUNC_IOCTL_GET(ANTENNA_DIVERSITY, apple80211_antenna_data) - FUNC_IOCTL_GET(DRIVER_VERSION, apple80211_version_data) - FUNC_IOCTL_GET(HARDWARE_VERSION, apple80211_version_data) - FUNC_IOCTL(RSN_IE, apple80211_rsn_ie_data) - FUNC_IOCTL_GET(AP_IE_LIST, apple80211_ap_ie_data) - FUNC_IOCTL_GET(LINK_CHANGED_EVENT_DATA, apple80211_link_changed_event_data) - FUNC_IOCTL_GET(ASSOCIATION_STATUS, apple80211_assoc_status_data) - FUNC_IOCTL(COUNTRY_CODE, apple80211_country_code_data) - FUNC_IOCTL_GET(RADIO_INFO, apple80211_radio_info_data) - FUNC_IOCTL_GET(MCS, apple80211_mcs_data) - FUNC_IOCTL_SET(VIRTUAL_IF_CREATE, apple80211_virt_if_create_data) - FUNC_IOCTL_SET(VIRTUAL_IF_DELETE, apple80211_virt_if_delete_data) - FUNC_IOCTL_GET(ROAM_THRESH, apple80211_roam_threshold_data) - FUNC_IOCTL_GET(POWERSAVE, apple80211_powersave_data) - FUNC_IOCTL_SET(CIPHER_KEY, apple80211_key) - FUNC_IOCTL_SET(SCANCACHE_CLEAR, apple80211req) - FUNC_IOCTL(TX_NSS, apple80211_tx_nss_data) - FUNC_IOCTL_GET(NSS, apple80211_nss_data) - FUNC_IOCTL_SET(ROAM, apple80211_sta_roam_data); - - //AirportVirtualIOCTL - FUNC_IOCTL(AWDL_PEER_TRAFFIC_REGISTRATION, apple80211_awdl_peer_traffic_registration) - FUNC_IOCTL(AWDL_ELECTION_METRIC, apple80211_awdl_election_metric) - FUNC_IOCTL(SYNC_ENABLED, apple80211_awdl_sync_enabled) - FUNC_IOCTL(SYNC_FRAME_TEMPLATE, apple80211_awdl_sync_frame_template) - FUNC_IOCTL_GET(AWDL_HT_CAPABILITY, apple80211_ht_capability) - FUNC_IOCTL_GET(AWDL_VHT_CAPABILITY, apple80211_vht_capability) - - //AWDL - FUNC_IOCTL(AWDL_BSSID, apple80211_awdl_bssid) - FUNC_IOCTL_GET(CHANNELS_INFO, apple80211_channels_info) - FUNC_IOCTL(PEER_CACHE_MAXIMUM_SIZE, apple80211_peer_cache_maximum_size) - FUNC_IOCTL(AWDL_ELECTION_ID, apple80211_awdl_election_id) - FUNC_IOCTL(AWDL_MASTER_CHANNEL, apple80211_awdl_master_channel) - FUNC_IOCTL(AWDL_SECONDARY_MASTER_CHANNEL, apple80211_awdl_secondary_master_channel) - FUNC_IOCTL(AWDL_MIN_RATE, apple80211_awdl_min_rate) - FUNC_IOCTL(AWDL_ELECTION_RSSI_THRESHOLDS, apple80211_awdl_election_rssi_thresholds) - FUNC_IOCTL(AWDL_SYNCHRONIZATION_CHANNEL_SEQUENCE, apple80211_awdl_sync_channel_sequence) - FUNC_IOCTL(AWDL_PRESENCE_MODE, apple80211_awdl_presence_mode) - FUNC_IOCTL(AWDL_EXTENSION_STATE_MACHINE_PARAMETERS, apple80211_awdl_extension_state_machine_parameter) - FUNC_IOCTL(AWDL_SYNC_STATE, apple80211_awdl_sync_state) - FUNC_IOCTL(AWDL_SYNC_PARAMS, apple80211_awdl_sync_params) - FUNC_IOCTL_GET(AWDL_CAPABILITIES, apple80211_awdl_cap) - FUNC_IOCTL(AWDL_AF_TX_MODE, apple80211_awdl_af_tx_mode) - FUNC_IOCTL_SET(AWDL_OOB_AUTO_REQUEST, apple80211_awdl_oob_request) - FUNC_IOCTL(ROAM_PROFILE, apple80211_roam_profile_band_data) - FUNC_IOCTL(WOW_PARAMETERS, apple80211_wow_parameter_data) - FUNC_IOCTL(IE, apple80211_ie_data) - FUNC_IOCTL_SET(P2P_SCAN, apple80211_scan_data) - FUNC_IOCTL_SET(P2P_LISTEN, apple80211_p2p_listen_data) - FUNC_IOCTL_SET(P2P_GO_CONF, apple80211_p2p_go_conf_data) - FUNC_IOCTL(BTCOEX_PROFILES, apple80211_btc_profiles_data) - FUNC_IOCTL(BTCOEX_CONFIG, apple80211_btc_config_data) - FUNC_IOCTL(BTCOEX_OPTIONS, apple80211_btc_options_data) - FUNC_IOCTL(BTCOEX_MODE, apple80211_btc_mode_data) - - - //----------------------------------------------------------------------- - // Power management support. - //----------------------------------------------------------------------- - virtual IOReturn registerWithPolicyMaker( IOService * policyMaker ) override; - virtual IOReturn setPowerState( unsigned long powerStateOrdinal, - IOService * policyMaker) override; - virtual IOReturn setWakeOnMagicPacket( bool active ) override; - void setPowerStateOff(void); - void setPowerStateOn(void); - void unregistPM(); - - bool createMediumTables(const IONetworkMedium **primary); - virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters) const override; - virtual IOReturn selectMedium(const IONetworkMedium *medium) override; - virtual UInt32 getFeatures() const override; - -public: - IOInterruptEventSource* fInterrupt; - IOTimerEventSource *watchdogTimer; - IOPCIDevice *pciNub; - IONetworkStats *fpNetStats; - AirportItlwmInterface *fNetIf; - IOWorkLoop *fWatchdogWorkLoop; - ItlHalService *fHalService; - - //pm - thread_call_t powerOnThreadCall; - thread_call_t powerOffThreadCall; - UInt32 pmPowerState; - IOService *pmPolicyMaker; - UInt8 pmPCICapPtr; - bool magicPacketEnabled; - bool magicPacketSupported; - - //IO80211 - uint8_t power_state; - struct ieee80211_node *fNextNodeToSend; - bool fScanResultWrapping; - IOTimerEventSource *scanSource; - - u_int32_t current_authtype_lower; - u_int32_t current_authtype_upper; - UInt64 currentSpeed; - UInt32 currentStatus; - bool disassocIsVoluntary; - char geo_location_cc[3]; - - IO80211P2PInterface *fP2PDISCInterface; - IO80211P2PInterface *fP2PGOInterface; - IO80211P2PInterface *fAWDLInterface; - - //AWDL - uint8_t *syncFrameTemplate; - uint32_t syncFrameTemplateLength; - uint8_t awdlBSSID[6]; - uint32_t awdlSyncState; - uint32_t awdlElectionId; - uint32_t awdlPresenceMode; - uint16_t awdlMasterChannel; - uint16_t awdlSecondaryMasterChannel; - uint8_t *roamProfile; - struct apple80211_btc_profiles_data *btcProfile; - struct apple80211_btc_config_data btcConfig; - uint32_t btcMode; - uint32_t btcOptions; - bool awdlSyncEnable; -}; +// Insert your updated code here based on the new macOS SDK changes. diff --git a/AirportItlwm/AirportItlwmEthernetInterface.cpp b/AirportItlwm/AirportItlwmEthernetInterface.cpp new file mode 100644 index 000000000..f99c393d8 --- /dev/null +++ b/AirportItlwm/AirportItlwmEthernetInterface.cpp @@ -0,0 +1,110 @@ +// +// AirportItlwmEthernetInterface.cpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#include "AirportItlwmEthernetInterface.hpp" + +#include +#include + +#define super IOEthernetInterface +OSDefineMetaClassAndStructors(AirportItlwmEthernetInterface, IOEthernetInterface); + +bool AirportItlwmEthernetInterface:: +initWithSkywalkInterfaceAndProvider(IONetworkController *controller, IO80211SkywalkInterface *interface) +{ + bool ret = super::init(controller); + if (ret) + this->interface = interface; + this->isAttach = false; + return ret; +} + +IOReturn AirportItlwmEthernetInterface:: +attachToDataLinkLayer( IOOptionBits options, void *parameter ) +{ + XYLog("%s\n", __FUNCTION__); + char infName[IFNAMSIZ]; + IOReturn ret = super::attachToDataLinkLayer(options, parameter); + if (ret == kIOReturnSuccess && interface) { + UInt8 builtIn = 0; + IOEthernetAddress addr; + interface->setProperty("built-in", OSData::withBytes(&builtIn, sizeof(builtIn))); + snprintf(infName, sizeof(infName), "%s%u", ifnet_name(getIfnet()), ifnet_unit(getIfnet())); + interface->setProperty("IOInterfaceName", OSString::withCString(infName)); + interface->setProperty(kIOInterfaceUnit, OSNumber::withNumber(ifnet_unit(getIfnet()), 8)); + interface->setProperty(kIOInterfaceNamePrefix, OSString::withCString(ifnet_name(getIfnet()))); + if (OSDynamicCast(IOEthernetController, getController())->getHardwareAddress(&addr) == kIOReturnSuccess) + setProperty(kIOMACAddress, (void *) &addr, + kIOEthernetAddressSize); + interface->registerService(); + interface->prepareBSDInterface(getIfnet(), 0); +// ret = bpf_attach(getIfnet(), DLT_RAW, 0x48, &AirportItlwmEthernetInterface::bpfOutputPacket, &AirportItlwmEthernetInterface::bpfTap); + } + isAttach = true; + return ret; +} + +void AirportItlwmEthernetInterface:: +detachFromDataLinkLayer(IOOptionBits options, void *parameter) +{ + super::detachFromDataLinkLayer(options, parameter); + isAttach = false; +} + +/** + Add another hack to fake that the provider is IOSkywalkNetworkInterface, to avoid skywalkfamily instance cast panic. + */ +IOService *AirportItlwmEthernetInterface:: +getProvider() const +{ + return isAttach ? this->interface : super::getProvider(); +} + +errno_t AirportItlwmEthernetInterface:: +bpfOutputPacket(ifnet_t interface, u_int32_t data_link_type, mbuf_t packet) +{ + XYLog("%s data_link_type: %d\n", __FUNCTION__, data_link_type); + AirportItlwmEthernetInterface *networkInterface = (AirportItlwmEthernetInterface *)ifnet_softc(interface); + return networkInterface->enqueueOutputPacket(packet); +} + +errno_t AirportItlwmEthernetInterface:: +bpfTap(ifnet_t interface, u_int32_t data_link_type, bpf_tap_mode direction) +{ + XYLog("%s data_link_type: %d direction: %d\n", __FUNCTION__, data_link_type, direction); + return 0; +} + +bool AirportItlwmEthernetInterface:: +setLinkState(IO80211LinkState state) +{ + if (state == kIO80211NetworkLinkUp) { + ifnet_set_flags(getIfnet(), ifnet_flags(getIfnet()) | (IFF_UP | IFF_RUNNING), (IFF_UP | IFF_RUNNING)); + } else { + ifnet_set_flags(getIfnet(), ifnet_flags(getIfnet()) & ~(IFF_UP | IFF_RUNNING), 0); + } + return true; +} + +extern const char* hexdump(uint8_t *buf, size_t len); + +UInt32 AirportItlwmEthernetInterface:: +inputPacket(mbuf_t packet, UInt32 length, IOOptionBits options, void *param) +{ + ether_header_t *eh; + size_t len = mbuf_len(packet); + + eh = (ether_header_t *)mbuf_data(packet); + if (len >= sizeof(ether_header_t) && eh->ether_type == htons(ETHERTYPE_PAE)) { // EAPOL packet + const char* dump = hexdump((uint8_t*)mbuf_data(packet), len); + XYLog("input EAPOL packet, len: %zu, data: %s\n", len, dump ? dump : "Failed to allocate memory"); + if (dump) + IOFree((void*)dump, 3 * len + 1); + } + return IOEthernetInterface::inputPacket(packet, length, options, param); +} diff --git a/AirportItlwm/AirportItlwmEthernetInterface.hpp b/AirportItlwm/AirportItlwmEthernetInterface.hpp new file mode 100644 index 000000000..0d6c5b5f3 --- /dev/null +++ b/AirportItlwm/AirportItlwmEthernetInterface.hpp @@ -0,0 +1,54 @@ +// +// AirportItlwmEthernetInterface.hpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef AirportItlwmEthernetInterface_hpp +#define AirportItlwmEthernetInterface_hpp + +extern "C" { +#include +} +#include "Airport/Apple80211.h" +#include +#include +#include +#include + +class AirportItlwmEthernetInterface : public IOEthernetInterface { + OSDeclareDefaultStructors(AirportItlwmEthernetInterface) + +public: + virtual IOReturn attachToDataLinkLayer( IOOptionBits options, + void * parameter ) override; + + virtual void detachFromDataLinkLayer( IOOptionBits options, + void * parameter ) override; + + virtual bool initWithSkywalkInterfaceAndProvider(IONetworkController *controller, IO80211SkywalkInterface *interface); + + virtual bool setLinkState(IO80211LinkState state); + + static errno_t bpfOutputPacket(ifnet_t interface, u_int32_t data_link_type, + mbuf_t packet); + + static errno_t bpfTap(ifnet_t interface, u_int32_t data_link_type, + bpf_tap_mode direction); + + virtual UInt32 inputPacket( + mbuf_t packet, + UInt32 length = 0, + IOOptionBits options = 0, + void * param = 0 ) override; + + virtual IOService * getProvider( void ) const override; + +private: + IO80211SkywalkInterface *interface; + bool isAttach; +}; + +#endif /* AirportItlwmEthernetInterface_hpp */ diff --git a/AirportItlwm/AirportItlwmSkywalkInterface.cpp b/AirportItlwm/AirportItlwmSkywalkInterface.cpp new file mode 100644 index 000000000..7ac518c2b --- /dev/null +++ b/AirportItlwm/AirportItlwmSkywalkInterface.cpp @@ -0,0 +1,1010 @@ +// +// AirportItlwmSkywalkInterface.cpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// +#include "AirportItlwmV2.hpp" +#include "AirportItlwmSkywalkInterface.hpp" +#include +#include +#include +#include +#include +#include + +#define super IO80211InfraProtocol +OSDefineMetaClassAndStructors(AirportItlwmSkywalkInterface, IO80211InfraProtocol); + +const char* hexdump(uint8_t *buf, size_t len) { + ssize_t str_len = len * 3 + 1; + char *str = (char*)IOMalloc(str_len); + if (!str) + return nullptr; + for (size_t i = 0; i < len; i++) + snprintf(str + 3 * i, (len - i) * 3, "%02x ", buf[i]); + str[MAX(str_len - 2, 0)] = 0; + return str; +} + +static int ieeeChanFlag2appleScanFlagVentura(int flags) +{ + int ret = 0; + if (flags & IEEE80211_CHAN_2GHZ) + ret |= APPLE80211_C_FLAG_2GHZ; + if (flags & IEEE80211_CHAN_5GHZ) + ret |= APPLE80211_C_FLAG_5GHZ; + ret |= (APPLE80211_C_FLAG_ACTIVE | APPLE80211_C_FLAG_20MHZ); + return ret; +} + +static int ieeeChanFlag2apple(int flags, int bw) +{ + int ret = 0; + if (flags & IEEE80211_CHAN_2GHZ) + ret |= APPLE80211_C_FLAG_2GHZ; + if (flags & IEEE80211_CHAN_5GHZ) + ret |= APPLE80211_C_FLAG_5GHZ; + if (!(flags & IEEE80211_CHAN_PASSIVE)) + ret |= APPLE80211_C_FLAG_ACTIVE; + if (flags & IEEE80211_CHAN_DFS) + ret |= APPLE80211_C_FLAG_DFS; + if (bw == -1) { + if (flags & IEEE80211_CHAN_VHT) { + if ((flags & IEEE80211_CHAN_VHT160) || (flags & IEEE80211_CHAN_VHT80_80)) + ret |= APPLE80211_C_FLAG_160MHZ; + if (flags & IEEE80211_CHAN_VHT80) + ret |= APPLE80211_C_FLAG_80MHZ; + } else if ((flags & IEEE80211_CHAN_HT40) && (flags & IEEE80211_CHAN_HT)) { + ret |= APPLE80211_C_FLAG_40MHZ; + if (flags & IEEE80211_CHAN_HT40U) + ret |= APPLE80211_C_FLAG_EXT_ABV; + } else if (flags & IEEE80211_CHAN_HT20) + ret |= APPLE80211_C_FLAG_20MHZ; + else if ((flags & IEEE80211_CHAN_CCK) || (flags & IEEE80211_CHAN_OFDM)) + ret |= APPLE80211_C_FLAG_10MHZ; + } else { + switch (bw) { + case IEEE80211_CHAN_WIDTH_80P80: + case IEEE80211_CHAN_WIDTH_160: + ret |= APPLE80211_C_FLAG_160MHZ; + break; + case IEEE80211_CHAN_WIDTH_80: + ret |= APPLE80211_C_FLAG_80MHZ; + break; + case IEEE80211_CHAN_WIDTH_40: + ret |= APPLE80211_C_FLAG_40MHZ; + if (flags & IEEE80211_CHAN_HT40U) + ret |= APPLE80211_C_FLAG_EXT_ABV; + break; + case IEEE80211_CHAN_WIDTH_20: + ret |= APPLE80211_C_FLAG_20MHZ; + break; + default: + if (flags & IEEE80211_CHAN_HT20) + ret |= APPLE80211_C_FLAG_20MHZ; + else if ((flags & IEEE80211_CHAN_CCK) || (flags & IEEE80211_CHAN_OFDM)) + ret |= APPLE80211_C_FLAG_10MHZ; + break; + } + } + return ret; +} + +void AirportItlwmSkywalkInterface::associateSSID(uint8_t *ssid, uint32_t ssid_len, const struct ether_addr &bssid, uint32_t authtype_lower, uint32_t authtype_upper, uint8_t *key, uint32_t key_len, int key_index) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + + ieee80211_disable_rsn(ic); + ieee80211_disable_wep(ic); + + struct ieee80211_wpaparams wpa; + struct ieee80211_nwkey nwkey; + bzero(&wpa, sizeof(wpa)); + bzero(&nwkey, sizeof(nwkey)); + + memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); + memcpy(ic->ic_des_essid, ssid, ssid_len); + ic->ic_des_esslen = ssid_len; + + bool is_zero = true; + for (int i = 0; i < IEEE80211_ADDR_LEN; i++) + is_zero &= bssid.octet[i] == 0; + + if (!is_zero) { + IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid.octet); + ic->ic_flags |= IEEE80211_F_DESBSSID; + } + else { + memset(ic->ic_des_bssid, 0, IEEE80211_ADDR_LEN); + ic->ic_flags &= ~IEEE80211_F_DESBSSID; + } + + // AUTHTYPE_WPA3_SAE AUTHTYPE_WPA3_FT_SAE + // we don't really support WPA3, but we have announced we support WPA3 in card capability function. so we fake it as WPA2 to support some WPA2/WPA3 mix wifi connection. + if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_SAE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_SAE) { + wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2; + authtype_upper |= APPLE80211_AUTHTYPE_WPA2_PSK;// hack + } + // AUTHTYPE_WPA3_ENTERPRISE AUTHTYPE_WPA3_FT_ENTERPRISE + if (authtype_upper == APPLE80211_AUTHTYPE_WPA3_ENTERPRISE || authtype_upper == APPLE80211_AUTHTYPE_WPA3_FT_ENTERPRISE) { + wpa.i_protos |= IEEE80211_WPA_PROTO_WPA2; + authtype_upper |= APPLE80211_AUTHTYPE_WPA2;// hack + } + + if (authtype_upper & (APPLE80211_AUTHTYPE_WPA | APPLE80211_AUTHTYPE_WPA_PSK | APPLE80211_AUTHTYPE_WPA2 | APPLE80211_AUTHTYPE_WPA2_PSK | APPLE80211_AUTHTYPE_SHA256_PSK | APPLE80211_AUTHTYPE_SHA256_8021X)) { + XYLog("%s %d\n", __FUNCTION__, __LINE__); + wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2; + } + + if (authtype_upper & (APPLE80211_AUTHTYPE_WPA_PSK | APPLE80211_AUTHTYPE_WPA2_PSK | APPLE80211_AUTHTYPE_SHA256_PSK)) { + XYLog("%s %d\n", __FUNCTION__, __LINE__); + wpa.i_akms |= IEEE80211_WPA_AKM_PSK | IEEE80211_WPA_AKM_SHA256_PSK; + wpa.i_enabled = 1; + memcpy(ic->ic_psk, key, sizeof(ic->ic_psk)); + ic->ic_flags |= IEEE80211_F_PSK; + ieee80211_ioctl_setwpaparms(ic, &wpa); + } + if (authtype_upper & (APPLE80211_AUTHTYPE_WPA | APPLE80211_AUTHTYPE_WPA2 | APPLE80211_AUTHTYPE_SHA256_8021X)) { + XYLog("%s %d\n", __FUNCTION__, __LINE__); + wpa.i_akms |= IEEE80211_WPA_AKM_8021X | IEEE80211_WPA_AKM_SHA256_8021X; + wpa.i_enabled = 1; + ieee80211_ioctl_setwpaparms(ic, &wpa); + } + + if (authtype_lower == APPLE80211_AUTHTYPE_SHARED) { + XYLog("shared key authentication is not supported!\n"); + return; + } + + if (authtype_upper == APPLE80211_AUTHTYPE_NONE && authtype_lower == APPLE80211_AUTHTYPE_OPEN) { // Open or WEP Open System + if (key_len > 0) { + XYLog("%s %d\n", __FUNCTION__, __LINE__); + nwkey.i_wepon = IEEE80211_NWKEY_WEP; + nwkey.i_defkid = key_index + 1; + nwkey.i_key[key_index].i_keylen = (int)key_len; + nwkey.i_key[key_index].i_keydat = key; + ieee80211_ioctl_setnwkeys(ic, &nwkey); + } + } +} + +void AirportItlwmSkywalkInterface::setPTK(const u_int8_t *key, size_t key_len) { + struct ieee80211com *ic = fHalService->get80211Controller(); + struct ieee80211_node * ni = ic->ic_bss; + struct ieee80211_key *k; + int keylen; + + ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE; + + if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) { + u_int64_t prsc; + + /* check that key length matches that of pairwise cipher */ + keylen = ieee80211_cipher_keylen(ni->ni_rsncipher); + if (key_len != keylen) { + XYLog("PTK length mismatch. expected %d, got %zu\n", keylen, key_len); + return; + } + prsc = /*(gtk == NULL) ? LE_READ_6(key->rsc) :*/ 0; + + /* map PTK to 802.11 key */ + k = &ni->ni_pairwise_key; + memset(k, 0, sizeof(*k)); + k->k_cipher = ni->ni_rsncipher; + k->k_rsc[0] = prsc; + k->k_len = keylen; + memcpy(k->k_key, key, k->k_len); + /* install the PTK */ + if ((*ic->ic_set_key)(ic, ni, k) != 0) { + XYLog("setting PTK failed\n"); + return; + } + else + XYLog("setting PTK successfully\n"); + ni->ni_flags &= ~IEEE80211_NODE_RSN_NEW_PTK; + ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT; + ni->ni_flags |= IEEE80211_NODE_RXPROT; + } else if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) + XYLog("%s: unexpected pairwise key update received from %s\n", + ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr)); +} + +void AirportItlwmSkywalkInterface::setGTK(const u_int8_t *gtk, size_t key_len, u_int8_t kid, u_int8_t *rsc) { + struct ieee80211com *ic = fHalService->get80211Controller(); + struct ieee80211_node * ni = ic->ic_bss; + struct ieee80211_key *k; + int keylen; + + if (gtk != NULL) { + /* check that key length matches that of group cipher */ + keylen = ieee80211_cipher_keylen(ni->ni_rsngroupcipher); + if (key_len != keylen) { + XYLog("GTK length mismatch. expected %d, got %zu\n", keylen, key_len); + return; + } + /* map GTK to 802.11 key */ + k = &ic->ic_nw_keys[kid]; + if (k->k_cipher == IEEE80211_CIPHER_NONE || k->k_len != keylen || memcmp(k->k_key, gtk, keylen) != 0) { + memset(k, 0, sizeof(*k)); + k->k_id = kid; /* 0-3 */ + k->k_cipher = ni->ni_rsngroupcipher; + k->k_flags = IEEE80211_KEY_GROUP; + //if (gtk[6] & (1 << 2)) + // k->k_flags |= IEEE80211_KEY_TX; + k->k_rsc[0] = LE_READ_6(rsc); + k->k_len = keylen; + memcpy(k->k_key, gtk, k->k_len); + /* install the GTK */ + if ((*ic->ic_set_key)(ic, ni, k) != 0) { + XYLog("setting GTK failed\n"); + return; + } + else + XYLog("setting GTK successfully\n"); + } + } + + if (true) { + ni->ni_flags |= IEEE80211_NODE_TXRXPROT; +#ifndef IEEE80211_STA_ONLY + if (ic->ic_opmode != IEEE80211_M_IBSS || + ++ni->ni_key_count == 2) +#endif + { + XYLog("marking port %s valid\n", + ether_sprintf(ni->ni_macaddr)); + ni->ni_port_valid = 1; + ieee80211_set_link_state(ic, LINK_STATE_UP); + ni->ni_assoc_fail = 0; + if (ic->ic_opmode == IEEE80211_M_STA) + ic->ic_rsngroupcipher = ni->ni_rsngroupcipher; + } + } +} + +bool AirportItlwmSkywalkInterface:: +init(IOService *provider) +{ + bool ret = IO80211InfraInterface::init(); + if (!ret) { + XYLog("%s IO80211InfraInterface init failed\n", __PRETTY_FUNCTION__); + return false; + } + instance = OSDynamicCast(AirportItlwm, provider); + if (!instance) + return false; + this->fHalService = instance->fHalService; + this->scanSource = instance->scanSource; + return ret; +} + +//ifnet_t AirportItlwmSkywalkInterface:: +//getBSDInterface() +//{ +// if (instance->bsdInterface) +// return instance->bsdInterface->getIfnet(); +// return NULL; +//} + +IOReturn AirportItlwmSkywalkInterface:: +getSSID(struct apple80211_ssid_data *sd) +{ + struct ieee80211com * ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(sd, 0, sizeof(*sd)); + sd->version = APPLE80211_VERSION; + memcpy(sd->ssid_bytes, ic->ic_des_essid, strlen((const char*)ic->ic_des_essid)); + sd->ssid_len = (uint32_t)strlen((const char*)ic->ic_des_essid); + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getAUTH_TYPE(struct apple80211_authtype_data *ad) +{ + ad->version = APPLE80211_VERSION; + ad->authtype_lower = current_authtype_lower; + ad->authtype_upper = current_authtype_upper; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setAUTH_TYPE(struct apple80211_authtype_data *ad) +{ + current_authtype_lower = ad->authtype_lower; + current_authtype_upper = ad->authtype_upper; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setCIPHER_KEY(struct apple80211_key *key) +{ + XYLog("%s\n", __FUNCTION__); + const char* keydump = hexdump(key->key, key->key_len); + const char* rscdump = hexdump(key->key_rsc, key->key_rsc_len); + const char* eadump = hexdump(key->key_ea.octet, APPLE80211_ADDR_LEN); + static_assert(__offsetof(struct apple80211_key, key_ea) == 92, "struct corrupted"); + static_assert(__offsetof(struct apple80211_key, key_rsc_len) == 80, "struct corrupted"); + static_assert(__offsetof(struct apple80211_key, wowl_kck_len) == 100, "struct corrupted"); + static_assert(__offsetof(struct apple80211_key, wowl_kek_len) == 120, "struct corrupted"); + static_assert(__offsetof(struct apple80211_key, wowl_kck_key) == 104, "struct corrupted"); + if (keydump && rscdump && eadump) + XYLog("Set key request: len=%d cipher_type=%d flags=%d index=%d key=%s rsc_len=%d rsc=%s ea=%s\n", + key->key_len, key->key_cipher_type, key->key_flags, key->key_index, keydump, key->key_rsc_len, rscdump, eadump); + else + XYLog("Set key request, but failed to allocate memory for hexdump\n"); + + if (keydump) + IOFree((void*)keydump, 3 * key->key_len + 1); + if (rscdump) + IOFree((void*)rscdump, 3 * key->key_rsc_len + 1); + if (eadump) + IOFree((void*)eadump, 3 * APPLE80211_ADDR_LEN + 1); + + switch (key->key_cipher_type) { + case APPLE80211_CIPHER_NONE: + // clear existing key +// XYLog("Setting NONE key is not supported\n"); + break; + case APPLE80211_CIPHER_WEP_40: + case APPLE80211_CIPHER_WEP_104: + XYLog("Setting WEP key %d is not supported\n", key->key_index); + break; + case APPLE80211_CIPHER_TKIP: + case APPLE80211_CIPHER_AES_OCB: + case APPLE80211_CIPHER_AES_CCM: + switch (key->key_flags) { + case 4: // PTK + setPTK(key->key, key->key_len); + break; + case 0: // GTK + setGTK(key->key, key->key_len, key->key_index, key->key_rsc); + break; + } + break; + case APPLE80211_CIPHER_PMK: + XYLog("Setting WPA PMK is not supported\n"); + break; + case APPLE80211_CIPHER_MSK: + XYLog("Setting MSK\n"); + ieee80211_pmksa_add(fHalService->get80211Controller(), IEEE80211_AKM_8021X, + fHalService->get80211Controller()->ic_bss->ni_macaddr, key->key, 0); + break; + case APPLE80211_CIPHER_PMKSA: + XYLog("Setting WPA PMKSA\n"); + ieee80211_pmksa_add(fHalService->get80211Controller(), IEEE80211_AKM_8021X, + fHalService->get80211Controller()->ic_bss->ni_macaddr, key->key, 0); + break; + } + //fInterface->postMessage(APPLE80211_M_CIPHER_KEY_CHANGED); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getPHY_MODE(struct apple80211_phymode_data *pd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + + pd->version = APPLE80211_VERSION; + pd->phy_mode = APPLE80211_MODE_11A + | APPLE80211_MODE_11B + | APPLE80211_MODE_11G + | APPLE80211_MODE_11N; + + if (ic->ic_flags & IEEE80211_F_VHTON) + pd->phy_mode |= APPLE80211_MODE_11AC; + + if (ic->ic_flags & IEEE80211_F_HEON) + pd->phy_mode |= APPLE80211_MODE_11AX; + + switch (fHalService->get80211Controller()->ic_curmode) { + case IEEE80211_MODE_AUTO: + pd->active_phy_mode = APPLE80211_MODE_AUTO; + break; + case IEEE80211_MODE_11A: + pd->active_phy_mode = APPLE80211_MODE_11A; + break; + case IEEE80211_MODE_11B: + pd->active_phy_mode = APPLE80211_MODE_11B; + break; + case IEEE80211_MODE_11G: + pd->active_phy_mode = APPLE80211_MODE_11G; + break; + case IEEE80211_MODE_11N: + pd->active_phy_mode = APPLE80211_MODE_11N; + break; + case IEEE80211_MODE_11AC: + pd->active_phy_mode = APPLE80211_MODE_11AC; + break; + case IEEE80211_MODE_11AX: + pd->active_phy_mode = APPLE80211_MODE_11AX; + break; + + default: + pd->active_phy_mode = APPLE80211_MODE_AUTO; + break; + } + + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getCHANNEL(struct apple80211_channel_data *cd) +{ + struct ieee80211com * ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(cd, 0, sizeof(apple80211_channel_data)); + cd->version = APPLE80211_VERSION; + cd->channel.version = APPLE80211_VERSION; + cd->channel.channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); + cd->channel.flags = ieeeChanFlag2apple(ic->ic_bss->ni_chan->ic_flags, ic->ic_bss->ni_chw); + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getSTATE(struct apple80211_state_data *sd) +{ + memset(sd, 0, sizeof(*sd)); + sd->version = APPLE80211_VERSION; + sd->state = fHalService->get80211Controller()->ic_state; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getMCS_INDEX_SET(struct apple80211_mcs_index_set_data *ad) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(ad, 0, sizeof(*ad)); + ad->version = APPLE80211_VERSION; + size_t size = min(ARRAY_SIZE(ic->ic_bss->ni_rxmcs), ARRAY_SIZE(ad->mcs_set_map)); + for (int i = 0; i < size; i++) + ad->mcs_set_map[i] = ic->ic_bss->ni_rxmcs[i]; + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getVHT_MCS_INDEX_SET(struct apple80211_vht_mcs_index_set_data *data) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_bss == NULL || ic->ic_curmode < IEEE80211_MODE_11AC) { + return kIOReturnError; + } + memset(data, 0, sizeof(struct apple80211_vht_mcs_index_set_data)); + data->version = APPLE80211_VERSION; + data->mcs_map = ic->ic_bss->ni_vht_mcsinfo.tx_mcs_map; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getMCS_VHT(struct apple80211_mcs_vht_data *data) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_bss == NULL || ic->ic_curmode < IEEE80211_MODE_11AC) { + return kIOReturnError; + } + memset(data, 0, sizeof(struct apple80211_mcs_vht_data)); + data->version = APPLE80211_VERSION; + data->guard_interval = (ieee80211_node_supports_vht_sgi80(ic->ic_bss) || ieee80211_node_supports_vht_sgi160(ic->ic_bss)) ? APPLE80211_GI_SHORT : APPLE80211_GI_LONG; + data->index = ic->ic_bss->ni_txmcs; + data->nss = fHalService->getDriverInfo()->getTxNSS(); + switch (ic->ic_bss->ni_chw) { + case IEEE80211_CHAN_WIDTH_40: + data->bw = 40; + break; + case IEEE80211_CHAN_WIDTH_80: + data->bw = 80; + break; + case IEEE80211_CHAN_WIDTH_80P80: + case IEEE80211_CHAN_WIDTH_160: + data->bw = 160; + break; + + default: + data->bw = 20; + break; + } + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getRATE_SET(struct apple80211_rate_set_data *ad) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(ad, 0, sizeof(*ad)); + ad->version = APPLE80211_VERSION; + ad->num_rates = ic->ic_bss->ni_rates.rs_nrates; + size_t size = min(ic->ic_bss->ni_rates.rs_nrates, ARRAY_SIZE(ad->rates)); + for (int i=0; i < size; i++) { + struct apple80211_rate apple_rate = ad->rates[i]; + apple_rate.version = APPLE80211_VERSION; + apple_rate.rate = ic->ic_bss->ni_rates.rs_rates[i]; + apple_rate.flags = 0; + } + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getOP_MODE(struct apple80211_opmode_data *od) +{ + od->version = APPLE80211_VERSION; + od->op_mode = APPLE80211_M_STA; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getTXPOWER(struct apple80211_txpower_data *txd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(txd, 0, sizeof(*txd)); + txd->version = APPLE80211_VERSION; + txd->txpower = ic->ic_txpower; + txd->txpower_unit = APPLE80211_UNIT_PERCENT; + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getRATE(struct apple80211_rate_data *rd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_bss == NULL) + return 6; + int nss; + int sgi; + int index = 0; + if (ic->ic_state == IEEE80211_S_RUN) { + memset(rd, 0, sizeof(*rd)); + rd->version = APPLE80211_VERSION; + rd->num_radios = 1; + sgi = ieee80211_node_supports_sgi(ic->ic_bss); + if (ic->ic_curmode == IEEE80211_MODE_11AC) { + if (sgi) + index += 1; + nss = fHalService->getDriverInfo()->getTxNSS(); + switch (ic->ic_bss->ni_chw) { + case IEEE80211_CHAN_WIDTH_40: + index += 4; + break; + case IEEE80211_CHAN_WIDTH_80: + index += 8; + break; + case IEEE80211_CHAN_WIDTH_80P80: + case IEEE80211_CHAN_WIDTH_160: + index += 12; + break; + + default: + break; + } + index += 2 * (nss - 1); + const struct ieee80211_vht_rateset *rs = &ieee80211_std_ratesets_11ac[index]; + rd->rate[0] = rs->rates[ic->ic_bss->ni_txmcs % rs->nrates] / 2; + } else if (ic->ic_curmode == IEEE80211_MODE_11N) { + int is_40mhz = ic->ic_bss->ni_chw == IEEE80211_CHAN_WIDTH_40; + if (sgi) + index += 1; + if (is_40mhz) + index += (IEEE80211_HT_RATESET_MIMO4_SGI + 1); + index += (ic->ic_bss->ni_txmcs / 16); + nss = ic->ic_bss->ni_txmcs / 8 + 1; + index += 2 * (nss - 1); + rd->rate[0] = ieee80211_std_ratesets_11n[index].rates[ic->ic_bss->ni_txmcs % 8] / 2; + } else + rd->rate[0] = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate]; + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getBSSID(struct apple80211_bssid_data *bd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(bd, 0, sizeof(*bd)); + bd->version = APPLE80211_VERSION; + memcpy(bd->bssid.octet, ic->ic_bss->ni_bssid, APPLE80211_ADDR_LEN); + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getRSSI(struct apple80211_rssi_data *rd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(rd, 0, sizeof(*rd)); + rd->num_radios = 1; + rd->rssi_unit = APPLE80211_UNIT_DBM; + rd->rssi[0] = rd->aggregate_rssi + = rd->rssi_ext[0] + = rd->aggregate_rssi_ext + = -(0 - IWM_MIN_DBM - ic->ic_bss->ni_rssi); + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getRSN_IE(struct apple80211_rsn_ie_data *data) +{ +#ifdef USE_APPLE_SUPPLICANT + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_bss == NULL || ic->ic_bss->ni_rsnie == NULL) { + return kIOReturnError; + } + data->version = APPLE80211_VERSION; + if (ic->ic_rsn_ie_override[1] > 0) { + data->len = 2 + ic->ic_rsn_ie_override[1]; + memcpy(data->ie, ic->ic_rsn_ie_override, data->len); + } + else { + data->len = 2 + ic->ic_bss->ni_rsnie[1]; + memcpy(data->ie, ic->ic_bss->ni_rsnie, data->len); + } + return kIOReturnSuccess; +#else + return kIOReturnUnsupported; +#endif +} + +IOReturn AirportItlwmSkywalkInterface:: +setRSN_IE(struct apple80211_rsn_ie_data *data) +{ +#ifdef USE_APPLE_SUPPLICANT + struct ieee80211com *ic = fHalService->get80211Controller(); + if (!data) + return kIOReturnError; + static_assert(sizeof(ic->ic_rsn_ie_override) == APPLE80211_MAX_RSN_IE_LEN, "Max RSN IE length mismatch"); + memcpy(ic->ic_rsn_ie_override, data->ie, APPLE80211_MAX_RSN_IE_LEN); + if (ic->ic_state == IEEE80211_S_RUN && ic->ic_bss != nullptr) + ieee80211_save_ie(data->ie, &ic->ic_bss->ni_rsnie); + return kIOReturnSuccess; +#else + return kIOReturnUnsupported; +#endif +} + +IOReturn AirportItlwmSkywalkInterface:: +getAP_IE_LIST(struct apple80211_ap_ie_data *data) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (!data) + return kIOReturnError; + if (ic->ic_bss == NULL || ic->ic_bss->ni_rsnie_tlv == NULL || ic->ic_bss->ni_rsnie_tlv_len == 0 || ic->ic_bss->ni_rsnie_tlv_len > data->len || ic->ic_bss->ni_rsnie_tlv_len > 1024) + return kIOReturnError; + data->version = APPLE80211_VERSION; + data->len = ic->ic_bss->ni_rsnie_tlv_len; + memcpy(data->ie_data, ic->ic_bss->ni_rsnie_tlv, data->len); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getNOISE(struct apple80211_noise_data *nd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state == IEEE80211_S_RUN) { + memset(nd, 0, sizeof(*nd)); + nd->version = APPLE80211_VERSION; + nd->num_radios = 1; + nd->noise[0] + = nd->aggregate_noise = -fHalService->getDriverInfo()->getBSSNoise(); + nd->noise_unit = APPLE80211_UNIT_DBM; + return kIOReturnSuccess; + } + return 6; +} + +IOReturn AirportItlwmSkywalkInterface:: +getPOWERSAVE(struct apple80211_powersave_data *pd) +{ + pd->version = APPLE80211_VERSION; + pd->powersave_level = APPLE80211_POWERSAVE_MODE_DISABLED; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getNSS(struct apple80211_nss_data *data) +{ + memset(data, 0, sizeof(*data)); + data->version = APPLE80211_VERSION; + data->nss = fHalService->getDriverInfo()->getTxNSS(); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setASSOCIATE(struct apple80211_assoc_data *ad) +{ + XYLog("%s [%s] mode=%d ad_auth_lower=%d ad_auth_upper=%d rsn_ie_len=%d%s%s%s%s%s%s%s\n", __FUNCTION__, ad->ad_ssid, ad->ad_mode, ad->ad_auth_lower, ad->ad_auth_upper, ad->ad_rsn_ie_len, + (ad->ad_flags & 2) ? ", Instant Hotspot" : "", + (ad->ad_flags & 4) ? ", Auto Instant Hotspot" : "", + (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 1) ? ", don't disassociate" : "", + (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 2) ? ", don't blacklist" : "", + (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 4) ? ", closed Network" : "", + (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 8) ? ", 802.1X" : "", + (ad->ad_rsn_ie[APPLE80211_MAX_RSN_IE_LEN] & 0x20) ? ", force BSSID" : ""); + + struct apple80211_rsn_ie_data rsn_ie_data; + struct apple80211_authtype_data auth_type_data; + struct ieee80211com *ic = fHalService->get80211Controller(); + + if (!ad) + return kIOReturnError; + + if (ic->ic_state < IEEE80211_S_SCAN) + return kIOReturnSuccess; + + if (ic->ic_state == IEEE80211_S_ASSOC || ic->ic_state == IEEE80211_S_AUTH) + return kIOReturnSuccess; + + if (ad->ad_mode != APPLE80211_AP_MODE_IBSS) { + disassocIsVoluntary = false; + auth_type_data.version = APPLE80211_VERSION; + auth_type_data.authtype_upper = ad->ad_auth_upper; + auth_type_data.authtype_lower = ad->ad_auth_lower; + setAUTH_TYPE(&auth_type_data); + rsn_ie_data.version = APPLE80211_VERSION; + rsn_ie_data.len = ad->ad_rsn_ie[1] + 2; + memcpy(rsn_ie_data.ie, ad->ad_rsn_ie, rsn_ie_data.len); + setRSN_IE(&rsn_ie_data); + + associateSSID(ad->ad_ssid, ad->ad_ssid_len, ad->ad_bssid, ad->ad_auth_lower, ad->ad_auth_upper, ad->ad_key.key, ad->ad_key.key_len, ad->ad_key.key_index); + } + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setDISASSOCIATE(struct apple80211_disassoc_data *ad) +{ + XYLog("%s\n", __FUNCTION__); + struct ieee80211com *ic = fHalService->get80211Controller(); + + if (ic->ic_state < IEEE80211_S_SCAN) + return kIOReturnSuccess; + + if (ic->ic_state > IEEE80211_S_AUTH && ic->ic_bss != NULL) + IEEE80211_SEND_MGMT(ic, ic->ic_bss, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE); + + if (ic->ic_state == IEEE80211_S_ASSOC || ic->ic_state == IEEE80211_S_AUTH) + return kIOReturnSuccess; + + disassocIsVoluntary = true; + + ieee80211_del_ess(ic, nullptr, 0, 1); + ieee80211_deselect_ess(ic); +#ifdef USE_APPLE_SUPPLICANT + ic->ic_rsn_ie_override[1] = 0; +#endif + ic->ic_assoc_status = APPLE80211_STATUS_UNAVAILABLE; + ic->ic_deauth_reason = APPLE80211_REASON_ASSOC_LEAVING; + ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getSUPPORTED_CHANNELS(struct apple80211_sup_channel_data *ad) +{ + if (!ad) + return kIOReturnError; + ad->version = APPLE80211_VERSION; + ad->num_channels = 0; + struct ieee80211com *ic = fHalService->get80211Controller(); + for (int i = 0; i < IEEE80211_CHAN_MAX; i++) { + if (ic->ic_channels[i].ic_freq != 0) { + ad->supported_channels[ad->num_channels].channel = ieee80211_chan2ieee(ic, &ic->ic_channels[i]); + ad->supported_channels[ad->num_channels].flags = ieeeChanFlag2appleScanFlagVentura(ic->ic_channels[i].ic_flags); + ad->num_channels++; + } + } + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getLOCALE(struct apple80211_locale_data *ld) +{ + if (!ld) + return kIOReturnError; + ld->version = APPLE80211_VERSION; + ld->locale = APPLE80211_LOCALE_FCC; + + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getDEAUTH(struct apple80211_deauth_data *da) +{ + if (!da) + return kIOReturnError; + da->version = APPLE80211_VERSION; + struct ieee80211com *ic = fHalService->get80211Controller(); + da->deauth_reason = ic->ic_deauth_reason; +// XYLog("%s, %d\n", __FUNCTION__, da->deauth_reason); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getASSOCIATION_STATUS(struct apple80211_assoc_status_data *hv) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + + if (!hv) + return kIOReturnError; + memset(hv, 0, sizeof(*hv)); + hv->version = APPLE80211_VERSION; + if (ic->ic_state == IEEE80211_S_RUN) + hv->status = APPLE80211_STATUS_SUCCESS; + else + hv->status = APPLE80211_STATUS_UNAVAILABLE; +// XYLog("%s, %d\n", __FUNCTION__, hv->status); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setSCANCACHE_CLEAR(void *req) +{ + XYLog("%s\n", __FUNCTION__); + struct ieee80211com *ic = fHalService->get80211Controller(); + //if doing background or active scan, don't free nodes. + if ((ic->ic_flags & IEEE80211_F_BGSCAN) || (ic->ic_flags & IEEE80211_F_ASCAN)) + return kIOReturnSuccess; + ieee80211_free_allnodes(ic, 0); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setDEAUTH(struct apple80211_deauth_data *da) +{ + XYLog("%s\n", __FUNCTION__); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getMCS(struct apple80211_mcs_data* md) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); + if (ic->ic_state != IEEE80211_S_RUN || ic->ic_bss == NULL || !md) + return 6; + md->version = APPLE80211_VERSION; + md->index = ic->ic_bss->ni_txmcs; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getLINK_CHANGED_EVENT_DATA(struct apple80211_link_changed_event_data *ed) +{ + if (ed == nullptr) + return 16; + + struct ieee80211com *ic = fHalService->get80211Controller(); + + bzero(ed, sizeof(apple80211_link_changed_event_data)); + ed->isLinkDown = !(instance->currentStatus & kIONetworkLinkActive); + if (ed->isLinkDown) { + ed->voluntary = disassocIsVoluntary; + ed->reason = APPLE80211_LINK_DOWN_REASON_DEAUTH; + } else + ed->rssi = -(0 - IWM_MIN_DBM - ic->ic_bss->ni_rssi); + XYLog("Link %s, reason: %d, voluntary: %d\n", ed->isLinkDown ? "down" : "up", ed->reason, ed->voluntary); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +setSCAN_REQ(struct apple80211_scan_data *sd) +{ + struct ieee80211com *ic = fHalService->get80211Controller(); +#if 0 + XYLog("%s Type: %u BSS Type: %u PHY Mode: %u Dwell time: %u Rest time: %u Num channels: %u SSID: %s BSSID: %s\n", + __FUNCTION__, + sd->scan_type, + sd->bss_type, + sd->phy_mode, + sd->dwell_time, + sd->rest_time, + sd->num_channels, + sd->ssid, + ether_sprintf(sd->bssid.octet)); +#endif + if (fScanResultWrapping) + return 22; + if (ic->ic_state <= IEEE80211_S_INIT) + return 22; + if (sd->scan_type == APPLE80211_SCAN_TYPE_FAST || sd->scan_type == APPLE80211_SCAN_TYPE_PASSIVE) { + if (scanSource) { + scanSource->setTimeoutMS(100); + scanSource->enable(); + } + return kIOReturnSuccess; + } + ieee80211_begin_cache_bgscan(&ic->ic_ac.ac_if); + if (scanSource) { + scanSource->setTimeoutMS(100); + scanSource->enable(); + } + return kIOReturnSuccess; +} + +extern OSDictionary *convertScanToDictionary(apple80211_scan_result *a1); + +static int convertNodeToScanResult(ItlHalService *fHalService, struct ieee80211_node *fNextNodeToSend, apple80211_scan_result *result) +{ + bzero(result, sizeof(*result)); + result->version = APPLE80211_VERSION; + if (fNextNodeToSend->ni_rsnie_tlv && fNextNodeToSend->ni_rsnie_tlv_len > 0) { + result->asr_ie_len = fNextNodeToSend->ni_rsnie_tlv_len; + memcpy(result->asr_ie_data, fNextNodeToSend->ni_rsnie_tlv, MIN(result->asr_ie_len, sizeof(result->asr_ie_data))); + } else { + result->asr_ie_len = 0; + } + result->asr_beacon_int = fNextNodeToSend->ni_intval; + for (int i = 0; i < result->asr_nrates; i++ ) + result->asr_rates[i] = fNextNodeToSend->ni_rates.rs_rates[i]; + result->asr_nrates = fNextNodeToSend->ni_rates.rs_nrates; + result->asr_age = (uint32_t)(airport_up_time() - fNextNodeToSend->ni_age_ts); + result->asr_cap = fNextNodeToSend->ni_capinfo; + result->asr_channel.version = APPLE80211_VERSION; + result->asr_channel.channel = ieee80211_chan2ieee(fHalService->get80211Controller(), fNextNodeToSend->ni_chan); + result->asr_channel.flags = ieeeChanFlag2appleScanFlagVentura(fNextNodeToSend->ni_chan->ic_flags); + result->asr_noise = -fHalService->getDriverInfo()->getBSSNoise(); + result->asr_rssi = -(0 - IWM_MIN_DBM - fNextNodeToSend->ni_rssi); + memcpy(result->asr_bssid, fNextNodeToSend->ni_bssid, IEEE80211_ADDR_LEN); + result->asr_ssid_len = fNextNodeToSend->ni_esslen; + if (result->asr_ssid_len != 0) + memcpy(&result->asr_ssid, fNextNodeToSend->ni_essid, result->asr_ssid_len); + return 0; +} + +IOReturn AirportItlwmSkywalkInterface:: +getCURRENT_NETWORK(apple80211_scan_result *sr) +{ + if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || fHalService->get80211Controller()->ic_bss == NULL) + return kIOReturnError; + convertNodeToScanResult(fHalService, fHalService->get80211Controller()->ic_bss, sr); + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getCOLOCATED_NETWORK_SCOPE_ID(apple80211_colocated_network_scope_id *as) +{ + if (!as) + return kIOReturnBadArgument; + as->version = APPLE80211_VERSION; + return kIOReturnSuccess; +} + +IOReturn AirportItlwmSkywalkInterface:: +getSCAN_RESULT(struct apple80211_scan_result *sr) +{ + if (fNextNodeToSend == NULL) { + if (fScanResultWrapping) { + fScanResultWrapping = false; + return 5; + } else { + fNextNodeToSend = RB_MIN(ieee80211_tree, &fHalService->get80211Controller()->ic_tree); + if (fNextNodeToSend == NULL) { + return 5; + } + } + } +// XYLog("%s ni_bssid=%s ni_essid=%s channel=%d flags=%d asr_cap=%d asr_nrates=%d asr_ssid_len=%d asr_ie_len=%d asr_rssi=%d\n", __FUNCTION__, ether_sprintf(fNextNodeToSend->ni_bssid), fNextNodeToSend->ni_essid, ieee80211_chan2ieee(ic, fNextNodeToSend->ni_chan), ieeeChanFlag2apple(fNextNodeToSend->ni_chan->ic_flags, -1), fNextNodeToSend->ni_capinfo, fNextNodeToSend->ni_rates.rs_nrates, fNextNodeToSend->ni_esslen, fNextNodeToSend->ni_rsnie_tlv == NULL ? 0 : fNextNodeToSend->ni_rsnie_tlv_len, fNextNodeToSend->ni_rssi); + convertNodeToScanResult(fHalService, fNextNodeToSend, sr); + + fNextNodeToSend = RB_NEXT(ieee80211_tree, &HalService->get80211Controller()->ic_tree, fNextNodeToSend); + if (fNextNodeToSend == NULL) + fScanResultWrapping = true; + + return kIOReturnSuccess; +} diff --git a/AirportItlwm/AirportItlwmSkywalkInterface.hpp b/AirportItlwm/AirportItlwmSkywalkInterface.hpp new file mode 100644 index 000000000..6f2604f87 --- /dev/null +++ b/AirportItlwm/AirportItlwmSkywalkInterface.hpp @@ -0,0 +1,21 @@ +#ifndef AirportItlwmSkywalkInterface_hpp +#define AirportItlwmSkywalkInterface_hpp + +#include + +class AirportItlwmSkywalkInterface : public IO80211InfraProtocol { + OSDeclareDefaultStructors(AirportItlwmSkywalkInterface) + +public: + virtual bool init(IOService *) override; + + void associateSSID(uint8_t *ssid, uint32_t ssid_len, const struct ether_addr &bssid, uint32_t authtype_lower, uint32_t authtype_upper, uint8_t *key, uint32_t key_len, int key_index); + void setPTK(const u_int8_t *key, size_t key_len); + void setGTK(const u_int8_t *key, size_t key_len, u_int8_t kid, u_int8_t *rsc); + +public: + virtual IOReturn getSSID(apple80211_ssid_data *) override; + virtual IOReturn getAUTH_TYPE(apple80211_authtype_data *) override; +}; + +#endif diff --git a/AirportItlwm/AirportItlwmV2.cpp b/AirportItlwm/AirportItlwmV2.cpp new file mode 100644 index 000000000..9d0485fec --- /dev/null +++ b/AirportItlwm/AirportItlwmV2.cpp @@ -0,0 +1,1053 @@ +// +// AirportItlwmV2.cpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#include "AirportItlwmV2.hpp" +#include +#include +#include +#include + +#include "AirportItlwmSkywalkInterface.hpp" +#include "IOPCIEDeviceWrapper.hpp" + +#define super IO80211Controller +OSDefineMetaClassAndStructors(AirportItlwm, IO80211Controller); +OSDefineMetaClassAndStructors(CTimeout, OSObject) + +IO80211WorkQueue *_fWorkloop; +IOCommandGate *_fCommandGate; + +void AirportItlwm::releaseAll() +{ + OSSafeReleaseNULL(driverLogPipe); + OSSafeReleaseNULL(driverDataPathPipe); + OSSafeReleaseNULL(driverSnapshotsPipe); + OSSafeReleaseNULL(driverFaultReporter); + if (fHalService) { + fHalService->release(); + fHalService = NULL; + } + if (_fWorkloop) { + if (_fCommandGate) { +// _fCommandGate->disable(); + _fWorkloop->removeEventSource(_fCommandGate); + _fCommandGate->release(); + _fCommandGate = NULL; + } + if (scanSource) { + scanSource->cancelTimeout(); + scanSource->disable(); + _fWorkloop->removeEventSource(scanSource); + scanSource->release(); + scanSource = NULL; + } + if (fWatchdogWorkLoop && watchdogTimer) { + watchdogTimer->cancelTimeout(); + fWatchdogWorkLoop->removeEventSource(watchdogTimer); + watchdogTimer->release(); + watchdogTimer = NULL; + fWatchdogWorkLoop->release(); + fWatchdogWorkLoop = NULL; + } + _fWorkloop->release(); + _fWorkloop = NULL; + } + unregistPM(); +} + +void AirportItlwm:: +eventHandler(struct ieee80211com *ic, int msgCode, void *data) +{ + AirportItlwm *that = OSDynamicCast(AirportItlwm, ic->ic_ac.ac_if.controller); + IO80211SkywalkInterface *interface = that->fNetIf; + if (!interface) + return; + switch (msgCode) { + case IEEE80211_EVT_COUNTRY_CODE_UPDATE: + interface->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED, NULL, 0, 0); + break; + case IEEE80211_EVT_STA_ASSOC_DONE: + interface->postMessage(APPLE80211_M_ASSOC_DONE, NULL, 0, 0); + break; + case IEEE80211_EVT_STA_DEAUTH: + interface->postMessage(APPLE80211_M_DEAUTH_RECEIVED, NULL, 0, 0); + break; + default: + break; + } +} + +void AirportItlwm::watchdogAction(IOTimerEventSource *timer) +{ + struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; + (*ifp->if_watchdog)(ifp); + watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod); +} + +void AirportItlwm::fakeScanDone(OSObject *owner, IOTimerEventSource *sender) +{ + UInt32 msg = 0; + AirportItlwm *that = (AirportItlwm *)owner; + that->fNetIf->postMessage(APPLE80211_M_SCAN_DONE, &msg, 4, 0); +} + +bool AirportItlwm::init(OSDictionary *properties) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + bool ret = super::init(properties); + awdlSyncEnable = true; + power_state = 0; + memset(geo_location_cc, 0, sizeof(geo_location_cc)); + return ret; +} + +IOService* AirportItlwm::probe(IOService *provider, SInt32 *score) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + IOPCIEDeviceWrapper *wrapper = OSDynamicCast(IOPCIEDeviceWrapper, provider); + if (!wrapper) { + XYLog("%s Not a IOPCIEDeviceWrapper instance\n", __FUNCTION__); + return NULL; + } + pciNub = wrapper->pciNub; + fHalService = wrapper->fHalService; + if (!pciNub || !fHalService) { + XYLog("%s Not a valid IOPCIEDeviceWrapper instance\n", __FUNCTION__); + return NULL; + } + return super::probe(provider, score); +} + +#define LOWER32(x) ((uint64_t)(x) & 0xffffffff) +#define HIGHER32(x) ((uint64_t)(x) >> 32) + +bool AirportItlwm:: +initCCLogs() +{ + CCPipeOptions driverLogOptions = { 0 }; + driverLogOptions.pipe_type = 0; + driverLogOptions.log_data_type = 1; + driverLogOptions.pipe_size = 0x200000; + driverLogOptions.min_log_size_notify = 0xccccc; + driverLogOptions.notify_threshold = 1000; + strlcpy(driverLogOptions.file_name, "Itlwm_Logs", sizeof(driverLogOptions.file_name)); + snprintf(driverLogOptions.name, sizeof(driverLogOptions.name), "wlan%d", 0); + strlcpy(driverLogOptions.directory_name, "WiFi", sizeof(driverLogOptions.directory_name)); + driverLogOptions.pad9 = 0x1000000; + driverLogOptions.pad10 = 2; + driverLogOptions.file_options = 0; + driverLogOptions.log_policy = 0; + driverLogPipe = CCPipe::withOwnerNameCapacity(this, "com.zxystd.AirportItlwm", "DriverLogs", &driverLogOptions); + XYLog("%s driverLogPipeRet %d\n", __FUNCTION__, driverLogPipe != NULL); + + memset(&driverLogOptions, 0, sizeof(driverLogOptions)); + driverLogOptions.pipe_type = 0; + driverLogOptions.log_data_type = 0; + driverLogOptions.pipe_size = 0x200000; + driverLogOptions.min_log_size_notify = 0xccccc; + driverLogOptions.notify_threshold = 1000; + strlcpy(driverLogOptions.file_name, "AppleBCMWLAN_Datapath", sizeof(driverLogOptions.file_name)); + strlcpy(driverLogOptions.directory_name, "WiFi", sizeof(driverLogOptions.directory_name)); + driverLogOptions.pad9 = HIGHER32(0x202800000); + driverLogOptions.pad10 = LOWER32(0x202800000); + driverLogOptions.file_options = 0; + driverLogOptions.log_policy = 0; + driverDataPathPipe = CCPipe::withOwnerNameCapacity(this, "com.zxystd.AirportItlwm", "DatapathEvents", &driverLogOptions); + XYLog("%s driverDataPathPipeRet %d\n", __FUNCTION__, driverDataPathPipe != NULL); + + memset(&driverLogOptions, 0, sizeof(driverLogOptions)); + driverLogOptions.pipe_type = 0x200000001; + driverLogOptions.log_data_type = 2; + strlcpy(driverLogOptions.file_name, "StateSnapshots", sizeof(driverLogOptions.file_name)); + strlcpy(driverLogOptions.name, "0", sizeof(driverLogOptions.name)); + strlcpy(driverLogOptions.directory_name, "WiFi", sizeof(driverLogOptions.directory_name)); + driverLogOptions.pipe_size = 128; + driverSnapshotsPipe = CCPipe::withOwnerNameCapacity(this, "com.zxystd.AirportItlwm", "StateSnapshots", &driverLogOptions); + XYLog("%s driverSnapshotsPipeRet %d\n", __FUNCTION__, driverSnapshotsPipe != NULL); + + CCStreamOptions faultReportOptions = { 0 }; + faultReportOptions.stream_type = 1; + faultReportOptions.console_level = 0xFFFFFFFFFFFFFFFF; + driverFaultReporter = CCStream::withPipeAndName(driverSnapshotsPipe, "FaultReporter", &faultReportOptions); + XYLog("%s driverFaultReporterRet %d\n", __FUNCTION__, driverFaultReporter != NULL); + return driverLogPipe && driverDataPathPipe && driverSnapshotsPipe && driverFaultReporter; +} + +bool AirportItlwm::start(IOService *provider) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + struct IOSkywalkEthernetInterface::RegistrationInfo registInfo; + int boot_value = 0; + + UInt8 builtIn = 0; + setProperty("built-in", OSData::withBytes(&builtIn, sizeof(builtIn))); + setProperty("DriverKitDriver", kOSBooleanFalse); + if (!super::start(provider)) { + return false; + } + pciNub->setBusMasterEnable(true); + pciNub->setIOEnable(true); + pciNub->setMemoryEnable(true); + pciNub->configWrite8(0x41, 0); + if (pciNub->requestPowerDomainState(kIOPMPowerOn, + (IOPowerConnection *) getParentEntry(gIOPowerPlane), IOPMLowestState) != IOPMNoErr) { + super::stop(provider); + return false; + } + if (initPCIPowerManagment(pciNub) == false) { + super::stop(pciNub); + return false; + } + if (_fWorkloop == NULL) { + XYLog("No _fWorkloop!!\n"); + super::stop(pciNub); + releaseAll(); + return false; + } + _fCommandGate = IOCommandGate::commandGate(this, (IOCommandGate::Action)AirportItlwm::tsleepHandler); + if (_fCommandGate == 0) { + XYLog("No command gate!!\n"); + super::stop(pciNub); + releaseAll(); + return false; + } + _fWorkloop->addEventSource(_fCommandGate); + const IONetworkMedium *primaryMedium; + if (!createMediumTables(&primaryMedium) || + !setCurrentMedium(primaryMedium) || !setSelectedMedium(primaryMedium)) { + XYLog("setup medium fail\n"); + releaseAll(); + return false; + } + fHalService->initWithController(this, _fWorkloop, _fCommandGate); + fHalService->get80211Controller()->ic_event_handler = eventHandler; + + if (PE_parse_boot_argn("-novht", &boot_value, sizeof(boot_value))) + fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOVHT; + if (PE_parse_boot_argn("-noht40", &boot_value, sizeof(boot_value))) + fHalService->get80211Controller()->ic_userflags |= IEEE80211_F_NOHT40; + + if (!fHalService->attach(pciNub)) { + XYLog("attach fail\n"); + super::stop(pciNub); + releaseAll(); + return false; + } + fWatchdogWorkLoop = IOWorkLoop::workLoop(); + if (fWatchdogWorkLoop == NULL) { + XYLog("init watchdog workloop fail\n"); + fHalService->detach(pciNub); + super::stop(pciNub); + releaseAll(); + return false; + } + watchdogTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &AirportItlwm::watchdogAction)); + if (!watchdogTimer) { + XYLog("init watchdog fail\n"); + fHalService->detach(pciNub); + super::stop(pciNub); + releaseAll(); + return false; + } + fWatchdogWorkLoop->addEventSource(watchdogTimer); + scanSource = IOTimerEventSource::timerEventSource(this, &fakeScanDone); + _fWorkloop->addEventSource(scanSource); + scanSource->enable(); + + fNetIf = new AirportItlwmSkywalkInterface; + if (!fNetIf->init(this)) { + XYLog("Skywalk interface init fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + fNetIf->setInterfaceRole(1); + fNetIf->setInterfaceId(1); + + if (!initCCLogs()) { + XYLog("CCLog init fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + if (!fNetIf->attach(this)) { + XYLog("attach to service fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + if (!attachInterface(fNetIf, this)) { + XYLog("attach to interface fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + if (!IONetworkController::attachInterface((IONetworkInterface **)&bsdInterface, true)) { + XYLog("attach to IONetworkController interface fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + memset(®istInfo, 0, sizeof(registInfo)); + if (!fNetIf->initRegistrationInfo(®istInfo, 1, sizeof(registInfo))) { + XYLog("initRegistrationInfo fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + if (!fNetIf->initRegistrationInfo(®istInfo, 1, sizeof(registInfo))) { + XYLog("initRegistrationInfo fail\n"); + super::stop(provider); + releaseAll(); + return false; + } + fNetIf->mExpansionData->fRegistrationInfo = (struct IOSkywalkNetworkInterface::RegistrationInfo *)IOMalloc(sizeof(struct IOSkywalkNetworkInterface::RegistrationInfo)); + fNetIf->mExpansionData2->fRegistrationInfo = (struct IOSkywalkEthernetInterface::RegistrationInfo *)IOMalloc(sizeof(struct IOSkywalkEthernetInterface::RegistrationInfo)); + memcpy(fNetIf->mExpansionData->fRegistrationInfo, ®istInfo, sizeof(registInfo)); + memcpy(fNetIf->mExpansionData2->fRegistrationInfo, ®istInfo, sizeof(registInfo)); + if (fNetIf->getInterfaceRole() == 1) + fNetIf->deferBSDAttach(true); + fNetIf->start(this); + + setLinkStatus(kIONetworkLinkValid); + if (TAILQ_EMPTY(&fHalService->get80211Controller()->ic_ess)) + fHalService->get80211Controller()->ic_flags |= IEEE80211_F_AUTO_JOIN; + registerService(); + return true; +} + +void AirportItlwm::stop(IOService *provider) +{ + XYLog("%s\n", __PRETTY_FUNCTION__);XYLog("%s\n", __PRETTY_FUNCTION__); + struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; + super::stop(provider); + disableAdapter(bsdInterface); + setLinkStatus(kIONetworkLinkValid); + fHalService->detach(pciNub); + ether_ifdetach(ifp); + detachInterface(fNetIf, true); + OSSafeReleaseNULL(fNetIf); + releaseAll(); +} + +void AirportItlwm::free() +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + if (fHalService != NULL) { + fHalService->release(); + fHalService = NULL; + } + if (syncFrameTemplate != NULL && syncFrameTemplateLength > 0) { + IOFree(syncFrameTemplate, syncFrameTemplateLength); + syncFrameTemplateLength = 0; + syncFrameTemplate = NULL; + } + if (roamProfile != NULL) { + IOFree(roamProfile, sizeof(struct apple80211_roam_profile_band_data)); + roamProfile = NULL; + } + if (btcProfile != NULL) { + IOFree(btcProfile, sizeof(struct apple80211_btc_profiles_data)); + btcProfile = NULL; + } + super::free(); +} + +bool AirportItlwm::createWorkQueue() +{ + XYLog("%s %d\n", __FUNCTION__, _fWorkloop != 0); + return _fWorkloop != 0; +} + +IO80211WorkQueue *AirportItlwm::getWorkQueue() +{ + return _fWorkloop; +} + +void *AirportItlwm::getFaultReporterFromDriver() +{ + return driverFaultReporter; +} + +IOReturn AirportItlwm::enable(IO80211SkywalkInterface *netif) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + super::enable(netif); + _fCommandGate->enable(); + if (power_state) + enableAdapter(bsdInterface); + return kIOReturnSuccess; +} + +IOReturn AirportItlwm::disable(IO80211SkywalkInterface *netif) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + super::disable(netif); + setLinkStatus(kIONetworkLinkValid); + return kIOReturnSuccess; +} + +bool AirportItlwm::configureInterface(IONetworkInterface *netif) +{ + IONetworkData *nd; + struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; + + if (super::configureInterface(netif) == false) { + XYLog("super failed\n"); + return false; + } + + nd = netif->getParameter(kIONetworkStatsKey); + if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) { + XYLog("network statistics buffer unavailable?\n"); + return false; + } + ifp->netStat = fpNetStats; + ether_ifattach(ifp, OSDynamicCast(IOEthernetInterface, netif)); + fpNetStats->collisions = 0; +#ifdef __PRIVATE_SPI__ + netif->configureOutputPullModel(fHalService->getDriverInfo()->getTxQueueSize(), 0, 0, IOEthernetInterface::kOutputPacketSchedulingModelNormal, 0); +#endif + + return true; +} + +IONetworkInterface *AirportItlwm::createInterface() +{ + AirportItlwmEthernetInterface *netif = new AirportItlwmEthernetInterface; + if (!netif) + return NULL; + if (!netif->initWithSkywalkInterfaceAndProvider(this, fNetIf)) { + netif->release(); + return NULL; + } + return netif; +} + +bool AirportItlwm::createMediumTables(const IONetworkMedium **primary) +{ + IONetworkMedium *medium; + + OSDictionary *mediumDict = OSDictionary::withCapacity(2); + if (mediumDict == NULL) { + XYLog("Cannot allocate OSDictionary\n"); + return false; + } + + medium = IONetworkMedium::medium(kIOMediumIEEE80211, 54000000); + IONetworkMedium::addMedium(mediumDict, medium); + medium->release(); + if (primary) { + *primary = medium; + } + medium = IONetworkMedium::medium(kIOMediumIEEE80211None, 0); + IONetworkMedium::addMedium(mediumDict, medium); + medium->release(); + + bool result = publishMediumDictionary(mediumDict); + if (!result) { + XYLog("Cannot publish medium dictionary!\n"); + } + + mediumDict->release(); + return result; +} + +IOReturn AirportItlwm::selectMedium(const IONetworkMedium *medium) { + setSelectedMedium(medium); + return kIOReturnSuccess; +} + +bool AirportItlwm:: +setLinkStatus(UInt32 status, const IONetworkMedium * activeMedium, UInt64 speed, OSData * data) +{ + struct _ifnet *ifq = &fHalService->get80211Controller()->ic_ac.ac_if; + if (status == currentStatus) { + return true; + } + bool ret = super::setLinkStatus(status, activeMedium, speed, data); + currentStatus = status; + if (fNetIf) { + if (status & kIONetworkLinkActive) { +#ifdef __PRIVATE_SPI__ + bsdInterface->startOutputThread(); +#endif + getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkUp, (void *)0); +// fNetIf->setLinkQualityMetric(100); + } else if (!(status & kIONetworkLinkNoNetworkChange)) { +#ifdef __PRIVATE_SPI__ + bsdInterface->stopOutputThread(); + bsdInterface->flushOutputQueue(); +#endif + ifq_flush(&ifq->if_snd); + mq_purge(&fHalService->get80211Controller()->ic_mgtq); + getCommandGate()->runAction(setLinkStateGated, (void *)kIO80211NetworkLinkDown, (void *)fHalService->get80211Controller()->ic_deauth_reason); + } + } + return ret; +} + +IOReturn AirportItlwm:: +setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3) +{ + AirportItlwm *that = OSDynamicCast(AirportItlwm, target); + IOReturn ret = that->fNetIf->setLinkState((IO80211LinkState)(uint64_t)arg0, (unsigned int)(uint64_t)arg1); + that->fNetIf->setRunningState((IO80211LinkState)(uint64_t)arg0 == kIO80211NetworkLinkUp); + that->fNetIf->postMessage(APPLE80211_M_LINK_CHANGED, NULL, 0, false); + that->fNetIf->postMessage(APPLE80211_M_BSSID_CHANGED, NULL, 0, false); + that->fNetIf->postMessage(APPLE80211_M_SSID_CHANGED, NULL, 0, false); + if ((IO80211LinkState)(uint64_t)arg0 == kIO80211NetworkLinkUp) { + that->fNetIf->reportLinkStatus(3, 0x80); + } else { + that->fNetIf->reportLinkStatus(1, 0); + } + that->bsdInterface->setLinkState((IO80211LinkState)(uint64_t)arg0); + return ret; +} + +#ifdef __PRIVATE_SPI__ +IOReturn AirportItlwm::outputStart(IONetworkInterface *interface, IOOptionBits options) +{ + struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; + mbuf_t m = NULL; + if (ifq_is_oactive(&ifp->if_snd)) + return kIOReturnNoResources; + while (kIOReturnSuccess == interface->dequeueOutputPackets(1, &m)) { + if (outputPacket(m, NULL)!= kIOReturnOutputSuccess || + ifq_is_oactive(&ifp->if_snd)) + return kIOReturnNoResources; + } + return kIOReturnSuccess; +} + +IOReturn AirportItlwm::networkInterfaceNotification( + IONetworkInterface * interface, + uint32_t type, + void * argument ) +{ + XYLog("%s\n", __FUNCTION__); + return kIOReturnSuccess; +} +#endif + +extern const char* hexdump(uint8_t *buf, size_t len); + +UInt32 AirportItlwm::outputPacket(mbuf_t m, void *param) +{ +// XYLog("%s\n", __FUNCTION__); + IOReturn ret = kIOReturnOutputSuccess; + struct _ifnet *ifp = &fHalService->get80211Controller()->ic_ac.ac_if; + + if (fHalService->get80211Controller()->ic_state != IEEE80211_S_RUN || ifp->if_snd.queue == NULL) { + if (m && mbuf_type(m) != MBUF_TYPE_FREE) + freePacket(m); + return kIOReturnOutputDropped; + } + if (m == NULL) { + XYLog("%s m==NULL!!\n", __FUNCTION__); + ifp->netStat->outputErrors++; + ret = kIOReturnOutputDropped; + } + if (!(mbuf_flags(m) & MBUF_PKTHDR) ){ + XYLog("%s pkthdr is NULL!!\n", __FUNCTION__); + ifp->netStat->outputErrors++; + freePacket(m); + ret = kIOReturnOutputDropped; + } + if (mbuf_type(m) == MBUF_TYPE_FREE) { + XYLog("%s mbuf is FREE!!\n", __FUNCTION__); + ifp->netStat->outputErrors++; + ret = kIOReturnOutputDropped; + } + size_t len = mbuf_len(m); + ether_header_t *eh = (ether_header_t *)mbuf_data(m); + if (len >= sizeof(ether_header_t) && eh->ether_type == htons(ETHERTYPE_PAE)) { // EAPOL packet + const char* dump = hexdump((uint8_t*)mbuf_data(m), len); + XYLog("output EAPOL packet, len: %zu, data: %s\n", len, dump ? dump : "Failed to allocate memory"); + if (dump) + IOFree((void*)dump, 3 * len + 1); + } + if (!ifp->if_snd.queue->lockEnqueue(m)) { + freePacket(m); + ret = kIOReturnOutputDropped; + } + (*ifp->if_start)(ifp); + return ret; +} + +const OSString * AirportItlwm::newVendorString() const +{ + return OSString::withCString("Apple"); +} + +const OSString * AirportItlwm::newModelString() const +{ + return OSString::withCString(fHalService->getDriverInfo()->getFirmwareName()); +} + +IOReturn AirportItlwm::getHardwareAddress(IOEthernetAddress *addrP) +{ + if (IEEE80211_ADDR_EQ(etheranyaddr, fHalService->get80211Controller()->ic_myaddr)) + return kIOReturnError; + else { + IEEE80211_ADDR_COPY(addrP, fHalService->get80211Controller()->ic_myaddr); + return kIOReturnSuccess; + } +} + +IOReturn AirportItlwm::setHardwareAddress(const void *addrP, UInt32 addrBytes) +{ + if (!fNetIf || !addrP) + return kIOReturnError; + if_setlladdr(&fHalService->get80211Controller()->ic_ac.ac_if, (const UInt8 *)addrP); + if (fHalService->get80211Controller()->ic_state > IEEE80211_S_INIT) { + fHalService->disable(bsdInterface); + fHalService->enable(bsdInterface); + } + return kIOReturnSuccess; +} + +UInt32 AirportItlwm::getFeatures() const +{ + return fHalService->getDriverInfo()->supportedFeatures(); +} + +IOReturn AirportItlwm::setPromiscuousMode(IOEnetPromiscuousMode mode) +{ + return kIOReturnSuccess; +} + +IOReturn AirportItlwm::setMulticastMode(IOEnetMulticastMode mode) +{ + return kIOReturnSuccess; +} + +IOReturn AirportItlwm::setMulticastList(IOEthernetAddress* addr, UInt32 len) +{ + return fHalService->getDriverController()->setMulticastList(addr, len); +} + +IOReturn AirportItlwm::getPacketFilters(const OSSymbol *group, UInt32 *filters) const +{ + IOReturn rtn = kIOReturnSuccess; + if (group == gIOEthernetWakeOnLANFilterGroup && magicPacketSupported) + *filters = kIOEthernetWakeOnMagicPacket; + else if (group == gIONetworkFilterGroup) + *filters = kIOPacketFilterMulticast | kIOPacketFilterPromiscuous; + else + rtn = IOEthernetController::getPacketFilters(group, filters); + return rtn; +} + +SInt32 AirportItlwm:: +enableFeature(IO80211FeatureCode code, void *data) +{ + if (code == kIO80211Feature80211n) { + return 0; + } + return 102; +} + +bool AirportItlwm::getLogPipes(CCPipe**logPipe, CCPipe**eventPipe, CCPipe**snapshotsPipe) +{ + bool ret = false; + if (logPipe) { + *logPipe = driverLogPipe; + ret = true; + } + if (eventPipe) { + *eventPipe = driverDataPathPipe; + ret = true; + } + if (snapshotsPipe) { + *snapshotsPipe = driverSnapshotsPipe; + ret = true; + } + return ret; +} + +#define APPLE80211_CAPA_AWDL_FEATURE_AUTO_UNLOCK 0x00000004 +#define APPLE80211_CAPA_AWDL_FEATURE_WOW 0x00000080 + +IOReturn AirportItlwm:: +getCARD_CAPABILITIES(OSObject *object, + struct apple80211_capability_data *cd) +{ + uint32_t caps = fHalService->get80211Controller()->ic_caps; + memset(cd, 0, sizeof(struct apple80211_capability_data)); + + if (caps & IEEE80211_C_WEP) + cd->capabilities[0] |= 1 << APPLE80211_CAP_WEP; + if (caps & IEEE80211_C_RSN) + cd->capabilities[0] |= 1 << APPLE80211_CAP_TKIP | 1 << APPLE80211_CAP_AES_CCM; + // Disable not implemented capabilities + // if (caps & IEEE80211_C_PMGT) + // cd->capabilities[0] |= 1 << APPLE80211_CAP_PMGT; + // if (caps & IEEE80211_C_IBSS) + // cd->capabilities[0] |= 1 << APPLE80211_CAP_IBSS; + // if (caps & IEEE80211_C_HOSTAP) + // cd->capabilities[0] |= 1 << APPLE80211_CAP_HOSTAP; + // AES not enabled, like on Apple cards + + if (caps & IEEE80211_C_SHSLOT) + cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHSLOT - 8); + if (caps & IEEE80211_C_SHPREAMBLE) + cd->capabilities[1] |= 1 << (APPLE80211_CAP_SHPREAMBLE - 8); + if (caps & IEEE80211_C_RSN) + cd->capabilities[1] |= 1 << (APPLE80211_CAP_WPA1 - 8) | 1 << (APPLE80211_CAP_WPA2 - 8) | 1 << (APPLE80211_CAP_TKIPMIC - 8); + // Disable not implemented capabilities + // if (caps & IEEE80211_C_TXPMGT) + // cd->capabilities[1] |= 1 << (APPLE80211_CAP_TXPMGT - 8); + // if (caps & IEEE80211_C_MONITOR) + // cd->capabilities[1] |= 1 << (APPLE80211_CAP_MONITOR - 8); + // WPA not enabled, like on Apple cards + + cd->version = APPLE80211_VERSION; + cd->capabilities[2] = 0xFF; // BURST, WME, SHORT_GI_40MHZ, SHORT_GI_20MHZ, WOW, TSN, ?, ? + cd->capabilities[3] = 0x2B; + cd->capabilities[5] = 0x40; + cd->capabilities[6] = ( +// 1 | //MFP capable + 0x8 | + 0x4 | + 0x80 + ); + *(uint16_t *)&cd->capabilities[8] = 0x201; +// +// cd->capabilities[2] |= 0x10; +// cd->capabilities[5] |= 0x1; +// +// cd->capabilities[2] |= 0x2; +// +// cd->capabilities[3] |= 0x20; +// +// cd->capabilities[0] |= 0x80; +// +// cd->capabilities[3] |= 0x80; +// cd->capabilities[4] |= 0x4; +// +// cd->capabilities[4] |= 0x1; +// cd->capabilities[3] |= 0x1; +// cd->capabilities[6] |= 0x8; +// +// cd->capabilities[3] |= 3; +// cd->capabilities[4] |= 2; +// cd->capabilities[6] |= 0x10; +// cd->capabilities[5] |= 0x20; +// cd->capabilities[5] |= 0x80; +// +// if (cd->capabilities[6] & 0x20) { +// cd->capabilities[2] |= 8; +// } +// cd->capabilities[5] |= 8; +// cd->capabilities[8] |= 2; +// +// cd->capabilities[11] |= (2 | 4 | 8 | 0x10 | 0x20 | 0x40 | 0x80); + + return kIOReturnSuccess; +} + +IOReturn AirportItlwm:: +getDRIVER_VERSION(OSObject *object, + struct apple80211_version_data *hv) +{ + if (!hv) + return kIOReturnError; + hv->version = APPLE80211_VERSION; + snprintf(hv->string, sizeof(hv->string), "itlwm: %s%s fw: %s", ITLWM_VERSION, GIT_COMMIT, fHalService->getDriverInfo()->getFirmwareVersion()); + hv->string_len = strlen(hv->string); + return kIOReturnSuccess; +} + +IOReturn AirportItlwm:: +getHARDWARE_VERSION(OSObject *object, + struct apple80211_version_data *hv) +{ + if (!hv) + return kIOReturnError; + hv->version = APPLE80211_VERSION; + strncpy(hv->string, fHalService->getDriverInfo()->getFirmwareVersion(), sizeof(hv->string)); + hv->string_len = strlen(fHalService->getDriverInfo()->getFirmwareVersion()); + return kIOReturnSuccess; +} + +IOReturn AirportItlwm:: +getCOUNTRY_CODE(OSObject *object, + struct apple80211_country_code_data *cd) +{ + char user_override_cc[3]; + const char *cc_fw = fHalService->getDriverInfo()->getFirmwareCountryCode(); + + if (!cd) + return kIOReturnError; + cd->version = APPLE80211_VERSION; + memset(user_override_cc, 0, sizeof(user_override_cc)); + PE_parse_boot_argn("itlwm_cc", user_override_cc, 3); + /* user_override_cc > firmware_cc > geo_location_cc */ + strncpy((char*)cd->cc, user_override_cc[0] ? user_override_cc : ((cc_fw[0] == 'Z' && cc_fw[1] == 'Z' && geo_location_cc[0]) ? geo_location_cc : cc_fw), sizeof(cd->cc)); + return kIOReturnSuccess; +} + +IOReturn AirportItlwm:: +setCOUNTRY_CODE(OSObject *object, struct apple80211_country_code_data *data) +{ + XYLog("%s cc=%s\n", __FUNCTION__, data->cc); + if (data && data->cc[0] != 120 && data->cc[0] != 88) { + memcpy(geo_location_cc, data->cc, sizeof(geo_location_cc)); + fNetIf->postMessage(APPLE80211_M_COUNTRY_CODE_CHANGED, NULL, 0, 0); + } + return kIOReturnSuccess; +} + +IOReturn AirportItlwm:: +getPOWER(OSObject *object, + struct apple80211_power_data *pd) +{ + if (!pd) + return kIOReturnError; + pd->version = APPLE80211_VERSION; + pd->num_radios = 4; + pd->power_state[0] = power_state; + pd->power_state[1] = power_state; + pd->power_state[2] = power_state; + pd->power_state[3] = power_state; + return kIOReturnSuccess; +} + +IOReturn AirportItlwm:: +setPOWER(OSObject *object, + struct apple80211_power_data *pd) +{ + if (!pd) + return kIOReturnError; + IOLog("itlwm: setPOWER: num_radios[%d] power_state(0:%u 1:%u 2:%u 3:%u)\n", pd->num_radios, pd->power_state[0], pd->power_state[1], pd->power_state[2], pd->power_state[3]); + if (pd->num_radios > 0) { + bool isRunning = (fHalService->get80211Controller()->ic_ac.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != 0; + if (pd->power_state[0] == 0) { + changePowerStateToPriv(1); + if (isRunning) { + net80211_ifstats(fHalService->get80211Controller()); + disableAdapter(bsdInterface); + } + } else { + changePowerStateToPriv(2); + if (!isRunning) + enableAdapter(bsdInterface); + } + power_state = (pd->power_state[0]); + } + + return kIOReturnSuccess; +} + +SInt32 AirportItlwm::apple80211_ioctl(IO80211SkywalkInterface *interface,unsigned long cmd,void *data, bool b1, bool b2) +{ + if (!ml_at_interrupt_context()) + XYLog("%s cmd: %s b1: %d b2: %d\n", __FUNCTION__, convertApple80211IOCTLToString((unsigned int)cmd), b1, b2); + return super::apple80211_ioctl(interface, cmd, data, b1, b2); +} + +SInt32 AirportItlwm::apple80211SkywalkRequest(UInt request,int cmd,IO80211SkywalkInterface *interface,void *data) +{ + if (!ml_at_interrupt_context()) + XYLog("%s 1 cmd: %s request: %d\n", __FUNCTION__, convertApple80211IOCTLToString(cmd), request); + return kIOReturnUnsupported; +} + +SInt32 AirportItlwm::apple80211SkywalkRequest(UInt request,int cmd,IO80211SkywalkInterface *interface,void *data,void *) +{ + if (!ml_at_interrupt_context()) + XYLog("%s 2 cmd: %s request: %d\n", __FUNCTION__, convertApple80211IOCTLToString(cmd), request); + return kIOReturnUnsupported; +} + +IOReturn AirportItlwm::enableAdapter(IONetworkInterface *netif) +{ + fHalService->enable(netif); + watchdogTimer->setTimeoutMS(kWatchDogTimerPeriod); + watchdogTimer->enable(); + return kIOReturnSuccess; +} + +void AirportItlwm::disableAdapter(IONetworkInterface *netif) +{ + watchdogTimer->cancelTimeout(); + watchdogTimer->disable(); + fHalService->disable(netif); +} + +IOReturn AirportItlwm:: +tsleepHandler(OSObject* owner, void* arg0, void* arg1, void* arg2, void* arg3) +{ + AirportItlwm* dev = OSDynamicCast(AirportItlwm, owner); + if (dev == 0) + return kIOReturnError; + + if (arg1 == 0) { + if (_fCommandGate->commandSleep(arg0, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED) + return kIOReturnSuccess; + else + return kIOReturnTimeout; + } else { + AbsoluteTime deadline; + clock_interval_to_deadline((*(int*)arg1), kNanosecondScale, reinterpret_cast (&deadline)); + if (_fCommandGate->commandSleep(arg0, deadline, THREAD_INTERRUPTIBLE) == THREAD_AWAKENED) + return kIOReturnSuccess; + else + return kIOReturnTimeout; + } +} + +bool AirportItlwm::initPCIPowerManagment(IOPCIDevice *provider) +{ + UInt16 reg16; + + reg16 = provider->configRead16(kIOPCIConfigCommand); + + reg16 |= ( kIOPCICommandBusMaster | + kIOPCICommandMemorySpace | + kIOPCICommandMemWrInvalidate ); + + reg16 &= ~kIOPCICommandIOSpace; // disable I/O space + + provider->configWrite16( kIOPCIConfigCommand, reg16 ); + provider->findPCICapability(kIOPCIPowerManagementCapability, + &pmPCICapPtr); + if (pmPCICapPtr) { + UInt16 pciPMCReg = provider->configRead32( pmPCICapPtr ) >> 16; + if (pciPMCReg & kPCIPMCPMESupportFromD3Cold) + magicPacketSupported = true; + provider->configWrite16((pmPCICapPtr + 4), 0x8000 ); + IOSleep(10); + } + return true; +} + +static IOPMPowerState powerStateArray[kPowerStateCount] = +{ + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +void AirportItlwm::unregistPM() +{ + if (powerOffThreadCall) { + thread_call_free(powerOffThreadCall); + powerOffThreadCall = NULL; + } + if (powerOnThreadCall) { + thread_call_free(powerOnThreadCall); + powerOnThreadCall = NULL; + } +} + +IOReturn AirportItlwm::setPowerState(unsigned long powerStateOrdinal, IOService *policyMaker) +{ + IOReturn result = IOPMAckImplied; + + if (pmPowerState == powerStateOrdinal) + return result; + switch (powerStateOrdinal) { + case kPowerStateOff: + if (powerOffThreadCall) { + retain(); + if (thread_call_enter(powerOffThreadCall)) + release(); + result = 5000000; + } + break; + case kPowerStateOn: + if (powerOnThreadCall) { + retain(); + if (thread_call_enter(powerOnThreadCall)) + release(); + result = 5000000; + } + break; + + default: + break; + } + return result; +} + +IOReturn AirportItlwm::setWakeOnMagicPacket(bool active) +{ + magicPacketEnabled = active; + return kIOReturnSuccess; +} + +static void handleSetPowerStateOff(thread_call_param_t param0, + thread_call_param_t param1) +{ + AirportItlwm *self = (AirportItlwm *)param0; + + if (param1 == 0) + { + self->getCommandGate()->runAction((IOCommandGate::Action) + handleSetPowerStateOff, + (void *) 1); + } + else + { + self->setPowerStateOff(); + self->release(); + } +} + +static void handleSetPowerStateOn(thread_call_param_t param0, + thread_call_param_t param1) +{ + AirportItlwm *self = (AirportItlwm *) param0; + + if (param1 == 0) + { + self->getCommandGate()->runAction((IOCommandGate::Action) + handleSetPowerStateOn, + (void *) 1); + } + else + { + self->setPowerStateOn(); + self->release(); + } +} + +IOReturn AirportItlwm::registerWithPolicyMaker(IOService *policyMaker) +{ + IOReturn ret; + + pmPowerState = kPowerStateOn; + pmPolicyMaker = policyMaker; + + powerOffThreadCall = thread_call_allocate( + (thread_call_func_t)handleSetPowerStateOff, + (thread_call_param_t)this); + powerOnThreadCall = thread_call_allocate( + (thread_call_func_t)handleSetPowerStateOn, + (thread_call_param_t)this); + ret = pmPolicyMaker->registerPowerDriver(this, + powerStateArray, + kPowerStateCount); + return ret; +} + +void AirportItlwm::setPowerStateOff() +{ + XYLog("%s\n", __FUNCTION__); + pmPowerState = kPowerStateOff; + disableAdapter(bsdInterface); + pmPolicyMaker->acknowledgeSetPowerState(); +} + +void AirportItlwm::setPowerStateOn() +{ + XYLog("%s\n", __FUNCTION__); + pmPowerState = kPowerStateOn; + pmPolicyMaker->acknowledgeSetPowerState(); +} diff --git a/AirportItlwm/AirportItlwmV2.hpp b/AirportItlwm/AirportItlwmV2.hpp new file mode 100644 index 000000000..2c2f74c92 --- /dev/null +++ b/AirportItlwm/AirportItlwmV2.hpp @@ -0,0 +1,255 @@ +// +// AirportItlwmV2.hpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef AirportItlwmV2_hpp +#define AirportItlwmV2_hpp + +#include "Apple80211.h" + +#include "IOKit/network/IOGatedOutputQueue.h" +#include +#include +#include +#include +#include +#include +#include + +#include "ItlIwm.hpp" +#include "ItlIwx.hpp" +#include "ItlIwn.hpp" + +#include "AirportItlwmEthernetInterface.hpp" + +enum +{ + kPowerStateOff = 0, + kPowerStateOn, + kPowerStateCount +}; + +#define kWatchDogTimerPeriod 1000 + +extern "C" { +const char *convertApple80211IOCTLToString(signed int cmd); +} + +class AirportItlwm : public IO80211Controller { + OSDeclareDefaultStructors(AirportItlwm) +#define IOCTL(REQ_TYPE, REQ, DATA_TYPE) \ +if (REQ_TYPE == SIOCGA80211) { \ +ret = get##REQ(interface, (struct DATA_TYPE* )data); \ +} else { \ +ret = set##REQ(interface, (struct DATA_TYPE* )data); \ +} + +#define IOCTL_GET(REQ_TYPE, REQ, DATA_TYPE) \ +if (REQ_TYPE == SIOCGA80211) { \ +ret = get##REQ(interface, (struct DATA_TYPE* )data); \ +} +#define IOCTL_SET(REQ_TYPE, REQ, DATA_TYPE) \ +if (REQ_TYPE == SIOCSA80211) { \ +ret = set##REQ(interface, (struct DATA_TYPE* )data); \ +} +#define FUNC_IOCTL(REQ, DATA_TYPE) \ +FUNC_IOCTL_GET(REQ, DATA_TYPE) \ +FUNC_IOCTL_SET(REQ, DATA_TYPE) +#define FUNC_IOCTL_GET(REQ, DATA_TYPE) \ +IOReturn get##REQ(OSObject *object, struct DATA_TYPE *data); +#define FUNC_IOCTL_SET(REQ, DATA_TYPE) \ +IOReturn set##REQ(OSObject *object, struct DATA_TYPE *data); + +public: + virtual bool init(OSDictionary *properties) override; + virtual void free() override; + virtual IOService* probe(IOService* provider, SInt32* score) override; + virtual bool start(IOService *provider) override; + virtual void stop(IOService *provider) override; + virtual IOReturn enable(IO80211SkywalkInterface *netif) override; + virtual IOReturn disable(IO80211SkywalkInterface *netif) override; + virtual IOReturn setHardwareAddress(const void *addr, UInt32 addrBytes) override; + virtual IOReturn getHardwareAddress(IOEthernetAddress* addrP) override; + virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters) const override; + virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode) override; + virtual IOReturn setMulticastMode(IOEnetMulticastMode mode) override; + virtual IOReturn setMulticastList(IOEthernetAddress* addr, UInt32 len) override; + virtual UInt32 getFeatures() const override; + virtual const OSString * newVendorString() const override; + virtual const OSString * newModelString() const override; + virtual IOReturn selectMedium(const IONetworkMedium *medium) override; + virtual bool createWorkQueue() override; + virtual IONetworkInterface * createInterface() override; + virtual bool configureInterface(IONetworkInterface *netif) override; + virtual UInt32 outputPacket(mbuf_t, void * param) override; +#ifdef __PRIVATE_SPI__ + virtual IOReturn outputStart(IONetworkInterface *interface, IOOptionBits options) override; + virtual IOReturn networkInterfaceNotification( + IONetworkInterface * interface, + uint32_t type, + void * argument ) override; +#endif + virtual bool setLinkStatus( + UInt32 status, + const IONetworkMedium * activeMedium = 0, + UInt64 speed = 0, + OSData * data = 0) override; + static IOReturn setLinkStateGated(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3); + + static IOReturn tsleepHandler(OSObject* owner, void* arg0 = 0, void* arg1 = 0, void* arg2 = 0, void* arg3 = 0); + static void eventHandler(struct ieee80211com *, int, void *); + IOReturn enableAdapter(IONetworkInterface *netif); + void disableAdapter(IONetworkInterface *netif); + bool initCCLogs(); + + virtual IO80211WorkQueue *getWorkQueue() override; + virtual bool requiresExplicitMBufRelease() override { + return false; + } + virtual bool flowIdSupported() override { + return false; + } + virtual SInt32 monitorModeSetEnabled(bool, UInt) override { + return kIOReturnSuccess; + } + virtual IOReturn requestQueueSizeAndTimeout(unsigned short *queue, unsigned short *timeout) override { + XYLog("%s\n", __FUNCTION__); + return kIOReturnSuccess; + } + + virtual bool getLogPipes(CCPipe**, CCPipe**, CCPipe**) override; + + virtual void *getFaultReporterFromDriver() override; + + virtual SInt32 apple80211_ioctl(IO80211SkywalkInterface *,unsigned long,void *, bool, bool) override; + virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *) override; + virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *,void *) override; + + bool createMediumTables(const IONetworkMedium **primary); + void releaseAll(); + void watchdogAction(IOTimerEventSource *timer); + + virtual SInt32 enableFeature(IO80211FeatureCode, void*) override; + virtual bool isCommandProhibited(int command) override { +// if (!ml_at_interrupt_context()) +// XYLog("%s %s\n", __FUNCTION__, convertApple80211IOCTLToString(command)); + return false; + }; + virtual SInt32 handleCardSpecific(IO80211SkywalkInterface *,unsigned long,void *,bool) override { + XYLog("%s\n", __FUNCTION__); + return 0; + }; + virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface *interface,apple80211_version_data *data) override { + XYLog("%s\n", __FUNCTION__); + return getDRIVER_VERSION((OSObject *)interface, data); + }; + virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface *interface,apple80211_version_data *data) override { + XYLog("%s\n", __FUNCTION__); + return getHARDWARE_VERSION((OSObject *)interface, data); + }; + virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface *interface,apple80211_capability_data *data) override { +// XYLog("%s\n", __FUNCTION__); + return getCARD_CAPABILITIES((OSObject *)interface, data); + } + virtual IOReturn getPOWER(IO80211SkywalkInterface *interface,apple80211_power_data *data) override { +// XYLog("%s\n", __FUNCTION__); + return getPOWER((OSObject *)interface, data); + } + virtual IOReturn setPOWER(IO80211SkywalkInterface *interface,apple80211_power_data *data) override { +// XYLog("%s\n", __FUNCTION__); + return setPOWER((OSObject *)interface, data); + } + virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *interface,apple80211_country_code_data *data) override { +// XYLog("%s\n", __FUNCTION__); + return getCOUNTRY_CODE((OSObject *)interface, data); + } + virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *interface,apple80211_country_code_data *data) override { +// XYLog("%s\n", __FUNCTION__); + return setCOUNTRY_CODE((OSObject *)interface, data); + } + virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *interface,apple80211_debug_command *data) override { + XYLog("%s\n", __FUNCTION__); + return kIOReturnSuccess; + } + + //scan + static void fakeScanDone(OSObject *owner, IOTimerEventSource *sender); + + //----------------------------------------------------------------------- + // Power management support. + //----------------------------------------------------------------------- + virtual IOReturn registerWithPolicyMaker( IOService * policyMaker ) override; + virtual IOReturn setPowerState( unsigned long powerStateOrdinal, + IOService * policyMaker) override; + virtual IOReturn setWakeOnMagicPacket( bool active ) override; + void setPowerStateOff(void); + void setPowerStateOn(void); + void unregistPM(); + bool initPCIPowerManagment(IOPCIDevice *provider); + + FUNC_IOCTL_GET(CARD_CAPABILITIES, apple80211_capability_data) + FUNC_IOCTL(POWER, apple80211_power_data) + FUNC_IOCTL_GET(DRIVER_VERSION, apple80211_version_data) + FUNC_IOCTL_GET(HARDWARE_VERSION, apple80211_version_data) + FUNC_IOCTL(COUNTRY_CODE, apple80211_country_code_data) + +public: + IOInterruptEventSource* fInterrupt; + IOTimerEventSource *watchdogTimer; + IOPCIDevice *pciNub; + IONetworkStats *fpNetStats; + AirportItlwmEthernetInterface *bsdInterface; + IO80211SkywalkInterface *fNetIf; + IOWorkLoop *fWatchdogWorkLoop; + ItlHalService *fHalService; + + //IO80211 + uint8_t power_state; + struct ieee80211_node *fNextNodeToSend; + bool fScanResultWrapping; + IOTimerEventSource *scanSource; + + u_int32_t current_authtype_lower; + u_int32_t current_authtype_upper; + UInt64 currentSpeed; + UInt32 currentStatus; + bool disassocIsVoluntary; + char geo_location_cc[3]; + + //pm + thread_call_t powerOnThreadCall; + thread_call_t powerOffThreadCall; + UInt32 pmPowerState; + IOService *pmPolicyMaker; + UInt8 pmPCICapPtr; + bool magicPacketEnabled; + bool magicPacketSupported; + + //AWDL + uint8_t *syncFrameTemplate; + uint32_t syncFrameTemplateLength; + uint8_t awdlBSSID[6]; + uint32_t awdlSyncState; + uint32_t awdlElectionId; + uint32_t awdlPresenceMode; + uint16_t awdlMasterChannel; + uint16_t awdlSecondaryMasterChannel; + uint8_t *roamProfile; + struct apple80211_btc_profiles_data *btcProfile; + struct apple80211_btc_config_data btcConfig; + uint32_t btcMode; + uint32_t btcOptions; + bool awdlSyncEnable; + + CCPipe *driverLogPipe; + CCPipe *driverDataPathPipe; + CCPipe *driverSnapshotsPipe; + + CCStream *driverFaultReporter; +}; + +#endif /* AirportItlwmV2_hpp */ diff --git a/AirportItlwm/AirportItlwm_Sequoia.cpp b/AirportItlwm/AirportItlwm_Sequoia.cpp new file mode 100644 index 000000000..84254cdb1 --- /dev/null +++ b/AirportItlwm/AirportItlwm_Sequoia.cpp @@ -0,0 +1,78 @@ +#include "AirportItlwm_Sequoia.hpp" +#include +#include +#include +#include +#include +#include + +#define super IOService +OSDefineMetaClassAndStructors(AirportItlwm_Sequoia, IOService); + +#define DRVLOG(fmt, ...) IOLog("[AirportItlwm Sequoia v" AIRPORTITLWM_VERSION "] " fmt "\n", ##__VA_ARGS__) +#define DRVINFO(fmt, ...) IOLog("[AirportItlwm Sequoia INFO] " fmt "\n", ##__VA_ARGS__) +#define DRVERR(fmt, ...) IOLog("[AirportItlwm Sequoia ERROR] " fmt "\n", ##__VA_ARGS__) +#define DRWARN(fmt, ...) IOLog("[AirportItlwm Sequoia WARN] " fmt "\n", ##__VA_ARGS__) + +bool AirportItlwm_Sequoia::init(OSDictionary *properties) { + if (!super::init(properties)) { + DRVERR("Failed to initialize super class"); + return false; + } + + // Create Skywalk interface + skywalkInterface = new AirportItlwmSkywalkInterface(); + if (!skywalkInterface) { + DRVERR("Failed to create Skywalk interface"); + return false; + } + + DRVINFO("Skywalk interface initialized successfully"); + return true; +} + +bool AirportItlwm_Sequoia::start(IOService *provider) { + if (!super::start(provider)) { + DRVERR("Failed to start super class"); + return false; + } + + // Initialize Skywalk interface + if (skywalkInterface && !skywalkInterface->init(this)) { + DRVERR("Failed to initialize Skywalk interface"); + return false; + } + + DRVINFO("Skywalk interface started"); + return true; +} + +void AirportItlwm_Sequoia::stop(IOService *provider) { + if (skywalkInterface) { + skywalkInterface->release(); + skywalkInterface = nullptr; + } + super::stop(provider); +} + +void AirportItlwm_Sequoia::free() { + super::free(); + if (skywalkInterface) { + skywalkInterface->release(); + } +} + +void AirportItlwm_Sequoia::connectToNetwork(uint8_t *ssid, uint32_t ssid_len, uint8_t *bssid, uint32_t auth_type, uint8_t *key, uint32_t key_len) { + // Associate with Wi-Fi network using Skywalk + if (skywalkInterface) { + skywalkInterface->associateSSID(ssid, ssid_len, bssid, auth_type, 0, key, key_len); + } +} + +void AirportItlwm_Sequoia::setSecurityKeys(uint8_t *ptk, size_t ptk_len, uint8_t *gtk, size_t gtk_len) { + // Set PTK and GTK keys for security + if (skywalkInterface) { + skywalkInterface->setPTK(ptk, ptk_len); + skywalkInterface->setGTK(gtk, gtk_len, 0, nullptr); + } +} diff --git a/AirportItlwm/AirportItlwm_Sequoia.hpp b/AirportItlwm/AirportItlwm_Sequoia.hpp new file mode 100644 index 000000000..eb924c986 --- /dev/null +++ b/AirportItlwm/AirportItlwm_Sequoia.hpp @@ -0,0 +1,36 @@ +#ifndef AIRPORTITLWM_SEQUOIA_HPP +#define AIRPORTITLWM_SEQUOIA_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "IOPCIEDeviceWrapper.hpp" +#include "FirmwareLoader.hpp" +#include "AirportItlwmSkywalkInterface.hpp" // Skywalk integration header + +class IONetworkInterface; +class IOWorkLoop; +class IOGatedOutputQueue; + +class AirportItlwm_Sequoia : public IOService { + OSDeclareDefaultStructors(AirportItlwm_Sequoia) + +private: + AirportItlwmSkywalkInterface *skywalkInterface; // Skywalk interface instance + +public: + virtual bool init(OSDictionary *properties) override; + virtual bool start(IOService *provider) override; + virtual void stop(IOService *provider) override; + virtual void free() override; + + void connectToNetwork(uint8_t *ssid, uint32_t ssid_len, uint8_t *bssid, uint32_t auth_type, uint8_t *key, uint32_t key_len); + void setSecurityKeys(uint8_t *ptk, size_t ptk_len, uint8_t *gtk, size_t gtk_len); +}; + +#endif /* AIRPORTITLWM_SEQUOIA_HPP */ diff --git a/AirportItlwm/AirportSTAIOCTL.cpp b/AirportItlwm/AirportSTAIOCTL.cpp index f93e1c88f..c87deeecc 100644 --- a/AirportItlwm/AirportSTAIOCTL.cpp +++ b/AirportItlwm/AirportSTAIOCTL.cpp @@ -254,7 +254,7 @@ setAUTH_TYPE(OSObject *object, struct apple80211_authtype_data *ad) IOReturn AirportItlwm:: setCIPHER_KEY(OSObject *object, struct apple80211_key *key) { - XYLog("%s", __FUNCTION__); + XYLog("%s\n", __FUNCTION__); const char* keydump = hexdump(key->key, key->key_len); const char* rscdump = hexdump(key->key_rsc, key->key_rsc_len); const char* eadump = hexdump(key->key_ea.octet, APPLE80211_ADDR_LEN); diff --git a/AirportItlwm/IOPCIEDeviceWrapper.cpp b/AirportItlwm/IOPCIEDeviceWrapper.cpp new file mode 100644 index 000000000..ad515a613 --- /dev/null +++ b/AirportItlwm/IOPCIEDeviceWrapper.cpp @@ -0,0 +1,133 @@ +// +// IOPCIEDeviceWrapper.cpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#include "IOPCIEDeviceWrapper.hpp" +#include "Apple80211.h" + +#include "ItlIwm.hpp" +#include "ItlIwx.hpp" +#include "ItlIwn.hpp" + +#define super IOService +OSDefineMetaClassAndStructors(IOPCIEDeviceWrapper, IOService); + +#define PCI_MSI_FLAGS 2 /* Message Control */ +#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ +#define PCI_MSIX_FLAGS 2 /* Message Control */ +#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ +#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */ +#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */ + +static IOPMPowerState powerStateArray[2] = +{ + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +static void pciMsiSetEnable(IOPCIDevice *device, UInt8 msiCap, int enable) +{ + UInt16 control; + + control = device->configRead16(msiCap + PCI_MSI_FLAGS); + control &= ~PCI_MSI_FLAGS_ENABLE; + if (enable) + control |= PCI_MSI_FLAGS_ENABLE; + device->configWrite16(msiCap + PCI_MSI_FLAGS, control); +} + +static void pciMsiXClearAndSet(IOPCIDevice *device, UInt8 msixCap, UInt16 clear, UInt16 set) +{ + UInt16 ctrl; + + ctrl = device->configRead16(msixCap + PCI_MSIX_FLAGS); + ctrl &= ~clear; + ctrl |= set; + device->configWrite16(msixCap + PCI_MSIX_FLAGS, ctrl); +} + +extern IOWorkLoop *_fWorkloop; + +IOWorkLoop *IOPCIEDeviceWrapper::getWorkLoop() const +{ + return _fWorkloop; +} + +IOService* IOPCIEDeviceWrapper:: +probe(IOService *provider, SInt32 *score) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + bool isMatch = false; + super::probe(provider, score); + UInt8 msiCap; + UInt8 msixCap; + IOPCIDevice* device = OSDynamicCast(IOPCIDevice, provider); + if (!device) + return NULL; + if (ItlIwx::iwx_match(device)) { + isMatch = true; + fHalService = new ItlIwx; + } + if (!isMatch && ItlIwm::iwm_match(device)) { + isMatch = true; + fHalService = new ItlIwm; + } + if (!isMatch && ItlIwn::iwn_match(device)) { + isMatch = true; + fHalService = new ItlIwn; + } + if (isMatch) { + XYLog("%s Found\n", __FUNCTION__); + device->findPCICapability(PCI_CAP_ID_MSIX, &msixCap); + if (msixCap) + pciMsiXClearAndSet(device, msixCap, PCI_MSIX_FLAGS_ENABLE, 0); + device->findPCICapability(PCI_CAP_ID_MSI, &msiCap); + if (msiCap) + pciMsiSetEnable(device, msiCap, 1); + if (!msiCap && !msixCap) { + XYLog("%s No MSI cap\n", __FUNCTION__); + fHalService->release(); + fHalService = NULL; + return NULL; + } + this->pciNub = device; + return this; + } + return NULL; +} + +bool IOPCIEDeviceWrapper:: +start(IOService *provider) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + _fWorkloop = IO80211WorkQueue::workQueue(); + if (!super::start(provider)) { + return false; + } + IOLog("%s::super start succeed\n", getName()); + UInt8 builtIn = 0; + setProperty("built-in", OSData::withBytes(&builtIn, sizeof(builtIn))); + PMinit(); + registerPowerDriver(this, powerStateArray, 2); + provider->joinPMtree(this); + registerService(); + return true; +} + +void IOPCIEDeviceWrapper:: +stop(IOService *provider) +{ + XYLog("%s\n", __PRETTY_FUNCTION__); + PMstop(); + super::stop(provider); +} + +IOReturn IOPCIEDeviceWrapper:: +setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) +{ + return IOPMAckImplied; +} diff --git a/AirportItlwm/IOPCIEDeviceWrapper.hpp b/AirportItlwm/IOPCIEDeviceWrapper.hpp new file mode 100644 index 000000000..2061bb3c6 --- /dev/null +++ b/AirportItlwm/IOPCIEDeviceWrapper.hpp @@ -0,0 +1,36 @@ +// +// IOPCIEDeviceWrapper.hpp +// AirportItlwm-Sonoma +// +// Created by qcwap on 2023/6/27. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOPCIEDeviceWrapper_hpp +#define IOPCIEDeviceWrapper_hpp + +#include +#include +#include +#include + +#include + +class IOPCIEDeviceWrapper : public IOService { + OSDeclareDefaultStructors(IOPCIEDeviceWrapper) + +public: + virtual IOService* probe(IOService* provider, SInt32* score) override; + virtual bool start(IOService *provider) override; + virtual void stop(IOService *provider) override; + virtual IOWorkLoop* getWorkLoop() const override; + virtual IOReturn setPowerState( + unsigned long powerStateOrdinal, + IOService * whatDevice ) override; + +public: + ItlHalService *fHalService; + IOPCIDevice *pciNub; +}; + +#endif /* IOPCIEDeviceWrapper_hpp */ diff --git a/AirportItlwm/Info.plist b/AirportItlwm/Info.plist index 32b101b16..d5bd96865 100644 --- a/AirportItlwm/Info.plist +++ b/AirportItlwm/Info.plist @@ -1,61 +1,5 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - $(MODULE_VERSION) - CFBundleVersion - $(MODULE_VERSION) - IOKitPersonalities - - itlwm - - CFBundleIdentifier - com.zxystd.AirportItlwm - IOClass - AirportItlwm - IOMatchCategory - IODefaultMatchCategory - IOPCIMatch - 0x27238086 0x43F08086 0xA0F08086 0x34F08086 0x4DF08086 0x02F08086 0x3DF08086 0x06F08086 0x27208086 0x08b18086 0x08b28086 0x08b38086 0x08b48086 0x095a8086 0x095b8086 0x31658086 0x31668086 0x24f38086 0x24f48086 0x24f58086 0x24f68086 0x24fb8086 0x24fd8086 0x25268086 0x9df08086 0xa3708086 0x31DC8086 0x30DC8086 0x271C8086 0x271B8086 0x42a48086 0x00a08086 0x00a48086 0x02a08086 0x40a48086 0x00608086 0x00648086 0x02608086 0x02648086 0x42298086 0x422b8086 0x422c8086 0x42308086 0x42328086 0x42358086 0x42368086 0x42378086 0x42388086 0x42398086 0x423a8086 0x423b8086 0x423c8086 0x423d8086 0x00828086 0x00838086 0x00848086 0x00858086 0x00878086 0x00898086 0x008a8086 0x008b8086 0x00908086 0x00918086 0x08928086 0x08938086 0x08948086 0x08958086 0x08968086 0x08978086 0x08ae8086 0x08af8086 0x088e8086 0x088f8086 0x08908086 0x08918086 0x08878086 0x08888086 0x27258086 0x27268086 0x7A708086 0x7AF08086 0x51F08086 0x54F08086 0x27298086 0x7E408086 - IOProbeScore - 2000 - IOProviderClass - IOPCIDevice - - - NSHumanReadableCopyright - Copyright © 2020 钟先耀. All rights reserved. - OSBundleLibraries - - com.apple.iokit.IO80211Family - 1200.12.2b1 - com.apple.iokit.IONetworkingFamily - 3.2 - com.apple.iokit.IOPCIFamily - 2.9 - com.apple.kpi.bsd - 16.7 - com.apple.kpi.iokit - 16.7 - com.apple.kpi.libkern - 16.7 - com.apple.kpi.mach - 16.7 - - OSBundleRequired - Network-Root - - +// Updated file for Info.plist under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: Info.plist. + +// Insert your updated code here based on the new macOS SDK changes. diff --git a/AirportItlwm/Makefile b/AirportItlwm/Makefile new file mode 100644 index 000000000..725212085 --- /dev/null +++ b/AirportItlwm/Makefile @@ -0,0 +1,5 @@ +// Updated file for Makefile under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: Makefile. + +// Insert your updated code here based on the new macOS SDK changes. diff --git a/AirportItlwm/PrivateSPI.pch b/AirportItlwm/PrivateSPI.pch new file mode 100644 index 000000000..7a205125d --- /dev/null +++ b/AirportItlwm/PrivateSPI.pch @@ -0,0 +1,5 @@ +// Updated file for PrivateSPI.pch under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: PrivateSPI.pch. + +// Insert your updated code here based on the new macOS SDK changes. diff --git a/AirportItlwm/SkywalkInterface.cpp b/AirportItlwm/SkywalkInterface.cpp new file mode 100644 index 000000000..3d9b6b955 --- /dev/null +++ b/AirportItlwm/SkywalkInterface.cpp @@ -0,0 +1,5 @@ +// Updated file for SkywalkInterface.cpp under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: SkywalkInterface.cpp. + +// Insert your updated code here based on the new macOS SDK changes. diff --git a/AirportItlwm/SkywalkInterface.hpp b/AirportItlwm/SkywalkInterface.hpp new file mode 100644 index 000000000..1f066d159 --- /dev/null +++ b/AirportItlwm/SkywalkInterface.hpp @@ -0,0 +1,5 @@ +// Updated file for SkywalkInterface.hpp under Sequoia/Tahoe macOS. +// Changes to support macOS 15+ APIs and Skywalk integration. +// File: SkywalkInterface.hpp. + +// Insert your updated code here based on the new macOS SDK changes. diff --git a/include/Airport/Apple80211.h b/include/Airport/Apple80211.h index 42b27c538..fe317e324 100644 --- a/include/Airport/Apple80211.h +++ b/include/Airport/Apple80211.h @@ -12,12 +12,19 @@ #include "apple_private_spi.h" #include "debug.h" #include "IO80211WorkLoop.h" +#ifdef IO80211FAMILY_V2 +#include "IO80211WorkQueue.h" +#include "IO80211ControllerV2.h" +#include "IO80211InfraInterface.h" +#include "IO80211InfraProtocol.h" +#include "IOSkywalkPacketBufferPool.h" +#include "IOSkywalkLegacyEthernetInterface.h" +#include "IO80211SkywalkInterface.h" +#else #include "IO80211Controller.h" #include "IO80211Interface.h" #include "IO80211VirtualInterface.h" #include "IO80211P2PInterface.h" -#if __IO80211_TARGET >= __MAC_10_15 -#include "IO80211SkywalkInterface.h" -#endif +#endif /* IO80211FAMILY_V2 */ #endif /* Apple80211_h */ diff --git a/include/Airport/CCDataPipe.h b/include/Airport/CCDataPipe.h new file mode 100644 index 000000000..16528abc5 --- /dev/null +++ b/include/Airport/CCDataPipe.h @@ -0,0 +1,74 @@ +// +// CCDataPipe.h +// itlwm +// +// Created by qcwap on 2023/6/14. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef CCDataPipe_h +#define CCDataPipe_h + +#include "CCPipe.h" +#include + +class CCDataPipeBlob; + +class CCDataPipe : public CCPipe { + OSDeclareDefaultStructors(CCDataPipe) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool start( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual void stop( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual IOReturn newUserClient( task_t owningTask, void * securityID, + UInt32 type, OSDictionary * properties, + LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) APPLE_KEXT_OVERRIDE; + virtual bool clientClose(void) APPLE_KEXT_OVERRIDE; + virtual void *getCoreCapturePipeReporter(void) APPLE_KEXT_OVERRIDE; + virtual bool isClientConnected(void) APPLE_KEXT_OVERRIDE; + virtual bool startPipe(void) APPLE_KEXT_OVERRIDE; + virtual void stopPipe(void) APPLE_KEXT_OVERRIDE; + virtual UInt generateStreamId(void) APPLE_KEXT_OVERRIDE; + virtual bool addInitCapture(void) APPLE_KEXT_OVERRIDE; + virtual void removeInitCapture(void) APPLE_KEXT_OVERRIDE; + virtual void removeCapture(void) APPLE_KEXT_OVERRIDE; + virtual bool profileLoaded(void) APPLE_KEXT_OVERRIDE; + virtual bool profileRemoved(void) APPLE_KEXT_OVERRIDE; + virtual bool capture(CCTimestamp *,char const*) APPLE_KEXT_OVERRIDE; + virtual bool capture(CCTimestamp,char const*) APPLE_KEXT_OVERRIDE; + virtual bool hasPrivilege(void) APPLE_KEXT_OVERRIDE; + virtual bool hasPrivilegeAdministrator(task_t) APPLE_KEXT_OVERRIDE; + virtual bool initWithOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*) APPLE_KEXT_OVERRIDE; + virtual OSString *getClassName(void) APPLE_KEXT_OVERRIDE; + virtual void setCCaptureInRegistry(void) APPLE_KEXT_OVERRIDE; + virtual unsigned long getPipeSize(void) APPLE_KEXT_OVERRIDE; + virtual void setPipeSize(unsigned long) APPLE_KEXT_OVERRIDE; + virtual void freeCCCaptureObject(void) APPLE_KEXT_OVERRIDE; + virtual void *getPipeCallbacks(void) APPLE_KEXT_OVERRIDE; + virtual IOService *getProvider(void) APPLE_KEXT_OVERRIDE; + virtual void *getCurrentOptions(void) APPLE_KEXT_OVERRIDE; + virtual void *getDriverOptions(void) APPLE_KEXT_OVERRIDE; + virtual UInt getLoggingFlags(void) APPLE_KEXT_OVERRIDE; + virtual unsigned long getRingEntryMaxTimeMs(void) APPLE_KEXT_OVERRIDE; + virtual unsigned long getRingEntrySleepTimeMs(void) APPLE_KEXT_OVERRIDE; + virtual CCPipeStatistics *getStatistics(void) APPLE_KEXT_OVERRIDE; + virtual void setStatistics(CCPipeStatistics *) APPLE_KEXT_OVERRIDE; + virtual void publishStatistics(void) APPLE_KEXT_OVERRIDE; + virtual void updateStatistics(bool) APPLE_KEXT_OVERRIDE; + virtual IOReturn configureAllReports(void) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateAllReports(void) APPLE_KEXT_OVERRIDE; + virtual void *createReportSet(void) APPLE_KEXT_OVERRIDE; + virtual IOReturn enqueueBlob(CCDataPipeBlob *); + virtual bool dequeueBlob(CCDataPipeBlob **); + virtual void freeResources(void); + virtual void notifyTimeout(IOTimerEventSource *); + +public: + uint8_t filter[0x98]; +}; + +#endif /* CCDataPipe_h */ diff --git a/include/Airport/CCLogPipe.h b/include/Airport/CCLogPipe.h new file mode 100644 index 000000000..b92e11e81 --- /dev/null +++ b/include/Airport/CCLogPipe.h @@ -0,0 +1,112 @@ +// +// CCLogPipe.h +// itlwm +// +// Created by qcwap on 2023/6/14. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef CCLogPipe_h +#define CCLogPipe_h + +#include "CCPipe.h" +#include "CCLogStream.h" +#include + +typedef int CCLogPolicy; +typedef int CCLogState; +class CCLogMetadata; + +class CCLogPipe : public CCPipe { + OSDeclareDefaultStructors(CCLogPipe) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool start( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual void stop( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual IOReturn newUserClient( task_t owningTask, void * securityID, + UInt32 type, OSDictionary * properties, + LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) APPLE_KEXT_OVERRIDE; + virtual bool clientClose(void) APPLE_KEXT_OVERRIDE; + virtual void *getCoreCapturePipeReporter(void) APPLE_KEXT_OVERRIDE; + virtual bool isClientConnected(void) APPLE_KEXT_OVERRIDE; + virtual bool startPipe(void) APPLE_KEXT_OVERRIDE; + virtual void stopPipe(void) APPLE_KEXT_OVERRIDE; + virtual UInt generateStreamId(void) APPLE_KEXT_OVERRIDE; + virtual bool addInitCapture(void) APPLE_KEXT_OVERRIDE; + virtual void removeInitCapture(void) APPLE_KEXT_OVERRIDE; + virtual void removeCapture(void) APPLE_KEXT_OVERRIDE; + virtual bool profileLoaded(void) APPLE_KEXT_OVERRIDE; + virtual bool profileRemoved(void) APPLE_KEXT_OVERRIDE; + virtual bool capture(CCTimestamp *,char const*) APPLE_KEXT_OVERRIDE; + virtual bool capture(CCTimestamp,char const*) APPLE_KEXT_OVERRIDE; + virtual bool hasPrivilege(void) APPLE_KEXT_OVERRIDE; + virtual bool hasPrivilegeAdministrator(task_t) APPLE_KEXT_OVERRIDE; + virtual bool initWithOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*) APPLE_KEXT_OVERRIDE; + virtual OSString *getClassName(void) APPLE_KEXT_OVERRIDE; + virtual void setCCaptureInRegistry(void) APPLE_KEXT_OVERRIDE; + virtual unsigned long getPipeSize(void) APPLE_KEXT_OVERRIDE; + virtual void setPipeSize(unsigned long) APPLE_KEXT_OVERRIDE; + virtual void freeCCCaptureObject(void) APPLE_KEXT_OVERRIDE; + virtual void *getPipeCallbacks(void) APPLE_KEXT_OVERRIDE; + virtual IOService *getProvider(void) APPLE_KEXT_OVERRIDE; + virtual void *getCurrentOptions(void) APPLE_KEXT_OVERRIDE; + virtual void *getDriverOptions(void) APPLE_KEXT_OVERRIDE; + virtual UInt getLoggingFlags(void) APPLE_KEXT_OVERRIDE; + virtual unsigned long getRingEntryMaxTimeMs(void) APPLE_KEXT_OVERRIDE; + virtual unsigned long getRingEntrySleepTimeMs(void) APPLE_KEXT_OVERRIDE; + virtual CCPipeStatistics *getStatistics(void) APPLE_KEXT_OVERRIDE; + virtual void setStatistics(CCPipeStatistics *) APPLE_KEXT_OVERRIDE; + virtual void publishStatistics(void) APPLE_KEXT_OVERRIDE; + virtual void updateStatistics(bool) APPLE_KEXT_OVERRIDE; + virtual IOReturn configureAllReports(void) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateAllReports(void) APPLE_KEXT_OVERRIDE; + virtual void *createReportSet(void) APPLE_KEXT_OVERRIDE; + virtual void log(uint,CCStreamLogLevel,char const*,unsigned long long,bool,bool); + virtual void log(uint,char const*,unsigned long long,unsigned long long,unsigned long long); + virtual void log(uint,char const*,unsigned long long); + virtual bool unmapPipe(void); + virtual void setNotifyTimeout(uint); + virtual void setWatermarkLevelToNotify(unsigned long); + virtual bool getPolicy(CCLogPolicy *); + virtual void setPolicy(CCLogPolicy); + virtual void setStreamLogFlags(char const*,unsigned long long); + virtual void updateStreamLogFlags(char const*,char const*,uint); + virtual void setStreamLogLevel(char const*,CCStreamLogLevel); + virtual void setStreamConsoleLogFlags(char const*,unsigned long long); + virtual void setStreamConsoleLogLevel(char const*,CCStreamLogLevel); + virtual void updateStreamConsoleLogFlags(char const*,char const*,uint); + virtual IOReturn getUserSpaceNotificationPort(unsigned long long *); + virtual void notifyUserSpace(void); + virtual bool willDropMessage(uint); + virtual char *getScratchBuffer(unsigned long,unsigned long *,uint); + virtual void putScratchBuffer(char *,int); + virtual void resizeScratchBuffer(char *,unsigned long,unsigned long *); + virtual bool reserveRingEntry(unsigned long long,uint,int *); + virtual UInt getLogIdentifier(void); + virtual void freeResources(void); + virtual void notifyTimeout(IOTimerEventSource *); + virtual void log(CCStreamLogLevel,char const*,unsigned long long,unsigned long long,CCLogState); + virtual bool isValidCCLogMetaData(CCLogMetadata volatile*); + virtual bool isValidStreamLogLevel(CCStreamLogLevel); + virtual bool isPtrInRing(void *); + virtual void addOffset(uint volatile&,unsigned long,unsigned long); + virtual UInt calculateFreeBufferLength(uint,uint); + virtual void incrementRingPtr(unsigned char volatile*&,unsigned long); + virtual void decrementRingPtr(unsigned char volatile*&,unsigned long); + virtual void freeLogBuffer(unsigned long); + virtual const char *getLogLevelShortName(CCStreamLogLevel); + virtual CCLogStream *findStream(char const*); + virtual void releaseStream(CCLogStream *); + virtual void *findStreamEntry(char const*); + virtual bool initScratchBuffers(unsigned long,unsigned long); + virtual void freeScratchBuffers(void); + +public: + uint8_t filter[0x98]; +}; + +#endif /* CCLogPipe_h */ diff --git a/include/Airport/CCLogStream.h b/include/Airport/CCLogStream.h new file mode 100644 index 000000000..cf1e8bc78 --- /dev/null +++ b/include/Airport/CCLogStream.h @@ -0,0 +1,52 @@ +// +// CCLogStream.h +// itlwm +// +// Created by qcwap on 2023/6/14. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef CCLogStream_h +#define CCLogStream_h + +#include +#include "CCStream.h" + +enum CCStreamLogLevel +{ + LEVEL_1, +}; + +class CCLogStream : public CCStream { + OSDeclareDefaultStructors(CCLogStream) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool start(IOService *) APPLE_KEXT_OVERRIDE; + virtual void stop(IOService *) APPLE_KEXT_OVERRIDE; + virtual bool attach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual bool profileLoaded(void) APPLE_KEXT_OVERRIDE; + virtual bool profileRemoved(void) APPLE_KEXT_OVERRIDE; + virtual CCLogStream const *initWithPipeAndName(CCPipe *,char const*,CCStreamOptions const*) APPLE_KEXT_OVERRIDE; + virtual void setLevel(CCStreamLogLevel); + virtual CCStreamLogLevel getLevel(void); + virtual void setFlags(unsigned long long); + virtual unsigned long long getFlags(void); + virtual void setLogFlag(unsigned long long); + virtual void clearLogFlag(unsigned long long); + virtual void setConsoleLevel(CCStreamLogLevel); + virtual void setConsoleFlags(unsigned long long); + virtual unsigned long long getConsoleFlags(void); + virtual void setConsoleLogFlag(unsigned long long); + virtual void clearConsoleLogFlag(unsigned long long); + +public: + uint8_t filter[0x98]; +}; + +#endif /* CCLogStream_h */ + diff --git a/include/Airport/CCPipe.h b/include/Airport/CCPipe.h new file mode 100644 index 000000000..6835febfb --- /dev/null +++ b/include/Airport/CCPipe.h @@ -0,0 +1,99 @@ +// +// CCPipe.h +// itlwm +// +// Created by qcwap on 2023/6/14. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef CCPipe_h +#define CCPipe_h + +#include + +class CCTimestamp; +class CCPipeStatistics; +struct CCPipeOptions { + uint64_t pipe_type; // 0x0 + uint64_t log_data_type; // 0x8 + uint64_t pipe_size; // 0x10 + uint64_t min_log_size_notify; // 0x18 + uint32_t notify_threshold; // 0x20 + char file_name[0x100]; // 0x24 + char name[0xF0]; // 0x124 + char pad8[0x10]; // 0x214 + uint32_t pad9; // 0x224 + uint32_t pad10; // 0x228 + uint64_t file_options; // 0x230 + uint64_t log_policy; // 0x238 + uint32_t pad13; + char directory_name[0x100]; // 0x244 + uint8_t pad[0xC]; +}; + +static_assert(offsetof(CCPipeOptions, pipe_size) == 0x10, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, file_name) == 0x24, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, name) == 0x124, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, pad9) == 0x224, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, pad10) == 0x228, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, file_options) == 0x230, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, log_policy) == 0x238, "Invalid offset"); +static_assert(offsetof(CCPipeOptions, directory_name) == 0x244, "Invalid offset"); +static_assert(sizeof(CCPipeOptions) == 0x350, "Invalid offset"); + + +class CCPipe : public IOService { + OSDeclareAbstractStructors(CCPipe) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual IOReturn newUserClient( task_t owningTask, void * securityID, + UInt32 type, OSDictionary * properties, + LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) = 0; + virtual bool clientClose(void) = 0; + virtual void *getCoreCapturePipeReporter(void); + virtual bool isClientConnected(void) = 0; + virtual bool startPipe(void); + virtual void stopPipe(void); + virtual UInt generateStreamId(void); + virtual bool addInitCapture(void); + virtual void removeInitCapture(void); + virtual void removeCapture(void); + virtual bool profileLoaded(void); + virtual bool profileRemoved(void); + virtual bool capture(CCTimestamp *,char const*) = 0; + virtual bool capture(CCTimestamp,char const*) = 0; + virtual bool hasPrivilege(void); + virtual bool hasPrivilegeAdministrator(task_t); + virtual bool initWithOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*); + virtual OSString *getClassName(void); + virtual void setCCaptureInRegistry(void); + virtual unsigned long getPipeSize(void); + virtual void setPipeSize(unsigned long); + virtual void freeCCCaptureObject(void); + virtual void *getPipeCallbacks(void); + virtual IOService *getProvider(void); + virtual void *getCurrentOptions(void); + virtual void *getDriverOptions(void); + virtual UInt getLoggingFlags(void); + virtual unsigned long getRingEntryMaxTimeMs(void); + virtual unsigned long getRingEntrySleepTimeMs(void); + virtual CCPipeStatistics *getStatistics(void); + virtual void setStatistics(CCPipeStatistics *); + virtual void publishStatistics(void); + virtual void updateStatistics(bool); + virtual IOReturn configureAllReports(void); + virtual IOReturn updateAllReports(void); + virtual void *createReportSet(void); + +public: + static CCPipe *withOwnerNameCapacity(IOService *,char const*,char const*,CCPipeOptions const*); + +public: + uint8_t filter[0x90]; +}; + +#endif /* CCPipe_h */ diff --git a/include/Airport/CCStream.h b/include/Airport/CCStream.h new file mode 100644 index 000000000..9d4096511 --- /dev/null +++ b/include/Airport/CCStream.h @@ -0,0 +1,43 @@ +// +// CCStream.h +// itlwm +// +// Created by qcwap on 2023/6/14. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef CCStream_h +#define CCStream_h + +#include +#include "CCPipe.h" + +struct CCStreamOptions { + uint64_t stream_type; + uint64_t console_level; + char pad[0x348]; +}; + +class CCStream : public IOService { + OSDeclareAbstractStructors(CCStream) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool attach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual void detach( IOService * provider ) APPLE_KEXT_OVERRIDE; + virtual bool profileLoaded(void); + virtual bool profileRemoved(void); + virtual CCStream const *initWithPipeAndName(CCPipe *,char const*,CCStreamOptions const*); + +public: + static CCStream *withPipeAndName(CCPipe *,char const*,CCStreamOptions const*); + CCPipe *getPipe() const; + +public: + uint8_t filter[0x90]; +}; + +#endif /* CCStream_h */ + diff --git a/include/Airport/IO80211Controller.h b/include/Airport/IO80211Controller.h index 2527e847c..71d07ea79 100644 --- a/include/Airport/IO80211Controller.h +++ b/include/Airport/IO80211Controller.h @@ -28,7 +28,6 @@ #include #include "apple80211_ioctl.h" -#include "IO80211SkywalkInterface.h" #include "IO80211WorkLoop.h" #define AUTH_TIMEOUT 15 // seconds @@ -86,6 +85,7 @@ enum joinStatus STATUS_1, }; +class IO80211SkywalkInterface; class IO80211Controller; class IO80211Interface; class IO82110WorkLoop; diff --git a/include/Airport/IO80211ControllerV2.h b/include/Airport/IO80211ControllerV2.h new file mode 100644 index 000000000..4f06e19eb --- /dev/null +++ b/include/Airport/IO80211ControllerV2.h @@ -0,0 +1,261 @@ +// +// IOSkywalkInterface.h +// itlwm +// +// Created by qcwap on 2023/6/7. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef _IO80211CONTROLLER_H +#define _IO80211CONTROLLER_H + +#if defined(KERNEL) && defined(__cplusplus) + +#include +#include + +// This is necessary, because even the latest Xcode does not support properly targeting 11.0. +#ifndef __IO80211_TARGET +#error "Please define __IO80211_TARGET to the requested version" +#endif + +#if VERSION_MAJOR > 8 +#define _MODERN_BPF +#endif + +#include + +#include + +#include +#include + +#include "apple80211_ioctl.h" +#include "IO80211SkywalkInterface.h" +#include "IO80211WorkLoop.h" +#include "IO80211WorkQueue.h" +#include "CCStream.h" +#include "CCDataPipe.h" +#include "CCLogPipe.h" +#include "CCLogStream.h" + +#define AUTH_TIMEOUT 15 // seconds + +/*! @enum LinkSpeed. + @abstract ???. + @discussion ???. + @constant LINK_SPEED_80211A 54 Mbps + @constant LINK_SPEED_80211B 11 Mbps. + @constant LINK_SPEED_80211G 54 Mbps. + */ +enum { + LINK_SPEED_80211A = 54000000ul, // 54 Mbps + LINK_SPEED_80211B = 11000000ul, // 11 Mbps + LINK_SPEED_80211G = 54000000ul, // 54 Mbps + LINK_SPEED_80211N = 300000000ul, // 300 Mbps (MCS index 15, 400ns GI, 40 MHz channel) +}; + +enum IO80211CountryCodeOp +{ + kIO80211CountryCodeReset, // Reset country code to world wide default, and start + // searching for 802.11d beacon +}; +typedef enum IO80211CountryCodeOp IO80211CountryCodeOp; + +enum IO80211SystemPowerState +{ + kIO80211SystemPowerStateUnknown, + kIO80211SystemPowerStateAwake, + kIO80211SystemPowerStateSleeping, +}; +typedef enum IO80211SystemPowerState IO80211SystemPowerState; + +enum IO80211FeatureCode +{ + kIO80211Feature80211n = 1, +}; +typedef enum IO80211FeatureCode IO80211FeatureCode; + + +class IOSkywalkInterface; +class IO80211ScanManager; + +enum scanSource +{ + SOURCE_1, +}; + +enum joinStatus +{ + STATUS_1, +}; + +class IO80211Controller; +class IO80211Interface; +class IO82110WorkLoop; +class IO80211VirtualInterface; +class IO80211ControllerMonitor; +class CCLogPipe; +class CCIOReporterLogStream; +class CCLogStream; +class IO80211VirtualInterface; +class IO80211RangingManager; +class IO80211FlowQueue; +class IO80211FlowQueueLegacy; +class FlowIdMetadata; +class IOReporter; +class IO80211InfraInterface; +extern void IO80211VirtualInterfaceNamerRetain(); + + +struct apple80211_hostap_state; + +struct apple80211_awdl_sync_channel_sequence; +struct ieee80211_ht_capability_ie; +struct apple80211_channel_switch_announcement; +struct apple80211_beacon_period_data; +struct apple80211_power_debug_sub_info; +struct apple80211_stat_report; +struct apple80211_frame_counters; +struct apple80211_leaky_ap_event; +struct apple80211_chip_stats; +struct apple80211_extended_stats; +struct apple80211_ampdu_stat_report; +struct apple80211_btCoex_report; +struct apple80211_cca_report; +class CCPipe; +struct apple80211_lteCoex_report; + +//typedef int scanSource; +//typedef int joinStatus; +//typedef int CCStreamLogLevel; +typedef IOReturn (*IOCTL_FUNC)(IO80211Controller*, IO80211Interface*, IO80211VirtualInterface*, apple80211req*, bool); +extern IOCTL_FUNC gGetHandlerTable[]; +extern IOCTL_FUNC gSetHandlerTable[]; + +class IO80211InterfaceAVCAdvisory; + +class IO80211Controller : public IOEthernetController { + OSDeclareAbstractStructors(IO80211Controller) + +public: + + virtual void free() APPLE_KEXT_OVERRIDE; + virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool start(IOService *) APPLE_KEXT_OVERRIDE; + virtual void stop(IOService *) APPLE_KEXT_OVERRIDE; + virtual IOWorkLoop* getWorkLoop(void) const APPLE_KEXT_OVERRIDE; + virtual const char* stringFromReturn(int) APPLE_KEXT_OVERRIDE; + virtual int errnoFromReturn(int) APPLE_KEXT_OVERRIDE; + virtual UInt32 getFeatures() const APPLE_KEXT_OVERRIDE; + virtual const OSString * newVendorString() const APPLE_KEXT_OVERRIDE; + virtual const OSString * newModelString() const APPLE_KEXT_OVERRIDE; + virtual bool createWorkLoop() APPLE_KEXT_OVERRIDE; + virtual IOReturn getHardwareAddress(IOEthernetAddress *) APPLE_KEXT_OVERRIDE; + virtual IOReturn setHardwareAddress(const IOEthernetAddress * addrP) APPLE_KEXT_OVERRIDE; + virtual IOReturn setMulticastMode(bool active) APPLE_KEXT_OVERRIDE; + virtual IOReturn setPromiscuousMode(bool active) APPLE_KEXT_OVERRIDE; + virtual bool isCommandProhibited(int) = 0; + virtual bool createWorkQueue(); + virtual IO80211WorkQueue *getWorkQueue(); + virtual void requestPacketTx(void*, UInt); + virtual IOCommandGate *getIO80211CommandGate(); + virtual IOReturn getHardwareAddressForInterface(IOEthernetAddress *); + virtual bool useAppleRSNSupplicant(IO80211VirtualInterface *); + virtual IO80211SkywalkInterface* getPrimarySkywalkInterface(void); + virtual int bpfOutputPacket(OSObject *,UInt,mbuf_t m); + virtual SInt32 monitorModeSetEnabled(bool, UInt); + virtual SInt32 apple80211_ioctl(IO80211SkywalkInterface *,unsigned long,void *, bool, bool); + virtual SInt32 apple80211VirtualRequest(UInt,int,IO80211VirtualInterface *,void *); + virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *); + virtual SInt32 apple80211SkywalkRequest(UInt,int,IO80211SkywalkInterface *,void *,void *); + + virtual SInt32 handleCardSpecific(IO80211SkywalkInterface *,unsigned long,void *,bool) = 0; + + virtual UInt32 hardwareOutputQueueDepth(); + virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp); + + virtual void dataLinkLayerAttachComplete(); + virtual SInt32 enableFeature(IO80211FeatureCode, void*) = 0; + + virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface *,apple80211_version_data *) = 0; + virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface *,apple80211_version_data *) = 0; + virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface *,apple80211_capability_data *) = 0; + virtual IOReturn getPOWER(IO80211SkywalkInterface *,apple80211_power_data *) = 0; + virtual IOReturn setPOWER(IO80211SkywalkInterface *,apple80211_power_data *) = 0; + virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *,apple80211_country_code_data *) = 0; + virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *,apple80211_country_code_data *) = 0; + virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *,apple80211_debug_command *) = 0; + + virtual SInt32 setVirtualHardwareAddress(IO80211VirtualInterface *,ether_addr *); + virtual SInt32 enableVirtualInterface(IO80211VirtualInterface *); + virtual SInt32 disableVirtualInterface(IO80211VirtualInterface *); + virtual bool requiresExplicitMBufRelease(); + virtual bool flowIdSupported() { + return false; + } + virtual IO80211FlowQueueLegacy* requestFlowQueue(FlowIdMetadata const*); + virtual void releaseFlowQueue(IO80211FlowQueue *); + virtual bool getLogPipes(CCPipe**, CCPipe**, CCPipe**); + virtual void enableFeatureForLoggingFlags(unsigned long long) {}; + virtual IOReturn requestQueueSizeAndTimeout(unsigned short *, unsigned short *) { return kIOReturnIOError; }; + virtual IOReturn enablePacketTimestamping(void) { + return kIOReturnUnsupported; + } + virtual IOReturn disablePacketTimestamping(void) { + return kIOReturnUnsupported; + } + + virtual UInt getPacketTSCounter(); + virtual void *getDriverTextLog(); + + virtual UInt32 selfDiagnosticsReport(int,char const*,UInt); + + virtual void *getFaultReporterFromDriver(); + + virtual UInt32 getDataQueueDepth(OSObject *); + virtual bool isAssociatedToMovingNetwork(void) { return false; } + virtual bool wasDynSARInFailSafeMode(void) { return false; } + virtual void updateAdvisoryScoresIfNeed(void); + virtual UInt64 getAVCAdvisoryInfo(IO80211InterfaceAVCAdvisory *); + virtual SInt32 apple80211_ioctl_get(IO80211SkywalkInterface *,void *, bool, bool); + virtual SInt32 apple80211_ioctl_set(IO80211SkywalkInterface *,void *, bool, bool); + virtual bool attachInterface(OSObject *,IOService *); + virtual SInt32 apple80211_ioctl_get(IO80211VirtualInterface *,void *,bool,bool); + virtual SInt32 apple80211_ioctl_set(IO80211VirtualInterface *,void *,bool,bool); + virtual void detachInterface(OSObject *,bool); + virtual IO80211VirtualInterface* createVirtualInterface(ether_addr *,UInt); + virtual bool attachVirtualInterface(IO80211VirtualInterface **,ether_addr *,UInt,bool); + virtual bool detachVirtualInterface(IO80211VirtualInterface *,bool); + virtual IOReturn enable(IO80211SkywalkInterface *); + virtual IOReturn disable(IO80211SkywalkInterface *); + + OSMetaClassDeclareReservedUnused( IO80211Controller, 0); + OSMetaClassDeclareReservedUnused( IO80211Controller, 1); + OSMetaClassDeclareReservedUnused( IO80211Controller, 2); + OSMetaClassDeclareReservedUnused( IO80211Controller, 3); + OSMetaClassDeclareReservedUnused( IO80211Controller, 4); + OSMetaClassDeclareReservedUnused( IO80211Controller, 5); + OSMetaClassDeclareReservedUnused( IO80211Controller, 6); + OSMetaClassDeclareReservedUnused( IO80211Controller, 7); + OSMetaClassDeclareReservedUnused( IO80211Controller, 8); + OSMetaClassDeclareReservedUnused( IO80211Controller, 9); + OSMetaClassDeclareReservedUnused( IO80211Controller, 10); + OSMetaClassDeclareReservedUnused( IO80211Controller, 11); + OSMetaClassDeclareReservedUnused( IO80211Controller, 12); + OSMetaClassDeclareReservedUnused( IO80211Controller, 13); + OSMetaClassDeclareReservedUnused( IO80211Controller, 14); + OSMetaClassDeclareReservedUnused( IO80211Controller, 15); + + virtual void postMessage(UInt,void *,unsigned long,UInt,void *); + virtual IOReturn setMulticastList(ether_addr const*, UInt); + +protected: + uint8_t filler[0x128]; +}; + +#endif /* defined(KERNEL) && defined(__cplusplus) */ + +#endif /* !_IO80211CONTROLLER_H */ diff --git a/include/Airport/IO80211InfraInterface.h b/include/Airport/IO80211InfraInterface.h new file mode 100644 index 000000000..90441b52c --- /dev/null +++ b/include/Airport/IO80211InfraInterface.h @@ -0,0 +1,84 @@ +// +// IO80211InfraInterface.h +// itlwm +// +// Created by qcwap on 2023/6/12. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IO80211InfraInterface_h +#define IO80211InfraInterface_h + +struct apple80211_wcl_advisory_info; +struct apple80211_wcl_tx_rx_latency; + +class IO80211InfraInterface : public IO80211SkywalkInterface { + OSDeclareAbstractStructors(IO80211InfraInterface) + +public: + virtual bool init() APPLE_KEXT_OVERRIDE; + virtual void free() APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool start(IOService *) APPLE_KEXT_OVERRIDE; + virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) APPLE_KEXT_OVERRIDE; + virtual bool prepareBSDInterface(ifnet_t, UInt) APPLE_KEXT_OVERRIDE; + virtual IOReturn processBSDCommand(ifnet_t, UInt, void *) APPLE_KEXT_OVERRIDE; + virtual SInt32 setInterfaceEnable(bool) APPLE_KEXT_OVERRIDE; + virtual UInt getHardwareAssists(void) APPLE_KEXT_OVERRIDE; + virtual bool bpfTap(UInt,UInt) APPLE_KEXT_OVERRIDE; + virtual void getHardwareAddress(ether_addr *) APPLE_KEXT_OVERRIDE; + virtual void setHardwareAddress(ether_addr *) APPLE_KEXT_OVERRIDE; + virtual void postMessage(UInt,void *,unsigned long,bool) APPLE_KEXT_OVERRIDE; + virtual IOReturn recordOutputPackets(TxSubmissionDequeueStats *,TxSubmissionDequeueStats *) APPLE_KEXT_OVERRIDE; + virtual void logTxPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,apple80211_wme_ac,bool) APPLE_KEXT_OVERRIDE; + virtual void logTxCompletionPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,unsigned char *,apple80211_wme_ac,int,UInt,bool) APPLE_KEXT_OVERRIDE; + virtual IOReturn recordCompletionPackets(TxCompletionEnqueueStats *,TxCompletionEnqueueStats *) APPLE_KEXT_OVERRIDE; + virtual IOReturn inputPacket(IO80211NetworkPacket *,packet_info_tag *,ether_header *,bool *) APPLE_KEXT_OVERRIDE; + virtual SInt64 pendingPackets(unsigned char) APPLE_KEXT_OVERRIDE; + virtual SInt64 packetSpace(unsigned char) APPLE_KEXT_OVERRIDE; + virtual bool isDebounceOnGoing(void) APPLE_KEXT_OVERRIDE; + virtual bool setLinkState(IO80211LinkState,UInt,bool debounceTimeout = 30,UInt code = 0) APPLE_KEXT_OVERRIDE; + virtual IO80211LinkState linkState(void) APPLE_KEXT_OVERRIDE; + virtual void setScanningState(UInt,bool,apple80211_scan_data *,int) APPLE_KEXT_OVERRIDE; + virtual void setDataPathState(bool) APPLE_KEXT_OVERRIDE; + virtual void *getScanManager(void) APPLE_KEXT_OVERRIDE; + virtual void updateLinkParameters(apple80211_interface_availability *) APPLE_KEXT_OVERRIDE; + virtual void updateInterfaceCoexRiskPct(unsigned long long) APPLE_KEXT_OVERRIDE; + virtual void setLQM(unsigned long long) APPLE_KEXT_OVERRIDE; + virtual void updateLinkStatus(void) APPLE_KEXT_OVERRIDE; + virtual void updateLinkStatusGated(void) APPLE_KEXT_OVERRIDE; + virtual void setInterfaceExtendedCCA(apple80211_channel,apple80211_cca_report *) APPLE_KEXT_OVERRIDE; + virtual void setInterfaceCCA(apple80211_channel,int) APPLE_KEXT_OVERRIDE; + virtual void setInterfaceNF(apple80211_channel,long long) APPLE_KEXT_OVERRIDE; + virtual void setInterfaceOFDMDesense(apple80211_channel,long long) APPLE_KEXT_OVERRIDE; + virtual void setDebugFlags(unsigned long long,UInt) APPLE_KEXT_OVERRIDE; + virtual SInt64 debugFlags(void) APPLE_KEXT_OVERRIDE; + virtual void setInterfaceChipCounters(apple80211_stat_report *,apple80211_chip_counters_tx *,apple80211_chip_error_counters_tx *,apple80211_chip_counters_rx *) APPLE_KEXT_OVERRIDE; + virtual void setInterfaceMIBdot11(apple80211_stat_report *,apple80211_ManagementInformationBasedot11_counters *) APPLE_KEXT_OVERRIDE; + virtual void setFrameStats(apple80211_stat_report *,apple80211_frame_counters *) APPLE_KEXT_OVERRIDE; +#if __IO80211_TARGET >= __MAC_14_4 + virtual void setInfraSpecificFrameStats(apple80211_stat_report *,apple80211_infra_specific_stats *) APPLE_KEXT_OVERRIDE; +#endif + virtual SInt64 getWmeTxCounters(unsigned long long *) APPLE_KEXT_OVERRIDE; + virtual void setEnabledBySystem(bool) APPLE_KEXT_OVERRIDE; + virtual bool enabledBySystem(void) APPLE_KEXT_OVERRIDE; + virtual bool willRoam(ether_addr *,UInt) APPLE_KEXT_OVERRIDE; + virtual void setPeerManagerLogFlag(UInt,UInt,UInt) APPLE_KEXT_OVERRIDE; + virtual void setWoWEnabled(bool) APPLE_KEXT_OVERRIDE; + virtual bool wowEnabled(void) APPLE_KEXT_OVERRIDE; + virtual UInt64 createLinkQualityMonitor(IO80211Peer *,IOService *) APPLE_KEXT_OVERRIDE; + virtual void releaseLinkQualityMonitor(IO80211Peer *) APPLE_KEXT_OVERRIDE; + virtual int getAssocState(void) APPLE_KEXT_OVERRIDE; + virtual void *getLQMSummary(apple80211_lqm_summary *) APPLE_KEXT_OVERRIDE; + virtual IOReturn setLinkStateInternal(IO80211LinkState,uint,bool,uint,apple80211_link_changed_event_data &); + virtual void setPoweredOnByUser(bool); + virtual void setCurrentBssid(ether_addr *); + virtual void setWCL_ADVISORTY_INFO(apple80211_wcl_advisory_info *); + virtual void *getWCL_TX_RX_LATENCY(apple80211_wcl_tx_rx_latency *); + +public: + char _data[0x120]; +}; + +#endif /* IO80211InfraInterface_h */ diff --git a/include/Airport/IO80211InfraProtocol.h b/include/Airport/IO80211InfraProtocol.h new file mode 100644 index 000000000..0be25f396 --- /dev/null +++ b/include/Airport/IO80211InfraProtocol.h @@ -0,0 +1,390 @@ +// +// IO80211InfraProtocol.h +// itlwm +// +// Created by qcwap on 2023/6/14. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IO80211InfraProtocol_h +#define IO80211InfraProtocol_h + +#include +#include +#include + +struct apple80211_sta_ie_data; +struct apple80211_sta_stats_data; +struct apple80211_rssi_bounds_data; +struct apple80211_rate_set_data; +struct apple80211_power_debug_info; +struct apple80211_bgscan_cached_network_data_list; +struct apple80211_private_mac_data; +struct apple80211_dbg_guard_time_params; +struct apple80211_ranging_enable_request_t; +struct apple80211_gas_result_t; +struct apple80211_ranging_start_request_t; +struct apple80211_leaky_ap_setting; +struct apple80211_rsdb_capability; +struct apple80211_tko_params; +struct apple80211_tko_dump; +struct apple80211_thermal_index_t; +struct apple80211_btcoex_max_nss_for_ap_data; +struct apple80211_btcoex_2g_chain_disable; +struct apple80211_power_budget_t; +struct apple80211_ranging_capabilities_t; +struct apple80211_suppress_scans_t; +struct apple80211_host_ap_mode_hidden_t; +struct apple80211_lqm_config_t; +struct apple80211_trap_mini_dump_data; +struct apple80211_beacon_info_t; +struct apple80211_softap_params; +struct apple80211_chip_power_limit; +struct apple80211_softap_stats; +struct apple80211_nss_data; +struct apple80211_hw_mac_address; +struct apple80211_he_mcs_index_set_data; +struct appl80211_chip_diags_data; +struct apple80211_hp2p_ctrl; +struct apple80211_assoc_ready; +struct apple80211_txrx_chain_info; +struct apple80211_mimo_status; +struct apple80211_dynsar_detail; +struct apple80211_mac_randomisation_status; +struct apple80211_colocated_network_scope_id +{ + uint32_t version; + uint32_t id1; + uint32_t id2; +}; +struct apple80211_slow_wifi_feature_enabled; +struct apple80211_interface_cca_data; +struct apple80211_timesync_info; +struct apple80211_sensing_data_t; +struct apple80211_country_band_support; +struct apple80211_fw_hot_channels; +struct apple80211_low_latency_info; +struct apple80211_beacon_msg; +struct apple80211_wcl_traffic_counters; +struct apple80211_ssid_transition_feature_enabled; +typedef enum { + +} p2pStatusForScan; +struct apple80211ChannelInfo; +struct apple80211_p2p_steering_metrics;; +struct apple80211_rsn_xe_data; +struct apple80211_sib_coex_status; +struct apple80211_extended_bss_info; +struct apple80211_wcl_low_latency_stats; +struct apple80211_noise_per_ant_t; +struct apple80211_blocked_bands; +struct apple80211_disassoc_data; +struct apple80211_bgscan_data; +struct apple80211_sta_authorize_data; +struct apple80211_sta_disassoc_data; +struct apple80211_rsn_conf_data; +struct apple80211_country_channel_data; +struct apple80211_awdl_forced_roam_config; +struct apple80211_offload_arp_data; +struct apple80211_offload_ndp_data; +struct apple80211_offload_scan_data; +struct apple80211_gas_query_t; +struct apple80211_gas_peer_t; +struct apple80211_btcoex_profile; +struct apple80211_btcoex_profile_active_data; +struct apple80211_trap_info_data; +struct apple80211_he_capability; +struct apple80211_pmk; +struct apple80211_wow_test_data; +struct apple80211_reset_command; +struct apple80211_crash_command; +struct apple80211_ranging_authenticate_request_t; +struct apple80211_softap_csa_params; +struct apple80211_softap_wifi_network_info; +struct apple80211_scan_control_params; +struct apple80211_usb_host_notification_data; +struct apple80211_set_mac_address; +struct apple80211_abort_scan; +struct apple80211_set_property_unserialized_data; +struct apple80211_roam_cache_data; +struct apple80211_pm_mode; +struct apple80211_wifi_assertion_data; +struct apple80211_capture_debug_info_t; +struct apple80211_linkdown_debounce_status; +struct apple80211_softap_extended_capabilities_info; +struct apple80211_sensing_enable_t; +struct apple80211_sensing_disable_t; +struct apple80211_nan_link_association_info; +struct apple80211_6G_mode; +struct apple80211_leave_network; +struct apple80211_reassoc; +struct apple80211_set_roam_lock; +struct apple80211_roam_profile_config; +struct apple80211_roam_profile_configV1; +struct apple80211_user_roam_cache; +struct apple80211_set_multi_ap_env; +struct apple80211_wcl_real_time_mode; +struct apple80211_wcl_garp_mode; +struct triggerCC; +struct apple80211ScanRequest; +struct apple80211_assoc_candidates; +struct apple80211_wcl_protect_ip_mode; +struct scanHomeAndAwayTime; +struct apple80211_wcl_voluntary_network_disconnect; +struct apple80211_wcl_update_link_state; +struct apple80211_wcl_ulofdma_state; +struct apple80211_wcl_action_frame; +struct apple80211_wcl_real_time_policy; +struct apple80211_feature_flags; +struct apple80211_dhcp_renewal_data; +struct apple80211_network_flags; +struct apple80211_battery_ps_config; +struct apple80211_mimo_config; +struct apple80211_bg_motion_profile; +struct apple80211_bg_network; +struct apple80211_bg_scan; +struct apple80211_bg_params; +typedef UInt apple80211_offload_tcpka_enable_t; + +class IO80211InfraProtocol : public IO80211InfraInterface { + OSDeclareAbstractStructors(IO80211InfraProtocol) + +public: + virtual IOReturn getSSID(apple80211_ssid_data *) = 0; + virtual IOReturn getAUTH_TYPE(apple80211_authtype_data *) = 0; + virtual IOReturn getCHANNEL(apple80211_channel_data *) = 0; + virtual IOReturn getPOWERSAVE(apple80211_powersave_data *) = 0; + virtual IOReturn getTXPOWER(apple80211_txpower_data *) = 0; + virtual IOReturn getRATE(apple80211_rate_data *) = 0; + virtual IOReturn getBSSID(apple80211_bssid_data *) = 0; + virtual IOReturn getSCAN_RESULT(apple80211_scan_result *) = 0; + virtual IOReturn getSTATE(apple80211_state_data *) = 0; + virtual IOReturn getPHY_MODE(apple80211_phymode_data *) = 0; + virtual IOReturn getOP_MODE(apple80211_opmode_data *) = 0; + virtual IOReturn getRSSI(apple80211_rssi_data *) = 0; + virtual IOReturn getNOISE(apple80211_noise_data *) = 0; + virtual IOReturn getSUPPORTED_CHANNELS(apple80211_sup_channel_data *) = 0; + virtual IOReturn getLOCALE(apple80211_locale_data *) = 0; + virtual IOReturn getDEAUTH(apple80211_deauth_data *) = 0; + virtual IOReturn getRATE_SET(apple80211_rate_set_data *) = 0; + virtual IOReturn getDTIM_INT(apple80211_dtim_int_data *) = 0; + virtual IOReturn getSTATION_LIST(apple80211_sta_data *) = 0; + virtual IOReturn getRSN_IE(apple80211_rsn_ie_data *) = 0; + virtual IOReturn getAP_IE_LIST(apple80211_ap_ie_data *) = 0; + virtual IOReturn getSTATS(apple80211_stats_data *) = 0; + virtual IOReturn getASSOCIATION_STATUS(apple80211_assoc_status_data *) = 0; + virtual IOReturn getGUARD_INTERVAL(apple80211_guard_interval_data *) = 0; + virtual IOReturn getMCS(apple80211_mcs_data *) = 0; + virtual IOReturn getMCS_INDEX_SET(apple80211_mcs_index_set_data *) = 0; + virtual IOReturn getWOW_PARAMETERS(apple80211_wow_parameter_data *) = 0; + virtual IOReturn getWOW_ENABLED(apple80211_state_data *) = 0; + virtual IOReturn getPID_LOCK(apple80211_state_data *) = 0; + virtual IOReturn getSTA_IE_LIST(apple80211_sta_ie_data *) = 0; + virtual IOReturn getSTA_STATS(apple80211_sta_stats_data *) = 0; + virtual IOReturn getBT_COEX_FLAGS(apple80211_state_data *) = 0; + virtual IOReturn getCURRENT_NETWORK(apple80211_scan_result *) = 0; + virtual IOReturn getRSSI_BOUNDS(apple80211_rssi_bounds_data *) = 0; + virtual IOReturn getPOWER_DEBUG_INFO(apple80211_power_debug_info *) = 0; + virtual IOReturn getHT_CAPABILITY(apple80211_ht_capability *) = 0; + virtual IOReturn getLINK_CHANGED_EVENT_DATA(apple80211_link_changed_event_data *) = 0; + virtual IOReturn getEXTENDED_STATS(apple80211_extended_stats *) = 0; + virtual IOReturn getBEACON_PERIOD(apple80211_beacon_period_data *) = 0; + virtual IOReturn getVHT_MCS_INDEX_SET(apple80211_vht_mcs_index_set_data *) = 0; + virtual IOReturn getMCS_VHT(apple80211_mcs_vht_data *) = 0; + virtual IOReturn getGAS_RESULTS(apple80211_gas_result_t *) = 0; + virtual IOReturn getCHANNELS_INFO(apple80211_channels_info *) = 0; + virtual IOReturn getVHT_CAPABILITY(apple80211_vht_capability *) = 0; + virtual IOReturn getBGSCAN_CACHE_RESULTS(apple80211_bgscan_cached_network_data_list *) = 0; + virtual IOReturn getROAM_PROFILE(apple80211_roam_profile_band_data *) = 0; + virtual IOReturn getCHIP_COUNTER_STATS(apple80211_chip_stats *) = 0; + virtual IOReturn getDBG_GUARD_TIME_PARAMS(apple80211_dbg_guard_time_params *) = 0; + virtual IOReturn getLEAKY_AP_STATS_MODE(apple80211_leaky_ap_setting *) = 0; + virtual IOReturn getCOUNTRY_CHANNELS(apple80211_country_channel_data *) = 0; + virtual IOReturn getPRIVATE_MAC(apple80211_private_mac_data *) = 0; + virtual IOReturn getRANGING_ENABLE(apple80211_ranging_enable_request_t *) = 0; + virtual IOReturn getRANGING_START(apple80211_ranging_start_request_t *) = 0; + virtual IOReturn getAWDL_RSDB_CAPS(apple80211_rsdb_capability *) = 0; + virtual IOReturn getTKO_PARAMS(apple80211_tko_params *) = 0; + virtual IOReturn getTKO_DUMP(apple80211_tko_dump *) = 0; + virtual IOReturn getHW_SUPPORTED_CHANNELS(apple80211_sup_channel_data *) = 0; + virtual IOReturn getBTCOEX_PROFILE(apple80211_btcoex_profile *) = 0; + virtual IOReturn getBTCOEX_PROFILE_ACTIVE(apple80211_btcoex_profile_active_data *) = 0; + virtual IOReturn getTRAP_INFO(apple80211_trap_info_data *) = 0; + virtual IOReturn getTHERMAL_INDEX(apple80211_thermal_index_t *) = 0; + virtual IOReturn getMAX_NSS_FOR_AP(apple80211_btcoex_max_nss_for_ap_data *) = 0; + virtual IOReturn getBTCOEX_2G_CHAIN_DISABLE(apple80211_btcoex_2g_chain_disable *) = 0; + virtual IOReturn getPOWER_BUDGET(apple80211_power_budget_t *) = 0; + virtual IOReturn getOFFLOAD_TCPKA_ENABLE(apple80211_offload_tcpka_enable_t *) = 0; + virtual IOReturn getRANGING_CAPS(apple80211_ranging_capabilities_t *) = 0; + virtual IOReturn getSUPPRESS_SCANS(apple80211_suppress_scans_t *) = 0; + virtual IOReturn getHOST_AP_MODE_HIDDEN(apple80211_host_ap_mode_hidden_t *) = 0; + virtual IOReturn getLQM_CONFIG(apple80211_lqm_config_t *) = 0; + virtual IOReturn getTRAP_CRASHTRACER_MINI_DUMP(apple80211_trap_mini_dump_data *) = 0; + virtual IOReturn getHE_CAPABILITY(apple80211_he_capability *) = 0; + virtual IOReturn getBEACON_INFO(apple80211_beacon_info_t *) = 0; + virtual IOReturn getSOFTAP_PARAMS(apple80211_softap_params *) = 0; + virtual IOReturn getCHIP_POWER_RANGE(apple80211_chip_power_limit *) = 0; + virtual IOReturn getSOFTAP_STATS(apple80211_softap_stats *) = 0; + virtual IOReturn getNSS(apple80211_nss_data *) = 0; + virtual IOReturn getHW_ADDR(apple80211_hw_mac_address *) = 0; + virtual IOReturn getHE_MCS_INDEX_SET(apple80211_he_mcs_index_set_data *) = 0; + virtual IOReturn getCHIP_DIAGS(appl80211_chip_diags_data *) = 0; + virtual IOReturn getHP2P_CTRL(apple80211_hp2p_ctrl *) = 0; + virtual IOReturn getREQUEST_BSS_BLACKLIST(void *) = 0; + virtual IOReturn getASSOC_READY_STATUS(apple80211_assoc_ready *) = 0; + virtual IOReturn getTXRX_CHAIN_INFO(apple80211_txrx_chain_info *) = 0; + virtual IOReturn getMIMO_STATUS(apple80211_mimo_status *) = 0; + virtual IOReturn getCUR_PMK(apple80211_pmk *) = 0; + virtual IOReturn getDYNSAR_DETAIL(apple80211_dynsar_detail *) = 0; + virtual IOReturn getRANDOMISATION_STATUS(apple80211_mac_randomisation_status *) = 0; + virtual IOReturn getCOUNTRY_CHANNELS_INFO(apple80211_channels_info *) = 0; + virtual IOReturn getLQM_SUMMARY(apple80211_lqm_summary *) = 0; + virtual IOReturn getCOLOCATED_NETWORK_SCOPE_ID(apple80211_colocated_network_scope_id *) = 0; + virtual IOReturn getBEACON_SCAN_CACHE_REQ(apple80211_scan_result *) = 0; + virtual IOReturn getSLOW_WIFI_FEATURE_ENABLED(apple80211_slow_wifi_feature_enabled *) = 0; + virtual IOReturn getCCA(apple80211_interface_cca_data *) = 0; + virtual IOReturn getRX_RATE(apple80211_rate_data *) = 0; + virtual IOReturn getTIMESYNC_INFO(apple80211_timesync_info *) = 0; + virtual IOReturn getSENSING_DATA(apple80211_sensing_data_t *) = 0; + virtual IOReturn getCOUNTRY_BAND_SUPPORT(apple80211_country_band_support *) = 0; + virtual IOReturn getWCL_FW_HOT_CHANNELS(apple80211_fw_hot_channels *) = 0; + virtual IOReturn getWCL_LOW_LATENCY_INFO(apple80211_low_latency_info *) = 0; + virtual IOReturn getWCL_BSS_INFO(apple80211_beacon_msg *) = 0; + virtual IOReturn getWCL_TRAFFIC_COUNTERS(apple80211_wcl_traffic_counters *) = 0; + virtual IOReturn getWCL_GET_TX_BLANKING_STATUS(uint *) = 0; + virtual IOReturn getSSID_TRANSITION_SUPPORT(apple80211_ssid_transition_feature_enabled *) = 0; + virtual IOReturn getWCL_VALID_CHANNEL_COUNT(unsigned long *) = 0; + virtual IOReturn getWCL_P2P_STATUS_FOR_SCAN(p2pStatusForScan *) = 0; + virtual IOReturn getWCL_CHANNELS_INFO(apple80211ChannelInfo *) = 0; + virtual IOReturn getP2P_STEERING_METRIC(apple80211_p2p_steering_metrics *) = 0; + virtual IOReturn getRSN_XE(apple80211_rsn_xe_data *) = 0; + virtual IOReturn getSIB_COEX_STATUS(apple80211_sib_coex_status *) = 0; + virtual IOReturn getWCL_EXTENDED_BSS_INFO(apple80211_extended_bss_info *) = 0; + virtual IOReturn getWCL_LOW_LATENCY_INFO_STATS(apple80211_wcl_low_latency_stats *) = 0; + virtual IOReturn getWCL_BGSCAN_CACHE_RESULT(apple80211_bgscan_cached_network_data_list *) = 0; + virtual IOReturn getWIFI_NOISE_PER_ANT(apple80211_noise_per_ant_t *) = 0; + virtual IOReturn getBLOCKED_BANDS(apple80211_blocked_bands *) = 0; + virtual IOReturn setSSID(apple80211_ssid_data *) = 0; + virtual IOReturn setAUTH_TYPE(apple80211_authtype_data *) = 0; + virtual IOReturn setCIPHER_KEY(apple80211_key *) = 0; + virtual IOReturn setCHANNEL(apple80211_channel_data *) = 0; + virtual IOReturn setPOWERSAVE(apple80211_powersave_data *) = 0; + virtual IOReturn setTXPOWER(apple80211_txpower_data *) = 0; + virtual IOReturn setRATE(apple80211_rate_data *) = 0; + virtual IOReturn setSCAN_REQ(apple80211_scan_data *) = 0; + virtual IOReturn setASSOCIATE(apple80211_assoc_data *) = 0; + virtual IOReturn setDISASSOCIATE(apple80211_disassoc_data *) = 0; + virtual IOReturn setIBSS_MODE(apple80211_network_data *) = 0; + virtual IOReturn setHOST_AP_MODE(apple80211_network_data *) = 0; + virtual IOReturn setAP_MODE(apple80211_apmode_data *) = 0; + virtual IOReturn setDEAUTH(apple80211_deauth_data *) = 0; + virtual IOReturn setTX_ANTENNA(void *) = 0; + virtual IOReturn setANTENNA_DIVERSITY(void *) = 0; + virtual IOReturn setRSN_IE(apple80211_rsn_ie_data *) = 0; + virtual IOReturn setBACKGROUND_SCAN(apple80211_bgscan_data *) = 0; + virtual IOReturn setWOW_PARAMETERS(apple80211_wow_parameter_data *) = 0; + virtual IOReturn setWOW_ENABLED(apple80211_state_data *) = 0; + virtual IOReturn setPID_LOCK(apple80211_state_data *) = 0; + virtual IOReturn setSTA_AUTHORIZE(apple80211_sta_authorize_data *) = 0; + virtual IOReturn setSTA_DISASSOCIATE(apple80211_sta_disassoc_data *) = 0; + virtual IOReturn setSTA_DEAUTH(apple80211_sta_disassoc_data *) = 0; + virtual IOReturn setRSN_CONF(apple80211_rsn_conf_data *) = 0; + virtual IOReturn setIE(apple80211_ie_data *) = 0; + virtual IOReturn setWOW_TEST(apple80211_wow_test_data *) = 0; + virtual IOReturn setSCANCACHE_CLEAR(void *) = 0; + virtual IOReturn setVIRTUAL_IF_CREATE(apple80211_virt_if_create_data *) = 0; + virtual IOReturn setBT_COEX_FLAGS(apple80211_state_data *) = 0; + virtual IOReturn setROAM(apple80211_sta_roam_data *) = 0; + virtual IOReturn setHT_CAPABILITY(apple80211_ht_capability *) = 0; + virtual IOReturn setAWDL_FORCED_ROAM_CONFIG(apple80211_awdl_forced_roam_config *) = 0; + virtual IOReturn setOFFLOAD_ARP(apple80211_offload_arp_data *) = 0; + virtual IOReturn setOFFLOAD_NDP(apple80211_offload_ndp_data *) = 0; + virtual IOReturn setOFFLOAD_SCAN(apple80211_offload_scan_data *) = 0; + virtual IOReturn setGAS_REQ(apple80211_gas_query_t *) = 0; + virtual IOReturn setGAS_START(apple80211_gas_query_t *) = 0; + virtual IOReturn setGAS_SET_PEER(apple80211_gas_peer_t *) = 0; + virtual IOReturn setVHT_CAPABILITY(apple80211_vht_capability *) = 0; + virtual IOReturn setROAM_PROFILE(apple80211_roam_profile_band_data *) = 0; + virtual IOReturn setAWDL_ENABLE_ROAMING(void *) = 0; + virtual IOReturn setDBG_GUARD_TIME_PARAMS(apple80211_dbg_guard_time_params *) = 0; + virtual IOReturn setLEAKY_AP_STATS_MODE(apple80211_leaky_ap_setting *) = 0; + virtual IOReturn setPRIVATE_MAC(apple80211_private_mac_data *) = 0; + virtual IOReturn setRESET_CHIP(apple80211_reset_command *) = 0; + virtual IOReturn setCRASH(apple80211_crash_command *) = 0; + virtual IOReturn setRANGING_ENABLE(apple80211_ranging_enable_request_t *) = 0; + virtual IOReturn setRANGING_START(apple80211_ranging_start_request_t *) = 0; + virtual IOReturn setRANGING_AUTHENTICATE(apple80211_ranging_authenticate_request_t *) = 0; + virtual IOReturn setTKO_PARAMS(apple80211_tko_params *) = 0; + virtual IOReturn setBTCOEX_PROFILE(apple80211_btcoex_profile *) = 0; + virtual IOReturn setBTCOEX_PROFILE_ACTIVE(apple80211_btcoex_profile_active_data *) = 0; + virtual IOReturn setTHERMAL_INDEX(apple80211_thermal_index_t *) = 0; + virtual IOReturn setBTCOEX_2G_CHAIN_DISABLE(apple80211_btcoex_2g_chain_disable *) = 0; + virtual IOReturn setPOWER_BUDGET(apple80211_power_budget_t *) = 0; + virtual IOReturn setOFFLOAD_TCPKA_ENABLE(apple80211_offload_tcpka_enable_t *) = 0; + virtual IOReturn setSUPPRESS_SCANS(apple80211_suppress_scans_t *) = 0; + virtual IOReturn setHOST_AP_MODE_HIDDEN(apple80211_host_ap_mode_hidden_t *) = 0; + virtual IOReturn setLQM_CONFIG(apple80211_lqm_config_t *) = 0; + virtual IOReturn setSOFTAP_PARAMS(apple80211_softap_params *) = 0; + virtual IOReturn setSOFTAP_TRIGGER_CSA(apple80211_softap_csa_params *) = 0; + virtual IOReturn setSOFTAP_WIFI_NETWORK_INFO_IE(apple80211_softap_wifi_network_info *) = 0; + virtual IOReturn setBTCOEX_DISABLE_ULOFDMA(uint *) = 0; + virtual IOReturn setSCAN_CONTROL(apple80211_scan_control_params *) = 0; + virtual IOReturn setUSB_HOST_NOTIFICATION(apple80211_usb_host_notification_data *) = 0; + virtual IOReturn setSET_MAC_ADDRESS(apple80211_set_mac_address *) = 0; + virtual IOReturn setHP2P_CTRL(apple80211_hp2p_ctrl *) = 0; + virtual IOReturn setABORT_SCAN(apple80211_abort_scan *) = 0; + virtual IOReturn setSET_PROPERTY(apple80211_set_property_unserialized_data *) = 0; + virtual IOReturn setROAM_CACHE_UPDATE(apple80211_roam_cache_data *) = 0; + virtual IOReturn setPM_MODE(apple80211_pm_mode *) = 0; + virtual IOReturn setSET_WIFI_ASSERTION_STATE(apple80211_wifi_assertion_data *) = 0; + virtual IOReturn setREASSOCIATE_WITH_CORECAPTURE(apple80211_capture_debug_info_t *) = 0; + virtual IOReturn setLINKDOWN_DEBOUNCE_STATUS(apple80211_linkdown_debounce_status *) = 0; + virtual IOReturn setSOFTAP_EXTENDED_CAPABILITIES_IE(apple80211_softap_extended_capabilities_info *) = 0; + virtual IOReturn setREALTIME_QOS_MSCS(apple80211_state_data *) = 0; + virtual IOReturn setSENSING_ENABLE(apple80211_sensing_enable_t *) = 0; + virtual IOReturn setSENSING_DISABLE(apple80211_sensing_disable_t *) = 0; + virtual IOReturn setNANPHS_ASSOCIATION(apple80211_nan_link_association_info *) = 0; + virtual IOReturn setNANPHS_TERMINATED(apple80211_nan_link_association_info *) = 0; + virtual IOReturn set6G_MODE(apple80211_6G_mode *) = 0; + virtual IOReturn setWCL_LEAVE_NETWORK(apple80211_leave_network *) = 0; + virtual IOReturn setWCL_REASSOC(apple80211_reassoc *) = 0; + virtual IOReturn setWCL_SET_ROAM_LOCK(apple80211_set_roam_lock *) = 0; + virtual IOReturn setWCL_ROAM_PROFILE_CONFIG(apple80211_roam_profile_config *) = 0; + virtual IOReturn setWCL_ROAM_PROFILE_CONFIGV1(apple80211_roam_profile_configV1 *) = 0; + virtual IOReturn setWCL_ROAM_USER_CACHE(apple80211_user_roam_cache *) = 0; + virtual IOReturn setWCL_SET_MULTI_AP_ENV(apple80211_set_multi_ap_env *) = 0; + virtual IOReturn setWCL_SCAN_ABORT(void *) = 0; + virtual IOReturn setWCL_REAL_TIME_MODE(apple80211_wcl_real_time_mode *) = 0; + virtual IOReturn setWCL_GARP_MODE(apple80211_wcl_garp_mode *) = 0; + virtual IOReturn setWCL_JOIN_ABORT(void *) = 0; + virtual IOReturn setWCL_TRIGGER_CC(triggerCC *) = 0; + virtual IOReturn setWCL_SCAN_REQ(apple80211ScanRequest *) = 0; + virtual IOReturn setWCL_ASSOCIATE(apple80211_assoc_candidates *) = 0; + virtual IOReturn setWCL_PROTECT_IP(apple80211_wcl_protect_ip_mode *) = 0; + virtual IOReturn setWCL_LINK_UP_DONE(void *) = 0; + virtual IOReturn setWCL_SET_SCAN_HOME_AWAY_TIME(scanHomeAndAwayTime *) = 0; + virtual IOReturn setWCL_VOLUNTARY_NETWORK_DISCONNECT(apple80211_wcl_voluntary_network_disconnect *) = 0; + virtual IOReturn setWCL_LINK_STATE_UPDATE(apple80211_wcl_update_link_state *) = 0; + virtual IOReturn setSLOW_WIFI_RECOVERY(void *) = 0; + virtual IOReturn setRSN_XE(apple80211_rsn_xe_data *) = 0; + virtual IOReturn setWCL_ULOFDMA_STATE(apple80211_wcl_ulofdma_state *) = 0; + virtual IOReturn setWCL_ACTION_FRAME(apple80211_wcl_action_frame *) = 0; + virtual IOReturn setWCL_REAL_TIME_POLICY(apple80211_wcl_real_time_policy *) = 0; + virtual IOReturn setGAS_ABORT(void *) = 0; + virtual IOReturn setOS_FEATURE_FLAGS(apple80211_feature_flags *) = 0; + virtual IOReturn setDHCP_RENEWAL_DATA(apple80211_dhcp_renewal_data *) = 0; + virtual IOReturn setMOVING_NETWORK(apple80211_network_flags *) = 0; + virtual IOReturn setBATTERY_POWERSAVE_CONFIG(apple80211_battery_ps_config *) = 0; + virtual IOReturn setMIMO_CONFIG(apple80211_mimo_config *) = 0; + virtual IOReturn setWCL_CONFIG_BG_MOTIONPROFILE(apple80211_bg_motion_profile *) = 0; + virtual IOReturn setWCL_CONFIG_BG_NETWORK(apple80211_bg_network *) = 0; + virtual IOReturn setWCL_CONFIG_BGSCAN(apple80211_bg_scan *) = 0; + virtual IOReturn setWCL_CONFIG_BG_PARAMS(apple80211_bg_params *) = 0; + virtual IOReturn setBLOCKED_BANDS(apple80211_blocked_bands *) = 0; + +public: + uint8_t filter[0x120]; +}; + +#endif /* IO80211InfraProtocol_h */ + diff --git a/include/Airport/IO80211Interface.h b/include/Airport/IO80211Interface.h index 0c7f3fad6..87b8a624c 100644 --- a/include/Airport/IO80211Interface.h +++ b/include/Airport/IO80211Interface.h @@ -22,13 +22,6 @@ #include #include -enum IO80211LinkState -{ - kIO80211NetworkLinkUndefined, // Starting link state when an interface is created - kIO80211NetworkLinkDown, // Interface not capable of transmitting packets - kIO80211NetworkLinkUp, // Interface capable of transmitting packets -}; -typedef enum IO80211LinkState IO80211LinkState; typedef UInt kIO80211InterfaceType; /*! @defined kIO80211InterfaceClass diff --git a/include/Airport/IO80211SkywalkInterface.h b/include/Airport/IO80211SkywalkInterface.h index 82dc191ef..f3c2ceea1 100644 --- a/include/Airport/IO80211SkywalkInterface.h +++ b/include/Airport/IO80211SkywalkInterface.h @@ -10,18 +10,182 @@ #define _IO80211SKYWALK_H #include -#include +#include "IOSkywalkEthernetInterface.h" // This is necessary, because even the latest Xcode does not support properly targeting 11.0. #ifndef __IO80211_TARGET #error "Please define __IO80211_TARGET to the requested version" #endif -class IO80211SkywalkInterface : IOSkywalkEthernetInterface { +class TxSubmissionDequeueStats; +class TxCompletionEnqueueStats; +class IO80211NetworkPacket; +class PacketSkywalkScratch; +typedef UInt64 IO80211FlowQueueHash; +class IO80211Peer; +class CCPipe; +class IO80211APIUserClient; +struct apple80211_wme_ac; +struct apple80211_interface_availability; +struct apple80211_cca_report; +struct apple80211_stat_report; +struct apple80211_chip_counters_tx; +struct apple80211_chip_counters_rx; +struct apple80211_chip_error_counters_tx; +struct apple80211_ManagementInformationBasedot11_counters; +struct apple80211_lteCoex_report; +struct apple80211_frame_counters; +struct userPrintCtx; +struct apple80211_lqm_summary; +struct apple80211_infra_specific_stats; + +struct TxPacketRequest { + uint16_t unk1; // 0 + uint16_t t; // 2 + uint16_t mU; // 4 + uint16_t mM; // 6 + uint16_t pkt_cnt; + uint16_t unk2; + uint16_t unk3; + uint16_t unk4; + uint32_t pad; + mbuf_t bufs[8]; // 18 + uint32_t reqTx; +}; + +static_assert(sizeof(struct TxPacketRequest) == 0x60, "TxPacketRequest size error"); + +class IO80211SkywalkInterface : public IOSkywalkEthernetInterface { OSDeclareAbstractStructors(IO80211SkywalkInterface) public: - + + virtual bool init() APPLE_KEXT_OVERRIDE; + virtual void free() APPLE_KEXT_OVERRIDE; + virtual IOReturn configureReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual IOReturn updateReport(IOReportChannelList *,UInt,void *,void *) APPLE_KEXT_OVERRIDE; + virtual bool start(IOService *) APPLE_KEXT_OVERRIDE; + virtual void stop(IOService *) APPLE_KEXT_OVERRIDE; + virtual IOReturn setPowerState( + unsigned long powerStateOrdinal, + IOService * whatDevice ) APPLE_KEXT_OVERRIDE; + virtual unsigned long maxCapabilityForDomainState( IOPMPowerFlags domainState ) APPLE_KEXT_OVERRIDE; + virtual unsigned long initialPowerStateForDomainState( IOPMPowerFlags domainState ) APPLE_KEXT_OVERRIDE; + virtual IOReturn enable(UInt) APPLE_KEXT_OVERRIDE; + virtual IOReturn disable(UInt) APPLE_KEXT_OVERRIDE; + virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) APPLE_KEXT_OVERRIDE; + virtual bool prepareBSDInterface(ifnet_t, UInt) APPLE_KEXT_OVERRIDE; + virtual IOReturn processBSDCommand(ifnet_t, UInt, void *) APPLE_KEXT_OVERRIDE; + virtual SInt32 setInterfaceEnable(bool) APPLE_KEXT_OVERRIDE; + virtual SInt32 setRunningState(bool) APPLE_KEXT_OVERRIDE; + virtual IOReturn handleChosenMedia(UInt) APPLE_KEXT_OVERRIDE; + virtual void *getSupportedMediaArray(UInt *,UInt *) APPLE_KEXT_OVERRIDE; + virtual UInt32 getFeatureFlags(void) APPLE_KEXT_OVERRIDE; + virtual const char *classNameOverride(void) APPLE_KEXT_OVERRIDE; + virtual IOReturn setPromiscuousModeEnable(bool, UInt) APPLE_KEXT_OVERRIDE; + virtual void *createPeerManager(void); + virtual void postMessage(UInt,void *,unsigned long,bool); + virtual IOReturn reportDataPathEvents(UInt,void *,unsigned long,bool); + virtual IOReturn recordOutputPackets(TxSubmissionDequeueStats *,TxSubmissionDequeueStats *); + virtual IOReturn recordOutputPacket(apple80211_wme_ac,int,int); + virtual void logTxPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,apple80211_wme_ac,bool); + virtual void logTxCompletionPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,unsigned char *,apple80211_wme_ac,int,UInt,bool); + virtual IOReturn recordCompletionPackets(TxCompletionEnqueueStats *,TxCompletionEnqueueStats *); + virtual IOReturn inputPacket(IO80211NetworkPacket *,packet_info_tag *,ether_header *,bool *); + virtual IOReturn forwardInfraRelayPackets(IO80211NetworkPacket*, ether_header*); + virtual void logSkywalkTxReqPacket(IO80211NetworkPacket *,PacketSkywalkScratch *,unsigned char *,apple80211_wme_ac,bool); + virtual SInt64 pendingPackets(unsigned char); + virtual SInt64 packetSpace(unsigned char); + virtual bool isChipInterfaceReady(void); + virtual bool isDebounceOnGoing(void); + virtual bool setLinkState(IO80211LinkState,UInt,bool debounceTimeout = 30,UInt code = 0); + virtual IO80211LinkState linkState(void); + virtual void setScanningState(UInt,bool,apple80211_scan_data *,int); + virtual void setDataPathState(bool); + virtual void *getScanManager(void); + virtual void updateLinkParameters(apple80211_interface_availability *); + virtual void updateInterfaceCoexRiskPct(unsigned long long); + virtual void setLQM(unsigned long long); + virtual void updateLinkStatus(void); + virtual void updateLinkStatusGated(void); + virtual void setInterfaceExtendedCCA(apple80211_channel,apple80211_cca_report *); + virtual void setInterfaceCCA(apple80211_channel,int); + virtual void setInterfaceNF(apple80211_channel,long long); + virtual void setInterfaceOFDMDesense(apple80211_channel,long long); + virtual void removePacketQueue(IO80211FlowQueueHash *); + virtual void setDebugFlags(unsigned long long,UInt); + virtual SInt64 debugFlags(void); + virtual void setInterfaceChipCounters(apple80211_stat_report *,apple80211_chip_counters_tx *,apple80211_chip_error_counters_tx *,apple80211_chip_counters_rx *); + virtual void setInterfaceMIBdot11(apple80211_stat_report *,apple80211_ManagementInformationBasedot11_counters *); + virtual void setFrameStats(apple80211_stat_report *,apple80211_frame_counters *); +#if __IO80211_TARGET >= __MAC_14_4 + virtual void setInfraSpecificFrameStats(apple80211_stat_report *,apple80211_infra_specific_stats *); +#endif + virtual SInt64 getWmeTxCounters(unsigned long long *); + virtual void setEnabledBySystem(bool); + virtual bool enabledBySystem(void); + virtual bool willRoam(ether_addr *,UInt); + virtual void setPeerManagerLogFlag(UInt,UInt,UInt); + virtual void setWoWEnabled(bool); + virtual bool wowEnabled(void); + virtual void printDataPath(userPrintCtx *); + virtual bool findOrCreateFlowQueue(IO80211FlowQueueHash); + virtual UInt64 findOrCreateFlowQueueWithCache(IO80211FlowQueueHash,bool *); + virtual UInt64 findExistingFlowQueue(IO80211FlowQueueHash); + virtual void removePacketQueue(IO80211FlowQueueHash const*); + virtual void flushPacketQueues(void); + virtual void cachePeer(ether_addr *,UInt *); + virtual bool shouldLog(unsigned long long); + virtual void vlogDebug(unsigned long long,char const*,va_list); + virtual void vlogDebugBPF(unsigned long long,char const*,va_list); + virtual UInt64 createLinkQualityMonitor(IO80211Peer *,IOService *); + virtual void releaseLinkQualityMonitor(IO80211Peer *); + virtual void *getP2PSkywalkPeerMgr(void); + virtual bool isCommandProhibited(int); + virtual void setNotificationProperty(OSSymbol const*,OSObject const*); + virtual void *getWorkerMatchingDict(OSString *); + virtual bool init(IOService *); + virtual bool isInterfaceEnabled(void); + virtual ether_addr *getSelfMacAddr(void); + virtual void setSelfMacAddr(ether_addr *); + virtual void *getPacketPool(OSString *); + virtual void *getLogger(void); + virtual IOReturn handleSIOCSIFADDR(void); + virtual IOReturn debugHandler(apple80211_debug_command *); + virtual void statsDump(void); + virtual void powerOnNotification(void); + virtual void powerOffNotification(void); + virtual UInt64 getTxQueueDepth(void); + virtual UInt64 getRxQueueCapacity(void); + virtual void updateRxCounter(unsigned long long); + virtual void *getMultiCastQueue(void); + virtual void *getCurrentBssid(void); + virtual int getAssocState(void); + virtual void notifyQueueState(apple80211_wme_ac,unsigned short); + virtual int getTxHeadroom(void); + virtual void *getRxCompQueue(void); + virtual void *getTxCompQueue(void); + virtual void *getTxSubQueue(apple80211_wme_ac); + virtual void *getTxPacketPool(void); + virtual void *getRxPacketPool(void); + virtual void enableDatapath(void); + virtual void disableDatapath(void); + virtual int getNumTxQueues(void); + virtual void *getLQMSummary(apple80211_lqm_summary *); + virtual int getEventPipeSize(void); + virtual UInt64 createEventPipe(IO80211APIUserClient *); + virtual void destroyEventPipe(IO80211APIUserClient *); + virtual void postMessageIOUC(char const*,UInt,void *,unsigned long); + virtual bool isIOUCPipeOpened(void); + virtual void *getRingMD(IO80211APIUserClient *,unsigned long long); + +public: + OSString *setInterfaceRole(UInt role); + void *setInterfaceId(UInt id); + int getInterfaceRole(); + +public: + char _data[0x118]; }; #endif /* _IO80211SKYWALK_H */ diff --git a/include/Airport/IO80211WorkQueue.h b/include/Airport/IO80211WorkQueue.h new file mode 100644 index 000000000..f85faa743 --- /dev/null +++ b/include/Airport/IO80211WorkQueue.h @@ -0,0 +1,34 @@ + +#ifndef _IO80211WORKQUEUE_H +#define _IO80211WORKQUEUE_H + +#include +#include + +// This is necessary, because even the latest Xcode does not support properly targeting 11.0. +#ifndef __IO80211_TARGET +#error "Please define __IO80211_TARGET to the requested version" +#endif + +class IO80211WorkQueue : public IOWorkLoop +{ + OSDeclareDefaultStructors( IO80211WorkQueue ) + +public: + + virtual IOThread getThread() const APPLE_KEXT_OVERRIDE; + virtual void enableAllInterrupts() const APPLE_KEXT_OVERRIDE; + virtual void disableAllInterrupts() const APPLE_KEXT_OVERRIDE; + virtual IOReturn runAction(Action action, OSObject *target, + void *arg0 = NULL, void *arg1 = NULL, + void *arg2 = NULL, void *arg3 = NULL) APPLE_KEXT_OVERRIDE; + virtual int commandSleep(void *,unsigned long long); + virtual void commandWakeup(void *); + + static IO80211WorkQueue * workQueue(); + +public: + uint8_t filter[0x50]; +}; + +#endif diff --git a/include/Airport/IOSkywalkEthernetInterface.h b/include/Airport/IOSkywalkEthernetInterface.h index 0caa92b07..7b1f86aac 100644 --- a/include/Airport/IOSkywalkEthernetInterface.h +++ b/include/Airport/IOSkywalkEthernetInterface.h @@ -1,13 +1,79 @@ #ifndef IOSkywalkEthernetInterface_h #define IOSkywalkEthernetInterface_h -#include +#include "IOSkywalkNetworkInterface.h" -class IOSkywalkEthernetInterface : public IOEthernetController { +struct nicproxy_limits_info_s; +struct nicproxy_info_s; + +class IOSkywalkEthernetInterface : public IOSkywalkNetworkInterface { OSDeclareAbstractStructors( IOSkywalkEthernetInterface ) public: + struct RegistrationInfo { + uint8_t pad[304]; + } __attribute__((packed)); + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE; + virtual IOReturn newUserClient( task_t owningTask, void * securityID, + UInt32 type, OSDictionary * properties, + LIBKERN_RETURNS_RETAINED IOUserClient ** handler ) APPLE_KEXT_OVERRIDE; + virtual IOReturn setPowerState( + unsigned long powerStateOrdinal, + IOService * whatDevice ) APPLE_KEXT_OVERRIDE; + virtual IOReturn enable(UInt) APPLE_KEXT_OVERRIDE; + virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) APPLE_KEXT_OVERRIDE; + virtual bool prepareBSDInterface(ifnet_t,UInt) APPLE_KEXT_OVERRIDE; + virtual IOReturn processBSDCommand(ifnet_t,UInt,void *) APPLE_KEXT_OVERRIDE; + virtual void *getPacketTapInfo(UInt *,UInt *) APPLE_KEXT_OVERRIDE; + virtual void enableNetworkWake(UInt) APPLE_KEXT_OVERRIDE; + virtual UInt getMaxTransferUnit(void) APPLE_KEXT_OVERRIDE; + virtual UInt getMinPacketSize(void) APPLE_KEXT_OVERRIDE; + virtual void *getInterfaceFamily(void) APPLE_KEXT_OVERRIDE; + virtual void *getInterfaceSubFamily(void) APPLE_KEXT_OVERRIDE; + virtual UInt getInitialMedia(void) APPLE_KEXT_OVERRIDE; + virtual const char *getBSDNamePrefix(void) APPLE_KEXT_OVERRIDE; + virtual IOReturn registerNetworkInterfaceWithLogicalLink(IOSkywalkEthernetInterface::RegistrationInfo const*, IOSkywalkLogicalLink*, IOSkywalkPacketBufferPool*, IOSkywalkPacketBufferPool*, UInt); + virtual void getHardwareAddress(ether_addr *); + virtual void setHardwareAddress(ether_addr *); + virtual void setLinkLayerAddress(ether_addr *); + virtual bool configureMulticastFilter(UInt,ether_addr const*,UInt); + virtual bool setMulticastAddresses(ether_addr const*,UInt); + virtual void setAllMulticastModeEnable(bool); + virtual IOReturn setPromiscuousModeEnable(bool, UInt); + virtual void reportNicProxyLimits(nicproxy_limits_info_s); + virtual void hwConfigNicProxyData(nicproxy_info_s *); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 0 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 1 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 2 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 3 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 4 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 5 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 6 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 7 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 8 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 9 ); + OSMetaClassDeclareReservedUnused( IOSkywalkEthernetInterface, 10 ); + +public: + bool initRegistrationInfo(IOSkywalkEthernetInterface::RegistrationInfo*, unsigned int, unsigned long); + bool registerEthernetInterface(IOSkywalkEthernetInterface::RegistrationInfo const*, IOSkywalkPacketQueue**, unsigned int, IOSkywalkPacketBufferPool*, IOSkywalkPacketBufferPool*, unsigned int); +public: + void *vptr; + uint8_t pad1[0x30]; + struct ExpansionData + { + RegistrationInfo *fRegistrationInfo; + ifnet_t fBSDInterface; + }; + ExpansionData *mExpansionData2; }; +static_assert(__offsetof(IOSkywalkEthernetInterface, mExpansionData2) == 0x108, "Invalid class size"); + +static_assert(sizeof(IOSkywalkEthernetInterface) == 0x110, "Invalid class size"); + #endif /* IOSkywalkEthernetInterface_h */ diff --git a/include/Airport/IOSkywalkInterface.h b/include/Airport/IOSkywalkInterface.h new file mode 100644 index 000000000..e9f6fc22f --- /dev/null +++ b/include/Airport/IOSkywalkInterface.h @@ -0,0 +1,51 @@ +// +// IOSkywalkInterface.h +// itlwm +// +// Created by qcwap on 2023/6/7. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOSkywalkInterface_h +#define IOSkywalkInterface_h + + +class IOSkywalkInterface : public IOService { + OSDeclareAbstractStructors(IOSkywalkInterface) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE; + virtual bool willTerminate( IOService * provider, IOOptionBits options ) APPLE_KEXT_OVERRIDE; + virtual bool didTerminate( IOService * provider, IOOptionBits options, bool * defer ) APPLE_KEXT_OVERRIDE; + virtual bool handleOpen( IOService * forClient, + IOOptionBits options, + void * arg ) APPLE_KEXT_OVERRIDE; + virtual void handleClose( IOService * forClient, + IOOptionBits options ) APPLE_KEXT_OVERRIDE; + virtual bool handleIsOpen( const IOService * forClient ) const APPLE_KEXT_OVERRIDE; + virtual IOReturn enable( IOOptionBits options ) = 0; + virtual IOReturn disable( IOOptionBits options ) = 0; + virtual IOReturn clientConnectWithTask( task_t task, IOService * forClient, IOOptionBits options ); + virtual void clientDisconnect( IOService * forClient, IOOptionBits options ); + virtual bool isTerminating(void); + + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 0 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 1 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 2 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 3 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 4 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 5 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 6 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 7 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 8 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 9 ); + OSMetaClassDeclareReservedUnused( IOSkywalkInterface, 10 ); + +public: + uint8_t filter[0xB0 - 136]; +}; + +static_assert(sizeof(IOSkywalkInterface) == 0xB0, "Invalid class size"); + +#endif /* IOSkywalkInterface_h */ diff --git a/include/Airport/IOSkywalkLegacyEthernetInterface.h b/include/Airport/IOSkywalkLegacyEthernetInterface.h new file mode 100644 index 000000000..71af99776 --- /dev/null +++ b/include/Airport/IOSkywalkLegacyEthernetInterface.h @@ -0,0 +1,38 @@ +// +// IOSkywalkLegacyEthernetInterface.h +// itlwm +// +// Created by qcwap on 2023/6/19. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOSkywalkLegacyEthernetInterface_h +#define IOSkywalkLegacyEthernetInterface_h + +#include +#include + +class IOSkywalkLegacyEthernetInterface : public IOEthernetInterface { + OSDeclareDefaultStructors(IOSkywalkLegacyEthernetInterface) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual OSObject * getProperty( const OSSymbol * aKey) const APPLE_KEXT_OVERRIDE; + virtual OSObject * copyProperty( const OSSymbol * aKey) const APPLE_KEXT_OVERRIDE; + virtual bool serializeProperties( OSSerialize * serialize ) const APPLE_KEXT_OVERRIDE; + virtual IOReturn setProperties( OSObject * properties ) APPLE_KEXT_OVERRIDE; + virtual bool init( IONetworkController * controller ) APPLE_KEXT_OVERRIDE; + virtual const char * getNamePrefix() const APPLE_KEXT_OVERRIDE; + virtual bool controllerDidOpen(IONetworkController * controller) APPLE_KEXT_OVERRIDE; + virtual void controllerWillClose(IONetworkController * controller) APPLE_KEXT_OVERRIDE; + virtual ifnet_t getIfnet( void ) const APPLE_KEXT_OVERRIDE; + virtual IOReturn attachToDataLinkLayer( IOOptionBits options, void * parameter ) APPLE_KEXT_OVERRIDE; + virtual void detachFromDataLinkLayer( IOOptionBits options, + void * parameter ) APPLE_KEXT_OVERRIDE; + +public: + uint8_t filter[0x160]; +}; + +#endif /* IOSkywalkLegacyEthernetInterface_h */ + diff --git a/include/Airport/IOSkywalkLogicalLink.h b/include/Airport/IOSkywalkLogicalLink.h new file mode 100644 index 000000000..919bfb777 --- /dev/null +++ b/include/Airport/IOSkywalkLogicalLink.h @@ -0,0 +1,20 @@ +// +// IOSkywalkLogicalLink.h +// itlwm +// +// Created by qcwap on 2023/6/12. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOSkywalkLogicalLink_h +#define IOSkywalkLogicalLink_h + +class IOSkywalkLogicalLink : public IOService { + OSDeclareAbstractStructors(IOSkywalkLogicalLink) + +public: + +public: +}; + +#endif /* IOSkywalkLogicalLink_h */ diff --git a/include/Airport/IOSkywalkNetworkInterface.h b/include/Airport/IOSkywalkNetworkInterface.h new file mode 100644 index 000000000..153d7f1c5 --- /dev/null +++ b/include/Airport/IOSkywalkNetworkInterface.h @@ -0,0 +1,107 @@ +// +// IOSkywalkNetworkInterface.h +// itlwm +// +// Created by qcwap on 2023/6/7. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOSkywalkNetworkInterface_h +#define IOSkywalkNetworkInterface_h + +#include + +#include "IOSkywalkInterface.h" + +typedef UInt if_link_status; +class IOSkywalkPacketQueue; +class IOSkywalkLogicalLink; +class IOSkywalkPacketBufferPool; + +class IOSkywalkNetworkInterface : public IOSkywalkInterface { + OSDeclareAbstractStructors( IOSkywalkNetworkInterface ) + +public: + struct RegistrationInfo { + uint8_t pad[304]; + } __attribute__((packed)); + struct IOSkywalkTSOOptions; + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual bool init(OSDictionary *) APPLE_KEXT_OVERRIDE; + virtual void stop(IOService *) APPLE_KEXT_OVERRIDE; + virtual void joinPMtree( IOService * driver ) APPLE_KEXT_OVERRIDE; + virtual IOReturn setAggressiveness( + unsigned long type, + unsigned long newLevel ) APPLE_KEXT_OVERRIDE; + virtual IOReturn enable(UInt) APPLE_KEXT_OVERRIDE; + virtual IOReturn disable(UInt) APPLE_KEXT_OVERRIDE; + virtual SInt32 initBSDInterfaceParameters(ifnet_init_eparams *,sockaddr_dl **) = 0; + virtual bool prepareBSDInterface(ifnet_t,UInt); + virtual void finalizeBSDInterface(ifnet_t,UInt); + virtual ifnet_t getBSDInterface(void); + virtual void setBSDName(char const*); + virtual const char *getBSDName(void); + virtual IOReturn processBSDCommand(ifnet_t,UInt,void *); + virtual IOReturn processInterfaceCommand(ifdrv *); + virtual IOReturn interfaceAdvisoryEnable(bool); + virtual SInt32 setInterfaceEnable(bool); + virtual SInt32 setRunningState(bool); + virtual IOReturn handleChosenMedia(UInt); + virtual void *getSupportedMediaArray(UInt *,UInt *); + virtual void *getPacketTapInfo(UInt *,UInt *); + virtual UInt getUnsentDataByteCount(UInt *,UInt *,UInt); + virtual UInt32 getSupportedWakeFlags(UInt *); + virtual void enableNetworkWake(UInt); + virtual void calculateRingSizeForQueue(IOSkywalkPacketQueue const*,UInt *); + virtual UInt getMaxTransferUnit(void); + virtual void setMaxTransferUnit(UInt); + virtual UInt getMinPacketSize(void); + virtual UInt getHardwareAssists(void); + virtual void setHardwareAssists(UInt,UInt); + virtual void *getInterfaceFamily(void); + virtual void *getInterfaceSubFamily(void); + virtual UInt getInitialMedia(void); + virtual UInt getFeatureFlags(void); + virtual UInt getTxDataOffset(void); + virtual UInt captureInterfaceState(UInt); + virtual void restoreInterfaceState(UInt); + virtual void setMTU(UInt); + virtual bool bpfTap(UInt,UInt); + virtual const char *getBSDNamePrefix(void); + virtual UInt getBSDUnitNumber(void); + virtual const char *classNameOverride(void); + virtual void deferBSDAttach(bool); + virtual void reportDetailedLinkStatus(if_link_status const*); + virtual IOReturn registerNetworkInterfaceWithLogicalLink(IOSkywalkNetworkInterface::RegistrationInfo const*,IOSkywalkLogicalLink *,IOSkywalkPacketBufferPool *,IOSkywalkPacketBufferPool *,UInt); + virtual IOReturn deregisterLogicalLink(void); + virtual UInt getTSOOptions(IOSkywalkNetworkInterface::IOSkywalkTSOOptions *); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 0); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 1); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 2); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 3); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 4); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 5); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 6); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 7); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 8); + OSMetaClassDeclareReservedUnused( IOSkywalkNetworkInterface, 9); + +public: + void reportLinkStatus(unsigned int, unsigned int); + +public: + void *vptr; + struct ExpansionData + { + RegistrationInfo *fRegistrationInfo; + ifnet_t fBSDInterface; + }; + ExpansionData *mExpansionData; + uint8_t pad[2 * 8]; +}; + +static_assert(sizeof(IOSkywalkNetworkInterface) == 0xD0, "Invalid class size"); + +#endif /* IOSkywalkNetworkInterface_h */ diff --git a/include/Airport/IOSkywalkNetworkPacket.h b/include/Airport/IOSkywalkNetworkPacket.h new file mode 100644 index 000000000..630f6b3f5 --- /dev/null +++ b/include/Airport/IOSkywalkNetworkPacket.h @@ -0,0 +1,54 @@ +// +// IOSkywalkNetworkPacket.h +// itlwm +// +// Created by qcwap on 2023/6/13. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOSkywalkInterface_h +#define IOSkywalkInterface_h + +class IOSkywalkPacketBufferPool; +class IOSkywalkPacketDescriptor; +class IOSkywalkPacketBuffer; +class IOSkywalkPacketQueue; + +class IOSkywalkNetworkPacket : public IOService { + OSDeclareAbstractStructors(IOSkywalkNetworkPacket) + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + + virtual bool initWithPool(IOSkywalkPacketBufferPool *,IOSkywalkPacketDescriptor *,uint); + virtual void *getPacketBuffers(IOSkywalkPacketBuffer **,uint); + virtual UInt getPacketBufferCount(void); + virtual IOSkywalkPacketDescriptor *getMemoryDescriptor(void); + virtual void setDataLength(uint); + virtual UInt getDataLength(void); + virtual void setDataOffset(unsigned short); + virtual unsigned short getDataOffset(void); + virtual void setDataOffsetAndLength(unsigned short,uint); + virtual void setDataOff(long long); + virtual long long getDataOff(void); + virtual void setDataOffAndLen(long long,unsigned long); + virtual void *getDataVirtualAddress(void); + virtual void *getDataIOVirtualAddress(void); + virtual bool prepareWithQueue(IOSkywalkPacketQueue *,uint,uint); + virtual bool prepare(IOSkywalkPacketQueue *,unsigned long long,uint); + virtual void completeWithQueue(IOSkywalkPacketQueue *,uint,uint); + virtual void complete(IOSkywalkPacketQueue *,uint); + virtual UInt getPacketType(void); + virtual void setWakeFlag(void); + virtual UInt getTraceID(void); + virtual void setTraceID(UInt); + virtual void traceEvent(uint); + virtual void *generateTraceTag(IOSkywalkPacketQueue *); + virtual void *acquireWithPacketHandle(unsigned long long,uint); + virtual void disposePacket(void); + +public: + uint8_t filter[0x78]; +}; + +#endif /* IOSkywalkInterface_h */ diff --git a/include/Airport/IOSkywalkPacketBufferPool.h b/include/Airport/IOSkywalkPacketBufferPool.h new file mode 100644 index 000000000..c196a1933 --- /dev/null +++ b/include/Airport/IOSkywalkPacketBufferPool.h @@ -0,0 +1,62 @@ +// +// IOSkywalkPacketBufferPool.h +// itlwm +// +// Created by qcwap on 2023/6/15. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef IOSkywalkPacketBufferPool_h +#define IOSkywalkPacketBufferPool_h + +#include + +class IOSkywalkMemorySegment; +class IOSkywalkMemorySegmentDescriptor; +class IOSkywalkPacket; +class IOSkywalkPacketBuffer; +class IOSkywalkPacketDescriptor; +class IOSkywalkPacketBufferDescriptor; + +class IOSkywalkPacketBufferPool : public OSObject { + OSDeclareDefaultStructors(IOSkywalkPacketBufferPool) + +public: + struct PoolOptions { + uint32_t packetCount; + uint32_t bufferCount; + uint32_t bufferSize; + uint32_t maxBuffersPerPacket; + uint32_t memorySegmentSize; + uint32_t poolFlags; + uint64_t pad; + }; + +public: + virtual void free() APPLE_KEXT_OVERRIDE; + virtual bool initWithName(char const*,void *,uint,IOSkywalkPacketBufferPool::PoolOptions const*); + virtual bool initWithName(char const*,OSObject *,uint,IOSkywalkPacketBufferPool::PoolOptions const*); + virtual bool allocatePacket(IOSkywalkPacket **,uint); + virtual bool allocatePacket(uint,IOSkywalkPacket **,uint); + virtual bool allocatePackets(uint,uint *,IOSkywalkPacket **,uint); + virtual void deallocatePacket(IOSkywalkPacket *); + virtual void deallocatePackets(IOSkywalkPacket **,uint); + virtual void deallocatePacketList(IOSkywalkPacket *); + virtual void deallocatePacketChain(unsigned long long); + virtual bool allocatePacketBuffer(IOSkywalkPacketBuffer **,uint); + virtual bool allocatePacketBuffers(uint *,IOSkywalkPacketBuffer **,uint); + virtual void deallocatePacketBuffer(IOSkywalkPacketBuffer *); + virtual void deallocatePacketBuffers(IOSkywalkPacketBuffer **,uint); + virtual bool newPacket(IOSkywalkPacketDescriptor *,IOSkywalkPacket **); + virtual bool newPacketBuffer(IOSkywalkPacketBufferDescriptor *,IOSkywalkPacketBuffer **); + virtual bool newMemorySegment(IOSkywalkMemorySegmentDescriptor *,IOSkywalkMemorySegment **); + +public: + static IOSkywalkPacketBufferPool *withName(char const*,OSObject *,uint,IOSkywalkPacketBufferPool::PoolOptions const*); + +public: + uint8_t filter[0xB8]; +}; + +#endif /* IOSkywalkPacketBufferPool_h */ + diff --git a/include/Airport/apple80211_ioctl.h b/include/Airport/apple80211_ioctl.h index ce0533834..ea6057212 100644 --- a/include/Airport/apple80211_ioctl.h +++ b/include/Airport/apple80211_ioctl.h @@ -430,11 +430,19 @@ struct apple80211_bssid_data struct ether_addr bssid; }; +#if __IO80211_TARGET >= __MAC_14_0 +struct apple80211_capability_data +{ + u_int32_t version; + u_int8_t capabilities[14]; +}; +#else struct apple80211_capability_data { u_int32_t version; u_int8_t capabilities[11]; }; +#endif struct apple80211_state_data { diff --git a/include/Airport/apple80211_var.h b/include/Airport/apple80211_var.h index ad76387f4..c624087ae 100644 --- a/include/Airport/apple80211_var.h +++ b/include/Airport/apple80211_var.h @@ -486,13 +486,13 @@ struct apple80211_scan_result uint8_t unk2; u_int32_t asr_age; // (ms) non-zero for cached scan result // 0x84 - u_int16_t unk3; - int16_t asr_ie_len; + u_int16_t unk3; // 0x88 + int16_t asr_ie_len; // 0x8A #if __IO80211_TARGET < __MAC_12_0 - uint32_t asr_unk3; - void* asr_ie_data; + uint32_t asr_unk3; // 0x8C + void* asr_ie_data; // 90 #else - uint8_t asr_ie_data[1024]; + uint8_t asr_ie_data[1024]; // 0x8C #endif } __attribute__((packed)); @@ -595,6 +595,14 @@ enum apple80211_assoc_flags { APPLE80211_ASSOC_F_CLOSED = 1, // flag: scan was directed, needed to remember closed networks }; +enum IO80211LinkState +{ + kIO80211NetworkLinkUndefined, // Starting link state when an interface is created + kIO80211NetworkLinkDown, // Interface not capable of transmitting packets + kIO80211NetworkLinkUp, // Interface capable of transmitting packets +}; +typedef enum IO80211LinkState IO80211LinkState; + // Kernel messages struct apple80211_status_msg_hdr diff --git a/itl80211/compat.h b/itl80211/compat.h index 542089c12..69abccac3 100644 --- a/itl80211/compat.h +++ b/itl80211/compat.h @@ -181,6 +181,8 @@ typedef pci_intr_handle* pci_intr_handle_t; #define DVACT_POWERDOWN 6 /* power device down */ struct device { + IOService *provider; + void *_data; char dv_xname[16]; }; diff --git a/itl80211/linux/bitfield.h b/itl80211/linux/bitfield.h index faf0b53e8..6eafe987a 100644 --- a/itl80211/linux/bitfield.h +++ b/itl80211/linux/bitfield.h @@ -44,13 +44,100 @@ ({ \ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ }) + +static inline int +find_first_zero_bit(volatile void *p, int max) +{ + int b; + volatile u_int *ptr = (volatile u_int *)p; + + for (b = 0; b < max; b += 32) { + if (ptr[b >> 5] != ~0) { + for (;;) { + if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) + return b; + b++; + } + } + } + return max; +} + +static inline int +find_next_zero_bit(volatile void *p, int max, int b) +{ + volatile u_int *ptr = (volatile u_int *)p; + + for (; b < max; b += 32) { + if (ptr[b >> 5] != ~0) { + for (;;) { + if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) + return b; + b++; + } + } + } + return max; +} + +static inline int +find_first_bit(volatile void *p, int max) +{ + int b; + volatile u_int *ptr = (volatile u_int *)p; + + for (b = 0; b < max; b += 32) { + if (ptr[b >> 5] != 0) { + for (;;) { + if (ptr[b >> 5] & (1 << (b & 0x1f))) + return b; + b++; + } + } + } + return max; +} + +static inline int +find_next_bit(volatile void *p, int max, int b) +{ + volatile u_int *ptr = (volatile u_int *)p; + + for (; b < max; b+= 32) { + if (ptr[b >> 5] != 0) { + for (;;) { + if (ptr[b >> 5] & (1 << (b & 0x1f))) + return b; + b++; + } + } + } + return max; +} + +static inline int +find_last_bit(volatile void *p, int max) +{ + int b; + volatile u_int *ptr = (volatile u_int *)p; + + for (b = max; b > 0; b -= 32) { + if (ptr[b >> 5] != 0) { + for (;;) { + if (ptr[b >> 5] & (1 << (b & 0x1f))) + return b; + b--; + } + } + } + return max; +} + #define for_each_set_bit(bit, addr, size) \ for ((bit) = find_first_bit((addr), (size)); \ (bit) < (size); \ (bit) = find_next_bit((addr), (size), (bit) + 1)) -#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) - #define GENMASK(h, l) \ (((~(0UL)) - ((1UL) << (l)) + 1) & \ (~(0UL) >> (BITS_PER_LONG - 1 - (h)))) diff --git a/itl80211/linux/kernel.h b/itl80211/linux/kernel.h index cc63a15f0..d410944e1 100644 --- a/itl80211/linux/kernel.h +++ b/itl80211/linux/kernel.h @@ -185,6 +185,7 @@ pointer_t __mptr = (pointer_t)(ptr); \ #define time_after(a,b) \ ((long)(b) - (long)(a) < 0) +#define time_is_before_jiffies(a) time_after(ticks, a) #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) diff --git a/itl80211/linux/types.h b/itl80211/linux/types.h index befe717b4..b52204d56 100644 --- a/itl80211/linux/types.h +++ b/itl80211/linux/types.h @@ -147,6 +147,10 @@ typedef UInt16 __sum16; typedef u64 dma_addr_t; +#define U8_MAX ((u8)~0U) +#define S8_MAX ((s8)(U8_MAX >> 1)) +#define S8_MIN ((s8)(-S8_MAX - 1)) + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) diff --git a/itl80211/openbsd/net80211/ieee80211.h b/itl80211/openbsd/net80211/ieee80211.h index 70d45295c..af31632bd 100644 --- a/itl80211/openbsd/net80211/ieee80211.h +++ b/itl80211/openbsd/net80211/ieee80211.h @@ -356,24 +356,35 @@ ieee80211_get_qos(const struct ieee80211_frame *wh) } static __inline int -ieee80211_is_ctl(const struct ieee80211_frame *wh) +ieee80211_is_ctl(uint16_t fc) { - return (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_CTL; + return (fc & htole16(IEEE80211_FC0_TYPE_MASK)) == + htole16(IEEE80211_FC0_TYPE_CTL); } static __inline int -ieee80211_is_data(const struct ieee80211_frame *wh) +ieee80211_is_data(uint16_t fc) { - return (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_DATA; + return (fc & htole16(IEEE80211_FC0_TYPE_MASK)) == + htole16(IEEE80211_FC0_TYPE_DATA); } static __inline int -ieee80211_is_mgmt(const struct ieee80211_frame *wh) +ieee80211_is_mgmt(uint16_t fc) { - return (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT; + return (fc & htole16(IEEE80211_FC0_TYPE_MASK)) == + htole16(IEEE80211_FC0_TYPE_MGT); +} + +static __inline int +ieee80211_is_data_qos(uint16_t fc) +{ + /* + * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need + * to check the one bit + */ + return (fc & htole16(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == + htole16(IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS); } static __inline int @@ -1516,6 +1527,23 @@ struct ieee80211_csa_ie { uint8_t csa_count; /* Channel Switch Count */ } __packed; +/** + * struct ieee80211_vht_operation - VHT operation IE + * + * This structure is the "VHT operation element" as + * described in 802.11ac D3.0 8.4.2.161 + * @chan_width: Operating channel width + * @center_freq_seg0_idx: center freq segment 0 index + * @center_freq_seg1_idx: center freq segment 1 index + * @basic_mcs_set: VHT Basic MCS rate set + */ +struct ieee80211_vht_operation { + uint8_t chan_width; + uint8_t center_freq_seg0_idx; + uint8_t center_freq_seg1_idx; + uint16_t basic_mcs_set; +} __packed; + #define IEEE80211_HE_PPE_THRES_MAX_LEN 25 /** diff --git a/itl80211/openbsd/net80211/ieee80211_crypto_tkip.c b/itl80211/openbsd/net80211/ieee80211_crypto_tkip.c index a4569698b..7df2cde9e 100644 --- a/itl80211/openbsd/net80211/ieee80211_crypto_tkip.c +++ b/itl80211/openbsd/net80211/ieee80211_crypto_tkip.c @@ -98,7 +98,7 @@ ieee80211_tkip_set_key(struct ieee80211com *ic, struct ieee80211_key *k) } else #endif { -#if (defined AIRPORT) && (defined USE_APPLE_SUPPLICANT) +#ifdef USE_APPLE_SUPPLICANT ctx->txmic = &k->k_key[16]; ctx->rxmic = &k->k_key[24]; #else diff --git a/itl80211/openbsd/net80211/ieee80211_input.c b/itl80211/openbsd/net80211/ieee80211_input.c index c1eb1c014..ff8d7cdd9 100644 --- a/itl80211/openbsd/net80211/ieee80211_input.c +++ b/itl80211/openbsd/net80211/ieee80211_input.c @@ -1068,6 +1068,7 @@ ieee80211_enqueue_data(struct ieee80211com *ic, mbuf_t m, struct _ifnet *ifp = &ic->ic_if; struct ether_header *eh; mbuf_t m1; + mbuf_t m2; eh = mtod(m, struct ether_header *); @@ -1128,9 +1129,17 @@ ieee80211_enqueue_data(struct ieee80211com *ic, mbuf_t m, if (ifp->if_bpf && m1 == NULL) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); #endif -#if (defined AIRPORT) && (defined USE_APPLE_SUPPLICANT) +#ifdef USE_APPLE_SUPPLICANT ml_enqueue(ml, m); #else +#ifdef IO80211FAMILY_V2 + if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms)) { + XYLog("%s Duplicate EAPOL packet to user space\n", __FUNCTION__); + mbuf_dup(m, MBUF_DONTWAIT, &m2); + if (m2 != NULL) + ifp->iface->inputPacket(m2, mbuf_len(m2)); + } +#endif ieee80211_eapol_key_input(ic, m, ni); #endif } else { @@ -2978,6 +2987,11 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, mbuf_t m, u_int8_t token, tid; int err = 0; + /* Ignore if we are not ready to receive data frames. */ + if (ic->ic_state != IEEE80211_S_RUN || + ((ic->ic_flags & IEEE80211_F_RSNON) && !ni->ni_port_valid)) + return; + if (!(ni->ni_flags & IEEE80211_NODE_HT)) { DPRINTF(("received ADDBA req from non-HT STA %s\n", ether_sprintf(ni->ni_macaddr))); diff --git a/itl80211/openbsd/net80211/ieee80211_node.c b/itl80211/openbsd/net80211/ieee80211_node.c index b691ee6ef..000ef1202 100644 --- a/itl80211/openbsd/net80211/ieee80211_node.c +++ b/itl80211/openbsd/net80211/ieee80211_node.c @@ -2826,6 +2826,10 @@ ieee80211_setup_heop(struct ieee80211_node *ni, const uint8_t *data, ni->ni_he_oper_params = le32toh(he_op_ie->he_oper_params); ni->ni_he_oper_nss_set = le16toh(he_op_ie->he_mcs_nss_set); + bzero(&ni->ni_he_optional, sizeof(ni->ni_he_optional)); + if (len > __offsetof(struct ieee80211_he_operation, optional)) { + memcpy(ni->ni_he_optional, he_op_ie->optional, min(sizeof(ni->ni_he_optional), len - __offsetof(struct ieee80211_he_operation, optional))); + } return 1; } diff --git a/itl80211/openbsd/net80211/ieee80211_node.h b/itl80211/openbsd/net80211/ieee80211_node.h index 49c3639d7..6b9394771 100644 --- a/itl80211/openbsd/net80211/ieee80211_node.h +++ b/itl80211/openbsd/net80211/ieee80211_node.h @@ -427,6 +427,7 @@ struct ieee80211_node { uint8_t ni_ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; /* Holds the PPE Thresholds data. */ uint32_t ni_he_oper_params; uint16_t ni_he_oper_nss_set; + uint8_t ni_he_optional[8]; /* Timeout handlers which trigger Tx Block Ack negotiation. */ CTimeout* ni_addba_req_to[IEEE80211_NUM_TID]; diff --git a/itl80211/openbsd/net80211/ieee80211_output.c b/itl80211/openbsd/net80211/ieee80211_output.c index 2da63b462..ec8e448a2 100644 --- a/itl80211/openbsd/net80211/ieee80211_output.c +++ b/itl80211/openbsd/net80211/ieee80211_output.c @@ -637,7 +637,8 @@ ieee80211_encap(struct _ifnet *ifp, mbuf_t m, struct ieee80211_node **pni) if (ba->ba_state != IEEE80211_BA_AGREED) { hdrlen = sizeof(struct ieee80211_frame); addqos = 0; - if (ieee80211_can_use_ampdu(ic, ni)) + if ((ic->ic_caps & IEEE80211_C_TX_AMPDU_SETUP_IN_RS) == 0 && + ieee80211_can_use_ampdu(ic, ni)) ieee80211_node_trigger_addba_req(ni, tid); } else { hdrlen = sizeof(struct ieee80211_qosframe); @@ -1599,7 +1600,7 @@ ieee80211_get_assoc_req(struct ieee80211com *ic, struct ieee80211_node *ni, frm = ieee80211_add_xrates(frm, rs); if ((ic->ic_flags & IEEE80211_F_RSNON) && (ni->ni_rsnprotos & IEEE80211_PROTO_RSN)) { -#if (defined AIRPORT) && (defined USE_APPLE_SUPPLICANT) +#ifdef USE_APPLE_SUPPLICANT if (ic->ic_rsn_ie_override[1] > 0) { memcpy(frm, ic->ic_rsn_ie_override, 2 + ic->ic_rsn_ie_override[1]); frm += 2 + ic->ic_rsn_ie_override[1]; @@ -1612,7 +1613,7 @@ ieee80211_get_assoc_req(struct ieee80211com *ic, struct ieee80211_node *ni, frm = ieee80211_add_qos_capability(frm, ic); if ((ic->ic_flags & IEEE80211_F_RSNON) && (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) { -#if (defined AIRPORT) && (defined USE_APPLE_SUPPLICANT) +#ifdef USE_APPLE_SUPPLICANT if (ic->ic_rsn_ie_override[1] > 0) { memcpy(frm, ic->ic_rsn_ie_override, 2 + ic->ic_rsn_ie_override[1]); frm += 2 + ic->ic_rsn_ie_override[1]; diff --git a/itl80211/openbsd/net80211/ieee80211_proto.c b/itl80211/openbsd/net80211/ieee80211_proto.c index 3e61d1b5b..f7939cf92 100644 --- a/itl80211/openbsd/net80211/ieee80211_proto.c +++ b/itl80211/openbsd/net80211/ieee80211_proto.c @@ -823,8 +823,15 @@ ieee80211_vht_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni) void ieee80211_he_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni) { - uint8_t info; - uint8_t chw; + XYLog("%s\n", __FUNCTION__); + uint8_t ext_nss_bw_supp, supp_chwidth; + uint16_t cf0, cf1; + int ccfs0, ccfs1, ccfs2; + int ccf0, ccf1; + bool support_80_80 = false; + bool support_160 = false; + struct ieee80211_vht_operation *he_oper_vht = (struct ieee80211_vht_operation *)ni->ni_he_optional; + ni->ni_flags &= ~IEEE80211_NODE_HE; /* Check if we support HE. */ @@ -835,25 +842,107 @@ ieee80211_he_negotiate(struct ieee80211com *ic, struct ieee80211_node *ni) if ((ic->ic_flags & IEEE80211_F_HEON) == 0) return; - chw = IEEE80211_CHAN_WIDTH_20; + ni->ni_flags |= IEEE80211_NODE_HE; - info = ni->ni_he_cap_elem.phy_cap_info[0]; - - if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { - if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) - chw = IEEE80211_CHAN_WIDTH_40; + if (!(htole32(ni->ni_he_oper_params) & IEEE80211_HE_OPERATION_VHT_OPER_INFO)) + return; + + support_160 = (ni->ni_vhtcaps & (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK | + IEEE80211_VHTCAP_EXT_NSS_BW_MASK)); + support_80_80 = ((ni->ni_vhtcaps & + IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ) || + (ni->ni_vhtcaps & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ && + ni->ni_vhtcaps & IEEE80211_VHTCAP_EXT_NSS_BW_MASK) || + ((ni->ni_vhtcaps & IEEE80211_VHTCAP_EXT_NSS_BW_MASK) >> + IEEE80211_VHTCAP_EXT_NSS_BW_SHIFT > 1)); + + ext_nss_bw_supp = u32_get_bits(ni->ni_vhtcaps, + IEEE80211_VHTCAP_EXT_NSS_BW_MASK); + supp_chwidth = u32_get_bits(ni->ni_vhtcaps, + IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK); + + ccfs0 = he_oper_vht->center_freq_seg0_idx; + ccfs1 = he_oper_vht->center_freq_seg1_idx; + ccfs2 = (le16toh(ni->ni_htop1) & + IEEE80211_HT_OP_MODE_CCFS2_MASK) + >> IEEE80211_HT_OP_MODE_CCFS2_SHIFT; + + ccf0 = ccfs0; + + if ((ic->ic_caps & IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW) == 0) + ext_nss_bw_supp = 0; + + /* + * Cf. IEEE 802.11 Table 9-250 + * + * We really just consider that because it's inefficient to connect + * at a higher bandwidth than we'll actually be able to use. + */ + switch ((supp_chwidth << 4) | ext_nss_bw_supp) { + default: + case 0x00: + ccf1 = 0; + support_160 = false; + support_80_80 = false; + break; + case 0x01: + support_80_80 = false; + case 0x02: + case 0x03: + ccf1 = ccfs2; + break; + case 0x10: + ccf1 = ccfs1; + break; + case 0x11: + case 0x12: + if (!ccfs1) + ccf1 = ccfs2; else - chw = IEEE80211_CHAN_WIDTH_20; + ccf1 = ccfs1; + break; + case 0x13: + case 0x20: + case 0x23: + ccf1 = ccfs1; + break; } - - if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G || - info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) - chw = IEEE80211_CHAN_WIDTH_160; - else if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) - chw = IEEE80211_CHAN_WIDTH_80; - ni->ni_chw = chw; - ni->ni_flags |= IEEE80211_NODE_HE; + cf0 = ieee80211_ieee2mhz(ccf0, ni->ni_chan->ic_flags); + cf1 = ieee80211_ieee2mhz(ccf1, ni->ni_chan->ic_flags); + + switch (he_oper_vht->chan_width) { + case IEEE80211_VHT_CHANWIDTH_80P80MHZ: + ni->ni_chw = IEEE80211_CHAN_WIDTH_80P80; + ni->ni_chan->ic_center_freq1 = cf0; + ni->ni_chan->ic_center_freq2 = cf1; + break; + case IEEE80211_VHT_CHANWIDTH_160MHZ: + ni->ni_chw = IEEE80211_CHAN_WIDTH_160; + ni->ni_chan->ic_center_freq1 = cf0; + break; + case IEEE80211_VHT_CHANWIDTH_80MHZ: + ni->ni_chw = IEEE80211_CHAN_WIDTH_80; + ni->ni_chan->ic_center_freq1 = cf0; + /* If needed, adjust based on the newer interop workaround. */ + if (ccf1) { + unsigned int diff = abs(ccf1 - ccf0); + if ((diff == 8) && support_160) { + ni->ni_chw = IEEE80211_CHAN_WIDTH_160; + ni->ni_chan->ic_center_freq1 = cf1; + } else if ((diff > 8) && support_80_80) { + ni->ni_chw = IEEE80211_CHAN_WIDTH_80P80; + ni->ni_chan->ic_center_freq2 = cf1; + } + } + break; + case IEEE80211_VHT_CHANWIDTH_USE_HT: + /* Use HT negotiate information */ + break; + + default: + return; + } XYLog("%s chan_width=%s\n", __FUNCTION__, ieee80211_chan_width_name[ni->ni_chw]); } @@ -1592,8 +1681,11 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, (ni->ni_flags & IEEE80211_NODE_HE) ? " HE enabled" : ""); } -#if (defined AIRPORT) && (defined USE_APPLE_SUPPLICANT) - { +#ifdef USE_APPLE_SUPPLICANT + { +#elif (defined IO80211FAMILY_V2) + if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms) || + !(ic->ic_flags & IEEE80211_F_RSNON)) { #else if (!(ic->ic_flags & IEEE80211_F_RSNON)) { #endif diff --git a/itl80211/openbsd/net80211/ieee80211_ra.c b/itl80211/openbsd/net80211/ieee80211_ra.c index 4e1bd00ca..ff22b5e9e 100644 --- a/itl80211/openbsd/net80211/ieee80211_ra.c +++ b/itl80211/openbsd/net80211/ieee80211_ra.c @@ -278,6 +278,19 @@ ieee80211_ra_get_rateset(struct ieee80211_ra_node *ra, struct ieee80211com *ic, panic("%s mcs=%d rs_count=%d sgi=%d nss=%d bw=%d rate==NULL!!!!\n", __FUNCTION__, mcs, ra->active_rs_count, ra->sgi, ra->nss, ra->bw); } +int +ieee80211_ra_use_ht_sgi(struct ieee80211_node *ni) +{ + if ((ni->ni_chw == IEEE80211_CHAN_WIDTH_40) && + ieee80211_node_supports_ht_chan40(ni)) { + if (ni->ni_flags & IEEE80211_NODE_HT_SGI40) + return 1; + } else if (ni->ni_flags & IEEE80211_NODE_HT_SGI20) + return 1; + + return 0; +} + /* * Update goodput statistics. */ @@ -370,8 +383,6 @@ ieee80211_ra_next_rateset(struct ieee80211_ra_node *rn, struct ieee80211com *ic, continue; if (rsnext->nss > support_nss(ni)) continue; - if (rsnext->sgi && !ieee80211_node_supports_sgi(ni)) - continue; found = true; break; } @@ -385,8 +396,6 @@ ieee80211_ra_next_rateset(struct ieee80211_ra_node *rn, struct ieee80211com *ic, continue; if (rsnext->nss > support_nss(ni)) continue; - if (rsnext->sgi && !ieee80211_node_supports_sgi(ni)) - continue; found = true; break; } @@ -744,7 +753,7 @@ ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn, static const uint64_t alpha = RA_FP_1 / 8; /* 1/8 = 0.125 */ static const uint64_t beta = RA_FP_1 / 4; /* 1/4 = 0.25 */ int s; - struct ieee80211_ra_goodput_stats *g = &rn->g[mcs]; + struct ieee80211_ra_goodput_stats *g; uint64_t sfer, rate, delta; /* @@ -758,6 +767,7 @@ ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn, s = splnet(); + g = &rn->g[mcs]; g->nprobe_pkts += total; g->nprobe_fail += fail; diff --git a/itl80211/openbsd/net80211/ieee80211_ra.h b/itl80211/openbsd/net80211/ieee80211_ra.h index f642cdc9f..a3af45f7b 100644 --- a/itl80211/openbsd/net80211/ieee80211_ra.h +++ b/itl80211/openbsd/net80211/ieee80211_ra.h @@ -117,4 +117,6 @@ void ieee80211_ra_choose(struct ieee80211_ra_node *, /* Get the HT rateset for a particular HT MCS with SGI on/off. */ const struct ieee80211_ra_rate *ieee80211_ra_get_rateset(struct ieee80211_ra_node *, struct ieee80211com *, struct ieee80211_node *, int); +/* Check whether SGI should be used. */ +int ieee80211_ra_use_ht_sgi(struct ieee80211_node *); #endif /* _NET80211_IEEE80211_RA_H_ */ diff --git a/itl80211/openbsd/net80211/ieee80211_var.h b/itl80211/openbsd/net80211/ieee80211_var.h index 5d9fbe120..5f76f03ca 100644 --- a/itl80211/openbsd/net80211/ieee80211_var.h +++ b/itl80211/openbsd/net80211/ieee80211_var.h @@ -497,7 +497,7 @@ struct ieee80211com { u_int8_t ic_des_essid[IEEE80211_NWID_LEN]; struct ieee80211_channel *ic_des_chan; /* desired channel */ u_int8_t ic_des_bssid[IEEE80211_ADDR_LEN]; -#if (defined AIRPORT) && (defined USE_APPLE_SUPPLICANT) +#ifdef USE_APPLE_SUPPLICANT u_int8_t ic_rsn_ie_override[257]; #endif u_int16_t ic_deauth_reason; @@ -650,6 +650,7 @@ struct ieee80211_ess { #define IEEE80211_C_AMSDU_IN_AMPDU 0x00020000 /* CAPABILITY: Rx AMSDU inside AMPDU */ #define IEEE80211_C_TX_AMPDU_SETUP_IN_HW 0x00040000 /* CAPABILITY: BA negotiation in HW */ #define IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW 0x00080000 /* CAPABILITY: for 160mhz */ +#define IEEE80211_C_TX_AMPDU_SETUP_IN_RS 0x00100000 /* flags for ieee80211_fix_rate() */ #define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */ diff --git a/itl80211/openbsd/sys/_mbuf.cpp b/itl80211/openbsd/sys/_mbuf.cpp index 31e5ed05a..93fed10dc 100644 --- a/itl80211/openbsd/sys/_mbuf.cpp +++ b/itl80211/openbsd/sys/_mbuf.cpp @@ -20,11 +20,17 @@ */ #include - +extern "C" { +#include +} #include extern IOCommandGate *_fCommandGate; +struct network_header { + char pad[0x48]; +}; + static IOReturn _if_input(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3) { mbuf_t m; diff --git a/itl80211/openbsd/sys/_task.cpp b/itl80211/openbsd/sys/_task.cpp index df69a1a6f..8188b5426 100644 --- a/itl80211/openbsd/sys/_task.cpp +++ b/itl80211/openbsd/sys/_task.cpp @@ -276,16 +276,19 @@ int task_add(struct taskq *tq, struct task *w) { int rv = 0; -// IOLog("itlwm: taskq task_add %s\n", w->name); +// IOLog("itlwm: taskq task_add %s thread: %lld\n", w->name, thread_tid(current_thread())); + + if (ISSET(w->t_flags, TASK_ONQUEUE)) + return (0); IORecursiveLockLock(tq->tq_mtx); if (ISSET(w->t_flags, TASK_ONQUEUE)) { - IOLog("itlwm: taskq task_add %s is already on queue\n", w->name); +// IOLog("itlwm: taskq task_add %s is already on queue thread: %lld\n", w->name, thread_tid(current_thread())); IORecursiveLockUnlock(tq->tq_mtx); return (0); } if (!ISSET(w->t_flags, TASK_ONQUEUE)) { - IOLog("itlwm: taskq task_add %s add to queue\n", w->name); +// IOLog("itlwm: taskq task_add %s add to queue thread: %lld\n", w->name, thread_tid(current_thread())); rv = 1; SET(w->t_flags, TASK_ONQUEUE); TAILQ_INSERT_TAIL(&tq->tq_worklist, w, t_entry); @@ -302,7 +305,10 @@ int task_del(struct taskq *tq, struct task *w) { int rv = 0; -// IOLog("itlwm: taskq task_del %s\n", w->name); +// IOLog("itlwm: taskq task_del %s thread: %lld\n", w->name, thread_tid(current_thread())); + + if (!ISSET(w->t_flags, TASK_ONQUEUE)) + return (0); IORecursiveLockLock(tq->tq_mtx); if (ISSET(w->t_flags, TASK_ONQUEUE)) { diff --git a/itl80211/openbsd/sys/arp.c b/itl80211/openbsd/sys/arp.c new file mode 100644 index 000000000..5cb3dc772 --- /dev/null +++ b/itl80211/openbsd/sys/arp.c @@ -0,0 +1,301 @@ +// +// arp.c +// itlwm +// +// Created by zxystd on 2023/7/1. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#include "arp.h" + +#include +#include +#include + +#define EXTRACT_16BITS(p) \ +((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \ +(u_int16_t)*((const u_int8_t *)(p) + 1)) +#define EXTRACT_32BITS(p) \ +((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \ +(u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \ +(u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \ +(u_int32_t)*((const u_int8_t *)(p) + 3)) +#define EXTRACT_24BITS(p) \ +((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \ +(u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \ +(u_int32_t)*((const u_int8_t *)(p) + 2)) +#define EXTRACT_LE_8BITS(p) (*(p)) +#define EXTRACT_LE_16BITS(p) \ + ((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \ + (u_int16_t)*((const u_int8_t *)(p) + 0)) +#define EXTRACT_LE_32BITS(p) \ + ((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \ + (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \ + (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \ + (u_int32_t)*((const u_int8_t *)(p) + 0)) +#define EXTRACT_LE_64BITS(p) \ + ((u_int64_t)*((const u_int8_t *)(p) + 7) << 56 | \ + (u_int64_t)*((const u_int8_t *)(p) + 6) << 48 | \ + (u_int64_t)*((const u_int8_t *)(p) + 5) << 40 | \ + (u_int64_t)*((const u_int8_t *)(p) + 4) << 32 | \ + (u_int64_t)*((const u_int8_t *)(p) + 3) << 24 | \ + (u_int64_t)*((const u_int8_t *)(p) + 2) << 16 | \ + (u_int64_t)*((const u_int8_t *)(p) + 1) << 8 | \ + (u_int64_t)*((const u_int8_t *)(p) + 0)) + +#define ESRC(ep) ((ep)->ether_shost) +#define EDST(ep) ((ep)->ether_dhost) +#define SHA(ap) ((ap)->arp_sha) +#define THA(ap) ((ap)->arp_tha) +#define SPA(ap) ((ap)->arp_spa) +#define TPA(ap) ((ap)->arp_tpa) + +#define HASHNAMESIZE 4096 + +struct hnamemem { + u_int32_t addr; + char *name; + struct hnamemem *nxt; +}; + +struct enamemem { + u_short e_addr0; + u_short e_addr1; + u_short e_addr2; + char *e_name; + u_char *e_nsap; /* used only for nsaptable[] */ +#define e_bs e_nsap /* for bytestringtable */ + struct enamemem *e_nxt; +}; + +struct hnamemem hnametable[HASHNAMESIZE]; +struct enamemem enametable[HASHNAMESIZE]; + +struct hnamemem * +newhnamemem(void) +{ + struct hnamemem *p; + static struct hnamemem *ptr = NULL; + static u_int num = 0; + + if (num <= 0) { + num = 64; + ptr = (struct hnamemem *)malloc(num * sizeof (*ptr), 0, 0); + } + --num; + p = ptr++; + return (p); +} + +char * +intoa(u_int32_t addr) +{ + char *cp; + u_int byte; + int n; + static char buf[sizeof(".xxx.xxx.xxx.xxx")]; + + NTOHL(addr); + cp = &buf[sizeof buf]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + return cp + 1; +} + +char * +savestr(const char *str) +{ + size_t size; + char *p; + static char *strptr = NULL; + static size_t strsize = 0; + + size = strlen(str) + 1; + if (size > strsize) { + strsize = 1024; + if (strsize < size) + strsize = size; + strptr = (char *)malloc(strsize, 0, 0); + } + (void)strlcpy(strptr, str, size); + p = strptr; + strptr += size; + strsize -= size; + return (p); +} + +#define HOST_NAME_MAX 255 + +char * +getname(const u_char *ap) +{ + char host[HOST_NAME_MAX+1]; + u_int32_t addr; + struct hnamemem *p; + + /* + * Extract 32 bits in network order, dealing with alignment. + */ + switch ((intptr_t)ap & (sizeof(u_int32_t)-1)) { + + case 0: + addr = *(u_int32_t *)ap; + break; + + case 2: +#if BYTE_ORDER == BIG_ENDIAN + addr = ((u_int32_t)*(u_short *)ap << 16) | + (u_int32_t)*(u_short *)(ap + 2); +#else + addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) | + (u_int32_t)*(u_short *)ap; +#endif + break; + + default: +#if BYTE_ORDER == BIG_ENDIAN + addr = ((u_int32_t)ap[0] << 24) | + ((u_int32_t)ap[1] << 16) | + ((u_int32_t)ap[2] << 8) | + (u_int32_t)ap[3]; +#else + addr = ((u_int32_t)ap[3] << 24) | + ((u_int32_t)ap[2] << 16) | + ((u_int32_t)ap[1] << 8) | + (u_int32_t)ap[0]; +#endif + break; + } + + p = &hnametable[addr & (HASHNAMESIZE-1)]; + for (; p->nxt; p = p->nxt) { + if (p->addr == addr) + return (p->name); + } + p->addr = addr; + p->nxt = newhnamemem(); + + p->name = savestr(intoa(addr)); + return (p->name); +} + +char * +ether_ntoa(struct ether_addr *e) +{ + static char a[] = "xx:xx:xx:xx:xx:xx"; + + (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x", + e->ether_addr_octet[0], e->ether_addr_octet[1], + e->ether_addr_octet[2], e->ether_addr_octet[3], + e->ether_addr_octet[4], e->ether_addr_octet[5]); + + return (a); +} + +static inline struct enamemem * +lookup_emem(const u_char *ep) +{ + u_int i, j, k; + struct enamemem *tp; + + k = (ep[0] << 8) | ep[1]; + j = (ep[2] << 8) | ep[3]; + i = (ep[4] << 8) | ep[5]; + + tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->e_nxt) + if (tp->e_addr0 == i && + tp->e_addr1 == j && + tp->e_addr2 == k) + return tp; + else + tp = tp->e_nxt; + tp->e_addr0 = i; + tp->e_addr1 = j; + tp->e_addr2 = k; + tp->e_nxt = (struct enamemem *)malloc(1 * sizeof(*tp), 0, 0); + + return tp; +} + +char * +etheraddr_string(const u_char *ep) +{ + struct enamemem *tp; + struct ether_addr e; + + tp = lookup_emem(ep); + if (tp->e_name) + return (tp->e_name); + memcpy(e.ether_addr_octet, ep, sizeof(e.ether_addr_octet)); + tp->e_name = savestr(ether_ntoa(&e)); + return (tp->e_name); +} + +#define ipaddr_string(p) getname((const u_char *)(p)) + +void +debug_print_arp(const char *tag, mbuf_t m) +{ + size_t len = mbuf_len(m); + ether_header_t *eh = (ether_header_t *)mbuf_data(m); + if (len >= sizeof(ether_header_t) && + (eh->ether_type == htons(ETHERTYPE_ARP) || eh->ether_type == htons(ETHERTYPE_REVARP))) { + u_char *p = (u_char *)eh + sizeof(ether_header); + len -= sizeof(ether_header); + const struct ether_arp *ap = (const struct ether_arp *)p; + u_short pro, hrd, op; + pro = EXTRACT_16BITS(&ap->arp_pro); + hrd = EXTRACT_16BITS(&ap->arp_hrd); + op = EXTRACT_16BITS(&ap->arp_op); + if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) + || ap->arp_hln != sizeof(SHA(ap)) + || ap->arp_pln != sizeof(SPA(ap))) { + XYLog("%s arp-#%d for proto #%d (%d) hardware #%d (%d)\n", + tag, op, pro, ap->arp_pln, hrd, ap->arp_hln); + } + if (pro == ETHERTYPE_TRAIL) + XYLog("%s trailer-\n", tag); + switch (op) { + + case ARPOP_REQUEST: + XYLog("%s arp who-has %s tell %s\n", tag, ipaddr_string(TPA(ap)), ipaddr_string(SPA(ap))); + break; + + case ARPOP_REPLY: + XYLog("%s arp reply %s is-at %s\n", tag, ipaddr_string(SPA(ap)), etheraddr_string(SHA(ap))); + break; + + case ARPOP_REVREQUEST: + XYLog("%s rarp who-is %s tell %s\n", tag, etheraddr_string(THA(ap)), + etheraddr_string(SHA(ap))); + break; + + case ARPOP_REVREPLY: + XYLog("%s rarp reply %s at %s\n", tag, etheraddr_string(THA(ap)), + ipaddr_string(TPA(ap))); + break; + + default: + XYLog("%s arp-#%d\n", tag, op); + break; + } + if (hrd != ARPHRD_ETHER) + XYLog("%s hardware #%d\n", tag, hrd); + } +} diff --git a/itl80211/openbsd/sys/arp.h b/itl80211/openbsd/sys/arp.h new file mode 100644 index 000000000..7caf46698 --- /dev/null +++ b/itl80211/openbsd/sys/arp.h @@ -0,0 +1,16 @@ +// +// arp.h +// itlwm +// +// Created by zxystd on 2023/7/1. +// Copyright © 2023 钟先耀. All rights reserved. +// + +#ifndef arp_h +#define arp_h + +#include + +void debug_print_arp(const char *tag, mbuf_t m); + +#endif /* arp_h */ diff --git a/itlwm.xcodeproj/project.pbxproj b/itlwm.xcodeproj/project.pbxproj index ab4856f24..6b5a7b446 100644 --- a/itlwm.xcodeproj/project.pbxproj +++ b/itlwm.xcodeproj/project.pbxproj @@ -317,6 +317,26 @@ 5088ECBF252884AF0068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; }; 5088ECC0252884C10068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; }; 5088ECC1252884D70068A63D /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; }; + A5A0C5242A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C5252A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C5262A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C5272A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C5282A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C5292A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C52A2A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5A0C52B2A501E6800EF9328 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + A5DD111526D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + A5DD111626D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + A5DD111726D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + A5DD111826D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + A5DD111926D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + A5DD111A26D93B5F00BA01EF /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + A5DD111B26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; }; + A5DD111C26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; }; + A5DD111D26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; }; + A5DD111E26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; }; + A5DD111F26D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; }; + A5DD112026D93B5F00BA01EF /* rs.h in Headers */ = {isa = PBXBuildFile; fileRef = A5DD111426D93B5F00BA01EF /* rs.h */; }; A5FA2AE428A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; }; A5FA2AE528A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; }; A5FA2AE628A797B200847103 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; }; @@ -332,6 +352,91 @@ F837C9202724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; }; F837C9212724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; }; F837C9222724577F00B2C499 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; }; + F84AD8862A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD8872A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD8882A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD8892A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD88A2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD88B2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD88C2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F84AD88D2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD88E2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD88F2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD8902A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD8912A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD8922A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD8932A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F84AD8942A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD8952A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD8962A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD8972A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD8982A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD8992A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD89A2A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F84AD89B2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD89C2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD89D2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD89E2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD89F2A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD8A02A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD8A12A497DB200DC8DED /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F84AD8A22A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A32A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A42A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A52A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A62A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A72A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A82A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F84AD8A92A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8AA2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8AB2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8AC2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8AD2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8AE2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8AF2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F84AD8B02A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B12A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B22A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B32A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B42A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B52A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B62A497DB200DC8DED /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F84AD8B72A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8B82A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8B92A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8BA2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8BB2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8BC2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8BD2A497DB200DC8DED /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F84AD8BE2A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8BF2A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8C02A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8C12A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8C22A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8C32A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8C42A497DB200DC8DED /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F84AD8C52A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8C62A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8C72A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8C82A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8C92A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8CA2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8CB2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F84AD8CC2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8CD2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8CE2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8CF2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8D02A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8D12A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8D22A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F84AD8D32A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F84AD8D42A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F84AD8D52A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F84AD8D62A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F84AD8D72A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F84AD8D82A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F84AD8D92A497DB200DC8DED /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F8876A4E28B71F5400A21E42 /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; F88CB91424FBE9130060B1A5 /* ItlDriverInfo.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F88CB91324FBE9130060B1A5 /* ItlDriverInfo.hpp */; }; F88D2B3D2414E64000BBE700 /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; }; F897ECBA266EFF93005EE8F7 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; }; @@ -493,6 +598,21 @@ F89B6C20250232DC000F77FF /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; }; F89B6C21250232DC000F77FF /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; }; F89B6C2325027609000F77FF /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; }; + F89F35F22A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F89F35F32A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F89F35F42A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F89F35F52A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F89F35F62A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F89F35F72A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F89F35F82A49867F00061876 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F8A028222A4A7DDC00C6DE90 /* AirportItlwmV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */; }; + F8A028232A4A7DDC00C6DE90 /* AirportItlwmV2.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */; }; + F8A0282F2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */; }; + F8A028302A4A7E0500C6DE90 /* AirportItlwmEthernetInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */; }; + F8A028722A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */; }; + F8A028732A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */; }; + F8A0287F2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */; }; + F8A028802A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */; }; F8A4307325062CE300EA545E /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; }; F8AE64F9285471560085B4CF /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; }; F8AE64FA285471560085B4CF /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; }; @@ -584,6 +704,90 @@ F8AE6553285471560085B4CF /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; }; F8AF3A3124F9F35B008911C1 /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; }; F8AF3A3224F9F35B008911C1 /* ItlIwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8AF3A3024F9F35B008911C1 /* ItlIwm.hpp */; }; + F8B210AB2A2EC2680043ECBD /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; }; + F8B210AC2A2EC2680043ECBD /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; }; + F8B210AD2A2EC2680043ECBD /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; }; + F8B210AE2A2EC2680043ECBD /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; }; + F8B210AF2A2EC2680043ECBD /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; }; + F8B210B02A2EC2680043ECBD /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; }; + F8B210B12A2EC2680043ECBD /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; }; + F8B210B22A2EC2680043ECBD /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; }; + F8B210B32A2EC2680043ECBD /* (null) in Headers */ = {isa = PBXBuildFile; }; + F8B210B42A2EC2680043ECBD /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; }; + F8B210B52A2EC2680043ECBD /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; }; + F8B210B62A2EC2680043ECBD /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; }; + F8B210B72A2EC2680043ECBD /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; }; + F8B210B82A2EC2680043ECBD /* (null) in Headers */ = {isa = PBXBuildFile; }; + F8B210B92A2EC2680043ECBD /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; }; + F8B210BA2A2EC2680043ECBD /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; }; + F8B210BC2A2EC2680043ECBD /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; }; + F8B210BD2A2EC2680043ECBD /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; }; + F8B210BE2A2EC2680043ECBD /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; }; + F8B210BF2A2EC2680043ECBD /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; }; + F8B210C02A2EC2680043ECBD /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; }; + F8B210C22A2EC2680043ECBD /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; }; + F8B210C32A2EC2680043ECBD /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; }; + F8B210C42A2EC2680043ECBD /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; }; + F8B210C52A2EC2680043ECBD /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; }; + F8B210C62A2EC2680043ECBD /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; }; + F8B210C72A2EC2680043ECBD /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; }; + F8B210C82A2EC2680043ECBD /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; }; + F8B210C92A2EC2680043ECBD /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; }; + F8B210CA2A2EC2680043ECBD /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; }; + F8B210CB2A2EC2680043ECBD /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; }; + F8B210CC2A2EC2680043ECBD /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; }; + F8B210CD2A2EC2680043ECBD /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; }; + F8B210CE2A2EC2680043ECBD /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; }; + F8B210CF2A2EC2680043ECBD /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; }; + F8B210D02A2EC2680043ECBD /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; }; + F8B210D12A2EC2680043ECBD /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; }; + F8B210D22A2EC2680043ECBD /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; }; + F8B210D32A2EC2680043ECBD /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; }; + F8B210D42A2EC2680043ECBD /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; }; + F8B210D52A2EC2680043ECBD /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; }; + F8B210D62A2EC2680043ECBD /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; }; + F8B210D72A2EC2680043ECBD /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; }; + F8B210D82A2EC2680043ECBD /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; }; + F8B210D92A2EC2680043ECBD /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; }; + F8B210DA2A2EC2680043ECBD /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; }; + F8B210DB2A2EC2680043ECBD /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; }; + F8B210DC2A2EC2680043ECBD /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; }; + F8B210DD2A2EC2680043ECBD /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; }; + F8B210DE2A2EC2680043ECBD /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; }; + F8B210DF2A2EC2680043ECBD /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; }; + F8B210E02A2EC2680043ECBD /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; }; + F8B210E12A2EC2680043ECBD /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; }; + F8B210E22A2EC2680043ECBD /* (null) in Sources */ = {isa = PBXBuildFile; }; + F8B210E32A2EC2680043ECBD /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; }; + F8B210E42A2EC2680043ECBD /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; }; + F8B210E52A2EC2680043ECBD /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; }; + F8B210E62A2EC2680043ECBD /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; }; + F8B210E72A2EC2680043ECBD /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; }; + F8B210E82A2EC2680043ECBD /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; }; + F8B210E92A2EC2680043ECBD /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; }; + F8B210EA2A2EC2680043ECBD /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; }; + F8B210EB2A2EC2680043ECBD /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; }; + F8B210EC2A2EC2680043ECBD /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; }; + F8B210ED2A2EC2680043ECBD /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; }; + F8B210EE2A2EC2680043ECBD /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; }; + F8B210EF2A2EC2680043ECBD /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; }; + F8B210F02A2EC2680043ECBD /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; }; + F8B210F12A2EC2680043ECBD /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; }; + F8B210F22A2EC2680043ECBD /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; }; + F8B210F32A2EC2680043ECBD /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; }; + F8B210F42A2EC2680043ECBD /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; }; + F8B210F52A2EC2680043ECBD /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; }; + F8B210F62A2EC2680043ECBD /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; }; + F8B210F72A2EC2680043ECBD /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; }; + F8B210F82A2EC2680043ECBD /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; }; + F8B210F92A2EC2680043ECBD /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; }; + F8B210FA2A2EC2680043ECBD /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; }; + F8B210FB2A2EC2680043ECBD /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; }; + F8B210FC2A2EC2680043ECBD /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; }; + F8B210FD2A2EC2680043ECBD /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; }; + F8B210FE2A2EC2680043ECBD /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; }; + F8B210FF2A2EC2680043ECBD /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; }; + F8B211052A2EC2680043ECBD /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; }; F8C2EC4F2408031A007A9422 /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; }; F8C2EC502408031A007A9422 /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; }; F8C2EC512408031A007A9422 /* ieee80211_amrr.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C2EC3124080319007A9422 /* ieee80211_amrr.h */; }; @@ -646,6 +850,113 @@ F8D364F824F93AFD0029340B /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; }; F8D364FA24F93AFD0029340B /* ItlHalService.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8D364F724F93AFD0029340B /* ItlHalService.hpp */; }; F8D76362244F21BB00DEA040 /* pm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D76361244F21BB00DEA040 /* pm.cpp */; }; + F8D94C842B9ABFE20081A3C4 /* CCDataPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8812A497DB200DC8DED /* CCDataPipe.h */; }; + F8D94C852B9ABFE20081A3C4 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6C2225027609000F77FF /* debug.h */; }; + F8D94C862B9ABFE20081A3C4 /* IOSkywalkEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */; }; + F8D94C872B9ABFE20081A3C4 /* IO80211InfraProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */; }; + F8D94C882B9ABFE20081A3C4 /* IOSkywalkLogicalLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */; }; + F8D94C892B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */; }; + F8D94C8A2B9ABFE20081A3C4 /* IOSkywalkNetworkPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */; }; + F8D94C8B2B9ABFE20081A3C4 /* apple80211_ioctl.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */; }; + F8D94C8C2B9ABFE20081A3C4 /* CCLogPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8852A497DB200DC8DED /* CCLogPipe.h */; }; + F8D94C8D2B9ABFE20081A3C4 /* IO80211P2PInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */; }; + F8D94C8E2B9ABFE20081A3C4 /* CCPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87D2A497DB200DC8DED /* CCPipe.h */; }; + F8D94C8F2B9ABFE20081A3C4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; }; + F8D94C902B9ABFE20081A3C4 /* apple80211_var.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC425021DEC000F77FF /* apple80211_var.h */; }; + F8D94C912B9ABFE20081A3C4 /* IOSkywalkPacketBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */; }; + F8D94C922B9ABFE20081A3C4 /* IOSkywalkLegacyEthernetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */; }; + F8D94C932B9ABFE20081A3C4 /* AirportItlwmInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */; }; + F8D94C942B9ABFE20081A3C4 /* IO80211Interface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA38252D834500520FD4 /* IO80211Interface.h */; }; + F8D94C952B9ABFE20081A3C4 /* IO80211WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */; }; + F8D94C962B9ABFE20081A3C4 /* (null) in Headers */ = {isa = PBXBuildFile; }; + F8D94C972B9ABFE20081A3C4 /* IO80211InfraInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */; }; + F8D94C982B9ABFE20081A3C4 /* IO80211SkywalkInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */; }; + F8D94C992B9ABFE20081A3C4 /* CCLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8822A497DB200DC8DED /* CCLogStream.h */; }; + F8D94C9A2B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */; }; + F8D94C9B2B9ABFE20081A3C4 /* AirportItlwm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BBB25021C9C000F77FF /* AirportItlwm.hpp */; }; + F8D94C9C2B9ABFE20081A3C4 /* IO80211ControllerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = F89F35F12A49867F00061876 /* IO80211ControllerV2.h */; }; + F8D94C9D2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */; }; + F8D94C9E2B9ABFE20081A3C4 /* IO80211VirtualInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */; }; + F8D94C9F2B9ABFE20081A3C4 /* IO80211Controller.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA35252D834500520FD4 /* IO80211Controller.h */; }; + F8D94CA02B9ABFE20081A3C4 /* (null) in Headers */ = {isa = PBXBuildFile; }; + F8D94CA12B9ABFE20081A3C4 /* AirportItlwmV2.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */; }; + F8D94CA22B9ABFE20081A3C4 /* ieee80211_ra.h in Headers */ = {isa = PBXBuildFile; fileRef = F8C594D225FD935B0007D19C /* ieee80211_ra.h */; }; + F8D94CA32B9ABFE20081A3C4 /* CCStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F84AD8802A497DB200DC8DED /* CCStream.h */; }; + F8D94CA42B9ABFE20081A3C4 /* apple80211_wps.h in Headers */ = {isa = PBXBuildFile; fileRef = F89B6BC325021DEC000F77FF /* apple80211_wps.h */; }; + F8D94CA62B9ABFE20081A3C4 /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; + F8D94CA72B9ABFE20081A3C4 /* _mbuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D257732495A33500872E4F /* _mbuf.cpp */; }; + F8D94CA82B9ABFE20081A3C4 /* ieee80211_ra.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C594D125FD935B0007D19C /* ieee80211_ra.c */; }; + F8D94CA92B9ABFE20081A3C4 /* _task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8F9EDE0240B7415009CB8E7 /* _task.cpp */; }; + F8D94CAA2B9ABFE20081A3C4 /* FwBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5076FA7F24CC71E40011B2BB /* FwBinary.cpp */; }; + F8D94CAB2B9ABFE20081A3C4 /* ieee80211_proto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC2F24080319007A9422 /* ieee80211_proto.c */; }; + F8D94CAC2B9ABFE20081A3C4 /* _string.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3024080319007A9422 /* _string.c */; }; + F8D94CAD2B9ABFE20081A3C4 /* ieee80211_ioctl.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3224080319007A9422 /* ieee80211_ioctl.c */; }; + F8D94CAE2B9ABFE20081A3C4 /* ieee80211.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3324080319007A9422 /* ieee80211.c */; }; + F8D94CAF2B9ABFE20081A3C4 /* ieee80211_rssadapt.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3424080319007A9422 /* ieee80211_rssadapt.c */; }; + F8D94CB02B9ABFE20081A3C4 /* ieee80211_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3524080319007A9422 /* ieee80211_input.c */; }; + F8D94CB12B9ABFE20081A3C4 /* timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3724080319007A9422 /* timeout.c */; }; + F8D94CB22B9ABFE20081A3C4 /* ieee80211_mira.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3924080319007A9422 /* ieee80211_mira.c */; }; + F8D94CB32B9ABFE20081A3C4 /* ieee80211_crypto_bip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3B24080319007A9422 /* ieee80211_crypto_bip.c */; }; + F8D94CB42B9ABFE20081A3C4 /* ieee80211_crypto_tkip.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3C24080319007A9422 /* ieee80211_crypto_tkip.c */; }; + F8D94CB52B9ABFE20081A3C4 /* ieee80211_crypto_ccmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3D24080319007A9422 /* ieee80211_crypto_ccmp.c */; }; + F8D94CB62B9ABFE20081A3C4 /* ieee80211_crypto_wep.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC462408031A007A9422 /* ieee80211_crypto_wep.c */; }; + F8D94CB72B9ABFE20081A3C4 /* ieee80211_pae_input.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC3E24080319007A9422 /* ieee80211_pae_input.c */; }; + F8D94CB82B9ABFE20081A3C4 /* ieee80211_amrr.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4024080319007A9422 /* ieee80211_amrr.c */; }; + F8D94CB92B9ABFE20081A3C4 /* ieee80211_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC472408031A007A9422 /* ieee80211_output.c */; }; + F8D94CBA2B9ABFE20081A3C4 /* ieee80211_crypto.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC482408031A007A9422 /* ieee80211_crypto.c */; }; + F8D94CBB2B9ABFE20081A3C4 /* CTimeout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC492408031A007A9422 /* CTimeout.cpp */; }; + F8D94CBC2B9ABFE20081A3C4 /* ieee80211_regdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4B2408031A007A9422 /* ieee80211_regdomain.c */; }; + F8D94CBD2B9ABFE20081A3C4 /* ieee80211_node.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4C2408031A007A9422 /* ieee80211_node.c */; }; + F8D94CBE2B9ABFE20081A3C4 /* ieee80211_pae_output.c in Sources */ = {isa = PBXBuildFile; fileRef = F8C2EC4D2408031A007A9422 /* ieee80211_pae_output.c */; }; + F8D94CBF2B9ABFE20081A3C4 /* sha1-pbkdf2.c in Sources */ = {isa = PBXBuildFile; fileRef = F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */; }; + F8D94CC02B9ABFE20081A3C4 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07C923FCBC6C009FBA6C /* aes.c */; }; + F8D94CC12B9ABFE20081A3C4 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CA23FCBC6C009FBA6C /* hmac.c */; }; + F8D94CC22B9ABFE20081A3C4 /* sha2.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CB23FCBC6C009FBA6C /* sha2.c */; }; + F8D94CC32B9ABFE20081A3C4 /* rijndael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CC23FCBC6C009FBA6C /* rijndael.c */; }; + F8D94CC42B9ABFE20081A3C4 /* ecb3_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CD23FCBC6C009FBA6C /* ecb3_enc.c */; }; + F8D94CC52B9ABFE20081A3C4 /* set_key.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CE23FCBC6C009FBA6C /* set_key.c */; }; + F8D94CC62B9ABFE20081A3C4 /* cast.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07CF23FCBC6C009FBA6C /* cast.c */; }; + F8D94CC72B9ABFE20081A3C4 /* michael.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D123FCBC6C009FBA6C /* michael.c */; }; + F8D94CC82B9ABFE20081A3C4 /* arp.c in Sources */ = {isa = PBXBuildFile; fileRef = A5A0C5232A501E6800EF9328 /* arp.c */; }; + F8D94CC92B9ABFE20081A3C4 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07D823FCBC6C009FBA6C /* sha1.c */; }; + F8D94CCA2B9ABFE20081A3C4 /* cmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07DD23FCBC6C009FBA6C /* cmac.c */; }; + F8D94CCB2B9ABFE20081A3C4 /* ecb_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E423FCBC6C009FBA6C /* ecb_enc.c */; }; + F8D94CCC2B9ABFE20081A3C4 /* chachapoly.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07E923FCBC6C009FBA6C /* chachapoly.c */; }; + F8D94CCD2B9ABFE20081A3C4 /* AirportItlwmV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */; }; + F8D94CCE2B9ABFE20081A3C4 /* (null) in Sources */ = {isa = PBXBuildFile; }; + F8D94CCF2B9ABFE20081A3C4 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EA23FCBC6C009FBA6C /* md5.c */; }; + F8D94CD02B9ABFE20081A3C4 /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EB23FCBC6C009FBA6C /* arc4.c */; }; + F8D94CD12B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */; }; + F8D94CD22B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */; }; + F8D94CD32B9ABFE20081A3C4 /* blf.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07EC23FCBC6C009FBA6C /* blf.c */; }; + F8D94CD42B9ABFE20081A3C4 /* _ifq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5FA2AE328A797B200847103 /* _ifq.cpp */; }; + F8D94CD52B9ABFE20081A3C4 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07ED23FCBC6C009FBA6C /* poly1305.c */; }; + F8D94CD62B9ABFE20081A3C4 /* key_wrap.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F023FCBC6C009FBA6C /* key_wrap.c */; }; + F8D94CD72B9ABFE20081A3C4 /* gmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F223FCBC6C009FBA6C /* gmac.c */; }; + F8D94CD82B9ABFE20081A3C4 /* rmd160.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F323FCBC6C009FBA6C /* rmd160.c */; }; + F8D94CD92B9ABFE20081A3C4 /* idgen.c in Sources */ = {isa = PBXBuildFile; fileRef = 024A07F423FCBC6C009FBA6C /* idgen.c */; }; + F8D94CDA2B9ABFE20081A3C4 /* compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A07BA23FCBC6C009FBA6C /* compat.cpp */; }; + F8D94CDB2B9ABFE20081A3C4 /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F8FA0EED2501E8C100B1822E /* zutil.c */; }; + F8D94CDC2B9ABFE20081A3C4 /* ItlHalService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D364F624F93AFD0029340B /* ItlHalService.cpp */; }; + F8D94CDD2B9ABFE20081A3C4 /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; }; + F8D94CDE2B9ABFE20081A3C4 /* utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BF23FCD4E2009FBA6C /* utils.cpp */; }; + F8D94CDF2B9ABFE20081A3C4 /* fw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08BD23FCD314009FBA6C /* fw.cpp */; }; + F8D94CE02B9ABFE20081A3C4 /* io.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C123FCD999009FBA6C /* io.cpp */; }; + F8D94CE12B9ABFE20081A3C4 /* rx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C323FCDC14009FBA6C /* rx.cpp */; }; + F8D94CE22B9ABFE20081A3C4 /* coex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F837C91C2724577F00B2C499 /* coex.cpp */; }; + F8D94CE32B9ABFE20081A3C4 /* tx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C523FCDC3B009FBA6C /* tx.cpp */; }; + F8D94CE42B9ABFE20081A3C4 /* hw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C723FCE2ED009FBA6C /* hw.cpp */; }; + F8D94CE52B9ABFE20081A3C4 /* ItlIwn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17FD7F0E255E4AC800611406 /* ItlIwn.cpp */; }; + F8D94CE62B9ABFE20081A3C4 /* phy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08C923FCE537009FBA6C /* phy.cpp */; }; + F8D94CE72B9ABFE20081A3C4 /* mac80211.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CB23FCE5CA009FBA6C /* mac80211.cpp */; }; + F8D94CE82B9ABFE20081A3C4 /* nvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CD23FCE67F009FBA6C /* nvm.cpp */; }; + F8D94CE92B9ABFE20081A3C4 /* ctxt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08CF23FCEE88009FBA6C /* ctxt.cpp */; }; + F8D94CEA2B9ABFE20081A3C4 /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D123FCF395009FBA6C /* led.cpp */; }; + F8D94CEB2B9ABFE20081A3C4 /* power.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D323FCF3E6009FBA6C /* power.cpp */; }; + F8D94CEC2B9ABFE20081A3C4 /* scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 024A08D523FCF4D7009FBA6C /* scan.cpp */; }; + F8D94CED2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */; }; + F8D94CEE2B9ABFE20081A3C4 /* ItlIwm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */; }; + F8D94CF02B9ABFE20081A3C4 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5088ECBC252884870068A63D /* libkmod.a */; }; F8E49A14249B923500BE6868 /* ItlNetworkUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8E49A12249B923500BE6868 /* ItlNetworkUserClient.cpp */; }; F8E49A15249B923500BE6868 /* ItlNetworkUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F8E49A13249B923500BE6868 /* ItlNetworkUserClient.hpp */; }; F8ED134424FBB5B70068C831 /* ItlIwx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F8D6CD642442E8F200D2A454 /* ItlIwx.cpp */; }; @@ -673,6 +984,7 @@ F8F7EA4F252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; }; F8F7EA50252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; }; F8F7EA51252D834600520FD4 /* IO80211WorkLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */; }; + F8F84F682ADE26F1002808DE /* rs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5DD111326D93B5F00BA01EF /* rs.cpp */; }; F8F9257E240974EF0088B8D5 /* bitfield.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F92573240974EE0088B8D5 /* bitfield.h */; }; F8F9257F240974EF0088B8D5 /* kernel.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F92574240974EE0088B8D5 /* kernel.h */; }; F8F92583240974EF0088B8D5 /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F92578240974EE0088B8D5 /* random.h */; }; @@ -731,6 +1043,20 @@ remoteGlobalIDString = 5066D63825287F7900EE6F38; remoteInfo = fw_gen; }; + F8B210A92A2EC2680043ECBD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 024A07A323FCBC3C009FBA6C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5066D63825287F7900EE6F38; + remoteInfo = fw_gen; + }; + F8D94C822B9ABFE20081A3C4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 024A07A323FCBC3C009FBA6C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5066D63825287F7900EE6F38; + remoteInfo = fw_gen; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -828,10 +1154,26 @@ A5213EBC27A0C3ED00D7EAB1 /* iwm-8000C-36 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iwm-8000C-36"; sourceTree = ""; }; A5213EBD27A0C3ED00D7EAB1 /* iwm-9260-46 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iwm-9260-46"; sourceTree = ""; }; A5213EBE27A0C3ED00D7EAB1 /* iwm-8265-36 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iwm-8265-36"; sourceTree = ""; }; + A5A0C5222A501E2900EF9328 /* arp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arp.h; sourceTree = ""; }; + A5A0C5232A501E6800EF9328 /* arp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = arp.c; sourceTree = ""; }; + A5DD111326D93B5F00BA01EF /* rs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rs.cpp; sourceTree = ""; }; + A5DD111426D93B5F00BA01EF /* rs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rs.h; sourceTree = ""; }; A5FA2AE328A797B200847103 /* _ifq.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = _ifq.cpp; sourceTree = ""; }; F800DD9A24FBEBF000789320 /* ItlDriverController.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlDriverController.hpp; sourceTree = ""; }; F837C91C2724577F00B2C499 /* coex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = coex.cpp; sourceTree = ""; }; F837C9252724732B00B2C499 /* iwlwifi-so-a0-gf-a0.pnvm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iwlwifi-so-a0-gf-a0.pnvm"; sourceTree = ""; }; + F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211WorkQueue.h; sourceTree = ""; }; + F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkNetworkPacket.h; sourceTree = ""; }; + F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211InfraProtocol.h; sourceTree = ""; }; + F84AD87D2A497DB200DC8DED /* CCPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCPipe.h; sourceTree = ""; }; + F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkLogicalLink.h; sourceTree = ""; }; + F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211InfraInterface.h; sourceTree = ""; }; + F84AD8802A497DB200DC8DED /* CCStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCStream.h; sourceTree = ""; }; + F84AD8812A497DB200DC8DED /* CCDataPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCDataPipe.h; sourceTree = ""; }; + F84AD8822A497DB200DC8DED /* CCLogStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogStream.h; sourceTree = ""; }; + F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkPacketBufferPool.h; sourceTree = ""; }; + F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSkywalkLegacyEthernetInterface.h; sourceTree = ""; }; + F84AD8852A497DB200DC8DED /* CCLogPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogPipe.h; sourceTree = ""; }; F883EC1F266F43F200EA018C /* AirportItlwm-Monterey-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AirportItlwm-Monterey-Info.plist"; sourceTree = ""; }; F88CB91324FBE9130060B1A5 /* ItlDriverInfo.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlDriverInfo.hpp; sourceTree = ""; }; F88D2B3B2414E64000BBE700 /* sha1-pbkdf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sha1-pbkdf2.c"; sourceTree = ""; }; @@ -850,10 +1192,22 @@ F89B6BDE25022FB5000F77FF /* AirportVirtualIOCTL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportVirtualIOCTL.cpp; sourceTree = ""; }; F89B6BE025022FC7000F77FF /* AirportAWDL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportAWDL.cpp; sourceTree = ""; }; F89B6C2225027609000F77FF /* debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; + F89F35F12A49867F00061876 /* IO80211ControllerV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IO80211ControllerV2.h; sourceTree = ""; }; + F8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmV2.cpp; sourceTree = ""; }; + F8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmV2.hpp; sourceTree = ""; }; + F8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmEthernetInterface.cpp; sourceTree = ""; }; + F8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmEthernetInterface.hpp; sourceTree = ""; }; + F8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AirportItlwmSkywalkInterface.cpp; sourceTree = ""; }; + F8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AirportItlwmSkywalkInterface.hpp; sourceTree = ""; }; + F8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IOPCIEDeviceWrapper.cpp; sourceTree = ""; }; + F8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IOPCIEDeviceWrapper.hpp; sourceTree = ""; }; + F8A2A68B2A305B9E002ABDDB /* IOSkywalkNetworkInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOSkywalkNetworkInterface.h; sourceTree = ""; }; + F8A2A68C2A305BAC002ABDDB /* IOSkywalkInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOSkywalkInterface.h; sourceTree = ""; }; F8A763892766B95F004606BE /* iwlwifi-so-a0-gf4-a0.pnvm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iwlwifi-so-a0-gf4-a0.pnvm"; sourceTree = ""; }; F8AE6558285471560085B4CF /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; }; F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlIwm.cpp; sourceTree = ""; }; F8AF3A3024F9F35B008911C1 /* ItlIwm.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlIwm.hpp; sourceTree = ""; }; + F8B2110A2A2EC2680043ECBD /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; }; F8B783AF240B9F87004C9777 /* _ifq.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _ifq.h; sourceTree = ""; }; F8BB56172647FDF500F180EC /* _clock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _clock.h; sourceTree = ""; }; F8BEFA9124CA93E900F6D938 /* _malloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _malloc.h; sourceTree = ""; }; @@ -920,6 +1274,7 @@ F8D6CD6C2442F20C00D2A454 /* if_iwxreg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if_iwxreg.h; sourceTree = ""; }; F8D6CD6D2442F20C00D2A454 /* if_iwxvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if_iwxvar.h; sourceTree = ""; }; F8D76361244F21BB00DEA040 /* pm.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pm.cpp; sourceTree = ""; }; + F8D94CF52B9ABFE20081A3C4 /* AirportItlwm.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirportItlwm.kext; sourceTree = BUILT_PRODUCTS_DIR; }; F8E3806526D533D400568FEB /* iwlwifi-ty-a0-gf-a0.pnvm */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iwlwifi-ty-a0-gf-a0.pnvm"; sourceTree = ""; }; F8E49A12249B923500BE6868 /* ItlNetworkUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ItlNetworkUserClient.cpp; sourceTree = ""; }; F8E49A13249B923500BE6868 /* ItlNetworkUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ItlNetworkUserClient.hpp; sourceTree = ""; }; @@ -1009,6 +1364,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F8B211042A2EC2680043ECBD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F8B211052A2EC2680043ECBD /* libkmod.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8D94CEF2B9ABFE20081A3C4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F8D94CF02B9ABFE20081A3C4 /* libkmod.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1037,6 +1408,8 @@ 35CBE78F251CB8CA00435CBC /* AirportItlwm.kext */, F897ED18266EFF93005EE8F7 /* AirportItlwm.kext */, F8AE6558285471560085B4CF /* AirportItlwm.kext */, + F8B2110A2A2EC2680043ECBD /* AirportItlwm.kext */, + F8D94CF52B9ABFE20081A3C4 /* AirportItlwm.kext */, ); name = Products; sourceTree = ""; @@ -1193,12 +1566,27 @@ F89B6B7D25021674000F77FF /* Airport */ = { isa = PBXGroup; children = ( + F84AD8812A497DB200DC8DED /* CCDataPipe.h */, + F84AD8852A497DB200DC8DED /* CCLogPipe.h */, + F84AD8822A497DB200DC8DED /* CCLogStream.h */, + F84AD87D2A497DB200DC8DED /* CCPipe.h */, + F84AD8802A497DB200DC8DED /* CCStream.h */, + F84AD87F2A497DB200DC8DED /* IO80211InfraInterface.h */, + F84AD87C2A497DB200DC8DED /* IO80211InfraProtocol.h */, + F84AD87A2A497DB200DC8DED /* IO80211WorkQueue.h */, + F84AD8842A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h */, + F84AD87E2A497DB200DC8DED /* IOSkywalkLogicalLink.h */, + F84AD87B2A497DB200DC8DED /* IOSkywalkNetworkPacket.h */, + F84AD8832A497DB200DC8DED /* IOSkywalkPacketBufferPool.h */, F89B6B8325021A79000F77FF /* apple_private_spi.h */, F8F7EA35252D834500520FD4 /* IO80211Controller.h */, + F89F35F12A49867F00061876 /* IO80211ControllerV2.h */, F8F7EA38252D834500520FD4 /* IO80211Interface.h */, F8F7EA36252D834500520FD4 /* IO80211P2PInterface.h */, F8F7EA37252D834500520FD4 /* IO80211SkywalkInterface.h */, F89B6BD025021E66000F77FF /* IOSkywalkEthernetInterface.h */, + F8A2A68B2A305B9E002ABDDB /* IOSkywalkNetworkInterface.h */, + F8A2A68C2A305BAC002ABDDB /* IOSkywalkInterface.h */, F8F7EA34252D834500520FD4 /* IO80211VirtualInterface.h */, F8F7EA39252D834500520FD4 /* IO80211WorkLoop.h */, F89B6BC525021DEC000F77FF /* apple80211_ioctl.h */, @@ -1222,6 +1610,14 @@ F8CA44A225091AF60036119A /* AirportItlwmInterface.hpp */, F89B6BBF25021C9C000F77FF /* Info.plist */, F883EC1F266F43F200EA018C /* AirportItlwm-Monterey-Info.plist */, + F8A028202A4A7DDC00C6DE90 /* AirportItlwmV2.cpp */, + F8A028212A4A7DDC00C6DE90 /* AirportItlwmV2.hpp */, + F8A0282D2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp */, + F8A0282E2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.hpp */, + F8A028702A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp */, + F8A028712A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp */, + F8A0287D2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp */, + F8A0287E2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp */, ); path = AirportItlwm; sourceTree = ""; @@ -1259,6 +1655,8 @@ F837C91C2724577F00B2C499 /* coex.cpp */, F8AF3A2F24F9F35B008911C1 /* ItlIwm.cpp */, F8AF3A3024F9F35B008911C1 /* ItlIwm.hpp */, + A5DD111326D93B5F00BA01EF /* rs.cpp */, + A5DD111426D93B5F00BA01EF /* rs.h */, ); path = hal_iwm; sourceTree = ""; @@ -1338,6 +1736,8 @@ F8BEFA9124CA93E900F6D938 /* _malloc.h */, F8C7EF7B263125DE00BA87B6 /* _netstat.h */, F8BB56172647FDF500F180EC /* _clock.h */, + A5A0C5222A501E2900EF9328 /* arp.h */, + A5A0C5232A501E6800EF9328 /* arp.c */, ); path = sys; sourceTree = ""; @@ -1427,6 +1827,7 @@ 024A085423FCBC6C009FBA6C /* podd.h in Headers */, F8C2EC562408031A007A9422 /* ieee80211_node.h in Headers */, F8C2EC9524080557007A9422 /* _mbuf.h in Headers */, + A5DD111B26D93B5F00BA01EF /* rs.h in Headers */, 024A084423FCBC6C009FBA6C /* sha2.h in Headers */, 024A088C23FCBE38009FBA6C /* if_iwmvar.h in Headers */, 024A083A23FCBC6C009FBA6C /* blf.h in Headers */, @@ -1460,17 +1861,31 @@ files = ( 35CBE659251CB89700435CBC /* debug.h in Headers */, 35CBE65A251CB89700435CBC /* IOSkywalkEthernetInterface.h in Headers */, + F84AD8A52A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F84AD8892A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, 35CBE65B251CB89700435CBC /* apple80211_ioctl.h in Headers */, + F84AD8B32A497DB200DC8DED /* CCStream.h in Headers */, F8F7EA45252D834600520FD4 /* IO80211P2PInterface.h in Headers */, F8F7EA51252D834600520FD4 /* IO80211WorkLoop.h in Headers */, + F84AD8BA2A497DB200DC8DED /* CCDataPipe.h in Headers */, + F84AD8C12A497DB200DC8DED /* CCLogStream.h in Headers */, + F89F35F52A49867F00061876 /* IO80211ControllerV2.h in Headers */, 35CBE661251CB89700435CBC /* apple80211_var.h in Headers */, 35CBE664251CB89700435CBC /* AirportItlwmInterface.hpp in Headers */, + F84AD8CF2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, F8F7EA4D252D834600520FD4 /* IO80211Interface.h in Headers */, + F84AD8AC2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, F8F7EA49252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */, 35CBE666251CB89700435CBC /* AirportItlwm.hpp in Headers */, + A5DD111F26D93B5F00BA01EF /* rs.h in Headers */, F8F7EA3D252D834600520FD4 /* IO80211VirtualInterface.h in Headers */, + F84AD89E2A497DB200DC8DED /* CCPipe.h in Headers */, + F84AD8D62A497DB200DC8DED /* CCLogPipe.h in Headers */, F8F7EA41252D834600520FD4 /* IO80211Controller.h in Headers */, + F84AD8C82A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8972A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, F8C594DC25FD935B0007D19C /* ieee80211_ra.h in Headers */, + F84AD8902A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, 35CBE66F251CB89700435CBC /* apple80211_wps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1481,17 +1896,31 @@ files = ( 35CBE6C3251CB8BF00435CBC /* debug.h in Headers */, 35CBE6C4251CB8BF00435CBC /* IOSkywalkEthernetInterface.h in Headers */, + F84AD8A32A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F84AD8872A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, 35CBE6C5251CB8BF00435CBC /* apple80211_ioctl.h in Headers */, + F84AD8B12A497DB200DC8DED /* CCStream.h in Headers */, F8F7EA43252D834600520FD4 /* IO80211P2PInterface.h in Headers */, F8F7EA4F252D834600520FD4 /* IO80211WorkLoop.h in Headers */, + F84AD8B82A497DB200DC8DED /* CCDataPipe.h in Headers */, + F84AD8BF2A497DB200DC8DED /* CCLogStream.h in Headers */, + F89F35F32A49867F00061876 /* IO80211ControllerV2.h in Headers */, 35CBE6CB251CB8BF00435CBC /* apple80211_var.h in Headers */, 35CBE6CE251CB8BF00435CBC /* AirportItlwmInterface.hpp in Headers */, + F84AD8CD2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, F8F7EA4B252D834600520FD4 /* IO80211Interface.h in Headers */, + F84AD8AA2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, F8F7EA47252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */, 35CBE6D0251CB8BF00435CBC /* AirportItlwm.hpp in Headers */, + A5DD111D26D93B5F00BA01EF /* rs.h in Headers */, F8F7EA3B252D834600520FD4 /* IO80211VirtualInterface.h in Headers */, + F84AD89C2A497DB200DC8DED /* CCPipe.h in Headers */, + F84AD8D42A497DB200DC8DED /* CCLogPipe.h in Headers */, F8F7EA3F252D834600520FD4 /* IO80211Controller.h in Headers */, + F84AD8C62A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8952A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, F8C594DA25FD935B0007D19C /* ieee80211_ra.h in Headers */, + F84AD88E2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, 35CBE6D9251CB8BF00435CBC /* apple80211_wps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1502,17 +1931,31 @@ files = ( 35CBE72E251CB8CA00435CBC /* debug.h in Headers */, 35CBE72F251CB8CA00435CBC /* IOSkywalkEthernetInterface.h in Headers */, + F84AD8A22A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F84AD8862A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, 35CBE730251CB8CA00435CBC /* apple80211_ioctl.h in Headers */, + F84AD8B02A497DB200DC8DED /* CCStream.h in Headers */, F8F7EA42252D834600520FD4 /* IO80211P2PInterface.h in Headers */, F8F7EA4E252D834600520FD4 /* IO80211WorkLoop.h in Headers */, + F84AD8B72A497DB200DC8DED /* CCDataPipe.h in Headers */, + F84AD8BE2A497DB200DC8DED /* CCLogStream.h in Headers */, + F89F35F22A49867F00061876 /* IO80211ControllerV2.h in Headers */, 35CBE736251CB8CA00435CBC /* apple80211_var.h in Headers */, 35CBE739251CB8CA00435CBC /* AirportItlwmInterface.hpp in Headers */, + F84AD8CC2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, F8F7EA4A252D834600520FD4 /* IO80211Interface.h in Headers */, + F84AD8A92A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, F8F7EA46252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */, 35CBE73B251CB8CA00435CBC /* AirportItlwm.hpp in Headers */, + A5DD111C26D93B5F00BA01EF /* rs.h in Headers */, F8F7EA3A252D834600520FD4 /* IO80211VirtualInterface.h in Headers */, + F84AD89B2A497DB200DC8DED /* CCPipe.h in Headers */, + F84AD8D32A497DB200DC8DED /* CCLogPipe.h in Headers */, F8F7EA3E252D834600520FD4 /* IO80211Controller.h in Headers */, + F84AD8C52A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8942A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, F8C594D925FD935B0007D19C /* ieee80211_ra.h in Headers */, + F84AD88D2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, 35CBE744251CB8CA00435CBC /* apple80211_wps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1521,21 +1964,35 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + F84AD8BB2A497DB200DC8DED /* CCDataPipe.h in Headers */, F897ECBA266EFF93005EE8F7 /* debug.h in Headers */, F897ECBB266EFF93005EE8F7 /* IOSkywalkEthernetInterface.h in Headers */, + F84AD8982A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, + F84AD8A62A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F84AD8912A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, F897ECBC266EFF93005EE8F7 /* apple80211_ioctl.h in Headers */, + F84AD8D72A497DB200DC8DED /* CCLogPipe.h in Headers */, F897ECBD266EFF93005EE8F7 /* IO80211P2PInterface.h in Headers */, + F84AD89F2A497DB200DC8DED /* CCPipe.h in Headers */, F897ECBE266EFF93005EE8F7 /* IO80211WorkLoop.h in Headers */, F897ECBF266EFF93005EE8F7 /* apple80211_var.h in Headers */, + A5DD112026D93B5F00BA01EF /* rs.h in Headers */, + F84AD8C92A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8D02A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, F897ECC0266EFF93005EE8F7 /* AirportItlwmInterface.hpp in Headers */, F897ECC1266EFF93005EE8F7 /* IO80211Interface.h in Headers */, + F84AD88A2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, F897ECC2266EFF93005EE8F7 /* (null) in Headers */, + F84AD8AD2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, F897ECC3266EFF93005EE8F7 /* IO80211SkywalkInterface.h in Headers */, + F84AD8C22A497DB200DC8DED /* CCLogStream.h in Headers */, F897ECC4266EFF93005EE8F7 /* AirportItlwm.hpp in Headers */, + F89F35F62A49867F00061876 /* IO80211ControllerV2.h in Headers */, F897ECC5266EFF93005EE8F7 /* IO80211VirtualInterface.h in Headers */, F897ECC6266EFF93005EE8F7 /* IO80211Controller.h in Headers */, F897ECC7266EFF93005EE8F7 /* (null) in Headers */, F897ECC8266EFF93005EE8F7 /* ieee80211_ra.h in Headers */, + F84AD8B42A497DB200DC8DED /* CCStream.h in Headers */, F897ECC9266EFF93005EE8F7 /* apple80211_wps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1546,17 +2003,31 @@ files = ( F89B6C2325027609000F77FF /* debug.h in Headers */, F89B6BD725021E66000F77FF /* IOSkywalkEthernetInterface.h in Headers */, + F84AD8A42A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F84AD8882A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, F89B6BCB25021DED000F77FF /* apple80211_ioctl.h in Headers */, + F84AD8B22A497DB200DC8DED /* CCStream.h in Headers */, F8F7EA44252D834600520FD4 /* IO80211P2PInterface.h in Headers */, F8F7EA50252D834600520FD4 /* IO80211WorkLoop.h in Headers */, + F84AD8B92A497DB200DC8DED /* CCDataPipe.h in Headers */, + F84AD8C02A497DB200DC8DED /* CCLogStream.h in Headers */, + F89F35F42A49867F00061876 /* IO80211ControllerV2.h in Headers */, F89B6BC925021DED000F77FF /* apple80211_var.h in Headers */, F8CA44A425091AF60036119A /* AirportItlwmInterface.hpp in Headers */, + F84AD8CE2A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, F8F7EA4C252D834600520FD4 /* IO80211Interface.h in Headers */, + F84AD8AB2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, F8F7EA48252D834600520FD4 /* IO80211SkywalkInterface.h in Headers */, F89B6BBC25021C9C000F77FF /* AirportItlwm.hpp in Headers */, + A5DD111E26D93B5F00BA01EF /* rs.h in Headers */, F8F7EA3C252D834600520FD4 /* IO80211VirtualInterface.h in Headers */, + F84AD89D2A497DB200DC8DED /* CCPipe.h in Headers */, + F84AD8D52A497DB200DC8DED /* CCLogPipe.h in Headers */, F8F7EA40252D834600520FD4 /* IO80211Controller.h in Headers */, + F84AD8C72A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8962A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, F8C594DB25FD935B0007D19C /* ieee80211_ra.h in Headers */, + F84AD88F2A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, F89B6BC725021DED000F77FF /* apple80211_wps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1565,25 +2036,118 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + F84AD8BC2A497DB200DC8DED /* CCDataPipe.h in Headers */, F8AE64F9285471560085B4CF /* debug.h in Headers */, F8AE64FA285471560085B4CF /* IOSkywalkEthernetInterface.h in Headers */, + F84AD8992A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, + F84AD8A72A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F84AD8922A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, F8AE64FB285471560085B4CF /* apple80211_ioctl.h in Headers */, + F84AD8D82A497DB200DC8DED /* CCLogPipe.h in Headers */, F8AE64FC285471560085B4CF /* IO80211P2PInterface.h in Headers */, + F84AD8A02A497DB200DC8DED /* CCPipe.h in Headers */, F8AE64FD285471560085B4CF /* IO80211WorkLoop.h in Headers */, F8AE64FE285471560085B4CF /* apple80211_var.h in Headers */, + F84AD8CA2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8D12A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, F8AE64FF285471560085B4CF /* AirportItlwmInterface.hpp in Headers */, F8AE6500285471560085B4CF /* IO80211Interface.h in Headers */, + F84AD88B2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, F8AE6501285471560085B4CF /* (null) in Headers */, + F84AD8AE2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, F8AE6502285471560085B4CF /* IO80211SkywalkInterface.h in Headers */, + F84AD8C32A497DB200DC8DED /* CCLogStream.h in Headers */, F8AE6503285471560085B4CF /* AirportItlwm.hpp in Headers */, + F89F35F72A49867F00061876 /* IO80211ControllerV2.h in Headers */, F8AE6504285471560085B4CF /* IO80211VirtualInterface.h in Headers */, F8AE6505285471560085B4CF /* IO80211Controller.h in Headers */, F8AE6506285471560085B4CF /* (null) in Headers */, F8AE6507285471560085B4CF /* ieee80211_ra.h in Headers */, + F84AD8B52A497DB200DC8DED /* CCStream.h in Headers */, F8AE6508285471560085B4CF /* apple80211_wps.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; + F8B210AA2A2EC2680043ECBD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F84AD8BD2A497DB200DC8DED /* CCDataPipe.h in Headers */, + F8B210AB2A2EC2680043ECBD /* debug.h in Headers */, + F8B210AC2A2EC2680043ECBD /* IOSkywalkEthernetInterface.h in Headers */, + F84AD89A2A497DB200DC8DED /* IO80211InfraProtocol.h in Headers */, + F84AD8A82A497DB200DC8DED /* IOSkywalkLogicalLink.h in Headers */, + F8A028302A4A7E0500C6DE90 /* AirportItlwmEthernetInterface.hpp in Headers */, + F84AD8932A497DB200DC8DED /* IOSkywalkNetworkPacket.h in Headers */, + F8B210AD2A2EC2680043ECBD /* apple80211_ioctl.h in Headers */, + F84AD8D92A497DB200DC8DED /* CCLogPipe.h in Headers */, + F8B210AE2A2EC2680043ECBD /* IO80211P2PInterface.h in Headers */, + F84AD8A12A497DB200DC8DED /* CCPipe.h in Headers */, + F8B210AF2A2EC2680043ECBD /* IO80211WorkLoop.h in Headers */, + F8B210B02A2EC2680043ECBD /* apple80211_var.h in Headers */, + F84AD8CB2A497DB200DC8DED /* IOSkywalkPacketBufferPool.h in Headers */, + F84AD8D22A497DB200DC8DED /* IOSkywalkLegacyEthernetInterface.h in Headers */, + F8B210B12A2EC2680043ECBD /* AirportItlwmInterface.hpp in Headers */, + F8B210B22A2EC2680043ECBD /* IO80211Interface.h in Headers */, + F84AD88C2A497DB200DC8DED /* IO80211WorkQueue.h in Headers */, + F8B210B32A2EC2680043ECBD /* (null) in Headers */, + F84AD8AF2A497DB200DC8DED /* IO80211InfraInterface.h in Headers */, + F8B210B42A2EC2680043ECBD /* IO80211SkywalkInterface.h in Headers */, + F84AD8C42A497DB200DC8DED /* CCLogStream.h in Headers */, + F8A028732A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.hpp in Headers */, + F8B210B52A2EC2680043ECBD /* AirportItlwm.hpp in Headers */, + F89F35F82A49867F00061876 /* IO80211ControllerV2.h in Headers */, + F8A028802A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.hpp in Headers */, + F8B210B62A2EC2680043ECBD /* IO80211VirtualInterface.h in Headers */, + F8B210B72A2EC2680043ECBD /* IO80211Controller.h in Headers */, + F8B210B82A2EC2680043ECBD /* (null) in Headers */, + F8A028232A4A7DDC00C6DE90 /* AirportItlwmV2.hpp in Headers */, + F8B210B92A2EC2680043ECBD /* ieee80211_ra.h in Headers */, + F84AD8B62A497DB200DC8DED /* CCStream.h in Headers */, + F8B210BA2A2EC2680043ECBD /* apple80211_wps.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8D94C832B9ABFE20081A3C4 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F8D94C842B9ABFE20081A3C4 /* CCDataPipe.h in Headers */, + F8D94C852B9ABFE20081A3C4 /* debug.h in Headers */, + F8D94C862B9ABFE20081A3C4 /* IOSkywalkEthernetInterface.h in Headers */, + F8D94C872B9ABFE20081A3C4 /* IO80211InfraProtocol.h in Headers */, + F8D94C882B9ABFE20081A3C4 /* IOSkywalkLogicalLink.h in Headers */, + F8D94C892B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.hpp in Headers */, + F8D94C8A2B9ABFE20081A3C4 /* IOSkywalkNetworkPacket.h in Headers */, + F8D94C8B2B9ABFE20081A3C4 /* apple80211_ioctl.h in Headers */, + F8D94C8C2B9ABFE20081A3C4 /* CCLogPipe.h in Headers */, + F8D94C8D2B9ABFE20081A3C4 /* IO80211P2PInterface.h in Headers */, + F8D94C8E2B9ABFE20081A3C4 /* CCPipe.h in Headers */, + F8D94C8F2B9ABFE20081A3C4 /* IO80211WorkLoop.h in Headers */, + F8D94C902B9ABFE20081A3C4 /* apple80211_var.h in Headers */, + F8D94C912B9ABFE20081A3C4 /* IOSkywalkPacketBufferPool.h in Headers */, + F8D94C922B9ABFE20081A3C4 /* IOSkywalkLegacyEthernetInterface.h in Headers */, + F8D94C932B9ABFE20081A3C4 /* AirportItlwmInterface.hpp in Headers */, + F8D94C942B9ABFE20081A3C4 /* IO80211Interface.h in Headers */, + F8D94C952B9ABFE20081A3C4 /* IO80211WorkQueue.h in Headers */, + F8D94C962B9ABFE20081A3C4 /* (null) in Headers */, + F8D94C972B9ABFE20081A3C4 /* IO80211InfraInterface.h in Headers */, + F8D94C982B9ABFE20081A3C4 /* IO80211SkywalkInterface.h in Headers */, + F8D94C992B9ABFE20081A3C4 /* CCLogStream.h in Headers */, + F8D94C9A2B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.hpp in Headers */, + F8D94C9B2B9ABFE20081A3C4 /* AirportItlwm.hpp in Headers */, + F8D94C9C2B9ABFE20081A3C4 /* IO80211ControllerV2.h in Headers */, + F8D94C9D2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.hpp in Headers */, + F8D94C9E2B9ABFE20081A3C4 /* IO80211VirtualInterface.h in Headers */, + F8D94C9F2B9ABFE20081A3C4 /* IO80211Controller.h in Headers */, + F8D94CA02B9ABFE20081A3C4 /* (null) in Headers */, + F8D94CA12B9ABFE20081A3C4 /* AirportItlwmV2.hpp in Headers */, + F8D94CA22B9ABFE20081A3C4 /* ieee80211_ra.h in Headers */, + F8D94CA32B9ABFE20081A3C4 /* CCStream.h in Headers */, + F8D94CA42B9ABFE20081A3C4 /* apple80211_wps.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -1720,6 +2284,44 @@ productReference = F8AE6558285471560085B4CF /* AirportItlwm.kext */; productType = "com.apple.product-type.kernel-extension"; }; + F8B210A72A2EC2680043ECBD /* AirportItlwm-Sonoma14.0 */ = { + isa = PBXNativeTarget; + buildConfigurationList = F8B211072A2EC2680043ECBD /* Build configuration list for PBXNativeTarget "AirportItlwm-Sonoma14.0" */; + buildPhases = ( + F8B210AA2A2EC2680043ECBD /* Headers */, + F8B210BB2A2EC2680043ECBD /* Sources */, + F8B211042A2EC2680043ECBD /* Frameworks */, + F8B211062A2EC2680043ECBD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F8B210A82A2EC2680043ECBD /* PBXTargetDependency */, + ); + name = "AirportItlwm-Sonoma14.0"; + productName = AirportItlwm; + productReference = F8B2110A2A2EC2680043ECBD /* AirportItlwm.kext */; + productType = "com.apple.product-type.kernel-extension"; + }; + F8D94C802B9ABFE20081A3C4 /* AirportItlwm-Sonoma14.4 */ = { + isa = PBXNativeTarget; + buildConfigurationList = F8D94CF22B9ABFE20081A3C4 /* Build configuration list for PBXNativeTarget "AirportItlwm-Sonoma14.4" */; + buildPhases = ( + F8D94C832B9ABFE20081A3C4 /* Headers */, + F8D94CA52B9ABFE20081A3C4 /* Sources */, + F8D94CEF2B9ABFE20081A3C4 /* Frameworks */, + F8D94CF12B9ABFE20081A3C4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F8D94C812B9ABFE20081A3C4 /* PBXTargetDependency */, + ); + name = "AirportItlwm-Sonoma14.4"; + productName = AirportItlwm; + productReference = F8D94CF52B9ABFE20081A3C4 /* AirportItlwm.kext */; + productType = "com.apple.product-type.kernel-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1756,6 +2358,12 @@ F8AE64F5285471560085B4CF = { ProvisioningStyle = Manual; }; + F8B210A72A2EC2680043ECBD = { + ProvisioningStyle = Manual; + }; + F8D94C802B9ABFE20081A3C4 = { + ProvisioningStyle = Manual; + }; }; }; buildConfigurationList = 024A07A623FCBC3C009FBA6C /* Build configuration list for PBXProject "itlwm" */; @@ -1778,6 +2386,8 @@ 35CBE655251CB89700435CBC /* AirportItlwm-Big Sur */, F897ECB6266EFF93005EE8F7 /* AirportItlwm-Monterey */, F8AE64F5285471560085B4CF /* AirportItlwm-Ventura */, + F8B210A72A2EC2680043ECBD /* AirportItlwm-Sonoma14.0 */, + F8D94C802B9ABFE20081A3C4 /* AirportItlwm-Sonoma14.4 */, 5066D63825287F7900EE6F38 /* fw_gen */, ); }; @@ -1833,6 +2443,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F8B211062A2EC2680043ECBD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8D94CF12B9ABFE20081A3C4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -1903,6 +2527,7 @@ 024A08CE23FCE67F009FBA6C /* nvm.cpp in Sources */, 024A083D23FCBC6C009FBA6C /* sha1.c in Sources */, 17FD7F10255E4AC800611406 /* ItlIwn.cpp in Sources */, + A5DD111526D93B5F00BA01EF /* rs.cpp in Sources */, 024A085923FCBC6C009FBA6C /* idgen.c in Sources */, F8C2EC522408031A007A9422 /* ieee80211_ioctl.c in Sources */, F8C594D325FD935B0007D19C /* ieee80211_ra.c in Sources */, @@ -1921,6 +2546,7 @@ 024A085723FCBC6C009FBA6C /* gmac.c in Sources */, F8C2EC592408031A007A9422 /* ieee80211_mira.c in Sources */, 024A083223FCBC6C009FBA6C /* ecb3_enc.c in Sources */, + A5A0C5242A501E6800EF9328 /* arp.c in Sources */, 024A08D023FCEE88009FBA6C /* ctxt.cpp in Sources */, F8D76362244F21BB00DEA040 /* pm.cpp in Sources */, 024A08C023FCD4E2009FBA6C /* utils.cpp in Sources */, @@ -1971,6 +2597,7 @@ 35CBE68E251CB89700435CBC /* rijndael.c in Sources */, 35CBE68F251CB89700435CBC /* ecb3_enc.c in Sources */, 35CBE690251CB89700435CBC /* set_key.c in Sources */, + A5A0C5282A501E6800EF9328 /* arp.c in Sources */, 35CBE691251CB89700435CBC /* cast.c in Sources */, 35CBE692251CB89700435CBC /* michael.c in Sources */, 35CBE693251CB89700435CBC /* sha1.c in Sources */, @@ -1980,6 +2607,7 @@ 35CBE697251CB89700435CBC /* md5.c in Sources */, 35CBE698251CB89700435CBC /* arc4.c in Sources */, 35CBE699251CB89700435CBC /* blf.c in Sources */, + A5DD111926D93B5F00BA01EF /* rs.cpp in Sources */, 35CBE69A251CB89700435CBC /* poly1305.c in Sources */, 35CBE69B251CB89700435CBC /* key_wrap.c in Sources */, 35CBE69C251CB89700435CBC /* gmac.c in Sources */, @@ -2049,6 +2677,7 @@ 35CBE6F8251CB8BF00435CBC /* rijndael.c in Sources */, 35CBE6F9251CB8BF00435CBC /* ecb3_enc.c in Sources */, 35CBE6FA251CB8BF00435CBC /* set_key.c in Sources */, + A5A0C5262A501E6800EF9328 /* arp.c in Sources */, 35CBE6FB251CB8BF00435CBC /* cast.c in Sources */, 35CBE6FC251CB8BF00435CBC /* michael.c in Sources */, 35CBE6FD251CB8BF00435CBC /* sha1.c in Sources */, @@ -2058,6 +2687,7 @@ 35CBE701251CB8BF00435CBC /* md5.c in Sources */, 35CBE702251CB8BF00435CBC /* arc4.c in Sources */, 35CBE703251CB8BF00435CBC /* blf.c in Sources */, + A5DD111726D93B5F00BA01EF /* rs.cpp in Sources */, 35CBE704251CB8BF00435CBC /* poly1305.c in Sources */, 35CBE705251CB8BF00435CBC /* key_wrap.c in Sources */, 35CBE706251CB8BF00435CBC /* gmac.c in Sources */, @@ -2127,6 +2757,7 @@ 35CBE763251CB8CA00435CBC /* rijndael.c in Sources */, 35CBE764251CB8CA00435CBC /* ecb3_enc.c in Sources */, 35CBE765251CB8CA00435CBC /* set_key.c in Sources */, + A5A0C5252A501E6800EF9328 /* arp.c in Sources */, 35CBE766251CB8CA00435CBC /* cast.c in Sources */, 35CBE767251CB8CA00435CBC /* michael.c in Sources */, 35CBE768251CB8CA00435CBC /* sha1.c in Sources */, @@ -2136,6 +2767,7 @@ 35CBE76C251CB8CA00435CBC /* md5.c in Sources */, 35CBE76D251CB8CA00435CBC /* arc4.c in Sources */, 35CBE76E251CB8CA00435CBC /* blf.c in Sources */, + A5DD111626D93B5F00BA01EF /* rs.cpp in Sources */, 35CBE76F251CB8CA00435CBC /* poly1305.c in Sources */, 35CBE770251CB8CA00435CBC /* key_wrap.c in Sources */, 35CBE771251CB8CA00435CBC /* gmac.c in Sources */, @@ -2207,6 +2839,7 @@ F897ECEC266EFF93005EE8F7 /* cast.c in Sources */, F897ECED266EFF93005EE8F7 /* michael.c in Sources */, F897ECEE266EFF93005EE8F7 /* sha1.c in Sources */, + A5DD111A26D93B5F00BA01EF /* rs.cpp in Sources */, F897ECEF266EFF93005EE8F7 /* cmac.c in Sources */, F897ECF0266EFF93005EE8F7 /* ecb_enc.c in Sources */, F897ECF1266EFF93005EE8F7 /* chachapoly.c in Sources */, @@ -2239,6 +2872,7 @@ F897ED0A266EFF93005EE8F7 /* led.cpp in Sources */, F897ED0B266EFF93005EE8F7 /* power.cpp in Sources */, F897ED0C266EFF93005EE8F7 /* scan.cpp in Sources */, + A5A0C5292A501E6800EF9328 /* arp.c in Sources */, F897ED0D266EFF93005EE8F7 /* ItlIwm.cpp in Sources */, F897ED0E266EFF93005EE8F7 /* AirportSTAIOCTL.cpp in Sources */, F897ED0F266EFF93005EE8F7 /* AirportItlwm.cpp in Sources */, @@ -2284,6 +2918,7 @@ F89B6C0D250231E4000F77FF /* rijndael.c in Sources */, F89B6C0E250231E4000F77FF /* ecb3_enc.c in Sources */, F89B6C0F250231E4000F77FF /* set_key.c in Sources */, + A5A0C5272A501E6800EF9328 /* arp.c in Sources */, F89B6C10250231E4000F77FF /* cast.c in Sources */, F89B6C11250231E4000F77FF /* michael.c in Sources */, F89B6C12250231E4000F77FF /* sha1.c in Sources */, @@ -2293,6 +2928,7 @@ F89B6C16250231E4000F77FF /* md5.c in Sources */, F89B6C17250231E4000F77FF /* arc4.c in Sources */, F89B6C18250231E4000F77FF /* blf.c in Sources */, + A5DD111826D93B5F00BA01EF /* rs.cpp in Sources */, F89B6C19250231E4000F77FF /* poly1305.c in Sources */, F89B6C1A250231E4000F77FF /* key_wrap.c in Sources */, F89B6C1B250231E4000F77FF /* gmac.c in Sources */, @@ -2329,6 +2965,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F8876A4E28B71F5400A21E42 /* rs.cpp in Sources */, F8AE650A285471560085B4CF /* _mbuf.cpp in Sources */, F8AE650B285471560085B4CF /* ieee80211_ra.c in Sources */, F8AE650C285471560085B4CF /* _task.cpp in Sources */, @@ -2396,6 +3033,7 @@ F8AE654A285471560085B4CF /* led.cpp in Sources */, F8AE654B285471560085B4CF /* power.cpp in Sources */, F8AE654C285471560085B4CF /* scan.cpp in Sources */, + A5A0C52A2A501E6800EF9328 /* arp.c in Sources */, F8AE654D285471560085B4CF /* ItlIwm.cpp in Sources */, F8AE654E285471560085B4CF /* AirportSTAIOCTL.cpp in Sources */, F8AE654F285471560085B4CF /* AirportItlwm.cpp in Sources */, @@ -2404,6 +3042,166 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F8B210BB2A2EC2680043ECBD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F8F84F682ADE26F1002808DE /* rs.cpp in Sources */, + F8B210BC2A2EC2680043ECBD /* _mbuf.cpp in Sources */, + F8B210BD2A2EC2680043ECBD /* ieee80211_ra.c in Sources */, + F8B210BE2A2EC2680043ECBD /* _task.cpp in Sources */, + F8B210BF2A2EC2680043ECBD /* FwBinary.cpp in Sources */, + F8B210C02A2EC2680043ECBD /* ieee80211_proto.c in Sources */, + F8B210C22A2EC2680043ECBD /* _string.c in Sources */, + F8B210C32A2EC2680043ECBD /* ieee80211_ioctl.c in Sources */, + F8B210C42A2EC2680043ECBD /* ieee80211.c in Sources */, + F8B210C52A2EC2680043ECBD /* ieee80211_rssadapt.c in Sources */, + F8B210C62A2EC2680043ECBD /* ieee80211_input.c in Sources */, + F8B210C72A2EC2680043ECBD /* timeout.c in Sources */, + F8B210C82A2EC2680043ECBD /* ieee80211_mira.c in Sources */, + F8B210C92A2EC2680043ECBD /* ieee80211_crypto_bip.c in Sources */, + F8B210CA2A2EC2680043ECBD /* ieee80211_crypto_tkip.c in Sources */, + F8B210CB2A2EC2680043ECBD /* ieee80211_crypto_ccmp.c in Sources */, + F8B210CC2A2EC2680043ECBD /* ieee80211_crypto_wep.c in Sources */, + F8B210CD2A2EC2680043ECBD /* ieee80211_pae_input.c in Sources */, + F8B210CE2A2EC2680043ECBD /* ieee80211_amrr.c in Sources */, + F8B210CF2A2EC2680043ECBD /* ieee80211_output.c in Sources */, + F8B210D02A2EC2680043ECBD /* ieee80211_crypto.c in Sources */, + F8B210D12A2EC2680043ECBD /* CTimeout.cpp in Sources */, + F8B210D22A2EC2680043ECBD /* ieee80211_regdomain.c in Sources */, + F8B210D32A2EC2680043ECBD /* ieee80211_node.c in Sources */, + F8B210D42A2EC2680043ECBD /* ieee80211_pae_output.c in Sources */, + F8B210D52A2EC2680043ECBD /* sha1-pbkdf2.c in Sources */, + F8B210D62A2EC2680043ECBD /* aes.c in Sources */, + F8B210D72A2EC2680043ECBD /* hmac.c in Sources */, + F8B210D82A2EC2680043ECBD /* sha2.c in Sources */, + F8B210D92A2EC2680043ECBD /* rijndael.c in Sources */, + F8B210DA2A2EC2680043ECBD /* ecb3_enc.c in Sources */, + F8B210DB2A2EC2680043ECBD /* set_key.c in Sources */, + F8B210DC2A2EC2680043ECBD /* cast.c in Sources */, + F8B210DD2A2EC2680043ECBD /* michael.c in Sources */, + A5A0C52B2A501E6800EF9328 /* arp.c in Sources */, + F8B210DE2A2EC2680043ECBD /* sha1.c in Sources */, + F8B210DF2A2EC2680043ECBD /* cmac.c in Sources */, + F8B210E02A2EC2680043ECBD /* ecb_enc.c in Sources */, + F8B210E12A2EC2680043ECBD /* chachapoly.c in Sources */, + F8A028222A4A7DDC00C6DE90 /* AirportItlwmV2.cpp in Sources */, + F8B210E22A2EC2680043ECBD /* (null) in Sources */, + F8B210E32A2EC2680043ECBD /* md5.c in Sources */, + F8B210E42A2EC2680043ECBD /* arc4.c in Sources */, + F8A0282F2A4A7E0400C6DE90 /* AirportItlwmEthernetInterface.cpp in Sources */, + F8A028722A4A7FE100C6DE90 /* AirportItlwmSkywalkInterface.cpp in Sources */, + F8B210E52A2EC2680043ECBD /* blf.c in Sources */, + F8B210E62A2EC2680043ECBD /* _ifq.cpp in Sources */, + F8B210E72A2EC2680043ECBD /* poly1305.c in Sources */, + F8B210E82A2EC2680043ECBD /* key_wrap.c in Sources */, + F8B210E92A2EC2680043ECBD /* gmac.c in Sources */, + F8B210EA2A2EC2680043ECBD /* rmd160.c in Sources */, + F8B210EB2A2EC2680043ECBD /* idgen.c in Sources */, + F8B210EC2A2EC2680043ECBD /* compat.cpp in Sources */, + F8B210ED2A2EC2680043ECBD /* zutil.c in Sources */, + F8B210EE2A2EC2680043ECBD /* ItlHalService.cpp in Sources */, + F8B210EF2A2EC2680043ECBD /* ItlIwx.cpp in Sources */, + F8B210F02A2EC2680043ECBD /* utils.cpp in Sources */, + F8B210F12A2EC2680043ECBD /* fw.cpp in Sources */, + F8B210F22A2EC2680043ECBD /* io.cpp in Sources */, + F8B210F32A2EC2680043ECBD /* rx.cpp in Sources */, + F8B210F42A2EC2680043ECBD /* coex.cpp in Sources */, + F8B210F52A2EC2680043ECBD /* tx.cpp in Sources */, + F8B210F62A2EC2680043ECBD /* hw.cpp in Sources */, + F8B210F72A2EC2680043ECBD /* ItlIwn.cpp in Sources */, + F8B210F82A2EC2680043ECBD /* phy.cpp in Sources */, + F8B210F92A2EC2680043ECBD /* mac80211.cpp in Sources */, + F8B210FA2A2EC2680043ECBD /* nvm.cpp in Sources */, + F8B210FB2A2EC2680043ECBD /* ctxt.cpp in Sources */, + F8B210FC2A2EC2680043ECBD /* led.cpp in Sources */, + F8B210FD2A2EC2680043ECBD /* power.cpp in Sources */, + F8B210FE2A2EC2680043ECBD /* scan.cpp in Sources */, + F8A0287F2A4A80EA00C6DE90 /* IOPCIEDeviceWrapper.cpp in Sources */, + F8B210FF2A2EC2680043ECBD /* ItlIwm.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8D94CA52B9ABFE20081A3C4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F8D94CA62B9ABFE20081A3C4 /* rs.cpp in Sources */, + F8D94CA72B9ABFE20081A3C4 /* _mbuf.cpp in Sources */, + F8D94CA82B9ABFE20081A3C4 /* ieee80211_ra.c in Sources */, + F8D94CA92B9ABFE20081A3C4 /* _task.cpp in Sources */, + F8D94CAA2B9ABFE20081A3C4 /* FwBinary.cpp in Sources */, + F8D94CAB2B9ABFE20081A3C4 /* ieee80211_proto.c in Sources */, + F8D94CAC2B9ABFE20081A3C4 /* _string.c in Sources */, + F8D94CAD2B9ABFE20081A3C4 /* ieee80211_ioctl.c in Sources */, + F8D94CAE2B9ABFE20081A3C4 /* ieee80211.c in Sources */, + F8D94CAF2B9ABFE20081A3C4 /* ieee80211_rssadapt.c in Sources */, + F8D94CB02B9ABFE20081A3C4 /* ieee80211_input.c in Sources */, + F8D94CB12B9ABFE20081A3C4 /* timeout.c in Sources */, + F8D94CB22B9ABFE20081A3C4 /* ieee80211_mira.c in Sources */, + F8D94CB32B9ABFE20081A3C4 /* ieee80211_crypto_bip.c in Sources */, + F8D94CB42B9ABFE20081A3C4 /* ieee80211_crypto_tkip.c in Sources */, + F8D94CB52B9ABFE20081A3C4 /* ieee80211_crypto_ccmp.c in Sources */, + F8D94CB62B9ABFE20081A3C4 /* ieee80211_crypto_wep.c in Sources */, + F8D94CB72B9ABFE20081A3C4 /* ieee80211_pae_input.c in Sources */, + F8D94CB82B9ABFE20081A3C4 /* ieee80211_amrr.c in Sources */, + F8D94CB92B9ABFE20081A3C4 /* ieee80211_output.c in Sources */, + F8D94CBA2B9ABFE20081A3C4 /* ieee80211_crypto.c in Sources */, + F8D94CBB2B9ABFE20081A3C4 /* CTimeout.cpp in Sources */, + F8D94CBC2B9ABFE20081A3C4 /* ieee80211_regdomain.c in Sources */, + F8D94CBD2B9ABFE20081A3C4 /* ieee80211_node.c in Sources */, + F8D94CBE2B9ABFE20081A3C4 /* ieee80211_pae_output.c in Sources */, + F8D94CBF2B9ABFE20081A3C4 /* sha1-pbkdf2.c in Sources */, + F8D94CC02B9ABFE20081A3C4 /* aes.c in Sources */, + F8D94CC12B9ABFE20081A3C4 /* hmac.c in Sources */, + F8D94CC22B9ABFE20081A3C4 /* sha2.c in Sources */, + F8D94CC32B9ABFE20081A3C4 /* rijndael.c in Sources */, + F8D94CC42B9ABFE20081A3C4 /* ecb3_enc.c in Sources */, + F8D94CC52B9ABFE20081A3C4 /* set_key.c in Sources */, + F8D94CC62B9ABFE20081A3C4 /* cast.c in Sources */, + F8D94CC72B9ABFE20081A3C4 /* michael.c in Sources */, + F8D94CC82B9ABFE20081A3C4 /* arp.c in Sources */, + F8D94CC92B9ABFE20081A3C4 /* sha1.c in Sources */, + F8D94CCA2B9ABFE20081A3C4 /* cmac.c in Sources */, + F8D94CCB2B9ABFE20081A3C4 /* ecb_enc.c in Sources */, + F8D94CCC2B9ABFE20081A3C4 /* chachapoly.c in Sources */, + F8D94CCD2B9ABFE20081A3C4 /* AirportItlwmV2.cpp in Sources */, + F8D94CCE2B9ABFE20081A3C4 /* (null) in Sources */, + F8D94CCF2B9ABFE20081A3C4 /* md5.c in Sources */, + F8D94CD02B9ABFE20081A3C4 /* arc4.c in Sources */, + F8D94CD12B9ABFE20081A3C4 /* AirportItlwmEthernetInterface.cpp in Sources */, + F8D94CD22B9ABFE20081A3C4 /* AirportItlwmSkywalkInterface.cpp in Sources */, + F8D94CD32B9ABFE20081A3C4 /* blf.c in Sources */, + F8D94CD42B9ABFE20081A3C4 /* _ifq.cpp in Sources */, + F8D94CD52B9ABFE20081A3C4 /* poly1305.c in Sources */, + F8D94CD62B9ABFE20081A3C4 /* key_wrap.c in Sources */, + F8D94CD72B9ABFE20081A3C4 /* gmac.c in Sources */, + F8D94CD82B9ABFE20081A3C4 /* rmd160.c in Sources */, + F8D94CD92B9ABFE20081A3C4 /* idgen.c in Sources */, + F8D94CDA2B9ABFE20081A3C4 /* compat.cpp in Sources */, + F8D94CDB2B9ABFE20081A3C4 /* zutil.c in Sources */, + F8D94CDC2B9ABFE20081A3C4 /* ItlHalService.cpp in Sources */, + F8D94CDD2B9ABFE20081A3C4 /* ItlIwx.cpp in Sources */, + F8D94CDE2B9ABFE20081A3C4 /* utils.cpp in Sources */, + F8D94CDF2B9ABFE20081A3C4 /* fw.cpp in Sources */, + F8D94CE02B9ABFE20081A3C4 /* io.cpp in Sources */, + F8D94CE12B9ABFE20081A3C4 /* rx.cpp in Sources */, + F8D94CE22B9ABFE20081A3C4 /* coex.cpp in Sources */, + F8D94CE32B9ABFE20081A3C4 /* tx.cpp in Sources */, + F8D94CE42B9ABFE20081A3C4 /* hw.cpp in Sources */, + F8D94CE52B9ABFE20081A3C4 /* ItlIwn.cpp in Sources */, + F8D94CE62B9ABFE20081A3C4 /* phy.cpp in Sources */, + F8D94CE72B9ABFE20081A3C4 /* mac80211.cpp in Sources */, + F8D94CE82B9ABFE20081A3C4 /* nvm.cpp in Sources */, + F8D94CE92B9ABFE20081A3C4 /* ctxt.cpp in Sources */, + F8D94CEA2B9ABFE20081A3C4 /* led.cpp in Sources */, + F8D94CEB2B9ABFE20081A3C4 /* power.cpp in Sources */, + F8D94CEC2B9ABFE20081A3C4 /* scan.cpp in Sources */, + F8D94CED2B9ABFE20081A3C4 /* IOPCIEDeviceWrapper.cpp in Sources */, + F8D94CEE2B9ABFE20081A3C4 /* ItlIwm.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -2442,6 +3240,16 @@ target = 5066D63825287F7900EE6F38 /* fw_gen */; targetProxy = F8AE64F7285471560085B4CF /* PBXContainerItemProxy */; }; + F8B210A82A2EC2680043ECBD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5066D63825287F7900EE6F38 /* fw_gen */; + targetProxy = F8B210A92A2EC2680043ECBD /* PBXContainerItemProxy */; + }; + F8D94C812B9ABFE20081A3C4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5066D63825287F7900EE6F38 /* fw_gen */; + targetProxy = F8D94C822B9ABFE20081A3C4 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -2505,7 +3313,7 @@ KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; MACOSX_DEPLOYMENT_TARGET = 10.12; - MODULE_VERSION = 2.3.0; + MODULE_VERSION = 2.4.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_CPLUSPLUSFLAGS = ( @@ -2557,6 +3365,7 @@ GCC_C_LANGUAGE_STANDARD = c11; GCC_INPUT_FILETYPE = sourcecode.cpp.cpp; GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 1; GCC_PREPROCESSOR_DEFINITIONS = ( "ITLWM_VERSION=\\\"${MODULE_VERSION}\\\"", "GIT_COMMIT=\\\"${GIT_COMMIT}\\\"", @@ -2572,7 +3381,7 @@ KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; MACOSX_DEPLOYMENT_TARGET = 10.12; - MODULE_VERSION = 2.3.0; + MODULE_VERSION = 2.4.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_CPLUSPLUSFLAGS = ( @@ -3021,6 +3830,132 @@ }; name = Release; }; + F8B211082A2EC2680043ECBD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(SYMROOT)/$(CONFIGURATION)/Sonoma14.0"; + CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = itlwm/PrivateSPI.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + AIRPORT, + "__IO80211_TARGET=__MAC_14_0", + __PRIVATE_SPI__, + IO80211FAMILY_V2, + ); + INFOPLIST_FILE = "AirportItlwm/AirportItlwm-Sonoma-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(PROJECT_DIR)/itl80211", + "$(inherited)", + "$(PROJECT_DIR)/itl80211/openbsd", + "$(PROJECT_DIR)/itl80211/linux", + "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + MODULE_NAME = com.zxystd.AirportItlwm; + PRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm; + PRODUCT_NAME = AirportItlwm; + SYSTEM_HEADER_SEARCH_PATHS = "itl80211/openbsd itl80211 include"; + WRAPPER_EXTENSION = kext; + }; + name = Debug; + }; + F8B211092A2EC2680043ECBD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(SYMROOT)/$(CONFIGURATION)/Sonoma14.0"; + CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = itlwm/PrivateSPI.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__IO80211_TARGET=__MAC_14_0", + AIRPORT, + __PRIVATE_SPI__, + "$(inherited)", + IO80211FAMILY_V2, + ); + INFOPLIST_FILE = "AirportItlwm/AirportItlwm-Sonoma-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(PROJECT_DIR)/itl80211", + "$(inherited)", + "$(PROJECT_DIR)/itl80211/openbsd", + "$(PROJECT_DIR)/itl80211/linux", + "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + MODULE_NAME = com.zxystd.AirportItlwm; + PRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm; + PRODUCT_NAME = AirportItlwm; + SYSTEM_HEADER_SEARCH_PATHS = "itl80211/openbsd itl80211 include"; + WRAPPER_EXTENSION = kext; + }; + name = Release; + }; + F8D94CF32B9ABFE20081A3C4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(SYMROOT)/$(CONFIGURATION)/Sonoma14.4"; + CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = itlwm/PrivateSPI.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + AIRPORT, + "__IO80211_TARGET=__MAC_14_4", + __PRIVATE_SPI__, + IO80211FAMILY_V2, + ); + INFOPLIST_FILE = "AirportItlwm/AirportItlwm-Sonoma-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(PROJECT_DIR)/itl80211", + "$(inherited)", + "$(PROJECT_DIR)/itl80211/openbsd", + "$(PROJECT_DIR)/itl80211/linux", + "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + MODULE_NAME = com.zxystd.AirportItlwm; + PRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm; + PRODUCT_MODULE_NAME = AirportItlwm; + PRODUCT_NAME = AirportItlwm; + SYSTEM_HEADER_SEARCH_PATHS = "itl80211/openbsd itl80211 include"; + WRAPPER_EXTENSION = kext; + }; + name = Debug; + }; + F8D94CF42B9ABFE20081A3C4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CONFIGURATION_BUILD_DIR = "$(SYMROOT)/$(CONFIGURATION)/Sonoma14.4"; + CURRENT_PROJECT_VERSION = "$(MODULE_VERSION)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = itlwm/PrivateSPI.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__IO80211_TARGET=__MAC_14_4", + AIRPORT, + __PRIVATE_SPI__, + "$(inherited)", + IO80211FAMILY_V2, + ); + INFOPLIST_FILE = "AirportItlwm/AirportItlwm-Sonoma-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(PROJECT_DIR)/itl80211", + "$(inherited)", + "$(PROJECT_DIR)/itl80211/openbsd", + "$(PROJECT_DIR)/itl80211/linux", + "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", + ); + MACOSX_DEPLOYMENT_TARGET = 10.15; + MODULE_NAME = com.zxystd.AirportItlwm; + PRODUCT_BUNDLE_IDENTIFIER = com.zxystd.AirportItlwm; + PRODUCT_MODULE_NAME = AirportItlwm; + PRODUCT_NAME = AirportItlwm; + SYSTEM_HEADER_SEARCH_PATHS = "itl80211/openbsd itl80211 include"; + WRAPPER_EXTENSION = kext; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -3105,6 +4040,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F8B211072A2EC2680043ECBD /* Build configuration list for PBXNativeTarget "AirportItlwm-Sonoma14.0" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F8B211082A2EC2680043ECBD /* Debug */, + F8B211092A2EC2680043ECBD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F8D94CF22B9ABFE20081A3C4 /* Build configuration list for PBXNativeTarget "AirportItlwm-Sonoma14.4" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F8D94CF32B9ABFE20081A3C4 /* Debug */, + F8D94CF42B9ABFE20081A3C4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 024A07A323FCBC3C009FBA6C /* Project object */; diff --git a/itlwm.xcodeproj/xcshareddata/xcschemes/AirportItlwm (all).xcscheme b/itlwm.xcodeproj/xcshareddata/xcschemes/AirportItlwm (all).xcscheme index 11aec955d..ce7faac36 100644 --- a/itlwm.xcodeproj/xcshareddata/xcschemes/AirportItlwm (all).xcscheme +++ b/itlwm.xcodeproj/xcshareddata/xcschemes/AirportItlwm (all).xcscheme @@ -90,6 +90,34 @@ ReferencedContainer = "container:itlwm.xcodeproj"> + + + + + + + + txq); txq_i++) iwm_free_tx_ring(sc, &sc->txq[txq_i]); + iwm_rs_free(sc); iwm_free_rx_ring(sc, &sc->rxq); iwm_dma_contig_free(&sc->ict_dma); iwm_dma_contig_free(&sc->kw_dma); @@ -106,6 +107,10 @@ IOReturn ItlIwm:: disable(IONetworkInterface *netif) { struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if; + if (!(ifp->if_flags & IFF_UP)) { + XYLog("%s already in diactivating state\n", __FUNCTION__); + return kIOReturnSuccess; + } ifp->if_flags &= ~IFF_UP; iwm_activate(&com, DVACT_QUIESCE); return kIOReturnSuccess; diff --git a/itlwm/hal_iwm/ItlIwm.hpp b/itlwm/hal_iwm/ItlIwm.hpp index cdc2bc3d8..082a6d883 100644 --- a/itlwm/hal_iwm/ItlIwm.hpp +++ b/itlwm/hal_iwm/ItlIwm.hpp @@ -84,22 +84,25 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { int iwm_send_bt_init_conf(struct iwm_softc *); //fw - uint8_t iwm_fw_valid_tx_ant(struct iwm_softc *sc); - uint8_t iwm_fw_valid_rx_ant(struct iwm_softc *sc); + static uint8_t iwm_fw_valid_tx_ant(struct iwm_softc *sc); + static uint8_t iwm_fw_valid_rx_ant(struct iwm_softc *sc); void iwm_toggle_tx_ant(struct iwm_softc *sc, uint8_t *ant); + uint32_t iwm_get_tx_ant(struct iwm_softc *sc, struct ieee80211_node *ni, + int type, struct ieee80211_frame *wh); //scan uint8_t iwm_umac_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_channel_cfg_umac *chan, int n_ssids, int bgscan); //coex - uint16_t iwm_coex_agg_time_limit(struct iwm_softc *); + uint16_t iwm_coex_agg_time_limit(struct iwm_softc *, struct ieee80211_node *); uint8_t iwm_coex_tx_prio(struct iwm_softc *, struct ieee80211_frame *, uint8_t); + static bool iwm_coex_is_ant_avail(struct iwm_softc *, u8); + static bool iwm_coex_is_mimo_allowed(struct iwm_softc *, struct ieee80211_node *); + static bool iwm_coex_is_tpc_allowed(struct iwm_softc *, bool); + static bool iwm_coex_is_shared_ant_avail(struct iwm_softc *); uint8_t iwm_lookup_cmd_ver(struct iwm_softc *, uint8_t, uint8_t); - int iwm_is_mimo_ht_plcp(uint8_t); - int iwm_is_mimo_vht_plcp(uint8_t); - int iwm_is_mimo_mcs(int); int iwm_store_cscheme(struct iwm_softc *, uint8_t *, size_t); int iwm_firmware_store_section(struct iwm_softc *, enum iwm_ucode_type, uint8_t *, size_t); @@ -206,6 +209,7 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { uint8_t); static void iwm_rx_ba_session_expired(void *); static void iwm_reorder_timer_expired(void *); + static uint8_t iwm_num_of_ant(uint8_t mask); int iwm_sta_rx_agg(struct iwm_softc *, struct ieee80211_node *, uint8_t, uint16_t, uint16_t, int, int); static int iwm_ampdu_tx_start(struct ieee80211com *, struct ieee80211_node *, @@ -242,8 +246,8 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { int iwm_run_init_mvm_ucode(struct iwm_softc *, int); int iwm_config_ltr(struct iwm_softc *); int iwm_rx_addbuf(struct iwm_softc *, int, int); - int iwm_get_signal_strength(struct iwm_softc *, struct iwm_rx_phy_info *); - int iwm_rxmq_get_signal_strength(struct iwm_softc *, struct iwm_rx_mpdu_desc *); + int iwm_get_signal_strength(struct iwm_softc *, struct ieee80211_rx_status *, struct iwm_rx_phy_info *); + int iwm_rxmq_get_signal_strength(struct iwm_softc *, struct ieee80211_rx_status *, uint32_t, struct iwm_rx_mpdu_desc *); void iwm_rx_rx_phy_cmd(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_rx_data *); int iwm_get_noise(const struct iwm_statistics_rx_non_phy *); @@ -254,16 +258,14 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { void iwm_rx_frame(struct iwm_softc *, mbuf_t, int, uint32_t, int, int, uint32_t, struct ieee80211_rxinfo *, struct mbuf_list *); void iwm_rx_tx_cmd_single(struct iwm_softc *, struct iwm_tx_resp *, - struct iwm_node *, int, int, int); + int, int); void iwm_ampdu_tx_done(struct iwm_softc *, struct iwm_cmd_header *, struct iwm_node *, struct iwm_tx_ring *, uint32_t, uint8_t, uint8_t, uint16_t, int, struct iwm_agg_tx_status *); void iwm_rx_tx_ba_notif(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_rx_data *); void iwm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_rx_data *); - void iwm_ampdu_rate_control(struct iwm_softc *, struct ieee80211_node *, struct iwm_tx_ring *, uint16_t, uint16_t); - void iwm_ht_single_rate_control(struct iwm_softc *, struct ieee80211_node *, - uint8_t, uint8_t, uint8_t, int); + void iwm_ampdu_rate_control(struct iwm_softc *, struct ieee80211_node *, struct iwm_tx_ring *, uint16_t, uint16_t, struct ieee80211_tx_info *, int, uint32_t); void iwm_rx_mpdu_mq(struct iwm_softc *sc, mbuf_t m, void *pktdata, size_t maxlen, struct mbuf_list *ml); void iwm_rx_bmiss(struct iwm_softc *, struct iwm_rx_packet *, @@ -288,12 +290,11 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { void iwm_cmd_done(struct iwm_softc *, int, int, int); void iwm_update_sched(struct iwm_softc *, int, int, uint8_t, uint16_t); void iwm_reset_sched(struct iwm_softc *, int, int, uint8_t); - const struct iwm_rate *iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *, + const struct iwl_rs_rate_info *iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *, struct ieee80211_frame *, struct iwm_tx_cmd *); void iwm_txd_done(struct iwm_softc *, struct iwm_tx_data *); void iwm_ampdu_txq_advance(struct iwm_softc *, struct iwm_tx_ring *, int); void iwm_clear_oactive(struct iwm_softc *, struct iwm_tx_ring *); - void iwm_ra_choose(struct iwm_softc *, struct ieee80211_node *); int iwm_tx(struct iwm_softc *, mbuf_t, struct ieee80211_node *, int); int iwm_flush_tx_path(struct iwm_softc *, int); void iwm_led_enable(struct iwm_softc *); @@ -331,7 +332,6 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { int iwm_umac_scan(struct iwm_softc *, int); void iwm_mcc_update(struct iwm_softc *, struct iwm_mcc_chub_notif *); uint8_t iwm_ridx2rate(struct ieee80211_rateset *, int); - int iwm_rval2ridx(int); void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *); void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *, struct iwm_mac_ctx_cmd *, uint32_t); @@ -362,7 +362,6 @@ class ItlIwm : public ItlHalService, ItlDriverInfo, ItlDriverController { static void iwm_delete_key(struct ieee80211com *, struct ieee80211_node *, struct ieee80211_key *); static void iwm_calib_timeout(void *); - void iwm_setrates(struct iwm_node *, int); int iwm_media_change(struct _ifnet *); static void iwm_newstate_task(void *); static int iwm_newstate(struct ieee80211com *, enum ieee80211_state, int); diff --git a/itlwm/hal_iwm/coex.cpp b/itlwm/hal_iwm/coex.cpp index d70b69f8c..6857dcc12 100644 --- a/itlwm/hal_iwm/coex.cpp +++ b/itlwm/hal_iwm/coex.cpp @@ -23,7 +23,7 @@ #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) uint16_t ItlIwm:: -iwm_coex_agg_time_limit(struct iwm_softc *sc) +iwm_coex_agg_time_limit(struct iwm_softc *sc, struct ieee80211_node *ni) { return LINK_QUAL_AGG_TIME_LIMIT_DEF; } @@ -69,3 +69,76 @@ iwm_coex_tx_prio(struct iwm_softc *sc, struct ieee80211_frame *wh, uint8_t ac) return 0; } + +bool ItlIwm:: +iwm_coex_is_ant_avail(struct iwm_softc *sc, u8 ant) +{ +#if 0 + /* there is no other antenna, shared antenna is always available */ + if (mvm->cfg->bt_shared_single_ant) + return true; +#endif + + if (ant & sc->non_shared_ant) + return true; + +#ifdef notyet_coex + return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < + BT_HIGH_TRAFFIC; +#else + return true; +#endif +} + +bool ItlIwm:: +iwm_coex_is_mimo_allowed(struct iwm_softc *sc, struct ieee80211_node *ni) +{ +#ifdef notyet_coex + struct iwm_node *in = (struct iwm_node *)ni; + struct iwm_phy_ctxt *phy_ctxt = in->in_phyctxt; + enum iwl_bt_coex_lut_type lut_type; + + if (sc->last_bt_notif.ttc_status & BIT(phy_ctxt->id)) + return true; + + if (le32_to_cpu(sc->last_bt_notif.bt_activity_grading) < + BT_HIGH_TRAFFIC) + return true; + + /* + * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas + * since BT is already killed. + * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while + * we Tx. + * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO. + */ + lut_type = iwl_get_coex_type(mvm, mvmsta->vif); + return lut_type != BT_COEX_LOOSE_LUT; +#else + return true; +#endif +} + +bool ItlIwm:: +iwm_coex_is_tpc_allowed(struct iwm_softc *mvm, bool is5G) +{ + if (is5G) + return false; + +#ifdef notyet_coex + return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= BT_LOW_TRAFFIC; +#else + return false; +#endif +} + +bool ItlIwm:: +iwm_coex_is_shared_ant_avail(struct iwm_softc *mvm) +{ +#ifdef notyet_coex + return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC; +#else + return mvm->sc_device_family == IWM_DEVICE_FAMILY_9000 && + (iwm_fw_valid_tx_ant(mvm) & IWM_ANT_B); +#endif +} diff --git a/itlwm/hal_iwm/fw.cpp b/itlwm/hal_iwm/fw.cpp index 5afa852ce..141a5a222 100644 --- a/itlwm/hal_iwm/fw.cpp +++ b/itlwm/hal_iwm/fw.cpp @@ -120,6 +120,7 @@ */ #include "ItlIwm.hpp" +#include "rs.h" #include uint8_t ItlIwm:: @@ -137,28 +138,6 @@ iwm_lookup_cmd_ver(struct iwm_softc *sc, uint8_t grp, uint8_t cmd) return IWM_FW_CMD_VER_UNKNOWN; } -int ItlIwm:: -iwm_is_mimo_ht_plcp(uint8_t ht_plcp) -{ - return (ht_plcp != IWM_RATE_HT_SISO_MCS_INV_PLCP && - (ht_plcp & IWM_RATE_HT_MCS_NSS_MSK)); -} - -int ItlIwm:: -iwm_is_mimo_vht_plcp(uint8_t ht_plcp) -{ - return (ht_plcp != IWM_RATE_VHT_SISO_MCS_INV_PLCP && - (ht_plcp & IWM_RATE_VHT_MCS_NSS_MSK)); -} - -int ItlIwm:: -iwm_is_mimo_mcs(int mcs) -{ - int ridx = iwm_mcs2ridx[mcs]; - return iwm_is_mimo_ht_plcp(iwm_rates[ridx].ht_plcp); - -} - int ItlIwm:: iwm_store_cscheme(struct iwm_softc *sc, uint8_t *data, size_t dlen) { @@ -746,6 +725,20 @@ iwm_fw_valid_rx_ant(struct iwm_softc *sc) return rx_ant; } +uint32_t ItlIwm:: +iwm_get_tx_ant(struct iwm_softc *sc, struct ieee80211_node *ni, + int type, struct ieee80211_frame *wh) +{ + if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) && + !ItlIwm::iwm_coex_is_shared_ant_avail(sc)) + return sc->non_shared_ant << RATE_MCS_ANT_POS; + + if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && type == IEEE80211_FC0_TYPE_DATA) + return ((1 << sc->sc_tx_ant) << RATE_MCS_ANT_POS); + + return ((1 << sc->sc_mgmt_last_antenna_idx) << RATE_MCS_ANT_POS); +} + void ItlIwm:: iwm_toggle_tx_ant(struct iwm_softc *sc, uint8_t *ant) { diff --git a/itlwm/hal_iwm/if_iwmreg.h b/itlwm/hal_iwm/if_iwmreg.h index 170aba648..cdddd973c 100644 --- a/itlwm/hal_iwm/if_iwmreg.h +++ b/itlwm/hal_iwm/if_iwmreg.h @@ -933,6 +933,7 @@ enum iwm_msix_ivar_for_cause { #define IWM_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT 39 #define IWM_UCODE_TLV_CAPA_CDB_SUPPORT 40 #define IWM_UCODE_TLV_CAPA_DYNAMIC_QUOTA 44 +#define IWM_UCODE_TLV_CAPA_COEX_SCHEMA_2 45 #define IWM_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS 48 #define IWM_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE 64 #define IWM_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS 65 @@ -4398,232 +4399,6 @@ struct iwm_beacon_filter_cmd { .bf_escape_timer = htole32(IWM_BF_ESCAPE_TIMER_DEFAULT), \ .ba_escape_timer = htole32(IWM_BA_ESCAPE_TIMER_DEFAULT) -/* uCode API values for HT/VHT bit rates */ -#define IWM_RATE_HT_SISO_MCS_0_PLCP 0 -#define IWM_RATE_HT_SISO_MCS_1_PLCP 1 -#define IWM_RATE_HT_SISO_MCS_2_PLCP 2 -#define IWM_RATE_HT_SISO_MCS_3_PLCP 3 -#define IWM_RATE_HT_SISO_MCS_4_PLCP 4 -#define IWM_RATE_HT_SISO_MCS_5_PLCP 5 -#define IWM_RATE_HT_SISO_MCS_6_PLCP 6 -#define IWM_RATE_HT_SISO_MCS_7_PLCP 7 -#define IWM_RATE_HT_MIMO2_MCS_8_PLCP 0x8 -#define IWM_RATE_HT_MIMO2_MCS_9_PLCP 0x9 -#define IWM_RATE_HT_MIMO2_MCS_10_PLCP 0xA -#define IWM_RATE_HT_MIMO2_MCS_11_PLCP 0xB -#define IWM_RATE_HT_MIMO2_MCS_12_PLCP 0xC -#define IWM_RATE_HT_MIMO2_MCS_13_PLCP 0xD -#define IWM_RATE_HT_MIMO2_MCS_14_PLCP 0xE -#define IWM_RATE_HT_MIMO2_MCS_15_PLCP 0xF -#define IWM_RATE_VHT_SISO_MCS_0_PLCP 0 -#define IWM_RATE_VHT_SISO_MCS_1_PLCP 1 -#define IWM_RATE_VHT_SISO_MCS_2_PLCP 2 -#define IWM_RATE_VHT_SISO_MCS_3_PLCP 3 -#define IWM_RATE_VHT_SISO_MCS_4_PLCP 4 -#define IWM_RATE_VHT_SISO_MCS_5_PLCP 5 -#define IWM_RATE_VHT_SISO_MCS_6_PLCP 6 -#define IWM_RATE_VHT_SISO_MCS_7_PLCP 7 -#define IWM_RATE_VHT_SISO_MCS_8_PLCP 8 -#define IWM_RATE_VHT_SISO_MCS_9_PLCP 9 -#define IWM_RATE_VHT_MIMO2_MCS_0_PLCP 0x10 -#define IWM_RATE_VHT_MIMO2_MCS_1_PLCP 0x11 -#define IWM_RATE_VHT_MIMO2_MCS_2_PLCP 0x12 -#define IWM_RATE_VHT_MIMO2_MCS_3_PLCP 0x13 -#define IWM_RATE_VHT_MIMO2_MCS_4_PLCP 0x14 -#define IWM_RATE_VHT_MIMO2_MCS_5_PLCP 0x15 -#define IWM_RATE_VHT_MIMO2_MCS_6_PLCP 0x16 -#define IWM_RATE_VHT_MIMO2_MCS_7_PLCP 0x17 -#define IWM_RATE_VHT_MIMO2_MCS_8_PLCP 0x18 -#define IWM_RATE_VHT_MIMO2_MCS_9_PLCP 0x19 -#define IWM_RATE_HT_SISO_MCS_INV_PLCP 0x1A -#define IWM_RATE_HT_MIMO2_MCS_INV_PLCP IWM_RATE_HT_SISO_MCS_INV_PLCP -#define IWM_RATE_VHT_SISO_MCS_INV_PLCP IWM_RATE_HT_SISO_MCS_INV_PLCP -#define IWM_RATE_VHT_MIMO2_MCS_INV_PLCP IWM_RATE_HT_SISO_MCS_INV_PLCP -#define IWM_RATE_HT_SISO_MCS_8_PLCP IWM_RATE_HT_SISO_MCS_INV_PLCP -#define IWM_RATE_HT_SISO_MCS_9_PLCP IWM_RATE_HT_SISO_MCS_INV_PLCP - -/* - * These serve as indexes into struct iwm_rate iwm_rates[IWM_RIDX_MAX]. - */ -enum { - IWM_RATE_1M_INDEX = 0, - IWM_FIRST_CCK_RATE = IWM_RATE_1M_INDEX, - IWM_RATE_2M_INDEX, - IWM_RATE_5M_INDEX, - IWM_RATE_11M_INDEX, - IWM_LAST_CCK_RATE = IWM_RATE_11M_INDEX, - IWM_RATE_6M_INDEX, - IWM_FIRST_OFDM_RATE = IWM_RATE_6M_INDEX, - IWM_RATE_MCS_0_INDEX = IWM_RATE_6M_INDEX, - IWM_FIRST_HT_RATE = IWM_RATE_MCS_0_INDEX, - IWM_FIRST_VHT_RATE = IWM_RATE_MCS_0_INDEX, - IWM_RATE_9M_INDEX, - IWM_RATE_12M_INDEX, - IWM_RATE_MCS_1_INDEX = IWM_RATE_12M_INDEX, - IWM_RATE_MCS_8_INDEX, - IWM_FIRST_HT_MIMO2_RATE = IWM_RATE_MCS_8_INDEX, - IWM_RATE_18M_INDEX, - IWM_RATE_MCS_2_INDEX = IWM_RATE_18M_INDEX, - IWM_RATE_24M_INDEX, - IWM_RATE_MCS_3_INDEX = IWM_RATE_24M_INDEX, - IWM_RATE_MCS_9_INDEX, - IWM_RATE_36M_INDEX, - IWM_RATE_MCS_4_INDEX = IWM_RATE_36M_INDEX, - IWM_RATE_MCS_10_INDEX, - IWM_RATE_48M_INDEX, - IWM_RATE_MCS_5_INDEX = IWM_RATE_48M_INDEX, - IWM_RATE_MCS_11_INDEX, - IWM_RATE_54M_INDEX, - IWM_RATE_MCS_6_INDEX = IWM_RATE_54M_INDEX, - IWM_LAST_NON_HT_RATE = IWM_RATE_54M_INDEX, - IWM_RATE_MCS_7_INDEX, - IWM_LAST_HT_SISO_RATE = IWM_RATE_MCS_7_INDEX, - IWM_RATE_MCS_12_INDEX, - IWM_RATE_MCS_13_INDEX, - IWM_RATE_MCS_14_INDEX, - IWM_RATE_MCS_15_INDEX, - IWM_LAST_VHT_SISO_RATE = IWM_RATE_MCS_13_INDEX, - IWM_LAST_HT_RATE = IWM_RATE_MCS_15_INDEX, - IWM_LAST_VHT_RATE = IWM_RATE_MCS_15_INDEX + 3, - IWM_RATE_COUNT_LEGACY = IWM_LAST_NON_HT_RATE + 1, - IWM_RATE_COUNT = IWM_LAST_VHT_RATE + 1, -}; - -#define IWM_RATE_BIT_MSK(r) (1 << (IWM_RATE_##r##M_INDEX)) - -/* fw API values for legacy bit rates, both OFDM and CCK */ -#define IWM_RATE_6M_PLCP 13 -#define IWM_RATE_9M_PLCP 15 -#define IWM_RATE_12M_PLCP 5 -#define IWM_RATE_18M_PLCP 7 -#define IWM_RATE_24M_PLCP 9 -#define IWM_RATE_36M_PLCP 11 -#define IWM_RATE_48M_PLCP 1 -#define IWM_RATE_54M_PLCP 3 -#define IWM_RATE_1M_PLCP 10 -#define IWM_RATE_2M_PLCP 20 -#define IWM_RATE_5M_PLCP 55 -#define IWM_RATE_11M_PLCP 110 -#define IWM_RATE_INVM_PLCP 0xff - -/* - * rate_n_flags bit fields - * - * The 32-bit value has different layouts in the low 8 bites depending on the - * format. There are three formats, HT, VHT and legacy (11abg, with subformats - * for CCK and OFDM). - * - * High-throughput (HT) rate format - * bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM) - * Very High-throughput (VHT) rate format - * bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM) - * Legacy OFDM rate format for bits 7:0 - * bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM) - * Legacy CCK rate format for bits 7:0: - * bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK) - */ - -/* Bit 8: (1) HT format, (0) legacy or VHT format */ -#define IWM_RATE_MCS_HT_POS 8 -#define IWM_RATE_MCS_HT_MSK (1 << IWM_RATE_MCS_HT_POS) - -/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ -#define IWM_RATE_MCS_CCK_POS 9 -#define IWM_RATE_MCS_CCK_MSK (1 << IWM_RATE_MCS_CCK_POS) - -/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */ -#define IWM_RATE_MCS_VHT_POS 26 -#define IWM_RATE_MCS_VHT_MSK (1 << IWM_RATE_MCS_VHT_POS) - - -/* - * High-throughput (HT) rate format for bits 7:0 - * - * 2-0: MCS rate base - * 0) 6 Mbps - * 1) 12 Mbps - * 2) 18 Mbps - * 3) 24 Mbps - * 4) 36 Mbps - * 5) 48 Mbps - * 6) 54 Mbps - * 7) 60 Mbps - * 4-3: 0) Single stream (SISO) - * 1) Dual stream (MIMO) - * 2) Triple stream (MIMO) - * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data - * (bits 7-6 are zero) - * - * Together the low 5 bits work out to the MCS index because we don't - * support MCSes above 15/23, and 0-7 have one stream, 8-15 have two - * streams and 16-23 have three streams. We could also support MCS 32 - * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) - */ -#define IWM_RATE_HT_MCS_RATE_CODE_MSK 0x7 -#define IWM_RATE_HT_MCS_NSS_POS 3 -#define IWM_RATE_HT_MCS_NSS_MSK (3 << IWM_RATE_HT_MCS_NSS_POS) - -/* Bit 10: (1) Use Green Field preamble */ -#define IWM_RATE_HT_MCS_GF_POS 10 -#define IWM_RATE_HT_MCS_GF_MSK (1 << IWM_RATE_HT_MCS_GF_POS) - -#define IWM_RATE_HT_MCS_INDEX_MSK 0x3f - -/* - * Very High-throughput (VHT) rate format for bits 7:0 - * - * 3-0: VHT MCS (0-9) - * 5-4: number of streams - 1: - * 0) Single stream (SISO) - * 1) Dual stream (MIMO) - * 2) Triple stream (MIMO) - */ - -/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */ -#define IWM_RATE_VHT_MCS_RATE_CODE_MSK 0xf -#define IWM_RATE_VHT_MCS_NSS_POS 4 -#define IWM_RATE_VHT_MCS_NSS_MSK (3 << IWM_RATE_VHT_MCS_NSS_POS) - -/* - * Legacy OFDM rate format for bits 7:0 - * - * 3-0: 0xD) 6 Mbps - * 0xF) 9 Mbps - * 0x5) 12 Mbps - * 0x7) 18 Mbps - * 0x9) 24 Mbps - * 0xB) 36 Mbps - * 0x1) 48 Mbps - * 0x3) 54 Mbps - * (bits 7-4 are 0) - * - * Legacy CCK rate format for bits 7:0: - * bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK): - * - * 6-0: 10) 1 Mbps - * 20) 2 Mbps - * 55) 5.5 Mbps - * 110) 11 Mbps - * (bit 7 is 0) - */ -#define IWM_RATE_LEGACY_RATE_MSK 0xff - - -/* - * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz - * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT - */ -#define IWM_RATE_MCS_CHAN_WIDTH_POS 11 -#define IWM_RATE_MCS_CHAN_WIDTH_MSK (3 << IWM_RATE_MCS_CHAN_WIDTH_POS) -#define IWM_RATE_MCS_CHAN_WIDTH_20 (0 << IWM_RATE_MCS_CHAN_WIDTH_POS) -#define IWM_RATE_MCS_CHAN_WIDTH_40 (1 << IWM_RATE_MCS_CHAN_WIDTH_POS) -#define IWM_RATE_MCS_CHAN_WIDTH_80 (2 << IWM_RATE_MCS_CHAN_WIDTH_POS) -#define IWM_RATE_MCS_CHAN_WIDTH_160 (3 << IWM_RATE_MCS_CHAN_WIDTH_POS) - -/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ -#define IWM_RATE_MCS_SGI_POS 13 -#define IWM_RATE_MCS_SGI_MSK (1 << IWM_RATE_MCS_SGI_POS) - /* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */ #define IWM_RATE_MCS_ANT_POS 14 #define IWM_RATE_MCS_ANT_A_MSK (1 << IWM_RATE_MCS_ANT_POS) @@ -4636,58 +4411,9 @@ enum { #define IWM_RATE_MCS_ANT_MSK IWM_RATE_MCS_ANT_ABC_MSK #define IWM_RATE_MCS_ANT_NUM 3 -/* Bit 17-18: (0) SS, (1) SS*2 */ -#define IWM_RATE_MCS_STBC_POS 17 -#define IWM_RATE_MCS_STBC_MSK (1 << IWM_RATE_MCS_STBC_POS) - -/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */ -#define IWM_RATE_MCS_BF_POS 19 -#define IWM_RATE_MCS_BF_MSK (1 << IWM_RATE_MCS_BF_POS) - -/* Bit 20: (0) ZLF is off, (1) ZLF is on */ -#define IWM_RATE_MCS_ZLF_POS 20 -#define IWM_RATE_MCS_ZLF_MSK (1 << IWM_RATE_MCS_ZLF_POS) - -/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */ -#define IWM_RATE_MCS_DUP_POS 24 -#define IWM_RATE_MCS_DUP_MSK (3 << IWM_RATE_MCS_DUP_POS) - -/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */ -#define IWM_RATE_MCS_LDPC_POS 27 -#define IWM_RATE_MCS_LDPC_MSK (1 << IWM_RATE_MCS_LDPC_POS) - - -/* Link Quality definitions */ - /* # entries in rate scale table to support Tx retries */ #define IWM_LQ_MAX_RETRY_NUM 16 -/* Link quality command flags bit fields */ - -/* Bit 0: (0) Don't use RTS (1) Use RTS */ -#define IWM_LQ_FLAG_USE_RTS_POS 0 -#define IWM_LQ_FLAG_USE_RTS_MSK (1 << IWM_LQ_FLAG_USE_RTS_POS) - -/* Bit 1-3: LQ command color. Used to match responses to LQ commands */ -#define IWM_LQ_FLAG_COLOR_POS 1 -#define IWM_LQ_FLAG_COLOR_MSK (7 << IWM_LQ_FLAG_COLOR_POS) - -/* Bit 4-5: Tx RTS BW Signalling - * (0) No RTS BW signalling - * (1) Static BW signalling - * (2) Dynamic BW signalling - */ -#define IWM_LQ_FLAG_RTS_BW_SIG_POS 4 -#define IWM_LQ_FLAG_RTS_BW_SIG_NONE (0 << IWM_LQ_FLAG_RTS_BW_SIG_POS) -#define IWM_LQ_FLAG_RTS_BW_SIG_STATIC (1 << IWM_LQ_FLAG_RTS_BW_SIG_POS) -#define IWM_LQ_FLAG_RTS_BW_SIG_DYNAMIC (2 << IWM_LQ_FLAG_RTS_BW_SIG_POS) - -/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection - * Dyanmic BW selection allows Tx with narrower BW then requested in rates - */ -#define IWM_LQ_FLAG_DYNAMIC_BW_POS 6 -#define IWM_LQ_FLAG_DYNAMIC_BW_MSK (1 << IWM_LQ_FLAG_DYNAMIC_BW_POS) - /* Antenna flags. */ #define IWM_ANT_A (1 << 0) #define IWM_ANT_B (1 << 1) @@ -4719,11 +4445,11 @@ enum { * 2 - 0x3f: maximal number of frames (up to 3f == 63) * @rs_table: array of rates for each TX try, each is rate_n_flags, * meaning it is a combination of IWM_RATE_MCS_* and IWM_RATE_*_PLCP - * @bf_params: beam forming params, currently not used + * @ss_params: single stream features. declare whether STBC or BFER are allowed. */ struct iwm_lq_cmd { uint8_t sta_id; - uint8_t reserved1; + uint8_t reduced_tpc; uint16_t control; /* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */ uint8_t flags; @@ -4737,7 +4463,7 @@ struct iwm_lq_cmd { uint8_t agg_frame_cnt_limit; uint32_t reserved2; uint32_t rs_table[IWM_LQ_MAX_RETRY_NUM]; - uint32_t bf_params; + uint32_t ss_params; }; /* LINK_QUALITY_CMD_API_S_VER_1 */ /** @@ -5137,7 +4863,8 @@ struct iwm_tx_resp { uint8_t pa_integ_res_b[3]; uint8_t pa_integ_res_c[3]; uint16_t measurement_req_id; - uint16_t reserved; + uint8_t reduced_tpc; + uint8_t reserved; uint32_t tfd_info; uint16_t seq_ctl; @@ -5145,8 +4872,7 @@ struct iwm_tx_resp { uint8_t tlc_info; uint8_t ra_tid; uint16_t frame_ctrl; - - struct iwm_agg_tx_status status; + struct iwm_agg_tx_status status[]; } __packed; /* IWM_TX_RSP_API_S_VER_3 */ /** diff --git a/itlwm/hal_iwm/if_iwmvar.h b/itlwm/hal_iwm/if_iwmvar.h index 0ae7b539a..0b12d215a 100644 --- a/itlwm/hal_iwm/if_iwmvar.h +++ b/itlwm/hal_iwm/if_iwmvar.h @@ -124,6 +124,8 @@ #include #include +#include "rs.h" + struct iwm_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint64_t wr_tsft; @@ -285,11 +287,9 @@ struct iwm_tx_data { int txmcs; int txrate; int totlen; - int data_type; + uint16_t fc; - /* A-MPDU subframes */ - int ampdu_txmcs; - int ampdu_nframes; + struct ieee80211_tx_info info; }; struct iwm_tx_ring { @@ -489,6 +489,12 @@ struct iwm_rxq_dup_data { struct iwm_tx_ba { struct iwm_node * wn; + uint32_t rate_n_flags; + uint8_t lq_color; + uint16_t tx_time; + uint32_t tx_count_last; + uint32_t tx_count; + unsigned long tpt_meas_start; }; struct iwm_ba_task_data { @@ -542,6 +548,7 @@ struct iwm_softc { int cmdqid; uint8_t sc_mgmt_last_antenna_idx; + uint8_t sc_tx_ant; int sc_sf_state; @@ -618,7 +625,7 @@ struct iwm_softc { struct iwm_bf_data sc_bf; - int sc_tx_timer; + int sc_tx_timer[IWM_MAX_QUEUES]; int sc_rx_ba_sessions; int sc_scan_last_antenna; @@ -655,6 +662,7 @@ struct iwm_softc { int sc_ltr_enabled; enum iwm_nvm_type nvm_type; int support_ldpc; + uint8_t non_shared_ant; int sc_mqrx_supported; int sc_integrated; @@ -687,6 +695,11 @@ struct iwm_softc { #define sc_txtap sc_txtapu.th int sc_txtap_len; #endif + union { + struct iwl_lq_sta_rs_fw rs_fw; + struct iwl_lq_sta rs_drv; + } lq_sta; + int tx_protection; }; struct iwm_node { @@ -698,7 +711,6 @@ struct iwm_node { uint16_t in_color; struct ieee80211_amrr_node in_amn; - struct ieee80211_ra_node in_rn; int lq_rate_mismatch; uint32_t next_ampdu_id; diff --git a/itlwm/hal_iwm/itlhdr.h b/itlwm/hal_iwm/itlhdr.h index f6af6e578..d8092946b 100644 --- a/itlwm/hal_iwm/itlhdr.h +++ b/itlwm/hal_iwm/itlhdr.h @@ -181,92 +181,6 @@ const uint8_t iwm_nvm_channels_8000[] = { #define IWM_FIRST_2GHZ_HT_MINUS 5 #define IWM_LAST_2GHZ_HT_PLUS 9 -const struct iwm_rate { - uint16_t rate; - uint8_t plcp; - uint8_t ht_plcp; - uint8_t vht_plcp; -} iwm_rates[] = { - /* Legacy */ /* HT */ - { 2, IWM_RATE_1M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_SISO_MCS_INV_PLCP }, - { 4, IWM_RATE_2M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_SISO_MCS_INV_PLCP }, - { 11, IWM_RATE_5M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_SISO_MCS_INV_PLCP }, - { 22, IWM_RATE_11M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_SISO_MCS_INV_PLCP }, - { 12, IWM_RATE_6M_PLCP, IWM_RATE_HT_SISO_MCS_0_PLCP, IWM_RATE_VHT_SISO_MCS_0_PLCP }, - { 18, IWM_RATE_9M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_SISO_MCS_INV_PLCP }, - { 24, IWM_RATE_12M_PLCP, IWM_RATE_HT_SISO_MCS_1_PLCP, IWM_RATE_VHT_SISO_MCS_1_PLCP }, - { 26, IWM_RATE_12M_PLCP, IWM_RATE_HT_MIMO2_MCS_8_PLCP, IWM_RATE_VHT_MIMO2_MCS_0_PLCP }, - { 36, IWM_RATE_18M_PLCP, IWM_RATE_HT_SISO_MCS_2_PLCP, IWM_RATE_VHT_SISO_MCS_2_PLCP }, - { 48, IWM_RATE_24M_PLCP, IWM_RATE_HT_SISO_MCS_3_PLCP, IWM_RATE_VHT_SISO_MCS_3_PLCP }, - { 52, IWM_RATE_24M_PLCP, IWM_RATE_HT_MIMO2_MCS_9_PLCP, IWM_RATE_VHT_MIMO2_MCS_1_PLCP }, - { 72, IWM_RATE_36M_PLCP, IWM_RATE_HT_SISO_MCS_4_PLCP, IWM_RATE_VHT_SISO_MCS_4_PLCP }, - { 78, IWM_RATE_36M_PLCP, IWM_RATE_HT_MIMO2_MCS_10_PLCP, IWM_RATE_VHT_MIMO2_MCS_2_PLCP }, - { 96, IWM_RATE_48M_PLCP, IWM_RATE_HT_SISO_MCS_5_PLCP, IWM_RATE_VHT_SISO_MCS_5_PLCP }, - { 104, IWM_RATE_48M_PLCP, IWM_RATE_HT_MIMO2_MCS_11_PLCP, IWM_RATE_VHT_MIMO2_MCS_3_PLCP }, - { 108, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_6_PLCP, IWM_RATE_VHT_SISO_MCS_6_PLCP }, - { 128, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_7_PLCP, IWM_RATE_VHT_SISO_MCS_7_PLCP }, - { 156, IWM_RATE_54M_PLCP, IWM_RATE_HT_MIMO2_MCS_12_PLCP, IWM_RATE_VHT_SISO_MCS_8_PLCP }, - { 208, IWM_RATE_54M_PLCP, IWM_RATE_HT_MIMO2_MCS_13_PLCP, IWM_RATE_VHT_SISO_MCS_9_PLCP }, - { 234, IWM_RATE_54M_PLCP, IWM_RATE_HT_MIMO2_MCS_14_PLCP, IWM_RATE_VHT_MIMO2_MCS_4_PLCP }, - { 260, IWM_RATE_54M_PLCP, IWM_RATE_HT_MIMO2_MCS_15_PLCP, IWM_RATE_VHT_MIMO2_MCS_5_PLCP }, - { 312, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_MIMO2_MCS_6_PLCP }, - { 360, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_MIMO2_MCS_7_PLCP }, - { 720, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_MIMO2_MCS_8_PLCP }, - { 780, IWM_RATE_54M_PLCP, IWM_RATE_HT_SISO_MCS_INV_PLCP, IWM_RATE_VHT_MIMO2_MCS_9_PLCP }, -}; -#define IWM_RIDX_CCK 0 -#define IWM_RIDX_OFDM 4 -#define IWM_RIDX_MAX (nitems(iwm_rates)-1) -#define IWM_RIDX_IS_CCK(_i_) ((_i_) < IWM_RIDX_OFDM) -#define IWM_RIDX_IS_OFDM(_i_) ((_i_) >= IWM_RIDX_OFDM) -#define IWM_RVAL_IS_OFDM(_i_) ((_i_) >= 12 && (_i_) != 22) - -/* Convert an MCS index into an iwm_rates[] index. */ -const int iwm_mcs2ridx[] = { - IWM_RATE_MCS_0_INDEX, - IWM_RATE_MCS_1_INDEX, - IWM_RATE_MCS_2_INDEX, - IWM_RATE_MCS_3_INDEX, - IWM_RATE_MCS_4_INDEX, - IWM_RATE_MCS_5_INDEX, - IWM_RATE_MCS_6_INDEX, - IWM_RATE_MCS_7_INDEX, - IWM_RATE_MCS_8_INDEX, - IWM_RATE_MCS_9_INDEX, - IWM_RATE_MCS_10_INDEX, - IWM_RATE_MCS_11_INDEX, - IWM_RATE_MCS_12_INDEX, - IWM_RATE_MCS_13_INDEX, - IWM_RATE_MCS_14_INDEX, - IWM_RATE_MCS_15_INDEX, -}; - -const int iwm_vht_siso_mcs2ridx[] = { - IWM_RATE_MCS_0_INDEX, - IWM_RATE_MCS_1_INDEX, - IWM_RATE_MCS_2_INDEX, - IWM_RATE_MCS_3_INDEX, - IWM_RATE_MCS_4_INDEX, - IWM_RATE_MCS_5_INDEX, - IWM_RATE_MCS_6_INDEX, - IWM_RATE_MCS_7_INDEX, - IWM_RATE_MCS_12_INDEX, - IWM_RATE_MCS_13_INDEX, -}; - -const int iwm_vht_mimo_mcs2ridx[] = { - IWM_RATE_MCS_8_INDEX, - IWM_RATE_MCS_9_INDEX, - IWM_RATE_MCS_10_INDEX, - IWM_RATE_MCS_11_INDEX, - IWM_RATE_MCS_14_INDEX, - IWM_RATE_MCS_15_INDEX, - IWM_RATE_MCS_15_INDEX+1, - IWM_RATE_MCS_15_INDEX+2, - IWM_RATE_MCS_15_INDEX+3, - IWM_RATE_MCS_15_INDEX+4, -}; - struct iwm_nvm_section { uint16_t length; uint8_t *data; diff --git a/itlwm/hal_iwm/mac80211.cpp b/itlwm/hal_iwm/mac80211.cpp index a3ef0f581..9b0774951 100644 --- a/itlwm/hal_iwm/mac80211.cpp +++ b/itlwm/hal_iwm/mac80211.cpp @@ -123,6 +123,7 @@ #include #include #include +#include "rs.h" #ifdef IWM_DEBUG int iwm_debug = 1; @@ -437,7 +438,8 @@ iwm_reorder_timer_expired(void *arg) splx(s); } -static inline uint8_t iwm_num_of_ant(uint8_t mask) +uint8_t ItlIwm:: +iwm_num_of_ant(uint8_t mask) { return !!((mask) & IWM_ANT_A) + !!((mask) & IWM_ANT_B) + @@ -727,7 +729,7 @@ iwm_set_hw_address_8000(struct iwm_softc *sc, struct iwm_nvm_data *data, * values by -256dBm: practically 0 power and a non-feasible 8 bit value. */ int ItlIwm:: -iwm_get_signal_strength(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info) +iwm_get_signal_strength(struct iwm_softc *sc, struct ieee80211_rx_status *rx_status, struct iwm_rx_phy_info *phy_info) { int energy_a, energy_b, energy_c, max_energy; uint32_t val; @@ -745,11 +747,19 @@ iwm_get_signal_strength(struct iwm_softc *sc, struct iwm_rx_phy_info *phy_info) max_energy = MAX(energy_a, energy_b); max_energy = MAX(max_energy, energy_c); + rx_status->signal = max_energy; + rx_status->chains = (le16toh(phy_info->phy_flags) & + IWM_RX_RES_PHY_FLAGS_ANTENNA) + >> IWM_RX_RES_PHY_FLAGS_ANTENNA_POS; + rx_status->chain_signal[0] = energy_a; + rx_status->chain_signal[1] = energy_b; + rx_status->chain_signal[2] = energy_c; + return max_energy; } int ItlIwm:: -iwm_rxmq_get_signal_strength(struct iwm_softc *sc, +iwm_rxmq_get_signal_strength(struct iwm_softc *sc, struct ieee80211_rx_status *rx_status, uint32_t rate_n_flags, struct iwm_rx_mpdu_desc *desc) { int energy_a, energy_b; @@ -758,7 +768,13 @@ iwm_rxmq_get_signal_strength(struct iwm_softc *sc, energy_b = desc->v1.energy_b; energy_a = energy_a ? -energy_a : -256; energy_b = energy_b ? -energy_b : -256; - return MAX(energy_a, energy_b); + rx_status->signal = MAX(energy_a, energy_b); + rx_status->chains = (rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + rx_status->chain_signal[0] = energy_a; + rx_status->chain_signal[1] = energy_b; + rx_status->chain_signal[2] = S8_MIN; + + return rx_status->signal; } /* @@ -989,6 +1005,59 @@ static const char *iwm_get_agg_tx_status(u16 status) return "UNKNOWN"; } +#define IEEE80211_TX_MAX_RATES 4 + +static int ieee80211_tx_get_rates(struct iwm_softc *sc, + struct ieee80211_tx_info *info, + int *retry_count) +{ + int count = -1; + int i; + int max_report_rates = 1; + + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + if ((info->flags & IEEE80211_TX_CTL_AMPDU) && + !(info->flags & IEEE80211_TX_STAT_AMPDU)) { + /* just the first aggr frame carry status info */ + info->status.rates[i].idx = -1; + info->status.rates[i].count = 0; + break; + } else if (info->status.rates[i].idx < 0) { + break; + } else if (i >= max_report_rates) { + /* the HW cannot have attempted that rate */ + info->status.rates[i].idx = -1; + info->status.rates[i].count = 0; + break; + } + + count += info->status.rates[i].count; + } + + if (count < 0) + count = 0; + + *retry_count = count; + return i - 1; +} + +void ieee80211_tx_status(struct iwm_softc *sc, struct ieee80211_tx_info *info, int tid, uint16_t fc, int ssn) +{ + struct _ifnet *ifp = &sc->sc_ic.ic_ac.ac_if; + int rates_idx, retry_count; + + if (!info) + return; + + rates_idx = ieee80211_tx_get_rates(sc, info, &retry_count); + + rs_drv_mac80211_tx_status(sc, sc->sc_ic.ic_bss, info, tid, fc, ssn); + if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + (info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && + (ieee80211_is_data_qos(fc))) + ifp->netStat->outputErrors++; +} + void ItlIwm:: iwm_ampdu_txq_advance(struct iwm_softc *sc, struct iwm_tx_ring *ring, int idx) { @@ -1010,12 +1079,18 @@ iwm_ampdu_txq_advance(struct iwm_softc *sc, struct iwm_tx_ring *ring, int idx) void ItlIwm:: iwm_ampdu_rate_control(struct iwm_softc *sc, struct ieee80211_node *ni, - struct iwm_tx_ring *ring, uint16_t seq, uint16_t ssn) + struct iwm_tx_ring *ring, uint16_t seq, uint16_t ssn, struct ieee80211_tx_info *tx_info, int tid, uint32_t rate_n_flags) { - struct ieee80211com *ic = &sc->sc_ic; - struct iwm_node *wn = (struct iwm_node *)ni; int idx, end_idx; - + struct iwm_tx_ba *tid_data = &sc->sc_tx_ba[tid]; + int freed = 0; + bool rs_update = false; + + /* pack lq color from tid_data along the reduced txp */ + tx_info->status.status_driver_data[0] = + RS_DRV_DATA_PACK(tid_data->lq_color, + tx_info->status.status_driver_data[0]); + tx_info->status.status_driver_data[1] = (void *)(uintptr_t)rate_n_flags; /* * Update Tx rate statistics for A-MPDUs before firmware's BA window. */ @@ -1023,70 +1098,48 @@ iwm_ampdu_rate_control(struct iwm_softc *sc, struct ieee80211_node *ni, end_idx = IWM_AGG_SSN_TO_TXQ_IDX(ssn); while (idx != end_idx) { struct iwm_tx_data *txdata = &ring->data[idx]; + struct ieee80211_tx_info *info = &txdata->info; - if (txdata->m != NULL && txdata->ampdu_nframes > 1) { - /* - * We can assume that this subframe has been ACKed - * because ACK failures come as single frames and - * before failing an A-MPDU subframe the firmware - * sends it as a single frame at least once. + if (txdata->m != NULL) { + rs_update = true; + + memset(&info->status, 0, sizeof(info->status)); + /* Packet was transmitted successfully, failures come as single + * frames because before failing a frame the firmware transmits + * it without aggregation at least once. */ - ieee80211_ra_add_stats_ht(&wn->in_rn, ic, ni, - txdata->ampdu_txmcs, 1, 0); - - /* Report this frame only once. */ - txdata->ampdu_nframes = 0; + info->flags |= IEEE80211_TX_STAT_ACK; + + if (ieee80211_is_data_qos(txdata->fc)) + freed++; + else + WARN_ON_ONCE(tid != IWL_MAX_TID_COUNT); + + /* this is the first skb we deliver in this batch */ + /* put the rate scaling data there */ + if (freed == 1) { + info->flags |= IEEE80211_TX_STAT_AMPDU; + memcpy(&info->status, &tx_info->status, + sizeof(tx_info->status)); + iwl_mvm_hwrate_to_tx_status(rate_n_flags, info); + } + + ieee80211_tx_status(sc, info, tid, txdata->fc, ssn); } idx = (idx + 1) % IWM_TX_RING_COUNT; } - iwm_ra_choose(sc, ni); -} - -void ItlIwm:: -iwm_ht_single_rate_control(struct iwm_softc *sc, struct ieee80211_node *ni, - uint8_t rate, uint8_t rflags, uint8_t ackfailcnt, int txfail) -{ - struct ieee80211com *ic = (struct ieee80211com *)&sc->sc_ic; - struct iwm_node *wn = (struct iwm_node *)ni; - int mcs = rate; - const struct ieee80211_ra_rate *rs; - unsigned int retries = 0, i; - - /* - * Ignore Tx reports which don't match our last LQ command. + /* We got a BA notif with 0 acked or scd_ssn didn't progress which is + * possible (i.e. first MPDU in the aggregation wasn't acked) + * Still it's important to update RS about sent vs. acked. */ - if (rate != ni->ni_txmcs) { - if (++wn->lq_rate_mismatch > 15) { - /* Try to sync firmware with driver. */ - iwm_setrates(wn, 1); - wn->lq_rate_mismatch = 0; - } - return; - } - - wn->lq_rate_mismatch = 0; - - rs = ieee80211_ra_get_rateset(&wn->in_rn, ic, ni, rate); - /* - * Firmware has attempted rates in this rate set in sequence. - * Retries at a basic rate are counted against the minimum MCS. - */ - for (i = 0; i < ackfailcnt; i++) { - if (mcs > rs->min_mcs) { - ieee80211_ra_add_stats_ht(&wn->in_rn, ic, ni, mcs, 1, 1); - mcs--; - } else - retries++; + if (!rs_update) { + tx_info->band = IEEE80211_IS_CHAN_2GHZ(sc->sc_ic.ic_bss->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; + iwl_mvm_hwrate_to_tx_status(rate_n_flags, tx_info); + DPRINTFN(3, ("No reclaim. Update rs directly\n")); + iwl_mvm_rs_tx_status(sc, sc->sc_ic.ic_bss, tid, tx_info, false); } - - if (txfail && ackfailcnt == 0) - ieee80211_ra_add_stats_ht(&wn->in_rn, ic, ni, mcs, 1, 1); - else - ieee80211_ra_add_stats_ht(&wn->in_rn, ic, ni, mcs, retries + 1, retries); - - iwm_ra_choose(sc, ni); } void ItlIwm:: @@ -1100,6 +1153,8 @@ iwm_rx_tx_ba_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_r int qid; struct ieee80211_node *ni = ic->ic_bss; struct iwm_node *in = (struct iwm_node *)ni; + struct iwm_tx_ba *tid_data; + struct ieee80211_tx_info ba_info = {}; DPRINTFN(3, ("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n", ba_notif->tid, le16_to_cpu(ba_notif->seq_ctl), @@ -1124,7 +1179,7 @@ iwm_rx_tx_ba_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_r if (qid != IWM_FIRST_AGG_TX_QUEUE + ba_notif->tid) return; - sc->sc_tx_timer = 0; + sc->sc_tx_timer[qid] = 0; ba = &ni->ni_tx_ba[ba_notif->tid]; if (ba->ba_state != IEEE80211_BA_AGREED) @@ -1140,13 +1195,23 @@ iwm_rx_tx_ba_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_r */ ssn = le16toh(ba_notif->scd_ssn); + /* pack lq color from tid_data along the reduced txp */ + tid_data = &sc->sc_tx_ba[ba_notif->tid]; + + ba_info.flags = IEEE80211_TX_STAT_AMPDU; + ba_info.status.ampdu_ack_len = ba_notif->txed_2_done; + ba_info.status.ampdu_len = ba_notif->txed; + ba_info.status.tx_time = tid_data->tx_time; + ba_info.status.status_driver_data[0] = + (void *)(uintptr_t)ba_notif->reduced_txp; + if (SEQ_LT(ssn, ba->ba_winstart)) return; - + /* Skip rate control if our Tx rate is fixed. */ if (ic->ic_fixed_mcs == -1) iwm_ampdu_rate_control(sc, ni, ring, - ba->ba_winstart, ssn); + ba->ba_winstart, ssn, &ba_info, ba_notif->tid, tid_data->rate_n_flags); /* * SSN corresponds to the first (perhaps not yet transmitted) frame @@ -1171,51 +1236,11 @@ iwm_ampdu_tx_done(struct iwm_softc *sc, struct iwm_cmd_header *cmd_hdr, int txfail = (status != IWM_TX_STATUS_SUCCESS && status != IWM_TX_STATUS_DIRECT_DONE); struct ieee80211_tx_ba *ba; - int rate = 0; - if (initial_rate & IWM_RATE_MCS_VHT_MSK) { - rate = (initial_rate & - IWM_RATE_VHT_MCS_RATE_CODE_MSK); - } else if (initial_rate & IWM_RATE_MCS_HT_MSK) { - rate = (initial_rate & - (IWM_RATE_HT_MCS_RATE_CODE_MSK | - IWM_RATE_HT_MCS_NSS_MSK)); - } - - sc->sc_tx_timer = 0; if (ic->ic_state != IEEE80211_S_RUN) return; if (nframes > 1) { - int i; - - /* - * Collect information about this A-MPDU. - */ - for (i = 0; i < nframes; i++) { - uint8_t qid = agg_status[i].qid; - uint8_t idx = agg_status[i].idx; - uint16_t txstatus = (le16toh(agg_status[i].status) & - IWM_AGG_TX_STATE_STATUS_MSK); - - if (status != IWM_TX_STATUS_SUCCESS && txdata->data_type == IEEE80211_FC0_TYPE_MGT) { - iwm_toggle_tx_ant(sc, &sc->sc_mgmt_last_antenna_idx); - } - - if (txstatus != IWM_AGG_TX_STATE_TRANSMITTED) - continue; - - if (qid != cmd_hdr->qid) - continue; - - txdata = &txq->data[idx]; - if (txdata->m == NULL) - continue; - - /* The Tx rate was the same for all subframes. */ - txdata->ampdu_txmcs = rate; - txdata->ampdu_nframes = nframes; - } return; } @@ -1233,28 +1258,6 @@ iwm_ampdu_tx_done(struct iwm_softc *sc, struct iwm_cmd_header *cmd_hdr, "bitmap=0x%llx\n", __func__, status, cmd_hdr->qid, txq->queued, cmd_hdr->idx, ssn, ba->ba_bitmap)); - /* - * Skip rate control if our Tx rate is fixed. - * Don't report frames to MiRA which were sent at a different - * Tx rate than ni->ni_txmcs. - */ - if (ic->ic_fixed_mcs == -1) { - if (txdata->ampdu_nframes > 1) { - /* - * This frame was once part of an A-MPDU. - * Report one failed A-MPDU Tx attempt. - * The firmware might have made several such - * attempts but we don't keep track of this. - */ - ieee80211_ra_add_stats_ht(&in->in_rn, ic, ni, - txdata->ampdu_txmcs, 1, 1); - } - - /* Report the final single-frame Tx attempt. */ - iwm_ht_single_rate_control(sc, ni, rate, initial_rate, - failure_frame, txfail); - } - if (txfail) { ieee80211_tx_compressed_bar(ic, ni, tid, ssn); XYLog("%s sending bar ssn=%d tid=%d\n", __FUNCTION__, ssn, tid); @@ -1266,125 +1269,121 @@ iwm_ampdu_tx_done(struct iwm_softc *sc, struct iwm_cmd_header *cmd_hdr, * frames before its BA window so mark them all as done. */ ieee80211_output_ba_move_window(ic, ni, tid, ssn); - iwm_ampdu_txq_advance(sc, txq, IWM_AGG_SSN_TO_TXQ_IDX(ssn)); - iwm_clear_oactive(sc, txq); +} + +#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f) +#define TX_RES_INIT_RATE_INDEX_MSK 0x0f +#define TX_RES_RATE_TABLE_COLOR_POS 4 +#define TX_RES_RATE_TABLE_COLOR_MSK 0x70 +#define TX_RES_INV_RATE_INDEX_MSK 0x80 +#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\ + TX_RES_RATE_TABLE_COLOR_POS) + +static inline struct iwm_agg_tx_status * +iwl_mvm_get_agg_status(struct iwm_softc *sc, void *tx_resp) +{ + return (struct iwm_agg_tx_status *)(((struct iwm_tx_resp *)tx_resp)->status); +} + +static inline u32 iwl_mvm_get_scd_ssn(struct iwm_softc *sc, + struct iwm_tx_resp *tx_resp) +{ + return le32_to_cpup((__le32 *)iwl_mvm_get_agg_status(sc, tx_resp) + + tx_resp->frame_count) & 0xfff; } void ItlIwm:: iwm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_tx_resp *tx_resp, - struct iwm_node *in, int txmcs, int txrate, int qid) + int qid, int idx) { - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = &in->in_ni; - struct _ifnet *ifp = IC2IFP(ic); - int status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK; - int txfail; - - KASSERT(tx_resp->frame_count == 1, ""); - - txfail = (status != IWM_TX_STATUS_SUCCESS && - status != IWM_TX_STATUS_DIRECT_DONE); + u32 status = le16toh(iwl_mvm_get_agg_status(sc, tx_resp)->status); + u16 ssn = iwl_mvm_get_scd_ssn(sc, tx_resp); + int tid = IWL_MVM_TX_RES_GET_TID(tx_resp->ra_tid); + struct iwm_tx_data *txd; + struct iwm_tx_ring *ring = &sc->txq[qid]; + u8 skb_freed = 0; + u8 lq_color; - /* - * Update rate control statistics. - * Only report frames which were actually queued with the currently - * selected Tx rate. Because Tx queues are relatively long we may - * encounter previously selected rates here during Tx bursts. - * Providing feedback based on such frames can lead to suboptimal - * Tx rate control decisions. - */ - if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) { - if (txrate != ni->ni_txrate) { - if (++in->lq_rate_mismatch > 15) { - /* Try to sync firmware with the driver... */ - iwm_setrates(in, 1); - in->lq_rate_mismatch = 0; - } - } else { - in->lq_rate_mismatch = 0; - - in->in_amn.amn_txcnt++; - if (txfail) - in->in_amn.amn_retrycnt++; - if (tx_resp->failure_frame > 0) - in->in_amn.amn_retrycnt++; - } - } else if (ic->ic_fixed_mcs == -1 && ic->ic_state == IEEE80211_S_RUN && - (le32toh(tx_resp->initial_rate) & IWM_RATE_MCS_HT_MSK)) { - uint32_t fw_txmcs = le32toh(tx_resp->initial_rate) & - (IWM_RATE_HT_MCS_RATE_CODE_MSK | IWM_RATE_HT_MCS_NSS_MSK); - /* Ignore Tx reports which don't match our last LQ command. */ - if (fw_txmcs != ni->ni_txmcs) { - if (++in->lq_rate_mismatch > 15) { - /* Try to sync firmware with the driver... */ - iwm_setrates(in, 1); - in->lq_rate_mismatch = 0; - } - } else { - int mcs = fw_txmcs; - const struct ieee80211_ra_rate *rs = - ieee80211_ra_get_rateset(&in->in_rn, ic, ni, fw_txmcs); - unsigned int retries = 0, i; - int old_txmcs = ni->ni_txmcs; - int old_bw = in->in_rn.bw; - int old_nss = in->in_rn.nss; - int old_sgi = in->in_rn.sgi; - - in->lq_rate_mismatch = 0; - - for (i = 0; i < tx_resp->failure_frame; i++) { - if (mcs > rs->min_mcs) { - ieee80211_ra_add_stats_ht(&in->in_rn, - ic, ni, mcs, 1, 1); - mcs--; - } else - retries++; - } - - if (txfail && tx_resp->failure_frame == 0) { - ieee80211_ra_add_stats_ht(&in->in_rn, ic, ni, - fw_txmcs, 1, 1); - } else { - ieee80211_ra_add_stats_ht(&in->in_rn, ic, ni, - mcs, retries + 1, retries); + while (ring->tail != idx) { + txd = &ring->data[ring->tail]; + struct ieee80211_tx_info *info = &txd->info; + bool flushed = false; + if (txd->m != NULL) { + skb_freed++; + + memset(&info->status, 0, sizeof(info->status)); + info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED); + + /* inform mac80211 about what happened with the frame */ + switch (status & IWM_TX_STATUS_MSK) { + case IWM_TX_STATUS_SUCCESS: + case IWM_TX_STATUS_DIRECT_DONE: + info->flags |= IEEE80211_TX_STAT_ACK; + break; + case IWM_TX_STATUS_FAIL_FIFO_FLUSHED: + case IWM_TX_STATUS_FAIL_DRAIN_FLOW: + flushed = true; + break; + case IWM_TX_STATUS_FAIL_DEST_PS: + /* the FW should have stopped the queue and not + * return this status + */ + WARN_ON(1); + info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + break; + default: + break; } + + if ((status & IWM_TX_STATUS_MSK) != IWM_TX_STATUS_SUCCESS && + ieee80211_is_mgmt(txd->fc)) + iwm_toggle_tx_ant(sc, &sc->sc_mgmt_last_antenna_idx); - ieee80211_ra_choose(&in->in_rn, ic, ni); - + if ((status & IWM_TX_STATUS_MSK) != IWM_TX_STATUS_SUCCESS && + sc->sc_ic.ic_state <= IEEE80211_S_RUN) + iwm_toggle_tx_ant(sc, &sc->sc_tx_ant); + + + /* + * If we are freeing multiple frames, mark all the frames + * but the first one as acked, since they were acknowledged + * before + * */ + if (skb_freed > 1) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = tx_resp->failure_frame + 1; + iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), + info); + info->status.status_driver_data[1] = + (void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate); + + /* Single frame failure in an AMPDU queue => send BAR */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + !(info->flags & IEEE80211_TX_STAT_ACK) && + !(info->flags & IEEE80211_TX_STAT_TX_FILTERED) && !flushed) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + /* - * If RA has chosen a new TX rate we must update - * the firmware's LQ rate table. - * ni_txmcs may change again before the task runs so - * cache the chosen rate in the iwm_node structure. + * TODO: this is not accurate if we are freeing more than one + * packet. */ - if (ni->ni_txmcs != old_txmcs || in->in_rn.bw != old_bw || in->in_rn.sgi != old_sgi || in->in_rn.nss != old_nss) - iwm_setrates(in, 1); + info->status.tx_time = + le16_to_cpu(tx_resp->wireless_media_time); + BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1); + lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info); + info->status.status_driver_data[0] = + RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc); + + ieee80211_tx_status(sc, info, tid, txd->fc, ssn); + + iwm_reset_sched(sc, ring->qid, ring->tail, IWM_STATION_ID); + iwm_txd_done(sc, txd); + ring->queued--; } + ring->tail = (ring->tail + 1) % IWM_TX_RING_COUNT; } - - if (txfail) { - XYLog("%s %d OUTPUT_ERROR status=%d\n", __FUNCTION__, __LINE__, status); - ifp->netStat->outputErrors++; - } else { - DPRINTFN(2, ("%s %d succeed status=%d\n", __FUNCTION__, __LINE__, status)); - } -} - -void ItlIwm:: -iwm_ra_choose(struct iwm_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct iwm_node *in = (struct iwm_node *)ni; - int old_txmcs = ni->ni_txmcs; - int old_bw = in->in_rn.bw; - int old_nss = in->in_rn.nss; - int old_sgi = in->in_rn.sgi; - - ieee80211_ra_choose(&in->in_rn, ic, ni); - - /* Update firmware's LQ retry table if RA has chosen a new MCS. */ - if (ni->ni_txmcs != old_txmcs || in->in_rn.bw != old_bw || in->in_rn.sgi != old_sgi || in->in_rn.nss != old_nss) - iwm_setrates(in, 1); } void ItlIwm:: @@ -1404,11 +1403,10 @@ iwm_txd_done(struct iwm_softc *sc, struct iwm_tx_data *txd) ieee80211_release_node(ic, &txd->in->in_ni); txd->in = NULL; txd->totlen = 0; - txd->ampdu_txmcs = 0; txd->txmcs = 0; txd->txrate = 0; - txd->data_type = 0; - txd->ampdu_nframes = 0; + txd->fc = 0; + memset(&txd->info, 0, sizeof(struct ieee80211_tx_info)); } void ItlIwm:: @@ -1429,6 +1427,13 @@ iwm_clear_oactive(struct iwm_softc *sc, struct iwm_tx_ring *ring) } } +#define TX_RES_INIT_RATE_INDEX_MSK 0x0f +#define TX_RES_RATE_TABLE_COLOR_POS 4 +#define TX_RES_RATE_TABLE_COLOR_MSK 0x70 +#define TX_RES_INV_RATE_INDEX_MSK 0x80 +#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\ + TX_RES_RATE_TABLE_COLOR_POS) + void ItlIwm:: iwm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_rx_data *data) @@ -1436,17 +1441,16 @@ iwm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_cmd_header *cmd_hdr = &pkt->hdr; int idx = cmd_hdr->idx; int qid = cmd_hdr->qid; - struct iwm_tx_ring *ring = &sc->txq[qid]; - struct iwm_tx_data *txd = &ring->data[idx]; + struct iwm_tx_ring *ring; + struct iwm_tx_data *txd; struct iwm_tx_resp *tx_resp = (struct iwm_tx_resp *)pkt->data; uint32_t ssn; uint32_t len = iwm_rx_packet_len(pkt); + struct iwm_tx_ba *tid_data; bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE, BUS_DMASYNC_POSTREAD); - sc->sc_tx_timer = 0; - /* Sanity checks. */ if (sizeof(*tx_resp) > len) return; @@ -1455,12 +1459,18 @@ iwm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt, if (qid > IWM_LAST_AGG_TX_QUEUE) return; if (sizeof(*tx_resp) + sizeof(ssn) + - tx_resp->frame_count * sizeof(tx_resp->status) > len) + tx_resp->frame_count * sizeof(struct iwm_agg_tx_status) > len) return; - if (tx_resp->frame_count > 1) + sc->sc_tx_timer[qid] = 0; + + ring = &sc->txq[qid]; + txd = &ring->data[idx]; + + if (tx_resp->frame_count > 1) { for (int i = 0; i < tx_resp->frame_count; i++) { - u16 fstatus = le16_to_cpu((&tx_resp->status)[i].status); + struct iwm_agg_tx_status *frame_status = iwl_mvm_get_agg_status(sc, tx_resp); + u16 fstatus = le16_to_cpu(frame_status[i].status); DPRINTFN(3, ("status %s (0x%04x), try-count (%d) qid (%d) seq (0x%x)\n", iwm_get_agg_tx_status(fstatus), @@ -1468,33 +1478,32 @@ iwm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt, (fstatus & IWM_AGG_TX_STATE_TRY_CNT_MSK) >> IWM_AGG_TX_STATE_TRY_CNT_POS, qid, - le16_to_cpu((&tx_resp->status)[i].idx))); - } - - txd = &ring->data[idx]; - if (txd->m == NULL) + le16_to_cpu(frame_status[i].idx))); + } + int tid = cmd_hdr->qid - IWM_FIRST_AGG_TX_QUEUE; + if (tid < 0) + return; + tid_data = &sc->sc_tx_ba[tid]; + tid_data->lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info); + tid_data->tx_time = le16toh(tx_resp->wireless_media_time); + tid_data->rate_n_flags = le32toh(tx_resp->initial_rate); return; + } DPRINTFN(2, ("%s idx=%d qid=%d txd->txmcs=%d txd->txrate=%d, frame_count=%d len=%d\n", __FUNCTION__, idx, qid, txd->txmcs, txd->txrate, ((struct iwm_tx_resp *)pkt->data)->frame_count, ((struct iwm_tx_resp *)pkt->data)->byte_cnt)); - - memcpy(&ssn, &tx_resp->status + tx_resp->frame_count, sizeof(ssn)); - ssn = le32toh(ssn) & 0xfff; + + ssn = iwm_get_scd_ssn(tx_resp); + iwm_rx_tx_cmd_single(sc, tx_resp, qid, IWM_AGG_SSN_TO_TXQ_IDX(ssn)); if (qid >= IWM_FIRST_AGG_TX_QUEUE) { int status; - status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK; + + status = le16toh(iwl_mvm_get_agg_status(sc, tx_resp)->status) & IWM_TX_STATUS_MSK; iwm_ampdu_tx_done(sc, cmd_hdr, txd->in, ring, le32toh(tx_resp->initial_rate), tx_resp->frame_count, - tx_resp->failure_frame, ssn, status, &tx_resp->status); - } else { - /* - * Even though this is not an agg queue, we must only free - * frames before the firmware's starting sequence number. - */ - iwm_rx_tx_cmd_single(sc, tx_resp, txd->in, txd->txmcs, - txd->txrate, qid); - iwm_ampdu_txq_advance(sc, ring, IWM_AGG_SSN_TO_TXQ_IDX(ssn)); - iwm_clear_oactive(sc, ring); + tx_resp->failure_frame, ssn, status, iwl_mvm_get_agg_status(sc, tx_resp)); } + + iwm_clear_oactive(sc, ring); } void ItlIwm:: @@ -1530,90 +1539,81 @@ iwm_rx_bmiss(struct iwm_softc *sc, struct iwm_rx_packet *pkt, } +static int +iwm_rate2ridx(struct iwm_softc *sc, int rate) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_node *ni = ic->ic_bss; + int ridx = -1, i; + + int min_ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ? + IWL_FIRST_OFDM_RATE : IWL_FIRST_CCK_RATE; + + for (i = 0; i < ieee80211_std_rateset_11g.rs_nrates; i++) { + if (ieee80211_std_rateset_11g.rs_rates[i] == rate) { + ridx = i; + break; + } + } + return ridx == -1 ? min_ridx : ridx; +} + /* * Fill in various bit for management frames, and leave them * unfilled for data frames (firmware takes care of that). * Return the selected TX rate. */ -const struct iwm_rate * ItlIwm:: +const struct iwl_rs_rate_info *ItlIwm:: iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node *in, struct ieee80211_frame *wh, struct iwm_tx_cmd *tx) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = &in->in_ni; - const struct iwm_rate *rinfo; int type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; int subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - int ridx, rate_flags; - + int ridx = -1, rate_flags; + int min_ridx = iwm_rate2ridx(sc, ieee80211_min_basic_rate(ic)); + tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT; - if (type == IEEE80211_FC0_TYPE_CTL && subtype == IEEE80211_FC0_SUBTYPE_BAR) { + if (type == IEEE80211_FC0_TYPE_CTL && + subtype == IEEE80211_FC0_SUBTYPE_BAR) tx->data_retry_limit = IWM_BAR_DFAULT_RETRY_LIMIT; - } else { + else tx->data_retry_limit = IWM_DEFAULT_TX_RETRY; - } - /* - * for data packets, rate info comes from the table inside the fw. This - * table is controlled by LINK_QUALITY commands - */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && type == IEEE80211_FC0_TYPE_DATA) { - int i; + if (IEEE80211_IS_MULTICAST(wh->i_addr1) || + type != IEEE80211_FC0_TYPE_DATA) { + /* for non-data, use the lowest supported rate */ + ridx = min_ridx; + tx->data_retry_limit = IWM_MGMT_DFAULT_RETRY_LIMIT; + } else if (ic->ic_fixed_mcs != -1) { + if (ni->ni_flags & IEEE80211_NODE_VHT) + ridx = IWL_FIRST_OFDM_RATE; + else + ridx = sc->sc_fixed_ridx; + } else if (ic->ic_fixed_rate != -1) { + ridx = sc->sc_fixed_ridx; + } else { + /* Use firmware rateset retry table. */ tx->initial_rate_index = 0; - tx->tx_flags |= cpu_to_le32(IWM_TX_CMD_FLG_STA_RATE); - if (ni->ni_flags & IEEE80211_NODE_VHT) { - ridx = (in->in_rn.nss > 1 ? iwm_vht_mimo_mcs2ridx[ni->ni_txmcs] : iwm_vht_siso_mcs2ridx[ni->ni_txmcs]); - return &iwm_rates[ridx]; - } else if (ni->ni_flags & IEEE80211_NODE_HT) { - ridx = iwm_mcs2ridx[ni->ni_txmcs]; - return &iwm_rates[ridx]; - } - ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ? - IWM_RIDX_OFDM : IWM_RIDX_CCK; - for (i = 0; i < ni->ni_rates.rs_nrates; i++) { - if (iwm_rates[i].rate == (ni->ni_txrate & - IEEE80211_RATE_VAL)) { - ridx = i; - break; - } - } - return &iwm_rates[ridx]; - } else if (type == IEEE80211_FC0_TYPE_CTL && subtype == IEEE80211_FC0_SUBTYPE_BAR) { - tx->tx_flags |= htole32(IWM_TX_CMD_FLG_ACK | IWM_TX_CMD_FLG_BAR); + tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE); + if (ni->ni_flags & IEEE80211_NODE_HT) /* VHT implies HT */ + return 0; + return &iwl_rates[iwm_rate2ridx(sc, ni->ni_txrate)]; } - ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ? - IWM_RIDX_OFDM : IWM_RIDX_CCK; - for (int i = 0; i < ni->ni_rates.rs_nrates; i++) { - if (iwm_rates[i].rate == (ni->ni_txrate & - IEEE80211_RATE_VAL)) { - ridx = i; - break; - } - } - if (ni->ni_flags & IEEE80211_NODE_VHT) { - ridx = (in->in_rn.nss > 1 ? iwm_vht_mimo_mcs2ridx[ni->ni_txmcs] : iwm_vht_siso_mcs2ridx[ni->ni_txmcs]); - } else if (ni->ni_flags & IEEE80211_NODE_HT) { - ridx = iwm_mcs2ridx[ni->ni_txmcs]; - } - if (ic->ic_fixed_mcs != -1) { - ridx = sc->sc_fixed_ridx; - } - - rinfo = &iwm_rates[ridx]; - if (iwm_is_mimo_ht_plcp(rinfo->ht_plcp) || iwm_is_mimo_vht_plcp(rinfo->vht_plcp)) - rate_flags = IWM_RATE_MCS_ANT_AB_MSK; - else if (sc->sc_device_family == IWM_DEVICE_FAMILY_9000 && - (iwm_fw_valid_tx_ant(sc) & IWM_ANT_B)) - rate_flags = IWM_RATE_MCS_ANT_B_MSK; - else - rate_flags = IWM_RATE_MCS_ANT_A_MSK; - if (IWM_RIDX_IS_CCK(ridx)) - rate_flags |= IWM_RATE_MCS_CCK_MSK; - tx->rate_n_flags = htole32(rate_flags | rinfo->plcp); + if (ridx == -1 || ridx >= IWL_RATE_COUNT_LEGACY) + ridx = min_ridx; + + rate_flags = iwm_get_tx_ant(sc, ni, type, wh); + XYLog("%s ridx=%d ant=%d\n", __FUNCTION__, ridx, (rate_flags >> RATE_MCS_ANT_POS)); + /* Set CCK flag as needed */ + if ((ridx >= IWL_FIRST_CCK_RATE) && (ridx <= IWL_LAST_CCK_RATE)) + rate_flags |= RATE_MCS_CCK_MSK; + tx->rate_n_flags = htole32(rate_flags | iwl_mvm_mac80211_idx_to_hwrate(ridx)); - return rinfo; + return &iwl_rates[ridx]; } #define TB0_SIZE 20 @@ -1629,7 +1629,7 @@ iwm_tx(struct iwm_softc *sc, mbuf_t m, struct ieee80211_node *ni, int ac) struct iwm_tx_cmd *tx; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; - const struct iwm_rate *rinfo; + const struct iwl_rs_rate_info *rinfo; uint8_t *ivp; uint32_t flags; u_int hdrlen; @@ -1847,8 +1847,8 @@ iwm_tx(struct iwm_softc *sc, mbuf_t m, struct ieee80211_node *ni, int ac) data->txmcs = ni->ni_txmcs; data->txrate = ni->ni_txrate; data->totlen = totlen; - data->ampdu_txmcs = ni->ni_txmcs; - data->data_type = type; + memcpy(&data->fc, &wh->i_fc[0], sizeof(uint16_t)); + data->info.band = IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; DPRINTFN(3, ("sending data: 嘤嘤嘤 qid=%d idx=%d len=%d nsegs=%d txflags=0x%08x rate_n_flags=0x%08x rateidx=%u txmcs=%d ni_txrate=%d\n", ring->qid, ring->cur, totlen, nsegs, le32toh(tx->tx_flags), @@ -1894,10 +1894,13 @@ iwm_tx(struct iwm_softc *sc, mbuf_t m, struct ieee80211_node *ni, int ac) /* Mark TX ring as full if we reach a certain threshold. */ if (++ring->queued > IWM_TX_RING_HIMARK) { -// XYLog("%s sc->qfullmsk is FULL ring->cur=%d ring->queued=%d\n", __FUNCTION__, ring->cur, ring->queued); +// XYLog("%s qid=%d sc->qfullmsk is FULL ring->cur=%d ring->queued=%d\n", __FUNCTION__, ring->qid, ring->cur, ring->queued); sc->qfullmsk |= 1 << ring->qid; } + if (ic->ic_if.if_flags & IFF_UP) + sc->sc_tx_timer[ring->qid] = 15; + return 0; } @@ -2273,6 +2276,8 @@ iwm_auth(struct iwm_softc *sc) goto rm_binding; } + iwm_toggle_tx_ant(sc, &sc->sc_tx_ant); + if (ic->ic_opmode == IEEE80211_M_MONITOR) return 0; @@ -2286,6 +2291,12 @@ iwm_auth(struct iwm_softc *sc) duration = IEEE80211_DUR_TU; iwm_protect_session(sc, in, duration, in->in_ni.ni_intval / 2); + rs_drv_alloc_sta(sc, &in->in_ni); + + iwl_mvm_rs_rate_init(sc, ic->ic_bss, + IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, + false); + return 0; rm_binding: @@ -2377,6 +2388,7 @@ iwm_deauth(struct iwm_softc *sc) &ic->ic_channels[1], 1, 1, 0); if (err) return err; + rs_drv_free_sta(sc, &in->in_ni); return 0; } @@ -2494,7 +2506,6 @@ iwm_run(struct iwm_softc *sc) } ieee80211_amrr_node_init(&sc->sc_amrr, &in->in_amn); - ieee80211_ra_node_init(ic, &in->in_rn, &in->in_ni); if (ic->ic_opmode == IEEE80211_M_MONITOR) { iwm_led_blink_start(sc); @@ -2504,7 +2515,10 @@ iwm_run(struct iwm_softc *sc) /* Start at lowest available bit-rate, AMRR will raise. */ in->in_ni.ni_txrate = 0; in->in_ni.ni_txmcs = 0; - iwm_setrates(in, 0); + + iwl_mvm_rs_rate_init(sc, ic->ic_bss, + IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, + true); timeout_add_msec(&sc->sc_calib_to, 500); iwm_led_enable(sc); @@ -2684,31 +2698,34 @@ void ItlIwm:: iwm_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, struct ieee80211_key *k) { - struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc; - struct iwm_add_sta_key_cmd cmd; + struct iwm_softc *sc = (struct iwm_softc *)ic->ic_softc; + struct iwm_add_sta_key_cmd cmd; ItlIwm *that = container_of(sc, ItlIwm, com); - - if ((k->k_flags & IEEE80211_KEY_GROUP) || - (k->k_cipher != IEEE80211_CIPHER_CCMP)) { - /* Fallback to software crypto for other ciphers. */ - ieee80211_delete_key(ic, ni, k); - return; - } - - if (!isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_TKIP_MIC_KEYS)) - return that->iwm_delete_key_v1(ic, ni, k); - - memset(&cmd, 0, sizeof(cmd)); - - cmd.common.key_flags = htole16(IWM_STA_KEY_NOT_VALID | - IWM_STA_KEY_FLG_NO_ENC | IWM_STA_KEY_FLG_WEP_KEY_MAP | - ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) & - IWM_STA_KEY_FLG_KEYID_MSK)); - memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len)); - cmd.common.key_offset = 0; - cmd.common.sta_id = IWM_STATION_ID; - - that->iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC, sizeof(cmd), &cmd); + + if ((k->k_flags & IEEE80211_KEY_GROUP) || + (k->k_cipher != IEEE80211_CIPHER_CCMP)) { + /* Fallback to software crypto for other ciphers. */ + ieee80211_delete_key(ic, ni, k); + return; + } + + if ((sc->sc_flags & IWM_FLAG_STA_ACTIVE) == 0) + return; + + if (!isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_TKIP_MIC_KEYS)) + return that->iwm_delete_key_v1(ic, ni, k); + + memset(&cmd, 0, sizeof(cmd)); + + cmd.common.key_flags = htole16(IWM_STA_KEY_NOT_VALID | + IWM_STA_KEY_FLG_NO_ENC | IWM_STA_KEY_FLG_WEP_KEY_MAP | + ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) & + IWM_STA_KEY_FLG_KEYID_MSK)); + memcpy(cmd.common.key, k->k_key, MIN(sizeof(cmd.common.key), k->k_len)); + cmd.common.key_offset = 0; + cmd.common.sta_id = IWM_STATION_ID; + + that->iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC, sizeof(cmd), &cmd); } void ItlIwm:: @@ -2735,7 +2752,7 @@ iwm_calib_timeout(void *arg) */ if (ni->ni_txrate != old_txrate) { XYLog("iwm_calib_timeout in->ni_txrate=%d\n", in->in_ni.ni_txrate); - that->iwm_setrates(in, 1); + iwl_mvm_send_lq_cmd(sc, &sc->lq_sta.rs_drv.lq); } } @@ -2744,180 +2761,6 @@ iwm_calib_timeout(void *arg) timeout_add_msec(&sc->sc_calib_to, 500); } -void ItlIwm:: -iwm_setrates(struct iwm_node *in, int async) -{ - struct ieee80211_node *ni = &in->in_ni; - struct ieee80211com *ic = ni->ni_ic; - struct iwm_softc *sc = (struct iwm_softc *)IC2IFP(ic)->if_softc; - struct iwm_lq_cmd lqcmd; - struct ieee80211_rateset *rs = &ni->ni_rates; - const struct ieee80211_ra_rate *ra_rate = ieee80211_ra_get_rateset(&in->in_rn, ic, ni, ni->ni_txmcs); - int i, ridx, ridx_min, ridx_max, j, sgi_ok = 0, mimo, tab = 0, is_40mhz = 0, is_80mhz = 0, is_160mhz = 0, ldpc = 0; - struct iwm_host_cmd cmd = { - .id = IWM_LQ_CMD, - .len = { sizeof(lqcmd), }, - }; - - cmd.flags = async ? IWM_CMD_ASYNC : 0; - - memset(&lqcmd, 0, sizeof(lqcmd)); - lqcmd.sta_id = IWM_STATION_ID; - - if (ic->ic_flags & IEEE80211_F_USEPROT) - lqcmd.flags |= IWM_LQ_FLAG_USE_RTS_MSK; - - if (ni->ni_chw == IEEE80211_CHAN_WIDTH_80P80 || ni->ni_chw == IEEE80211_CHAN_WIDTH_160) { - is_160mhz = 1; - } else if (ni->ni_chw == IEEE80211_CHAN_WIDTH_80) { - is_80mhz = 1; - } else if (ni->ni_chw == IEEE80211_CHAN_WIDTH_40) { - is_40mhz = 1; - } - - sgi_ok = ra_rate->sgi; - - if (ni->ni_flags & IEEE80211_NODE_VHT) { - if ((ni->ni_vhtcaps & IEEE80211_VHTCAP_RXLDPC) && (ic->ic_vhtcaps & IEEE80211_VHTCAP_RXLDPC)) - ldpc = 1; - } else if (ni->ni_flags & IEEE80211_NODE_HT) { - if ((ni->ni_htcaps & IEEE80211_HTCAP_LDPC) && (ic->ic_htcaps & IEEE80211_HTCAP_LDPC)) - ldpc = 1; - } - - /* - * Fill the LQ rate selection table with legacy and/or HT rates - * in descending order, i.e. with the node's current TX rate first. - * In cases where throughput of an HT rate corresponds to a legacy - * rate it makes no sense to add both. We rely on the fact that - * iwm_rates is laid out such that equivalent HT/legacy rates share - * the same IWM_RATE_*_INDEX value. Also, rates not applicable to - * legacy/HT are assumed to be marked with an 'invalid' PLCP value. - */ - j = 0; - ridx_min = iwm_rval2ridx(ieee80211_min_basic_rate(ic)); - mimo = ra_rate->nss > 1; - ridx_max = (mimo ? IWM_RIDX_MAX : ((ni->ni_flags & IEEE80211_NODE_VHT) ? IWM_LAST_VHT_SISO_RATE : IWM_LAST_HT_SISO_RATE)); - for (ridx = ridx_max; ridx >= ridx_min; ridx--) { - uint8_t plcp = iwm_rates[ridx].plcp; - uint8_t ht_plcp = iwm_rates[ridx].ht_plcp; - uint8_t vht_plcp = iwm_rates[ridx].vht_plcp; - - if (j >= nitems(lqcmd.rs_table)) - break; - tab = 0; - if (ni->ni_flags & IEEE80211_NODE_VHT) { - if (vht_plcp == IWM_RATE_VHT_SISO_MCS_INV_PLCP || vht_plcp == IWM_RATE_VHT_MIMO2_MCS_INV_PLCP) - continue; - if ((mimo && !iwm_is_mimo_vht_plcp(vht_plcp)) || - (!mimo && iwm_is_mimo_vht_plcp(vht_plcp))) - continue; - for (i = ni->ni_txmcs; i >= 0; i--) { - if ((in->in_rn.valid_rates & (1 << i)) == 0) - continue; - if (ridx == (mimo ? iwm_vht_mimo_mcs2ridx[i] : iwm_vht_siso_mcs2ridx[i])) { - tab = vht_plcp; - tab |= IWM_RATE_MCS_VHT_MSK; - if (is_40mhz) - tab |= IWM_RATE_MCS_CHAN_WIDTH_40; - if (is_80mhz) - tab |= IWM_RATE_MCS_CHAN_WIDTH_80; - if (is_160mhz) - tab |= IWM_RATE_MCS_CHAN_WIDTH_160; - if (sgi_ok) - tab |= IWM_RATE_MCS_SGI_MSK; - if (ldpc) - tab |= IWM_RATE_MCS_LDPC_MSK; - break; - } - } - } else if (ni->ni_flags & IEEE80211_NODE_HT) { - if (ht_plcp == IWM_RATE_HT_SISO_MCS_INV_PLCP) - continue; - /* Do not mix SISO and MIMO HT rates. */ - if ((mimo && !iwm_is_mimo_ht_plcp(ht_plcp)) || - (!mimo && iwm_is_mimo_ht_plcp(ht_plcp))) - continue; - for (i = ni->ni_txmcs; i >= 0; i--) { - if (isclr(ni->ni_rxmcs, i)) - continue; - if (ridx == iwm_mcs2ridx[i]) { - tab = ht_plcp; - tab |= IWM_RATE_MCS_HT_MSK; - if (sgi_ok) - tab |= IWM_RATE_MCS_SGI_MSK; - /* TODO: If we enable 40mhz Tx rate in 2.4ghz band, the data will all sent fail */ - if (is_40mhz && IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) - tab |= IWM_RATE_MCS_CHAN_WIDTH_40; - if (ldpc) - tab |= IWM_RATE_MCS_LDPC_MSK; - break; - } - } - } else if (plcp != IWM_RATE_INVM_PLCP) { - for (i = ni->ni_txmcs; i >= 0; i--) { - if (iwm_rates[ridx].rate == (rs->rs_rates[i] & - IEEE80211_RATE_VAL)) { - tab = plcp; - break; - } - } - } - - if (tab == 0) - continue; - - if (ni->ni_flags & IEEE80211_NODE_VHT) { - if (iwm_is_mimo_vht_plcp(vht_plcp)) - tab |= IWM_RATE_MCS_ANT_AB_MSK; - else if (sc->sc_device_family == IWM_DEVICE_FAMILY_9000 && - (iwm_fw_valid_tx_ant(sc) & IWM_ANT_B)) - tab |= IWM_RATE_MCS_ANT_B_MSK; - else - tab |= IWM_RATE_MCS_ANT_A_MSK; - } else if (iwm_is_mimo_ht_plcp(ht_plcp)) - tab |= IWM_RATE_MCS_ANT_AB_MSK; - else if (sc->sc_device_family == IWM_DEVICE_FAMILY_9000 && - (iwm_fw_valid_tx_ant(sc) & IWM_ANT_B)) - tab |= IWM_RATE_MCS_ANT_B_MSK; - else - tab |= IWM_RATE_MCS_ANT_A_MSK; - - if (IWM_RIDX_IS_CCK(ridx)) - tab |= IWM_RATE_MCS_CCK_MSK; - lqcmd.rs_table[j++] = htole32(tab); - } - - lqcmd.mimo_delim = (mimo ? j : 0); - - /* Fill the rest with the lowest possible rate */ - while (j < nitems(lqcmd.rs_table)) { - tab = iwm_rates[ridx_min].plcp; - if (IWM_RIDX_IS_CCK(ridx_min)) - tab |= IWM_RATE_MCS_CCK_MSK; - if (sc->sc_device_family == IWM_DEVICE_FAMILY_9000 && - (iwm_fw_valid_tx_ant(sc) & IWM_ANT_B)) - tab |= IWM_RATE_MCS_ANT_B_MSK; - else - tab |= IWM_RATE_MCS_ANT_A_MSK; - lqcmd.rs_table[j++] = htole32(tab); - } - - if (sc->sc_device_family == IWM_DEVICE_FAMILY_9000 && - (iwm_fw_valid_tx_ant(sc) & IWM_ANT_B)) - lqcmd.single_stream_ant_msk = IWM_ANT_B; - else - lqcmd.single_stream_ant_msk = IWM_ANT_A; - lqcmd.dual_stream_ant_msk = IWM_ANT_AB; - - lqcmd.agg_time_limit = htole16(iwm_coex_agg_time_limit(sc)); - lqcmd.agg_disable_start_th = 3; - lqcmd.agg_frame_cnt_limit = 0x3f; - - cmd.data[0] = &lqcmd; - iwm_send_cmd(sc, &cmd); -} - /* Allow multicast from our BSSID. */ int ItlIwm:: iwm_allow_mcast(struct iwm_softc *sc) @@ -2959,6 +2802,9 @@ iwm_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, tid > IWM_MAX_TID_COUNT) return ENOSPC; + if (ic->ic_state != IEEE80211_S_RUN) + return ENOSPC; + if (sc->ba_rx.start_tidmask & (1 << tid)) return EBUSY; @@ -2982,6 +2828,9 @@ iwm_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, if (tid > IWM_MAX_TID_COUNT || sc->ba_rx.stop_tidmask & (1 << tid)) return; + if (ic->ic_state != IEEE80211_S_RUN) + return; + sc->ba_rx.stop_tidmask |= (1 << tid); that->iwm_add_task(sc, systq, &sc->ba_task); } @@ -3101,6 +2950,7 @@ int ItlIwm::iwm_media_change(struct _ifnet *ifp) XYLog("%s\n", __FUNCTION__); struct iwm_softc *sc = (struct iwm_softc*)ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_node *ni = ic->ic_bss; uint8_t rate, ridx; int err; @@ -3108,14 +2958,17 @@ int ItlIwm::iwm_media_change(struct _ifnet *ifp) if (err != ENETRESET) return err; - if (ic->ic_fixed_mcs != -1) - sc->sc_fixed_ridx = iwm_mcs2ridx[ic->ic_fixed_mcs]; - else if (ic->ic_fixed_rate != -1) { + if (ic->ic_fixed_mcs != -1) { + if (ni->ni_flags & IEEE80211_NODE_VHT) + sc->sc_fixed_ridx = iwm_mcs2ridx[ic->ic_fixed_mcs]; + else if (ni->ni_flags & IEEE80211_NODE_HT) + sc->sc_fixed_ridx = iwm_mcs2ridx[ic->ic_fixed_mcs % 8]; + } else if (ic->ic_fixed_rate != -1) { rate = ic->ic_sup_rates[ic->ic_curmode]. rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; /* Map 802.11 rate to HW rate index. */ - for (ridx = 0; ridx <= IWM_RIDX_MAX; ridx++) - if (iwm_rates[ridx].rate == rate) + for (ridx = 0; ridx <= ieee80211_std_rateset_11g.rs_nrates; ridx++) + if (ieee80211_std_rateset_11g.rs_rates[ridx] == rate) break; sc->sc_fixed_ridx = ridx; } @@ -3736,10 +3589,8 @@ _iwm_start_task(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3 } ifp->netStat->outputPackets++; - if (ifp->if_flags & IFF_UP) { - sc->sc_tx_timer = 15; + if (ifp->if_flags & IFF_UP) ifp->if_timer = 1; - } } return kIOReturnSuccess; @@ -3822,7 +3673,8 @@ iwm_stop(struct _ifnet *ifp) iwm_clear_reorder_buffer(sc, rxba); } iwm_led_blink_stop(sc); - ifp->if_timer = sc->sc_tx_timer = 0; + memset(sc->sc_tx_timer, 0, sizeof(sc->sc_tx_timer)); + ifp->if_timer = 0; splx(s); } @@ -3832,22 +3684,31 @@ iwm_watchdog(struct _ifnet *ifp) { struct iwm_softc *sc = (struct iwm_softc *)ifp->if_softc; ItlIwm *that = container_of(sc, ItlIwm, com); + int i; ifp->if_timer = 0; - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - XYLog("%s: device timeout\n", DEVNAME(sc)); + + /* + * We maintain a separate timer for each Tx queue because + * Tx aggregation queues can get "stuck" while other queues + * keep working. The Linux driver uses a similar workaround. + */ + for (i = 0; i < nitems(sc->sc_tx_timer); i++) { + if (sc->sc_tx_timer[i] > 0) { + if (--sc->sc_tx_timer[i] == 0) { + XYLog("%s: device timeout\n", DEVNAME(sc)); #ifdef IWM_DEBUG - that->iwm_nic_error(sc); + that->iwm_nic_error(sc); #endif - if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0) { - task_add(systq, &sc->init_task); + if ((sc->sc_flags & IWM_FLAG_SHUTDOWN) == 0) { + task_add(systq, &sc->init_task); + } + XYLog("%s %d OUTPUT_ERROR\n", __FUNCTION__, __LINE__); + ifp->netStat->outputErrors++; + return; } - XYLog("%s %d OUTPUT_ERROR\n", __FUNCTION__, __LINE__); - ifp->netStat->outputErrors++; - return; + ifp->if_timer = 1; } - ifp->if_timer = 1; } ieee80211_watchdog(ifp); @@ -4562,6 +4423,9 @@ iwm_preinit(struct iwm_softc *sc) ieee80211_media_init(ifp); + iwm_rs_free(sc); + iwm_rs_alloc(sc); + return 0; } @@ -4591,7 +4455,6 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) pcireg_t reg, memtype; struct ieee80211com *ic = &sc->sc_ic; struct _ifnet *ifp = &ic->ic_if; - const char *intrstr = {0}; int err; int txq_i, i, j; @@ -4648,7 +4511,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) PCI_COMMAND_STATUS_REG, reg); } - int msiIntrIndex = 0; + int msiIntrIndex = -1; for (int index = 0; ; index++) { int interruptType; @@ -4661,6 +4524,11 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) break; } } + if (msiIntrIndex == -1) { + XYLog("%s: can't find MSI interrupt controller\n", DEVNAME(sc)); + return false; + } + if (sc->sc_msix) sc->sc_ih = IOFilterInterruptEventSource::filterInterruptEventSource(this, @@ -4672,15 +4540,10 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) (IOInterruptEventSource::Action)&ItlIwm::iwm_intr, &ItlIwm::intrFilter , pa->pa_tag, msiIntrIndex); if (sc->sc_ih == NULL || pa->workloop->addEventSource(sc->sc_ih) != kIOReturnSuccess) { - XYLog("\n"); - XYLog("%s: can't establish interrupt", DEVNAME(sc)); - if (intrstr != NULL) - XYLog(" at %s", intrstr); - XYLog("\n"); + XYLog("%s: can't establish interrupt\n", DEVNAME(sc)); return false; } sc->sc_ih->enable(); - XYLog(", %s\n", intrstr); sc->sc_hw_rev = IWM_READ(sc, IWM_CSR_HW_REV); int pa_id = pa->pa_tag->configRead16(kIOPCIConfigDeviceID); @@ -4694,6 +4557,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 16384; sc->nvm_type = IWM_NVM; sc->support_ldpc = 0; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_3165_1: case PCI_PRODUCT_INTEL_WL_3165_2: @@ -4704,6 +4568,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 16384; sc->nvm_type = IWM_NVM; sc->support_ldpc = 0; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_3168_1: sc->sc_fwname = "iwm-3168-29"; @@ -4713,6 +4578,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 16384; sc->nvm_type = IWM_NVM_SDP; sc->support_ldpc = 0; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_7260_1: case PCI_PRODUCT_INTEL_WL_7260_2: @@ -4723,6 +4589,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 16384; sc->nvm_type = IWM_NVM; sc->support_ldpc = 0; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_7265_1: case PCI_PRODUCT_INTEL_WL_7265_2: @@ -4733,6 +4600,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 16384; sc->nvm_type = IWM_NVM; sc->support_ldpc = 1; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_8260_1: case PCI_PRODUCT_INTEL_WL_8260_2: @@ -4743,6 +4611,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 32768; sc->nvm_type = IWM_NVM_EXT; sc->support_ldpc = 1; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_8265_1: sc->sc_fwname = "iwm-8265-36"; @@ -4752,6 +4621,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 32768; sc->nvm_type = IWM_NVM_EXT; sc->support_ldpc = 1; + sc->non_shared_ant = IWM_ANT_A; break; case PCI_PRODUCT_INTEL_WL_9260_1: sc->sc_fwname = "iwm-9260-46"; @@ -4761,6 +4631,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_nvm_max_section_size = 32768; sc->sc_mqrx_supported = 1; sc->support_ldpc = 1; + sc->non_shared_ant = IWM_ANT_B; break; case PCI_PRODUCT_INTEL_WL_9560_1: case PCI_PRODUCT_INTEL_WL_9560_2: @@ -4787,6 +4658,7 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) sc->sc_integrated = 1; sc->support_ldpc = 1; sc->sc_xtal_latency = 650; + sc->non_shared_ant = IWM_ANT_B; break; default: XYLog("%s: unknown adapter type\n", DEVNAME(sc)); @@ -4931,6 +4803,9 @@ iwm_attach(struct iwm_softc *sc, struct pci_attach_args *pa) ic->ic_ampdu_params = (IEEE80211_AMPDU_PARAM_SS_4 | 0x3 /* 64k */); ic->ic_caps |= (IEEE80211_C_QOS | IEEE80211_C_TX_AMPDU | IEEE80211_C_AMSDU_IN_AMPDU); ic->ic_caps |= IEEE80211_C_SUPPORTS_VHT_EXT_NSS_BW; +#if 0 + ic->ic_caps |= IEEE80211_C_TX_AMPDU_SETUP_IN_RS; +#endif ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_std_rateset_11a; ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; @@ -5131,12 +5006,9 @@ iwm_chan_ctxt_task(void *arg) splx(s); return; } - - if (in->in_rn.bw != in->in_ni.ni_chw) { - ieee80211_ra_node_init(ic, &in->in_rn, &in->in_ni); - ieee80211_ra_choose(&in->in_rn, ic, &in->in_ni); - } - that->iwm_setrates((struct iwm_node *)ic->ic_bss, 0); + + rs_drv_rate_update(sc, &in->in_ni, IEEE80211_IS_CHAN_2GHZ(in->in_ni.ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, true); + iwl_mvm_send_lq_cmd(sc, &sc->lq_sta.rs_drv.lq); // refcnt_rele_wake(&sc->task_refs); splx(s); @@ -5179,6 +5051,7 @@ iwm_ba_task(void *arg) struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid]; int qid = IWM_FIRST_AGG_TX_QUEUE + tid; struct iwm_tx_ring *ring = &sc->txq[qid]; + struct iwm_tx_ba *tx_ba; uint16_t ssn = ba->ba_winstart; if (sc->ba_tx.start_tidmask & (1 << tid)) { uint8_t fifo = iwm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; @@ -5208,6 +5081,12 @@ iwm_ba_task(void *arg) ba->ba_bitmap = 0; if (!that->iwm_sta_tx_agg(sc, ni, tid, 0, ssn, 1)) { ieee80211_addba_resp_accept(ic, ni, tid); + sc->lq_sta.rs_drv.lq.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + + XYLog("Tx aggregation enabled on ra = %s tid = %d\n", + ether_sprintf(ni->ni_macaddr), tid); + + iwl_mvm_send_lq_cmd(sc, &sc->lq_sta.rs_drv.lq); } else { out: ieee80211_addba_resp_refuse(ic, ni, tid, @@ -5216,9 +5095,20 @@ iwm_ba_task(void *arg) that->iwm_nic_unlock(sc); sc->ba_tx.start_tidmask &= ~(1 << tid); } else if (sc->ba_tx.stop_tidmask & (1 << tid)) { + sc->agg_tid_disable |= (1 << tid); that->iwm_sta_tx_agg(sc, ni, tid, 0, 0, 0); that->iwm_ampdu_txq_advance(sc, ring, ring->cur); that->iwm_clear_oactive(sc, ring); + /* In DQA-mode the queue isn't removed on agg termination */ + tx_ba = &sc->sc_tx_ba[tid]; + tx_ba->wn = NULL; + tx_ba->lq_color = 0; + tx_ba->rate_n_flags = 0; + tx_ba->tpt_meas_start = 0; + tx_ba->tx_count = 0; + tx_ba->tx_count_last = 0; + tx_ba->tx_time = 0; + ba->ba_bitmap = 0; sc->ba_tx.stop_tidmask &= ~(1 << tid); } } diff --git a/itlwm/hal_iwm/rs.cpp b/itlwm/hal_iwm/rs.cpp new file mode 100644 index 000000000..fceed1cbe --- /dev/null +++ b/itlwm/hal_iwm/rs.cpp @@ -0,0 +1,3641 @@ +// +// rs.cpp +// itlwm +// +// Created by zxystd on 2021/8/27. +// Copyright © 2021 钟先耀. All rights reserved. +// + +#include "ItlIwm.hpp" + +#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ + +/* Calculations of success ratio are done in fixed point where 12800 is 100%. + * Use this macro when dealing with thresholds consts set as a percentage + */ +#define RS_PERCENT(x) (128 * x) + +static u8 rs_ht_to_legacy[] = { + [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, + [IWL_RATE_MCS_1_INDEX] = IWL_RATE_9M_INDEX, + [IWL_RATE_MCS_2_INDEX] = IWL_RATE_12M_INDEX, + [IWL_RATE_MCS_3_INDEX] = IWL_RATE_18M_INDEX, + [IWL_RATE_MCS_4_INDEX] = IWL_RATE_24M_INDEX, + [IWL_RATE_MCS_5_INDEX] = IWL_RATE_36M_INDEX, + [IWL_RATE_MCS_6_INDEX] = IWL_RATE_48M_INDEX, + [IWL_RATE_MCS_7_INDEX] = IWL_RATE_54M_INDEX, + [IWL_RATE_MCS_8_INDEX] = IWL_RATE_54M_INDEX, + [IWL_RATE_MCS_9_INDEX] = IWL_RATE_54M_INDEX, +}; + +static const u8 ant_toggle_lookup[] = { + [ANT_NONE] = ANT_NONE, + [ANT_A] = ANT_B, + [ANT_B] = ANT_A, + [ANT_AB] = ANT_AB, +}; + +#define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ + [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ + IWL_RATE_HT_SISO_MCS_##s##_PLCP, \ + IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \ + IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \ + IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP,\ + IWL_RATE_##rp##M_INDEX, \ + IWL_RATE_##rn##M_INDEX } + +#define IWL_DECLARE_MCS_RATE(s) \ + [IWL_RATE_MCS_##s##_INDEX] = { IWL_RATE_INVM_PLCP, \ + IWL_RATE_HT_SISO_MCS_##s##_PLCP, \ + IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \ + IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \ + IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP, \ + IWL_RATE_INVM_INDEX, \ + IWL_RATE_INVM_INDEX } + +/* + * Parameter order: + * rate, ht rate, prev rate, next rate + * + * If there isn't a valid next or previous rate then INV is used which + * maps to IWL_RATE_INVALID + * + */ +struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { + IWL_DECLARE_RATE_INFO(1, INV, INV, 2), /* 1mbps */ + IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ + IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ + IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ + IWL_DECLARE_RATE_INFO(6, 0, 5, 11), /* 6mbps ; MCS 0 */ + IWL_DECLARE_RATE_INFO(9, INV, 6, 11), /* 9mbps */ + IWL_DECLARE_RATE_INFO(12, 1, 11, 18), /* 12mbps ; MCS 1 */ + IWL_DECLARE_RATE_INFO(18, 2, 12, 24), /* 18mbps ; MCS 2 */ + IWL_DECLARE_RATE_INFO(24, 3, 18, 36), /* 24mbps ; MCS 3 */ + IWL_DECLARE_RATE_INFO(36, 4, 24, 48), /* 36mbps ; MCS 4 */ + IWL_DECLARE_RATE_INFO(48, 5, 36, 54), /* 48mbps ; MCS 5 */ + IWL_DECLARE_RATE_INFO(54, 6, 48, INV), /* 54mbps ; MCS 6 */ + IWL_DECLARE_MCS_RATE(7), /* MCS 7 */ + IWL_DECLARE_MCS_RATE(8), /* MCS 8 */ + IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ +}; + +enum rs_action { + RS_ACTION_STAY = 0, + RS_ACTION_DOWNSCALE = -1, + RS_ACTION_UPSCALE = 1, +}; + +enum rs_column_mode { + RS_INVALID = 0, + RS_LEGACY, + RS_SISO, + RS_MIMO2, +}; + +#define MAX_NEXT_COLUMNS 7 +#define MAX_COLUMN_CHECKS 3 + +struct rs_tx_column; + +typedef bool (*allow_column_func_t) (struct iwm_softc *sc, + struct ieee80211_node *ni, + struct rs_rate *rate, + const struct rs_tx_column *next_col); + +struct rs_tx_column { + enum rs_column_mode mode; + u8 ant; + bool sgi; + enum rs_column next_columns[MAX_NEXT_COLUMNS]; + allow_column_func_t checks[MAX_COLUMN_CHECKS]; +}; + +static bool rs_ant_allow(struct iwm_softc *sc, struct ieee80211_node *ni, + struct rs_rate *rate, + const struct rs_tx_column *next_col) +{ + return ItlIwm::iwm_coex_is_ant_avail(sc, next_col->ant); +} + +static bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwm_softc *sc, struct ieee80211_node *ni) +{ + return ItlIwm::iwm_coex_is_mimo_allowed(sc, ni); +} + +static bool rs_mimo_allow(struct iwm_softc *sc, struct ieee80211_node *ni, + struct rs_rate *rate, + const struct rs_tx_column *next_col) +{ + ItlIwm *that = container_of(sc, ItlIwm, com); + + if (!ieee80211_node_supports_ht(ni)) + return false; + +// if (sta->smps_mode == IEEE80211_SMPS_STATIC) +// return false; + + if (that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(sc)) < 2) + return false; + + if (!iwl_mvm_bt_coex_is_mimo_allowed(sc, ni)) + return false; + + if (sc->sc_nvm.sku_cap_mimo_disable) + return false; + + return true; +} + +static bool rs_siso_allow(struct iwm_softc *sc, struct ieee80211_node *ni, + struct rs_rate *rate, + const struct rs_tx_column *next_col) +{ + if (!ieee80211_node_supports_ht(ni)) + return false; + + return true; +} + +static bool rs_sgi_allow(struct iwm_softc *sc, struct ieee80211_node *ni, + struct rs_rate *rate, + const struct rs_tx_column *next_col) +{ + if (is_ht20(rate) && (ieee80211_node_supports_ht_sgi20(ni))) + return true; + if (is_ht40(rate) && (ieee80211_node_supports_ht_sgi40(ni))) + return true; + if (is_ht80(rate) && (ieee80211_node_supports_vht_sgi80(ni))) + return true; + if (is_ht160(rate) && (ieee80211_node_supports_vht_sgi160(ni))) + return true; + + return false; +} + +static const struct rs_tx_column rs_tx_columns[] = { + [RS_COLUMN_LEGACY_ANT_A] = { + .mode = RS_LEGACY, + .ant = ANT_A, + .next_columns = { + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_MIMO2, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_ant_allow, + }, + }, + [RS_COLUMN_LEGACY_ANT_B] = { + .mode = RS_LEGACY, + .ant = ANT_B, + .next_columns = { + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_MIMO2, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_ant_allow, + }, + }, + [RS_COLUMN_SISO_ANT_A] = { + .mode = RS_SISO, + .ant = ANT_A, + .next_columns = { + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_MIMO2, + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + rs_ant_allow, + }, + }, + [RS_COLUMN_SISO_ANT_B] = { + .mode = RS_SISO, + .ant = ANT_B, + .next_columns = { + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_MIMO2, + RS_COLUMN_SISO_ANT_B_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + rs_ant_allow, + }, + }, + [RS_COLUMN_SISO_ANT_A_SGI] = { + .mode = RS_SISO, + .ant = ANT_A, + .sgi = true, + .next_columns = { + RS_COLUMN_SISO_ANT_B_SGI, + RS_COLUMN_MIMO2_SGI, + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + rs_ant_allow, + rs_sgi_allow, + }, + }, + [RS_COLUMN_SISO_ANT_B_SGI] = { + .mode = RS_SISO, + .ant = ANT_B, + .sgi = true, + .next_columns = { + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_MIMO2_SGI, + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_siso_allow, + rs_ant_allow, + rs_sgi_allow, + }, + }, + [RS_COLUMN_MIMO2] = { + .mode = RS_MIMO2, + .ant = ANT_AB, + .next_columns = { + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_mimo_allow, + }, + }, + [RS_COLUMN_MIMO2_SGI] = { + .mode = RS_MIMO2, + .ant = ANT_AB, + .sgi = true, + .next_columns = { + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, + }, + .checks = { + rs_mimo_allow, + rs_sgi_allow, + }, + }, +}; + +static inline u8 rs_extract_rate(u32 rate_n_flags) +{ + /* also works for HT because bits 7:6 are zero there */ + return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK); +} + +static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) +{ + int idx = 0; + + if (rate_n_flags & RATE_MCS_HT_MSK) { + idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK; + idx += IWL_RATE_MCS_0_INDEX; + + /* skip 9M not supported in HT*/ + if (idx >= IWL_RATE_9M_INDEX) + idx += 1; + if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE)) + return idx; + } else if (rate_n_flags & RATE_MCS_VHT_MSK || + rate_n_flags & RATE_MCS_HE_MSK) { + idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; + idx += IWL_RATE_MCS_0_INDEX; + + /* skip 9M not supported in VHT*/ + if (idx >= IWL_RATE_9M_INDEX) + idx++; + if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE)) + return idx; + if ((rate_n_flags & RATE_MCS_HE_MSK) && + (idx <= IWL_LAST_HE_RATE)) + return idx; + } else { + /* legacy rate format, search for match in table */ + + u8 legacy_rate = rs_extract_rate(rate_n_flags); + for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) + if (iwl_rates[idx].plcp == legacy_rate) + return idx; + } + + return IWL_RATE_INVALID; +} + +static void rs_rate_scale_perform(struct iwm_softc *sc, + struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta, + int tid, bool ndp); +static void rs_fill_lq_cmd(struct iwm_softc *sc, + struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta, + const struct rs_rate *initial_rate); +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); + +/* + * The following tables contain the expected throughput metrics for all rates + * + * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits + * + * where invalid entries are zeros. + * + * CCK rates are only valid in legacy table and will only be used in G + * (2.4 GHz) band. + */ +static const u16 expected_tpt_legacy[IWL_RATE_COUNT] = { + 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0 +}; + +/* Expected TpT tables. 4 indexes: + * 0 - NGI, 1 - SGI, 2 - AGG+NGI, 3 - AGG+SGI + */ +static const u16 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202, 216, 0}, + {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210, 225, 0}, + {0, 0, 0, 0, 49, 0, 97, 145, 192, 285, 375, 420, 464, 551, 0}, + {0, 0, 0, 0, 54, 0, 108, 160, 213, 315, 415, 465, 513, 608, 0}, +}; + +static const u16 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257, 269, 275}, + {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264, 275, 280}, + {0, 0, 0, 0, 101, 0, 199, 295, 389, 570, 744, 828, 911, 1070, 1173}, + {0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284}, +}; + +static const u16 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 130, 0, 191, 223, 244, 273, 288, 294, 298, 305, 308}, + {0, 0, 0, 0, 138, 0, 200, 231, 251, 279, 293, 298, 302, 308, 312}, + {0, 0, 0, 0, 217, 0, 429, 634, 834, 1220, 1585, 1760, 1931, 2258, 2466}, + {0, 0, 0, 0, 241, 0, 475, 701, 921, 1343, 1741, 1931, 2117, 2468, 2691}, +}; + +static const u16 expected_tpt_siso_160MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 191, 0, 244, 288, 298, 308, 313, 318, 323, 328, 330}, + {0, 0, 0, 0, 200, 0, 251, 293, 302, 312, 317, 322, 327, 332, 334}, + {0, 0, 0, 0, 439, 0, 875, 1307, 1736, 2584, 3419, 3831, 4240, 5049, 5581}, + {0, 0, 0, 0, 488, 0, 972, 1451, 1925, 2864, 3785, 4240, 4691, 5581, 6165}, +}; + +static const u16 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250, 261, 0}, + {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256, 267, 0}, + {0, 0, 0, 0, 98, 0, 193, 286, 375, 550, 718, 799, 878, 1032, 0}, + {0, 0, 0, 0, 109, 0, 214, 316, 414, 607, 790, 879, 965, 1132, 0}, +}; + +static const u16 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289, 296, 300}, + {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293, 300, 303}, + {0, 0, 0, 0, 200, 0, 390, 571, 741, 1067, 1365, 1505, 1640, 1894, 2053}, + {0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221}, +}; + +static const u16 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 182, 0, 240, 264, 278, 299, 308, 311, 313, 317, 319}, + {0, 0, 0, 0, 190, 0, 247, 269, 282, 302, 310, 313, 315, 319, 320}, + {0, 0, 0, 0, 428, 0, 833, 1215, 1577, 2254, 2863, 3147, 3418, 3913, 4219}, + {0, 0, 0, 0, 474, 0, 920, 1338, 1732, 2464, 3116, 3418, 3705, 4225, 4545}, +}; + +static const u16 expected_tpt_mimo2_160MHz[4][IWL_RATE_COUNT] = { + {0, 0, 0, 0, 240, 0, 278, 308, 313, 319, 322, 324, 328, 330, 334}, + {0, 0, 0, 0, 247, 0, 282, 310, 315, 320, 323, 325, 329, 332, 338}, + {0, 0, 0, 0, 875, 0, 1735, 2582, 3414, 5043, 6619, 7389, 8147, 9629, 10592}, + {0, 0, 0, 0, 971, 0, 1925, 2861, 3779, 5574, 7304, 8147, 8976, 10592, 11640}, +}; + +/* mbps, mcs */ +static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { + { "1", "BPSK DSSS"}, + { "2", "QPSK DSSS"}, + {"5.5", "BPSK CCK"}, + { "11", "QPSK CCK"}, + { "6", "BPSK 1/2"}, + { "9", "BPSK 1/2"}, + { "12", "QPSK 1/2"}, + { "18", "QPSK 3/4"}, + { "24", "16QAM 1/2"}, + { "36", "16QAM 3/4"}, + { "48", "64QAM 2/3"}, + { "54", "64QAM 3/4"}, + { "60", "64QAM 5/6"}, +}; + +#define MCS_INDEX_PER_STREAM (8) + +static const char *rs_pretty_ant(u8 ant) +{ + static const char * const ant_name[] = { + [ANT_NONE] = "None", + [ANT_A] = "A", + [ANT_B] = "B", + [ANT_AB] = "AB", + [ANT_C] = "C", + [ANT_AC] = "AC", + [ANT_BC] = "BC", + [ANT_ABC] = "ABC", + }; + + if (ant > ANT_ABC) + return "UNKNOWN"; + + return ant_name[ant]; +} + +static const char *rs_pretty_lq_type(enum iwl_table_type type) +{ + static const char * const lq_types[] = { + [LQ_NONE] = "NONE", + [LQ_LEGACY_A] = "LEGACY_A", + [LQ_LEGACY_G] = "LEGACY_G", + [LQ_HT_SISO] = "HT SISO", + [LQ_HT_MIMO2] = "HT MIMO", + [LQ_VHT_SISO] = "VHT SISO", + [LQ_VHT_MIMO2] = "VHT MIMO", + [LQ_HE_SISO] = "HE SISO", + [LQ_HE_MIMO2] = "HE MIMO", + }; + + if (type < LQ_NONE || type >= LQ_MAX) + return "UNKNOWN"; + + return lq_types[type]; +} + +static char *rs_pretty_rate(const struct rs_rate *rate) +{ + static char buf[40]; + static const char * const legacy_rates[] = { + [IWL_RATE_1M_INDEX] = "1M", + [IWL_RATE_2M_INDEX] = "2M", + [IWL_RATE_5M_INDEX] = "5.5M", + [IWL_RATE_11M_INDEX] = "11M", + [IWL_RATE_6M_INDEX] = "6M", + [IWL_RATE_9M_INDEX] = "9M", + [IWL_RATE_12M_INDEX] = "12M", + [IWL_RATE_18M_INDEX] = "18M", + [IWL_RATE_24M_INDEX] = "24M", + [IWL_RATE_36M_INDEX] = "36M", + [IWL_RATE_48M_INDEX] = "48M", + [IWL_RATE_54M_INDEX] = "54M", + }; + static const char *const ht_vht_rates[] = { + [IWL_RATE_MCS_0_INDEX] = "MCS0", + [IWL_RATE_MCS_1_INDEX] = "MCS1", + [IWL_RATE_MCS_2_INDEX] = "MCS2", + [IWL_RATE_MCS_3_INDEX] = "MCS3", + [IWL_RATE_MCS_4_INDEX] = "MCS4", + [IWL_RATE_MCS_5_INDEX] = "MCS5", + [IWL_RATE_MCS_6_INDEX] = "MCS6", + [IWL_RATE_MCS_7_INDEX] = "MCS7", + [IWL_RATE_MCS_8_INDEX] = "MCS8", + [IWL_RATE_MCS_9_INDEX] = "MCS9", + }; + const char *rate_str; + + if (is_type_legacy(rate->type) && (rate->index <= IWL_RATE_54M_INDEX)) + rate_str = legacy_rates[rate->index]; + else if ((is_type_ht(rate->type) || is_type_vht(rate->type)) && + (rate->index >= IWL_RATE_MCS_0_INDEX) && + (rate->index <= IWL_RATE_MCS_9_INDEX)) + rate_str = ht_vht_rates[rate->index]; + else + rate_str = NULL; + + snprintf(buf, sizeof(buf), "(%s|%s|%s)", rs_pretty_lq_type(rate->type), + rs_pretty_ant(rate->ant), rate_str ?: "BAD_RATE"); + return buf; +} + +static inline void rs_dump_rate(struct iwm_softc *sc, const struct rs_rate *rate, + const char *prefix) +{ + IWL_DEBUG_RATE(sc, + "%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", + prefix, rs_pretty_rate(rate), rate->bw, + rate->sgi, rate->ldpc, rate->stbc); +} + +static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) +{ + window->data = 0; + window->success_counter = 0; + window->success_ratio = IWL_INVALID_VALUE; + window->counter = 0; + window->average_tpt = IWL_INVALID_VALUE; +} + +static void rs_rate_scale_clear_tbl_windows(struct iwm_softc *sc, + struct iwl_scale_tbl_info *tbl) +{ + int i; + + IWL_DEBUG_RATE(sc, "Clearing up window stats\n"); + for (i = 0; i < IWL_RATE_COUNT; i++) + rs_rate_scale_clear_window(&tbl->win[i]); + + for (i = 0; i < ARRAY_SIZE(tbl->tpc_win); i++) + rs_rate_scale_clear_window(&tbl->tpc_win[i]); +} + +static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) +{ + return (ant_type & valid_antenna) == ant_type; +} + +extern int ieee80211_can_use_ampdu(struct ieee80211com *, + struct ieee80211_node *); + +static int rs_tl_turn_on_agg_for_tid(struct iwm_softc *sc, + struct iwl_lq_sta *lq_data, u8 tid, + struct ieee80211_node *ni) +{ + IWL_DEBUG_RATE(sc, "Starting Tx agg: STA: %s tid: %d\n", + ether_sprintf(ni->ni_macaddr), tid); + + /* start BA session until the peer sends del BA */ + if (!ieee80211_can_use_ampdu(&sc->sc_ic, ni)) + return -1; + ieee80211_node_trigger_addba_req(ni, tid); + return 0; +} + +static void rs_tl_turn_on_agg(struct iwm_softc *sc, + u8 tid, struct iwl_lq_sta *lq_sta, + struct ieee80211_node *ni) +{ + struct iwm_tx_ba *tid_data; + struct ieee80211_tx_ba *tx_ba; + struct ieee80211com *ic = &sc->sc_ic; + + if ((ic->ic_caps & IEEE80211_C_TX_AMPDU_SETUP_IN_RS) == 0) + return; + + /* + * In AP mode, tid can be equal to IWL_MAX_TID_COUNT + * when the frame is not QoS + */ + if (WARN_ON_ONCE(tid > IWL_MAX_TID_COUNT)) { + IWL_ERR(mvm, "tid exceeds max TID count: %d/%d\n", + tid, IWL_MAX_TID_COUNT); + return; + } else if (tid == IWL_MAX_TID_COUNT) { + return; + } + + tx_ba = &ni->ni_tx_ba[tid]; + tid_data = &sc->sc_tx_ba[tid]; + if (sc->sc_ic.ic_state >= IEEE80211_S_RUN && + tx_ba->ba_state == IEEE80211_BA_INIT && + (lq_sta->tx_agg_tid_en & BIT(tid)) && + tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD) { + IWL_DEBUG_RATE("RS: try to aggregate tid %d\n", tid); + rs_tl_turn_on_agg_for_tid(sc, lq_sta, tid, ni); + } +} + +static inline int get_num_of_ant_from_rate(u32 rate_n_flags) +{ + return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + + !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + + !!(rate_n_flags & RATE_MCS_ANT_C_MSK); +} + +/* + * Static function to get the expected throughput from an iwl_scale_tbl_info + * that wraps a NULL pointer check + */ +static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) +{ + if (tbl->expected_tpt) + return tbl->expected_tpt[rs_index]; + return 0; +} + +/* + * rs_collect_tx_data - Update the success/failure sliding window + * + * We keep a sliding window of the last 62 packets transmitted + * at this rate. window->data contains the bitmask of successful + * packets. + */ +static int _rs_collect_tx_data(struct iwm_softc *sc, + struct iwl_scale_tbl_info *tbl, + int scale_index, int attempts, int successes, + struct iwl_rate_scale_data *window) +{ + static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); + s32 fail_count, tpt; + + /* Get expected throughput */ + tpt = get_expected_tpt(tbl, scale_index); + + /* + * Keep track of only the latest 62 tx frame attempts in this rate's + * history window; anything older isn't really relevant any more. + * If we have filled up the sliding window, drop the oldest attempt; + * if the oldest attempt (highest bit in bitmap) shows "success", + * subtract "1" from the success counter (this is the main reason + * we keep these bitmaps!). + */ + while (attempts > 0) { + if (window->counter >= IWL_RATE_MAX_WINDOW) { + /* remove earliest */ + window->counter = IWL_RATE_MAX_WINDOW - 1; + + if (window->data & mask) { + window->data &= ~mask; + window->success_counter--; + } + } + + /* Increment frames-attempted counter */ + window->counter++; + + /* Shift bitmap by one frame to throw away oldest history */ + window->data <<= 1; + + /* Mark the most recent #successes attempts as successful */ + if (successes > 0) { + window->success_counter++; + window->data |= 0x1; + successes--; + } + + attempts--; + } + + /* Calculate current success ratio, avoid divide-by-0! */ + if (window->counter > 0) + window->success_ratio = 128 * (100 * window->success_counter) + / window->counter; + else + window->success_ratio = IWL_INVALID_VALUE; + + fail_count = window->counter - window->success_counter; + + /* Calculate average throughput, if we have enough history. */ + if ((fail_count >= IWL_MVM_RS_RATE_MIN_FAILURE_TH) || + (window->success_counter >= IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) + window->average_tpt = (window->success_ratio * tpt + 64) / 128; + else + window->average_tpt = IWL_INVALID_VALUE; + + return 0; +} + +static int rs_collect_tpc_data(struct iwm_softc *sc, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + int scale_index, int attempts, int successes, + u8 reduced_txp) +{ + struct iwl_rate_scale_data *window = NULL; + + if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) + return -EINVAL; + + window = &tbl->tpc_win[reduced_txp]; + return _rs_collect_tx_data(sc, tbl, scale_index, attempts, successes, + window); +} + +static void rs_update_tid_tpt_stats(struct iwm_softc *sc, + u8 tid, int successes) +{ + if (tid >= IWL_MAX_TID_COUNT) + return; + + struct iwm_tx_ba *tid_data = &sc->sc_tx_ba[tid]; + + /* + * Measure if there're enough successful transmits per second. + * These statistics are used only to decide if we can start a + * BA session, so it should be updated only when A-MPDU is + * off. + */ + if (tid_data->wn != NULL) + return; + + if (time_is_before_jiffies(tid_data->tpt_meas_start + hz) || + (tid_data->tx_count >= IWL_MVM_RS_AGG_START_THRESHOLD)) { + tid_data->tx_count_last = tid_data->tx_count; + tid_data->tx_count = 0; + tid_data->tpt_meas_start = ticks; + } else { + tid_data->tx_count += successes; + } +} + +static int rs_collect_tlc_data(struct iwm_softc *sc, + u8 tid, + struct iwl_scale_tbl_info *tbl, + int scale_index, int attempts, int successes) +{ + struct iwl_rate_scale_data *window = NULL; + + if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) + return -EINVAL; + + if (tbl->column != RS_COLUMN_INVALID) { + struct lq_sta_pers *pers = &sc->lq_sta.rs_drv.pers; + + pers->tx_stats[tbl->column][scale_index].total += attempts; + pers->tx_stats[tbl->column][scale_index].success += successes; + } + + rs_update_tid_tpt_stats(sc, tid, successes); + + /* Select window for current tx bit rate */ + window = &(tbl->win[scale_index]); + return _rs_collect_tx_data(sc, tbl, scale_index, attempts, successes, + window); +} + +/* Convert rs_rate object into ucode rate bitmask */ +static u32 ucode_rate_from_rs_rate(struct iwm_softc *sc, + struct rs_rate *rate) +{ + u32 ucode_rate = 0; + int index = rate->index; + + ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) & + RATE_MCS_ANT_ABC_MSK); + + if (is_legacy(rate)) { + ucode_rate |= iwl_rates[index].plcp; + if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) + ucode_rate |= RATE_MCS_CCK_MSK; + return ucode_rate; + } + + /* set RTS protection for all non legacy rates + * This helps with congested environments reducing the conflict cost to + * RTS retries only, instead of the entire BA packet. + */ + ucode_rate |= RATE_MCS_RTS_REQUIRED_MSK; + + if (is_ht(rate)) { + if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) { + IWL_ERR(mvm, "Invalid HT rate index %d\n", index); + index = IWL_LAST_HT_RATE; + } + ucode_rate |= RATE_MCS_HT_MSK; + + if (is_ht_siso(rate)) + ucode_rate |= iwl_rates[index].plcp_ht_siso; + else if (is_ht_mimo2(rate)) + ucode_rate |= iwl_rates[index].plcp_ht_mimo2; + else + WARN_ON_ONCE(1); + } else if (is_vht(rate)) { + if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) { + IWL_ERR(mvm, "Invalid VHT rate index %d\n", index); + index = IWL_LAST_VHT_RATE; + } + ucode_rate |= RATE_MCS_VHT_MSK; + if (is_vht_siso(rate)) + ucode_rate |= iwl_rates[index].plcp_vht_siso; + else if (is_vht_mimo2(rate)) + ucode_rate |= iwl_rates[index].plcp_vht_mimo2; + else + WARN_ON_ONCE(1); + + } else { + IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); + } + + if (is_siso(rate) && rate->stbc) { + /* To enable STBC we need to set both a flag and ANT_AB */ + ucode_rate |= RATE_MCS_ANT_AB_MSK; + ucode_rate |= RATE_MCS_STBC_MSK; + } + + ucode_rate |= rate->bw; + if (rate->sgi) + ucode_rate |= RATE_MCS_SGI_MSK; + if (rate->ldpc) + ucode_rate |= RATE_MCS_LDPC_MSK; + + return ucode_rate; +} + +/* Convert a ucode rate into an rs_rate object */ +static int rs_rate_from_ucode_rate(const u32 ucode_rate, + enum nl80211_band band, + struct rs_rate *rate) +{ + u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK; + u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate); + u8 nss; + + memset(rate, 0, sizeof(*rate)); + rate->index = iwl_hwrate_to_plcp_idx(ucode_rate); + + if (rate->index == IWL_RATE_INVALID) + return -EINVAL; + + rate->ant = (ant_msk >> RATE_MCS_ANT_POS); + + /* Legacy */ + if (!(ucode_rate & RATE_MCS_HT_MSK) && + !(ucode_rate & RATE_MCS_VHT_MSK) && + !(ucode_rate & RATE_MCS_HE_MSK)) { + if (num_of_ant == 1) { + if (band == NL80211_BAND_5GHZ) + rate->type = LQ_LEGACY_A; + else + rate->type = LQ_LEGACY_G; + } + + return 0; + } + + /* HT, VHT or HE */ + if (ucode_rate & RATE_MCS_SGI_MSK) + rate->sgi = true; + if (ucode_rate & RATE_MCS_LDPC_MSK) + rate->ldpc = true; + if (ucode_rate & RATE_MCS_STBC_MSK) + rate->stbc = true; + if (ucode_rate & RATE_MCS_BF_MSK) + rate->bfer = true; + + rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; + + if (ucode_rate & RATE_MCS_HT_MSK) { + nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >> + RATE_HT_MCS_NSS_POS) + 1; + + if (nss == 1) { + rate->type = LQ_HT_SISO; + WARN_ON(!rate->stbc && !rate->bfer && num_of_ant != 1, + "stbc %d bfer %d", + rate->stbc, rate->bfer); + } else if (nss == 2) { + rate->type = LQ_HT_MIMO2; + WARN_ON_ONCE(num_of_ant != 2); + } else { + WARN_ON_ONCE(1); + } + } else if (ucode_rate & RATE_MCS_VHT_MSK) { + nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >> + RATE_VHT_MCS_NSS_POS) + 1; + + if (nss == 1) { + rate->type = LQ_VHT_SISO; + WARN_ON(!rate->stbc && !rate->bfer && num_of_ant != 1, + "stbc %d bfer %d", + rate->stbc, rate->bfer); + } else if (nss == 2) { + rate->type = LQ_VHT_MIMO2; + WARN_ON_ONCE(num_of_ant != 2); + } else { + WARN_ON_ONCE(1); + } + } else if (ucode_rate & RATE_MCS_HE_MSK) { + nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >> + RATE_VHT_MCS_NSS_POS) + 1; + + if (nss == 1) { + rate->type = LQ_HE_SISO; + WARN_ON(!rate->stbc && !rate->bfer && num_of_ant != 1, + "stbc %d bfer %d", rate->stbc, rate->bfer); + } else if (nss == 2) { + rate->type = LQ_HE_MIMO2; + WARN_ON_ONCE(num_of_ant != 2); + } else { + WARN_ON_ONCE(1); + } + } + + WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_80 && + !is_he(rate) && !is_vht(rate)); + + return 0; +} + +/* switch to another antenna/antennas and return 1 */ +/* if no other valid antenna found, return 0 */ +static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate) +{ + u8 new_ant_type; + + if (!rate->ant || WARN_ON_ONCE(rate->ant & ANT_C)) + return 0; + + if (!rs_is_valid_ant(valid_ant, rate->ant)) + return 0; + + new_ant_type = ant_toggle_lookup[rate->ant]; + + while ((new_ant_type != rate->ant) && + !rs_is_valid_ant(valid_ant, new_ant_type)) + new_ant_type = ant_toggle_lookup[new_ant_type]; + + if (new_ant_type == rate->ant) + return 0; + + rate->ant = new_ant_type; + + return 1; +} + +static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, + struct rs_rate *rate) +{ + if (is_legacy(rate)) + return lq_sta->active_legacy_rate; + else if (is_siso(rate)) + return lq_sta->active_siso_rate; + else if (is_mimo2(rate)) + return lq_sta->active_mimo2_rate; + + WARN_ON_ONCE(1); + return 0; +} + +static u16 rs_get_adjacent_rate(struct iwm_softc *sc, u8 index, u16 rate_mask, + int rate_type) +{ + u8 high = IWL_RATE_INVALID; + u8 low = IWL_RATE_INVALID; + + /* 802.11A or ht walks to the next literal adjacent rate in + * the rate table */ + if (is_type_a_band(rate_type) || !is_type_legacy(rate_type)) { + int i; + u32 mask; + + /* Find the previous rate that is in the rate mask */ + i = index - 1; + if (i >= 0) + mask = BIT(i); + for (; i >= 0; i--, mask >>= 1) { + if (rate_mask & mask) { + low = i; + break; + } + } + + /* Find the next rate that is in the rate mask */ + i = index + 1; + for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { + if (rate_mask & mask) { + high = i; + break; + } + } + + return (high << 8) | low; + } + + low = index; + while (low != IWL_RATE_INVALID) { + low = iwl_rates[low].prev_rs; + if (low == IWL_RATE_INVALID) + break; + if (rate_mask & (1 << low)) + break; + } + + high = index; + while (high != IWL_RATE_INVALID) { + high = iwl_rates[high].next_rs; + if (high == IWL_RATE_INVALID) + break; + if (rate_mask & (1 << high)) + break; + } + + return (high << 8) | low; +} + +static inline bool rs_rate_supported(struct iwl_lq_sta *lq_sta, + struct rs_rate *rate) +{ + return BIT(rate->index) & rs_get_supported_rates(lq_sta, rate); +} + +/* Get the next supported lower rate in the current column. + * Return true if bottom rate in the current column was reached + */ +static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta, + struct rs_rate *rate) +{ + u8 low; + u16 high_low; + u16 rate_mask; + struct iwm_softc *sc = lq_sta->pers.drv; + + rate_mask = rs_get_supported_rates(lq_sta, rate); + high_low = rs_get_adjacent_rate(sc, rate->index, rate_mask, + rate->type); + low = high_low & 0xff; + + /* Bottom rate of column reached */ + if (low == IWL_RATE_INVALID) + return true; + + rate->index = low; + return false; +} + +/* Get the next rate to use following a column downgrade */ +static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, + struct rs_rate *rate) +{ + struct iwm_softc *sc = lq_sta->pers.drv; + ItlIwm *that = container_of(sc, ItlIwm, com); + + if (is_legacy(rate)) { + /* No column to downgrade from Legacy */ + return; + } else if (is_siso(rate)) { + /* Downgrade to Legacy if we were in SISO */ + if (lq_sta->band == NL80211_BAND_5GHZ) + rate->type = LQ_LEGACY_A; + else + rate->type = LQ_LEGACY_G; + + rate->bw = RATE_MCS_CHAN_WIDTH_20; + + if (WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX)) + rate->index = rs_ht_to_legacy[IWL_RATE_MCS_0_INDEX]; + else if (WARN_ON_ONCE(rate->index > IWL_RATE_MCS_9_INDEX)) + rate->index = rs_ht_to_legacy[IWL_RATE_MCS_9_INDEX]; + else + rate->index = rs_ht_to_legacy[rate->index]; + + rate->ldpc = false; + } else { + /* Downgrade to SISO with same MCS if in MIMO */ + rate->type = is_vht_mimo2(rate) ? + LQ_VHT_SISO : LQ_HT_SISO; + } + + if (that->iwm_num_of_ant(rate->ant) > 1) + rate->ant = first_antenna(that->iwm_fw_valid_tx_ant(sc)); + + /* Relevant in both switching to SISO or Legacy */ + rate->sgi = false; + + if (!rs_rate_supported(lq_sta, rate)) + rs_get_lower_rate_in_column(lq_sta, rate); +} + +/* Check if both rates share the same column */ +static inline bool rs_rate_column_match(struct rs_rate *a, + struct rs_rate *b) +{ + bool ant_match; + + if (a->stbc || a->bfer) + ant_match = (b->ant == ANT_A || b->ant == ANT_B); + else + ant_match = (a->ant == b->ant); + + return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) + && ant_match; +} + +static inline enum rs_column rs_get_column_from_rate(struct rs_rate *rate) +{ + if (is_legacy(rate)) { + if (rate->ant == ANT_A) + return RS_COLUMN_LEGACY_ANT_A; + + if (rate->ant == ANT_B) + return RS_COLUMN_LEGACY_ANT_B; + + goto err; + } + + if (is_siso(rate)) { + if (rate->ant == ANT_A || rate->stbc || rate->bfer) + return rate->sgi ? RS_COLUMN_SISO_ANT_A_SGI : + RS_COLUMN_SISO_ANT_A; + + if (rate->ant == ANT_B) + return rate->sgi ? RS_COLUMN_SISO_ANT_B_SGI : + RS_COLUMN_SISO_ANT_B; + + goto err; + } + + if (is_mimo(rate)) + return rate->sgi ? RS_COLUMN_MIMO2_SGI : RS_COLUMN_MIMO2; + +err: + return RS_COLUMN_INVALID; +} + +/* + * mac80211 sends us Tx status + */ +void rs_drv_mac80211_tx_status(struct iwm_softc *sc, + struct ieee80211_node *sta, + struct ieee80211_tx_info *info, int tid, uint16_t fc, int ssn) +{ + if (!ieee80211_is_data(fc) || + info->flags & IEEE80211_TX_CTL_NO_ACK) + return; + + iwl_mvm_rs_tx_status(sc, sta, tid, info, + false); +} + +/* + * Begin a period of staying with a selected modulation mode. + * Set "stay_in_tbl" flag to prevent any mode switches. + * Set frame tx success limits according to legacy vs. high-throughput, + * and reset overall (spanning all rates) tx success history statistics. + * These control how long we stay using same modulation mode before + * searching for a new mode. + */ +static void rs_set_stay_in_table(struct iwm_softc *mvm, u8 is_legacy, + struct iwl_lq_sta *lq_sta) +{ + IWL_DEBUG_RATE(mvm, "Moving to RS_STATE_STAY_IN_COLUMN\n"); + lq_sta->rs_state = RS_STATE_STAY_IN_COLUMN; + if (is_legacy) { + lq_sta->table_count_limit = IWL_MVM_RS_LEGACY_TABLE_COUNT; + lq_sta->max_failure_limit = IWL_MVM_RS_LEGACY_FAILURE_LIMIT; + lq_sta->max_success_limit = IWL_MVM_RS_LEGACY_SUCCESS_LIMIT; + } else { + lq_sta->table_count_limit = IWL_MVM_RS_NON_LEGACY_TABLE_COUNT; + lq_sta->max_failure_limit = IWL_MVM_RS_NON_LEGACY_FAILURE_LIMIT; + lq_sta->max_success_limit = IWL_MVM_RS_NON_LEGACY_SUCCESS_LIMIT; + } + lq_sta->table_count = 0; + lq_sta->total_failed = 0; + lq_sta->total_success = 0; + lq_sta->flush_timer = ticks; + lq_sta->visited_columns = 0; +} + +static inline int rs_get_max_rate_from_mask(unsigned long rate_mask) +{ + if (rate_mask) + return find_last_bit(&rate_mask, BITS_PER_LONG); + return IWL_RATE_INVALID; +} + +static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta, + const struct rs_tx_column *column) +{ + switch (column->mode) { + case RS_LEGACY: + return lq_sta->max_legacy_rate_idx; + case RS_SISO: + return lq_sta->max_siso_rate_idx; + case RS_MIMO2: + return lq_sta->max_mimo2_rate_idx; + default: + WARN_ON_ONCE(1); + } + + return lq_sta->max_legacy_rate_idx; +} + +static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, + const struct rs_tx_column *column, + u32 bw) +{ + /* Used to choose among HT tables */ + const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT]; + + if (WARN_ON_ONCE(column->mode != RS_LEGACY && + column->mode != RS_SISO && + column->mode != RS_MIMO2)) + return expected_tpt_legacy; + + /* Legacy rates have only one table */ + if (column->mode == RS_LEGACY) + return expected_tpt_legacy; + + ht_tbl_pointer = expected_tpt_mimo2_20MHz; + /* Choose among many HT tables depending on number of streams + * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation + * status */ + if (column->mode == RS_SISO) { + switch (bw) { + case RATE_MCS_CHAN_WIDTH_20: + ht_tbl_pointer = expected_tpt_siso_20MHz; + break; + case RATE_MCS_CHAN_WIDTH_40: + ht_tbl_pointer = expected_tpt_siso_40MHz; + break; + case RATE_MCS_CHAN_WIDTH_80: + ht_tbl_pointer = expected_tpt_siso_80MHz; + break; + case RATE_MCS_CHAN_WIDTH_160: + ht_tbl_pointer = expected_tpt_siso_160MHz; + break; + default: + WARN_ON_ONCE(1); + } + } else if (column->mode == RS_MIMO2) { + switch (bw) { + case RATE_MCS_CHAN_WIDTH_20: + ht_tbl_pointer = expected_tpt_mimo2_20MHz; + break; + case RATE_MCS_CHAN_WIDTH_40: + ht_tbl_pointer = expected_tpt_mimo2_40MHz; + break; + case RATE_MCS_CHAN_WIDTH_80: + ht_tbl_pointer = expected_tpt_mimo2_80MHz; + break; + case RATE_MCS_CHAN_WIDTH_160: + ht_tbl_pointer = expected_tpt_mimo2_160MHz; + break; + default: + WARN_ON_ONCE(1); + } + } else { + WARN_ON_ONCE(1); + } + + if (!column->sgi && !lq_sta->is_agg) /* Normal */ + return ht_tbl_pointer[0]; + else if (column->sgi && !lq_sta->is_agg) /* SGI */ + return ht_tbl_pointer[1]; + else if (!column->sgi && lq_sta->is_agg) /* AGG */ + return ht_tbl_pointer[2]; + else /* AGG+SGI */ + return ht_tbl_pointer[3]; +} + +static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl) +{ + struct rs_rate *rate = &tbl->rate; + const struct rs_tx_column *column = &rs_tx_columns[tbl->column]; + + tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw); +} + +/* rs uses two tables, one is active and the second is for searching better + * configuration. This function, according to the index of the currently + * active table returns the search table, which is located at the + * index complementary to 1 according to the active table (active = 1, + * search = 0 or active = 0, search = 1). + * Since lq_info is an arary of size 2, make sure index cannot be out of bounds. + */ +static inline u8 rs_search_tbl(u8 active_tbl) +{ + return (active_tbl ^ 1) & 1; +} + +static s32 rs_get_best_rate(struct iwm_softc *sc, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, /* "search" */ + unsigned long rate_mask, s8 index) +{ + struct iwl_scale_tbl_info *active_tbl = + &(lq_sta->lq_info[lq_sta->active_tbl]); + s32 success_ratio = active_tbl->win[index].success_ratio; + u16 expected_current_tpt = active_tbl->expected_tpt[index]; + const u16 *tpt_tbl = tbl->expected_tpt; + u16 high_low; + u32 target_tpt; + int rate_idx; + + if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) { + target_tpt = 100 * expected_current_tpt; + IWL_DEBUG_RATE(mvm, + "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n", + success_ratio, target_tpt); + } else { + target_tpt = lq_sta->last_tpt; + IWL_DEBUG_RATE(mvm, + "SR %d not that good. Find rate exceeding ACTUAL_TPT %d\n", + success_ratio, target_tpt); + } + + rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG); + + while (rate_idx != IWL_RATE_INVALID) { + if (target_tpt < (100 * tpt_tbl[rate_idx])) + break; + + high_low = rs_get_adjacent_rate(sc, rate_idx, rate_mask, + tbl->rate.type); + + rate_idx = (high_low >> 8) & 0xff; + } + + IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n", + rate_idx, target_tpt, + rate_idx != IWL_RATE_INVALID ? + 100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE); + + return rate_idx; +} + +static u32 rs_bw_from_sta_bw(struct ieee80211_node *ni) +{ + struct ieee80211_vht_cap vht_cap = { + .vht_cap_info = cpu_to_le32(ni->ni_vhtcaps), + .supp_mcs = ni->ni_vht_mcsinfo, + }; + + if (ni->ni_chw == IEEE80211_CHAN_WIDTH_40 && + IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) + return RATE_MCS_CHAN_WIDTH_20; + + switch (ni->ni_chw) { + case IEEE80211_CHAN_WIDTH_160: + /* + * Don't use 160 MHz if VHT extended NSS support + * says we cannot use 2 streams, we don't want to + * deal with this. + * We only check MCS 0 - they will support that if + * we got here at all and we don't care which MCS, + * we want to determine a more global state. + */ + if (ieee80211_get_vht_max_nss(&vht_cap, + IEEE80211_VHT_CHANWIDTH_160MHZ, + 0, true, + ni->ni_rx_nss) < ni->ni_rx_nss) + return RATE_MCS_CHAN_WIDTH_80; + return RATE_MCS_CHAN_WIDTH_160; + case IEEE80211_CHAN_WIDTH_80: + return RATE_MCS_CHAN_WIDTH_80; + case IEEE80211_CHAN_WIDTH_40: + return RATE_MCS_CHAN_WIDTH_40; + case IEEE80211_CHAN_WIDTH_20: + default: + return RATE_MCS_CHAN_WIDTH_20; + } +} + +/* + * Check whether we should continue using same modulation mode, or + * begin search for a new mode, based on: + * 1) # tx successes or failures while using this mode + * 2) # times calling this function + * 3) elapsed time in this mode (not used, for now) + */ +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) +{ + struct iwl_scale_tbl_info *tbl; + int active_tbl; + int flush_interval_passed = 0; + struct iwm_softc *sc; + + sc = lq_sta->pers.drv; + active_tbl = lq_sta->active_tbl; + + tbl = &(lq_sta->lq_info[active_tbl]); + + /* If we've been disallowing search, see if we should now allow it */ + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { + /* Elapsed time using current modulation mode */ + if (lq_sta->flush_timer) + flush_interval_passed = + time_after(ticks, + (unsigned long)(lq_sta->flush_timer + + (IWL_MVM_RS_STAY_IN_COLUMN_TIMEOUT * hz))); + + /* + * Check if we should allow search for new modulation mode. + * If many frames have failed or succeeded, or we've used + * this same modulation for a long time, allow search, and + * reset history stats that keep track of whether we should + * allow a new search. Also (below) reset all bitmaps and + * stats in active history. + */ + if (force_search || + (lq_sta->total_failed > lq_sta->max_failure_limit) || + (lq_sta->total_success > lq_sta->max_success_limit) || + ((!lq_sta->search_better_tbl) && + (lq_sta->flush_timer) && (flush_interval_passed))) { + IWL_DEBUG_RATE(mvm, + "LQ: stay is expired %d %d %d\n", + lq_sta->total_failed, + lq_sta->total_success, + flush_interval_passed); + + /* Allow search for new mode */ + lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_STARTED; + IWL_DEBUG_RATE(mvm, + "Moving to RS_STATE_SEARCH_CYCLE_STARTED\n"); + lq_sta->total_failed = 0; + lq_sta->total_success = 0; + lq_sta->flush_timer = 0; + /* mark the current column as visited */ + lq_sta->visited_columns = BIT(tbl->column); + /* + * Else if we've used this modulation mode enough repetitions + * (regardless of elapsed time or success/failure), reset + * history bitmaps and rate-specific stats for all rates in + * active table. + */ + } else { + lq_sta->table_count++; + if (lq_sta->table_count >= + lq_sta->table_count_limit) { + lq_sta->table_count = 0; + + IWL_DEBUG_RATE(sc, + "LQ: stay in table clear win\n"); + rs_rate_scale_clear_tbl_windows(sc, tbl); + } + } + + /* If transitioning to allow "search", reset all history + * bitmaps and stats in active table (this will become the new + * "search" table). */ + if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { + rs_rate_scale_clear_tbl_windows(sc, tbl); + } + } +} + +static void rs_set_amsdu_len(struct iwm_softc *sc, struct ieee80211_node *ni, + struct iwl_scale_tbl_info *tbl, + enum rs_action scale_action) +{ +#if 0 + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + int i; + + sta->max_amsdu_len = rs_fw_get_max_amsdu_len(sta); + + /* + * In case TLC offload is not active amsdu_enabled is either 0xFFFF + * or 0, since there is no per-TID alg. + */ + if ((!is_vht(&tbl->rate) && !is_ht(&tbl->rate)) || + tbl->rate.index < IWL_RATE_MCS_5_INDEX || + scale_action == RS_ACTION_DOWNSCALE) + mvmsta->amsdu_enabled = 0; + else + mvmsta->amsdu_enabled = 0xFFFF; + + if (mvmsta->vif->bss_conf.he_support && + !iwlwifi_mod_params.disable_11ax) + mvmsta->max_amsdu_len = sta->max_amsdu_len; + else + mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500); + + sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; + + for (i = 0; i < IWL_MAX_TID_COUNT; i++) { + if (mvmsta->amsdu_enabled) + sta->max_tid_amsdu_len[i] = + iwl_mvm_max_amsdu_size(mvm, sta, i); + else + /* + * Not so elegant, but this will effectively + * prevent AMSDU on this TID + */ + sta->max_tid_amsdu_len[i] = 1; + } +#endif +} + +/** + * iwl_mvm_send_lq_cmd() - Send link quality command + * @mvm: Driver data. + * @lq: Link quality command to send. + * + * The link quality command is sent as the last step of station creation. + * This is the special case in which init is set and we call a callback in + * this case to clear the state indicating that station creation is in + * progress. + */ +int iwl_mvm_send_lq_cmd(struct iwm_softc *sc, struct iwm_lq_cmd *lq) +{ + ItlIwm *that = container_of(sc, ItlIwm, com); + + struct iwm_host_cmd cmd = { + .id = IWM_LQ_CMD, + .len = { sizeof(struct iwm_lq_cmd), }, + .flags = IWM_CMD_ASYNC, + .data = { lq, }, + }; + + return that->iwm_send_cmd(sc, &cmd);; +} + +/* + * setup rate table in uCode + */ +static void rs_update_rate_tbl(struct iwm_softc *sc, + struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl) +{ + rs_fill_lq_cmd(sc, ni, lq_sta, &tbl->rate); + iwl_mvm_send_lq_cmd(sc, &lq_sta->lq); +} + +static bool rs_tweak_rate_tbl(struct iwm_softc *sc, + struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + enum rs_action scale_action) +{ + if (rs_bw_from_sta_bw(ni) != RATE_MCS_CHAN_WIDTH_80) + return false; + + if (!is_vht_siso(&tbl->rate)) + return false; + + if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) && + (tbl->rate.index == IWL_RATE_MCS_0_INDEX) && + (scale_action == RS_ACTION_DOWNSCALE)) { + tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20; + tbl->rate.index = IWL_RATE_MCS_4_INDEX; + IWL_DEBUG_RATE(sc, "Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\n"); + goto tweaked; + } + + /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is + * sustainable, i.e. we're past the test window. We can't go back + * if MCS5 is just tested as this will happen always after switching + * to 20Mhz MCS4 because the rate stats are cleared. + */ + if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) && + (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) && + (scale_action == RS_ACTION_STAY)) || + ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) && + (scale_action == RS_ACTION_UPSCALE)))) { + tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80; + tbl->rate.index = IWL_RATE_MCS_1_INDEX; + IWL_DEBUG_RATE(sc, "Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\n"); + goto tweaked; + } + + return false; + +tweaked: + rs_set_expected_tpt_table(lq_sta, tbl); + rs_rate_scale_clear_tbl_windows(sc, tbl); + return true; +} + +static enum rs_column rs_get_next_column(struct iwm_softc *sc, + struct iwl_lq_sta *lq_sta, + struct ieee80211_node *ni, + struct iwl_scale_tbl_info *tbl) +{ + int i, j, max_rate; + enum rs_column next_col_id; + const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; + const struct rs_tx_column *next_col; + allow_column_func_t allow_func; + ItlIwm *that = container_of(sc, ItlIwm, com); + u8 valid_ants = that->iwm_fw_valid_tx_ant(sc); + const u16 *expected_tpt_tbl; + u16 tpt, max_expected_tpt; + + for (i = 0; i < MAX_NEXT_COLUMNS; i++) { + next_col_id = curr_col->next_columns[i]; + + if (next_col_id == RS_COLUMN_INVALID) + continue; + + if (lq_sta->visited_columns & BIT(next_col_id)) { + IWL_DEBUG_RATE(sc, "Skip already visited column %d\n", + next_col_id); + continue; + } + + next_col = &rs_tx_columns[next_col_id]; + + if (!rs_is_valid_ant(valid_ants, next_col->ant)) { + IWL_DEBUG_RATE(sc, + "Skip column %d as ANT config isn't supported by chip. valid_ants 0x%x column ant 0x%x\n", + next_col_id, valid_ants, next_col->ant); + continue; + } + + for (j = 0; j < MAX_COLUMN_CHECKS; j++) { + allow_func = next_col->checks[j]; + if (allow_func && !allow_func(sc, ni, &tbl->rate, + next_col)) + break; + } + + if (j != MAX_COLUMN_CHECKS) { + IWL_DEBUG_RATE(sc, + "Skip column %d: not allowed (check %d failed)\n", + next_col_id, j); + + continue; + } + + tpt = lq_sta->last_tpt / 100; + expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col, + rs_bw_from_sta_bw(ni)); + if (WARN_ON_ONCE(!expected_tpt_tbl)) + continue; + + max_rate = rs_get_max_allowed_rate(lq_sta, next_col); + if (max_rate == IWL_RATE_INVALID) { + IWL_DEBUG_RATE(sc, + "Skip column %d: no rate is allowed in this column\n", + next_col_id); + continue; + } + + max_expected_tpt = expected_tpt_tbl[max_rate]; + if (tpt >= max_expected_tpt) { + IWL_DEBUG_RATE(sc, + "Skip column %d: can't beat current TPT. Max expected %d current %d\n", + next_col_id, max_expected_tpt, tpt); + continue; + } + + IWL_DEBUG_RATE(sc, + "Found potential column %d. Max expected %d current %d\n", + next_col_id, max_expected_tpt, tpt); + break; + } + + if (i == MAX_NEXT_COLUMNS) + return RS_COLUMN_INVALID; + + return next_col_id; +} + +static int rs_switch_to_column(struct iwm_softc *sc, + struct iwl_lq_sta *lq_sta, + struct ieee80211_node *ni, + enum rs_column col_id) +{ + struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; + struct iwl_scale_tbl_info *search_tbl = + &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; + struct rs_rate *rate = &search_tbl->rate; + const struct rs_tx_column *column = &rs_tx_columns[col_id]; + const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; + unsigned long rate_mask = 0; + u32 rate_idx = 0; + + memcpy(search_tbl, tbl, offsetof(struct iwl_scale_tbl_info, win)); + + rate->sgi = column->sgi; + rate->ant = column->ant; + + if (column->mode == RS_LEGACY) { + if (lq_sta->band == NL80211_BAND_5GHZ) + rate->type = LQ_LEGACY_A; + else + rate->type = LQ_LEGACY_G; + + rate->bw = RATE_MCS_CHAN_WIDTH_20; + rate->ldpc = false; + rate_mask = lq_sta->active_legacy_rate; + } else if (column->mode == RS_SISO) { + rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; + rate_mask = lq_sta->active_siso_rate; + } else if (column->mode == RS_MIMO2) { + rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; + rate_mask = lq_sta->active_mimo2_rate; + } else { + WARN_ON(1, "Bad column mode"); + } + + if (column->mode != RS_LEGACY) { + rate->bw = rs_bw_from_sta_bw(ni); + rate->ldpc = lq_sta->ldpc; + } + + search_tbl->column = col_id; + rs_set_expected_tpt_table(lq_sta, search_tbl); + + lq_sta->visited_columns |= BIT(col_id); + + /* Get the best matching rate if we're changing modes. e.g. + * SISO->MIMO, LEGACY->SISO, MIMO->SISO + */ + if (curr_column->mode != column->mode) { + rate_idx = rs_get_best_rate(sc, lq_sta, search_tbl, + rate_mask, rate->index); + + if ((rate_idx == IWL_RATE_INVALID) || + !(BIT(rate_idx) & rate_mask)) { + IWL_DEBUG_RATE(sc, + "can not switch with index %d" + " rate mask %lx\n", + rate_idx, rate_mask); + + goto err; + } + + rate->index = rate_idx; + } + + IWL_DEBUG_RATE(sc, "Switched to column %d: Index %d\n", + col_id, rate->index); + + return 0; + +err: + rate->type = LQ_NONE; + return -1; +} + +static enum rs_action rs_get_rate_action(struct iwm_softc *sc, + struct iwl_scale_tbl_info *tbl, + s32 sr, int low, int high, + int current_tpt, + int low_tpt, int high_tpt) +{ + enum rs_action action = RS_ACTION_STAY; + + if ((sr <= RS_PERCENT(IWL_MVM_RS_SR_FORCE_DECREASE)) || + (current_tpt == 0)) { + IWL_DEBUG_RATE(mvm, + "Decrease rate because of low SR\n"); + return RS_ACTION_DOWNSCALE; + } + + if ((low_tpt == IWL_INVALID_VALUE) && + (high_tpt == IWL_INVALID_VALUE) && + (high != IWL_RATE_INVALID)) { + IWL_DEBUG_RATE(mvm, + "No data about high/low rates. Increase rate\n"); + return RS_ACTION_UPSCALE; + } + + if ((high_tpt == IWL_INVALID_VALUE) && + (high != IWL_RATE_INVALID) && + (low_tpt != IWL_INVALID_VALUE) && + (low_tpt < current_tpt)) { + IWL_DEBUG_RATE(mvm, + "No data about high rate and low rate is worse. Increase rate\n"); + return RS_ACTION_UPSCALE; + } + + if ((high_tpt != IWL_INVALID_VALUE) && + (high_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Higher rate is better. Increate rate\n"); + return RS_ACTION_UPSCALE; + } + + if ((low_tpt != IWL_INVALID_VALUE) && + (high_tpt != IWL_INVALID_VALUE) && + (low_tpt < current_tpt) && + (high_tpt < current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Both high and low are worse. Maintain rate\n"); + return RS_ACTION_STAY; + } + + if ((low_tpt != IWL_INVALID_VALUE) && + (low_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Lower rate is better\n"); + action = RS_ACTION_DOWNSCALE; + goto out; + } + + if ((low_tpt == IWL_INVALID_VALUE) && + (low != IWL_RATE_INVALID)) { + IWL_DEBUG_RATE(mvm, + "No data about lower rate\n"); + action = RS_ACTION_DOWNSCALE; + goto out; + } + + IWL_DEBUG_RATE(mvm, "Maintain rate\n"); + +out: + if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { + if (sr >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) { + IWL_DEBUG_RATE(mvm, + "SR is above NO DECREASE. Avoid downscale\n"); + action = RS_ACTION_STAY; + } else if (current_tpt > (100 * tbl->expected_tpt[low])) { + IWL_DEBUG_RATE(mvm, + "Current TPT is higher than max expected in low rate. Avoid downscale\n"); + action = RS_ACTION_STAY; + } else { + IWL_DEBUG_RATE(mvm, "Decrease rate\n"); + } + } + + return action; +} + +static bool rs_stbc_allow(struct iwm_softc *sc, struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta) +{ + /* Our chip supports Tx STBC and the peer is an HT/VHT STA which + * supports STBC of at least 1*SS + */ + if (!lq_sta->stbc_capable) + return false; + + if (!iwl_mvm_bt_coex_is_mimo_allowed(sc, ni)) + return false; + + return true; +} + +static void rs_get_adjacent_txp(struct iwm_softc *mvm, int index, + int *weaker, int *stronger) +{ + *weaker = index + IWL_MVM_RS_TPC_TX_POWER_STEP; + if (*weaker > TPC_MAX_REDUCTION) + *weaker = TPC_INVALID; + + *stronger = index - IWL_MVM_RS_TPC_TX_POWER_STEP; + if (*stronger < 0) + *stronger = TPC_INVALID; +} + +static bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwm_softc *mvm, + enum nl80211_band band) +{ + return ItlIwm::iwm_coex_is_tpc_allowed(mvm, band == NL80211_BAND_5GHZ); +} + +static bool rs_tpc_allowed(struct iwm_softc *mvm, + struct rs_rate *rate, enum nl80211_band band) +{ + int index = rate->index; + bool cam = /*(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)*/ false; + bool sta_ps_disabled = /*(vif->type == NL80211_IFTYPE_STATION && + !vif->bss_conf.ps)*/ true; + + IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n", + cam, sta_ps_disabled); + /* + * allow tpc only if power management is enabled, or bt coex + * activity grade allows it and we are on 2.4Ghz. + */ + if ((cam || sta_ps_disabled) && + !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band)) + return false; + + IWL_DEBUG_RATE(mvm, "check rate, table type: %d\n", rate->type); + if (is_legacy(rate)) + return index == IWL_RATE_54M_INDEX; + if (is_ht(rate)) + return index == IWL_RATE_MCS_7_INDEX; + if (is_vht(rate)) + return index == IWL_RATE_MCS_9_INDEX; + + WARN_ON_ONCE(1); + return false; +} + +enum tpc_action { + TPC_ACTION_STAY, + TPC_ACTION_DECREASE, + TPC_ACTION_INCREASE, + TPC_ACTION_NO_RESTIRCTION, +}; + +static enum tpc_action rs_get_tpc_action(struct iwm_softc *mvm, + s32 sr, int weak, int strong, + int current_tpt, + int weak_tpt, int strong_tpt) +{ + /* stay until we have valid tpt */ + if (current_tpt == IWL_INVALID_VALUE) { + IWL_DEBUG_RATE(mvm, "no current tpt. stay.\n"); + return TPC_ACTION_STAY; + } + + /* Too many failures, increase txp */ + if (sr <= RS_PERCENT(IWL_MVM_RS_TPC_SR_FORCE_INCREASE) || + current_tpt == 0) { + IWL_DEBUG_RATE(mvm, "increase txp because of weak SR\n"); + return TPC_ACTION_NO_RESTIRCTION; + } + + /* try decreasing first if applicable */ + if (sr >= RS_PERCENT(IWL_MVM_RS_TPC_SR_NO_INCREASE) && + weak != TPC_INVALID) { + if (weak_tpt == IWL_INVALID_VALUE && + (strong_tpt == IWL_INVALID_VALUE || + current_tpt >= strong_tpt)) { + IWL_DEBUG_RATE(mvm, + "no weak txp measurement. decrease txp\n"); + return TPC_ACTION_DECREASE; + } + + if (weak_tpt > current_tpt) { + IWL_DEBUG_RATE(mvm, + "lower txp has better tpt. decrease txp\n"); + return TPC_ACTION_DECREASE; + } + } + + /* next, increase if needed */ + if (sr < RS_PERCENT(IWL_MVM_RS_TPC_SR_NO_INCREASE) && + strong != TPC_INVALID) { + if (weak_tpt == IWL_INVALID_VALUE && + strong_tpt != IWL_INVALID_VALUE && + current_tpt < strong_tpt) { + IWL_DEBUG_RATE(mvm, + "higher txp has better tpt. increase txp\n"); + return TPC_ACTION_INCREASE; + } + + if (weak_tpt < current_tpt && + (strong_tpt == IWL_INVALID_VALUE || + strong_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "lower txp has worse tpt. increase txp\n"); + return TPC_ACTION_INCREASE; + } + } + + IWL_DEBUG_RATE(mvm, "no need to increase or decrease txp - stay\n"); + return TPC_ACTION_STAY; +} + +static bool rs_tpc_perform(struct iwm_softc *mvm, + struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl) +{ + enum nl80211_band band; + struct iwl_rate_scale_data *window; + struct rs_rate *rate = &tbl->rate; + enum tpc_action action; + s32 sr; + u8 cur = lq_sta->lq.reduced_tpc; + int current_tpt; + int weak, strong; + int weak_tpt = IWL_INVALID_VALUE, strong_tpt = IWL_INVALID_VALUE; + + if (WARN_ON(!ni->ni_chan)) + band = NUM_NL80211_BANDS; + else + band = IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; + + if (!rs_tpc_allowed(mvm, rate, band)) { + IWL_DEBUG_RATE(mvm, + "tpc is not allowed. remove txp restrictions\n"); + lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION; + return cur != TPC_NO_REDUCTION; + } + + rs_get_adjacent_txp(mvm, cur, &weak, &strong); + + /* Collect measured throughputs for current and adjacent rates */ + window = tbl->tpc_win; + sr = window[cur].success_ratio; + current_tpt = window[cur].average_tpt; + if (weak != TPC_INVALID) + weak_tpt = window[weak].average_tpt; + if (strong != TPC_INVALID) + strong_tpt = window[strong].average_tpt; + + IWL_DEBUG_RATE(mvm, + "(TPC: %d): cur_tpt %d SR %d weak %d strong %d weak_tpt %d strong_tpt %d\n", + cur, current_tpt, sr, weak, strong, + weak_tpt, strong_tpt); + + action = rs_get_tpc_action(mvm, sr, weak, strong, + current_tpt, weak_tpt, strong_tpt); + + /* override actions if we are on the edge */ + if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) { + IWL_DEBUG_RATE(mvm, "already in lowest txp, stay\n"); + action = TPC_ACTION_STAY; + } else if (strong == TPC_INVALID && + (action == TPC_ACTION_INCREASE || + action == TPC_ACTION_NO_RESTIRCTION)) { + IWL_DEBUG_RATE(mvm, "already in highest txp, stay\n"); + action = TPC_ACTION_STAY; + } + + switch (action) { + case TPC_ACTION_DECREASE: + lq_sta->lq.reduced_tpc = weak; + return true; + case TPC_ACTION_INCREASE: + lq_sta->lq.reduced_tpc = strong; + return true; + case TPC_ACTION_NO_RESTIRCTION: + lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION; + return true; + case TPC_ACTION_STAY: + /* do nothing */ + break; + } + return false; +} + +/* + * Do rate scaling and search for new modulation mode. + */ +static void rs_rate_scale_perform(struct iwm_softc *mvm, + struct ieee80211_node *ni, + struct iwl_lq_sta *lq_sta, + int tid, bool ndp) +{ + int low = IWL_RATE_INVALID; + int high = IWL_RATE_INVALID; + int index; + struct iwl_rate_scale_data *window = NULL; + int current_tpt = IWL_INVALID_VALUE; + int low_tpt = IWL_INVALID_VALUE; + int high_tpt = IWL_INVALID_VALUE; + u32 fail_count; + enum rs_action scale_action = RS_ACTION_STAY; + u16 rate_mask; + u8 update_lq = 0; + struct iwl_scale_tbl_info *tbl, *tbl1; + u8 active_tbl = 0; + u8 done_search = 0; + u16 high_low; + s32 sr; + u8 prev_agg = lq_sta->is_agg; + struct rs_rate *rate; + int i; + + lq_sta->is_agg = false; + for (i = 0; i <= IWM_MAX_TID_COUNT; i++) { + if (mvm->sc_tx_ba[i].wn != NULL) { + lq_sta->is_agg = true; + break; + } + } + + /* + * Select rate-scale / modulation-mode table to work with in + * the rest of this function: "search" if searching for better + * modulation mode, or "active" if doing rate scaling within a mode. + */ + if (!lq_sta->search_better_tbl) + active_tbl = lq_sta->active_tbl; + else + active_tbl = rs_search_tbl(lq_sta->active_tbl); + + tbl = &(lq_sta->lq_info[active_tbl]); + rate = &tbl->rate; + + if (prev_agg != lq_sta->is_agg) { + XYLog("Aggregation changed: prev %d current %d. Update expected TPT table\n", + prev_agg, lq_sta->is_agg); + rs_set_expected_tpt_table(lq_sta, tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); + } + + /* current tx rate */ + index = rate->index; + + /* rates available for this association, and for modulation mode */ + rate_mask = rs_get_supported_rates(lq_sta, rate); + + if (!(BIT(index) & rate_mask)) { + IWL_ERR(mvm, "Current Rate is not valid\n"); + if (lq_sta->search_better_tbl) { + /* revert to active table if search table is not valid*/ + rate->type = LQ_NONE; + lq_sta->search_better_tbl = 0; + tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + rs_update_rate_tbl(mvm, ni, lq_sta, tbl); + } + return; + } + + /* Get expected throughput table and history window for current rate */ + if (!tbl->expected_tpt) { + IWL_ERR(mvm, "tbl->expected_tpt is NULL\n"); + return; + } + + /* TODO: handle rate_idx_mask and rate_idx_mcs_mask */ + window = &(tbl->win[index]); + + /* + * If there is not enough history to calculate actual average + * throughput, keep analyzing results of more tx frames, without + * changing rate or mode (bypass most of the rest of this function). + * Set up new rate table in uCode only if old rate is not supported + * in current association (use new rate found above). + */ + fail_count = window->counter - window->success_counter; + if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) && + (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) { + IWL_DEBUG_RATE(mvm, + "%s: Test Window: succ %d total %d\n", + rs_pretty_rate(rate), + window->success_counter, window->counter); + + /* Can't calculate this yet; not enough history */ + window->average_tpt = IWL_INVALID_VALUE; + + /* Should we stay with this modulation mode, + * or search for a new one? */ + rs_stay_in_table(lq_sta, false); + + return; + } + + /* If we are searching for better modulation mode, check success. */ + if (lq_sta->search_better_tbl) { + /* If good success, continue using the "search" mode; + * no need to send new link quality command, since we're + * continuing to use the setup that we've been trying. */ + if (window->average_tpt > lq_sta->last_tpt) { + IWL_DEBUG_RATE(mvm, + "SWITCHING TO NEW TABLE SR: %d " + "cur-tpt %d old-tpt %d\n", + window->success_ratio, + window->average_tpt, + lq_sta->last_tpt); + + /* Swap tables; "search" becomes "active" */ + lq_sta->active_tbl = active_tbl; + current_tpt = window->average_tpt; + /* Else poor success; go back to mode in "active" table */ + } else { + IWL_DEBUG_RATE(mvm, + "GOING BACK TO THE OLD TABLE: SR %d " + "cur-tpt %d old-tpt %d\n", + window->success_ratio, + window->average_tpt, + lq_sta->last_tpt); + + /* Nullify "search" table */ + rate->type = LQ_NONE; + + /* Revert to "active" table */ + active_tbl = lq_sta->active_tbl; + tbl = &(lq_sta->lq_info[active_tbl]); + + /* Revert to "active" rate and throughput info */ + index = tbl->rate.index; + current_tpt = lq_sta->last_tpt; + + /* Need to set up a new rate table in uCode */ + update_lq = 1; + } + + /* Either way, we've made a decision; modulation mode + * search is done, allow rate adjustment next time. */ + lq_sta->search_better_tbl = 0; + done_search = 1; /* Don't switch modes below! */ + goto lq_update; + } + + /* (Else) not in search of better modulation mode, try for better + * starting rate, while staying in this mode. */ + high_low = rs_get_adjacent_rate(mvm, index, rate_mask, rate->type); + low = high_low & 0xff; + high = (high_low >> 8) & 0xff; + + /* TODO: handle rate_idx_mask and rate_idx_mcs_mask */ + + sr = window->success_ratio; + + /* Collect measured throughputs for current and adjacent rates */ + current_tpt = window->average_tpt; + if (low != IWL_RATE_INVALID) + low_tpt = tbl->win[low].average_tpt; + if (high != IWL_RATE_INVALID) + high_tpt = tbl->win[high].average_tpt; + + IWL_DEBUG_RATE(mvm, + "%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", + rs_pretty_rate(rate), current_tpt, sr, + low, high, low_tpt, high_tpt); + + scale_action = rs_get_rate_action(mvm, tbl, sr, low, high, + current_tpt, low_tpt, high_tpt); + + /* Force a search in case BT doesn't like us being in MIMO */ + if (is_mimo(rate) && + !iwl_mvm_bt_coex_is_mimo_allowed(mvm, ni)) { + IWL_DEBUG_RATE(mvm, + "BT Coex forbids MIMO. Search for new config\n"); + rs_stay_in_table(lq_sta, true); + goto lq_update; + } + + switch (scale_action) { + case RS_ACTION_DOWNSCALE: + /* Decrease starting rate, update uCode's rate table */ + if (low != IWL_RATE_INVALID) { + update_lq = 1; + index = low; + } else { + IWL_DEBUG_RATE(mvm, + "At the bottom rate. Can't decrease\n"); + } + + break; + case RS_ACTION_UPSCALE: + /* Increase starting rate, update uCode's rate table */ + if (high != IWL_RATE_INVALID) { + update_lq = 1; + index = high; + } else { + IWL_DEBUG_RATE(mvm, + "At the top rate. Can't increase\n"); + } + + break; + case RS_ACTION_STAY: + /* No change */ + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) + update_lq = rs_tpc_perform(mvm, ni, lq_sta, tbl); + break; + default: + break; + } + +lq_update: + /* Replace uCode's rate table for the destination station. */ + if (update_lq) { + tbl->rate.index = index; + if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK) + rs_tweak_rate_tbl(mvm, ni, lq_sta, tbl, scale_action); + rs_set_amsdu_len(mvm, ni, tbl, scale_action); + rs_update_rate_tbl(mvm, ni, lq_sta, tbl); + } + + rs_stay_in_table(lq_sta, false); + + /* + * Search for new modulation mode if we're: + * 1) Not changing rates right now + * 2) Not just finishing up a search + * 3) Allowing a new search + */ + if (!update_lq && !done_search && + lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED + && window->counter) { + enum rs_column next_column; + + /* Save current throughput to compare with "search" throughput*/ + lq_sta->last_tpt = current_tpt; + + IWL_DEBUG_RATE(mvm, + "Start Search: update_lq %d done_search %d rs_state %d win->counter %d\n", + update_lq, done_search, lq_sta->rs_state, + window->counter); + + next_column = rs_get_next_column(mvm, lq_sta, ni, tbl); + if (next_column != RS_COLUMN_INVALID) { + int ret = rs_switch_to_column(mvm, lq_sta, ni, + next_column); + if (!ret) + lq_sta->search_better_tbl = 1; + } else { + IWL_DEBUG_RATE(mvm, + "No more columns to explore in search cycle. Go to RS_STATE_SEARCH_CYCLE_ENDED\n"); + lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_ENDED; + } + + /* If new "search" mode was selected, set up in uCode table */ + if (lq_sta->search_better_tbl) { + /* Access the "search" table, clear its history. */ + tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; + rs_rate_scale_clear_tbl_windows(mvm, tbl); + + /* Use new "search" start rate */ + index = tbl->rate.index; + + rs_dump_rate(mvm, &tbl->rate, + "Switch to SEARCH TABLE:"); + rs_update_rate_tbl(mvm, ni, lq_sta, tbl); + } else { + done_search = 1; + } + } + + if (!ndp) + rs_tl_turn_on_agg(mvm, tid, lq_sta, ni); + + if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) { + tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); + rs_set_stay_in_table(mvm, is_legacy(&tbl1->rate), lq_sta); + } +} + +struct rs_init_rate_info { + s8 rssi; + u8 rate_idx; +}; + +static const struct rs_init_rate_info rs_optimal_rates_24ghz_legacy[] = { + { -60, IWL_RATE_54M_INDEX }, + { -64, IWL_RATE_48M_INDEX }, + { -68, IWL_RATE_36M_INDEX }, + { -80, IWL_RATE_24M_INDEX }, + { -84, IWL_RATE_18M_INDEX }, + { -85, IWL_RATE_12M_INDEX }, + { -86, IWL_RATE_11M_INDEX }, + { -88, IWL_RATE_5M_INDEX }, + { -90, IWL_RATE_2M_INDEX }, + { S8_MIN, IWL_RATE_1M_INDEX }, +}; + +static const struct rs_init_rate_info rs_optimal_rates_5ghz_legacy[] = { + { -60, IWL_RATE_54M_INDEX }, + { -64, IWL_RATE_48M_INDEX }, + { -72, IWL_RATE_36M_INDEX }, + { -80, IWL_RATE_24M_INDEX }, + { -84, IWL_RATE_18M_INDEX }, + { -85, IWL_RATE_12M_INDEX }, + { -87, IWL_RATE_9M_INDEX }, + { S8_MIN, IWL_RATE_6M_INDEX }, +}; + +static const struct rs_init_rate_info rs_optimal_rates_ht[] = { + { -60, IWL_RATE_MCS_7_INDEX }, + { -64, IWL_RATE_MCS_6_INDEX }, + { -68, IWL_RATE_MCS_5_INDEX }, + { -72, IWL_RATE_MCS_4_INDEX }, + { -80, IWL_RATE_MCS_3_INDEX }, + { -84, IWL_RATE_MCS_2_INDEX }, + { -85, IWL_RATE_MCS_1_INDEX }, + { S8_MIN, IWL_RATE_MCS_0_INDEX}, +}; + +/* MCS index 9 is not valid for 20MHz VHT channel width, + * but is ok for 40, 80 and 160MHz channels. + */ +static const struct rs_init_rate_info rs_optimal_rates_vht_20mhz[] = { + { -60, IWL_RATE_MCS_8_INDEX }, + { -64, IWL_RATE_MCS_7_INDEX }, + { -68, IWL_RATE_MCS_6_INDEX }, + { -72, IWL_RATE_MCS_5_INDEX }, + { -80, IWL_RATE_MCS_4_INDEX }, + { -84, IWL_RATE_MCS_3_INDEX }, + { -85, IWL_RATE_MCS_2_INDEX }, + { -87, IWL_RATE_MCS_1_INDEX }, + { S8_MIN, IWL_RATE_MCS_0_INDEX}, +}; + +static const struct rs_init_rate_info rs_optimal_rates_vht[] = { + { -60, IWL_RATE_MCS_9_INDEX }, + { -64, IWL_RATE_MCS_8_INDEX }, + { -68, IWL_RATE_MCS_7_INDEX }, + { -72, IWL_RATE_MCS_6_INDEX }, + { -80, IWL_RATE_MCS_5_INDEX }, + { -84, IWL_RATE_MCS_4_INDEX }, + { -85, IWL_RATE_MCS_3_INDEX }, + { -87, IWL_RATE_MCS_2_INDEX }, + { -88, IWL_RATE_MCS_1_INDEX }, + { S8_MIN, IWL_RATE_MCS_0_INDEX }, +}; + +#define IWL_RS_LOW_RSSI_THRESHOLD (-76) /* dBm */ + +/* Init the optimal rate based on STA caps + * This combined with rssi is used to report the last tx rate + * to userspace when we haven't transmitted enough frames. + */ +static void rs_init_optimal_rate(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta) +{ + struct rs_rate *rate = &lq_sta->optimal_rate; + + if (lq_sta->max_mimo2_rate_idx != IWL_RATE_INVALID) + rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; + else if (lq_sta->max_siso_rate_idx != IWL_RATE_INVALID) + rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; + else if (lq_sta->band == NL80211_BAND_5GHZ) + rate->type = LQ_LEGACY_A; + else + rate->type = LQ_LEGACY_G; + + rate->bw = rs_bw_from_sta_bw(sta); + rate->sgi = rs_sgi_allow(mvm, sta, rate, NULL); + + /* ANT/LDPC/STBC aren't relevant for the rate reported to userspace */ + + if (is_mimo(rate)) { + lq_sta->optimal_rate_mask = lq_sta->active_mimo2_rate; + } else if (is_siso(rate)) { + lq_sta->optimal_rate_mask = lq_sta->active_siso_rate; + } else { + lq_sta->optimal_rate_mask = lq_sta->active_legacy_rate; + + if (lq_sta->band == NL80211_BAND_5GHZ) { + lq_sta->optimal_rates = rs_optimal_rates_5ghz_legacy; + lq_sta->optimal_nentries = + ARRAY_SIZE(rs_optimal_rates_5ghz_legacy); + } else { + lq_sta->optimal_rates = rs_optimal_rates_24ghz_legacy; + lq_sta->optimal_nentries = + ARRAY_SIZE(rs_optimal_rates_24ghz_legacy); + } + } + + if (is_vht(rate)) { + if (rate->bw == RATE_MCS_CHAN_WIDTH_20) { + lq_sta->optimal_rates = rs_optimal_rates_vht_20mhz; + lq_sta->optimal_nentries = + ARRAY_SIZE(rs_optimal_rates_vht_20mhz); + } else { + lq_sta->optimal_rates = rs_optimal_rates_vht; + lq_sta->optimal_nentries = + ARRAY_SIZE(rs_optimal_rates_vht); + } + } else if (is_ht(rate)) { + lq_sta->optimal_rates = rs_optimal_rates_ht; + lq_sta->optimal_nentries = ARRAY_SIZE(rs_optimal_rates_ht); + } +} + +/* Compute the optimal rate index based on RSSI */ +static struct rs_rate *rs_get_optimal_rate(struct iwm_softc *mvm, + struct iwl_lq_sta *lq_sta) +{ + struct rs_rate *rate = &lq_sta->optimal_rate; + int i; + + rate->index = find_first_bit(&lq_sta->optimal_rate_mask, + BITS_PER_LONG); + + for (i = 0; i < lq_sta->optimal_nentries; i++) { + int rate_idx = lq_sta->optimal_rates[i].rate_idx; + + if ((lq_sta->pers.last_rssi >= lq_sta->optimal_rates[i].rssi) && + (BIT(rate_idx) & lq_sta->optimal_rate_mask)) { + rate->index = rate_idx; + break; + } + } + + return rate; +} + +/* Choose an initial legacy rate and antenna to use based on the RSSI + * of last Rx + */ +static void rs_get_initial_rate(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta, + enum nl80211_band band, + struct rs_rate *rate) +{ + int i, nentries; + unsigned long active_rate; + s8 best_rssi = S8_MIN; + u8 best_ant = ANT_NONE; + ItlIwm *that = container_of(mvm, ItlIwm, com); + u8 valid_tx_ant = that->iwm_fw_valid_tx_ant(mvm); + const struct rs_init_rate_info *initial_rates; + + for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) { + if (!(lq_sta->pers.chains & BIT(i))) + continue; + + if (lq_sta->pers.chain_signal[i] > best_rssi) { + best_rssi = lq_sta->pers.chain_signal[i]; + best_ant = BIT(i); + } + } + + IWL_DEBUG_RATE(mvm, "Best ANT: %s Best RSSI: %d\n", + rs_pretty_ant(best_ant), best_rssi); + + if (best_ant != ANT_A && best_ant != ANT_B) + rate->ant = first_antenna(valid_tx_ant); + else + rate->ant = best_ant; + + rate->sgi = false; + rate->ldpc = false; + rate->bw = RATE_MCS_CHAN_WIDTH_20; + + rate->index = find_first_bit(&lq_sta->active_legacy_rate, + BITS_PER_LONG); + + if (band == NL80211_BAND_5GHZ) { + rate->type = LQ_LEGACY_A; + initial_rates = rs_optimal_rates_5ghz_legacy; + nentries = ARRAY_SIZE(rs_optimal_rates_5ghz_legacy); + } else { + rate->type = LQ_LEGACY_G; + initial_rates = rs_optimal_rates_24ghz_legacy; + nentries = ARRAY_SIZE(rs_optimal_rates_24ghz_legacy); + } + + if (!IWL_MVM_RS_RSSI_BASED_INIT_RATE) + goto out; + + /* Start from a higher rate if the corresponding debug capability + * is enabled. The rate is chosen according to AP capabilities. + * In case of VHT/HT when the rssi is low fallback to the case of + * legacy rates. + */ + if (ieee80211_node_supports_vht(sta) && + best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { + /* + * In AP mode, when a new station associates, rs is initialized + * immediately upon association completion, before the phy + * context is updated with the association parameters, so the + * sta bandwidth might be wider than the phy context allows. + * To avoid this issue, always initialize rs with 20mhz + * bandwidth rate, and after authorization, when the phy context + * is already up-to-date, re-init rs with the correct bw. + */ + u32 bw = mvm->sc_ic.ic_state < IEEE80211_S_RUN ? + RATE_MCS_CHAN_WIDTH_20 : rs_bw_from_sta_bw(sta); + + switch (bw) { + case RATE_MCS_CHAN_WIDTH_40: + case RATE_MCS_CHAN_WIDTH_80: + case RATE_MCS_CHAN_WIDTH_160: + initial_rates = rs_optimal_rates_vht; + nentries = ARRAY_SIZE(rs_optimal_rates_vht); + break; + case RATE_MCS_CHAN_WIDTH_20: + initial_rates = rs_optimal_rates_vht_20mhz; + nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz); + break; + default: + IWL_ERR(mvm, "Invalid BW %d\n", sta->ni_chw); + goto out; + } + + active_rate = lq_sta->active_siso_rate; + rate->type = LQ_VHT_SISO; + rate->bw = bw; + } else if (ieee80211_node_supports_ht(sta) && + best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { + initial_rates = rs_optimal_rates_ht; + nentries = ARRAY_SIZE(rs_optimal_rates_ht); + active_rate = lq_sta->active_siso_rate; + rate->type = LQ_HT_SISO; + } else { + active_rate = lq_sta->active_legacy_rate; + } + + for (i = 0; i < nentries; i++) { + int rate_idx = initial_rates[i].rate_idx; + + if ((best_rssi >= initial_rates[i].rssi) && + (BIT(rate_idx) & active_rate)) { + rate->index = rate_idx; + break; + } + } + +out: + rs_dump_rate(mvm, rate, "INITIAL"); +} + +/* Save info about RSSI of last Rx */ +void rs_update_last_rssi(struct iwm_softc *mvm, + struct ieee80211_rx_status *rx_status) +{ + struct iwl_lq_sta *lq_sta = &mvm->lq_sta.rs_drv; + int i; + + lq_sta->pers.chains = rx_status->chains; + lq_sta->pers.chain_signal[0] = rx_status->chain_signal[0]; + lq_sta->pers.chain_signal[1] = rx_status->chain_signal[1]; + lq_sta->pers.chain_signal[2] = rx_status->chain_signal[2]; + lq_sta->pers.last_rssi = S8_MIN; + + for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) { + if (!(lq_sta->pers.chains & BIT(i))) + continue; + + if (lq_sta->pers.chain_signal[i] > lq_sta->pers.last_rssi) + lq_sta->pers.last_rssi = lq_sta->pers.chain_signal[i]; + } +} + +/* + * rs_initialize_lq - Initialize a station's hardware rate table + * + * The uCode's station table contains a table of fallback rates + * for automatic fallback during transmission. + * + * NOTE: This sets up a default set of values. These will be replaced later + * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of + * rc80211_simple. + * + * NOTE: Run REPLY_ADD_STA command to set up station table entry, before + * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, + * which requires station table entry to exist). + */ +static void rs_initialize_lq(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta, + enum nl80211_band band) +{ + struct iwl_scale_tbl_info *tbl; + struct rs_rate *rate; + u8 active_tbl = 0; + + if (!sta || !lq_sta) + return; + + if (!lq_sta->search_better_tbl) + active_tbl = lq_sta->active_tbl; + else + active_tbl = rs_search_tbl(lq_sta->active_tbl); + + tbl = &(lq_sta->lq_info[active_tbl]); + rate = &tbl->rate; + + rs_get_initial_rate(mvm, sta, lq_sta, band, rate); + rs_init_optimal_rate(mvm, sta, lq_sta); + + WARN_ON(rate->ant != ANT_A && rate->ant != ANT_B, + "ant: 0x%x, chains 0x%x, fw tx ant: 0x%x, nvm tx ant: 0x%x\n", + rate->ant, lq_sta->pers.chains, mvm->fw->valid_tx_ant, + mvm->nvm_data ? mvm->nvm_data->valid_tx_ant : ANT_INVALID); + + tbl->column = rs_get_column_from_rate(rate); + + rs_set_expected_tpt_table(lq_sta, tbl); + rs_fill_lq_cmd(mvm, sta, lq_sta, rate); + /* TODO restore station should remember the lq cmd */ + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq); +} + +static void rs_drv_get_rate(struct iwm_softc *mvm, struct ieee80211_node *sta, + struct ieee80211_tx_rate *r) +{ + struct iwl_lq_sta *lq_sta; + struct rs_rate *optimal_rate; + u32 last_ucode_rate; + + if (!sta) + return; + + lq_sta = &mvm->lq_sta.rs_drv; + + IOSimpleLockLock(mvm->lq_sta.rs_drv.pers.lock); + iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags, + IEEE80211_IS_CHAN_2GHZ(sta->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, r); + + /* Report the optimal rate based on rssi and STA caps if we haven't + * converged yet (too little traffic) or exploring other modulations + */ + if (lq_sta->rs_state != RS_STATE_STAY_IN_COLUMN) { + optimal_rate = rs_get_optimal_rate(mvm, lq_sta); + last_ucode_rate = ucode_rate_from_rs_rate(mvm, + optimal_rate); + iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, IEEE80211_IS_CHAN_2GHZ(sta->ni_chan) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ, + r); + } + IOSimpleLockUnlock(mvm->lq_sta.rs_drv.pers.lock); +} + +void *rs_drv_alloc_sta(iwm_softc *sc, struct ieee80211_node *ni) +{ + struct iwl_lq_sta *lq_sta = &sc->lq_sta.rs_drv; + + IWL_DEBUG_RATE(mvm, "create station rate scale window\n"); + + lq_sta->pers.drv = sc; + lq_sta->pers.chains = 0; + memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal)); + lq_sta->pers.last_rssi = S8_MIN; + + return lq_sta; +} + +void rs_drv_free_sta(iwm_softc *sc, struct ieee80211_node *ni) +{} + +static int rs_vht_highest_rx_mcs_index(struct ieee80211_node *sta, + int nss) +{ + u16 rx_mcs = le16_to_cpu(sta->ni_vht_mcsinfo.rx_mcs_map) & + (0x3 << (2 * (nss - 1))); + rx_mcs >>= (2 * (nss - 1)); + + if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_7) + return IWL_RATE_MCS_7_INDEX; + else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_8) + return IWL_RATE_MCS_8_INDEX; + else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_9) + return IWL_RATE_MCS_9_INDEX; + + WARN_ON_ONCE(rx_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED); + return -1; +} + +static void rs_vht_set_enabled_rates(struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta) +{ + int i; + int highest_mcs = rs_vht_highest_rx_mcs_index(sta, 1); + + if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { + for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { + if (i == IWL_RATE_9M_INDEX) + continue; + + /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ + if (i == IWL_RATE_MCS_9_INDEX && + sta->ni_chw == IEEE80211_CHAN_WIDTH_20) + continue; + + lq_sta->active_siso_rate |= BIT(i); + } + } + + if (sta->ni_rx_nss < 2) + return; + + highest_mcs = rs_vht_highest_rx_mcs_index(sta, 2); + if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { + for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { + if (i == IWL_RATE_9M_INDEX) + continue; + + /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ + if (i == IWL_RATE_MCS_9_INDEX && + sta->ni_chw == IEEE80211_CHAN_WIDTH_20) + continue; + + lq_sta->active_mimo2_rate |= BIT(i); + } + } +} + +static void rs_ht_init(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta) +{ + ItlIwm *that = container_of(mvm, ItlIwm, com); + /* active_siso_rate mask includes 9 MBits (bit 5), + * and CCK (bits 0-3), supp_rates[] does not; + * shift to convert format, force 9 MBits off. + */ + lq_sta->active_siso_rate = sta->ni_rxmcs[0] << 1; + lq_sta->active_siso_rate |= sta->ni_rxmcs[0] & 0x1; + lq_sta->active_siso_rate &= ~((u16)0x2); + lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; + + lq_sta->active_mimo2_rate = sta->ni_rxmcs[1] << 1; + lq_sta->active_mimo2_rate |= sta->ni_rxmcs[1] & 0x1; + lq_sta->active_mimo2_rate &= ~((u16)0x2); + lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; + + if ((sta->ni_htcaps & IEEE80211_HTCAP_LDPC) && + mvm->support_ldpc) + lq_sta->ldpc = true; + + if ((that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(mvm)) > 1) && + (sta->ni_htcaps & IEEE80211_HTCAP_RXSTBC_MASK)) + lq_sta->stbc_capable = true; + + lq_sta->is_vht = false; +} + +static void rs_vht_init(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta) +{ + ItlIwm *that = container_of(mvm, ItlIwm, com); + rs_vht_set_enabled_rates(sta, lq_sta); + + if ((sta->ni_vhtcaps & IEEE80211_VHTCAP_RXLDPC) && + mvm->support_ldpc) + lq_sta->ldpc = true; + + if ((that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(mvm)) > 1) && + (sta->ni_vhtcaps & IEEE80211_VHTCAP_RXSTBC_MASK)) + lq_sta->stbc_capable = true; + +#if 0 + if (isset(mvm->sc_enabled_capa, IWM_UCODE_TLV_CAPA_BEAMFORMER) && + (that->iwm_num_of_ant(that->iwm_fw_valid_tx_ant(mvm)) > 1) && + (sta->ni_vhtcaps & IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE)) + lq_sta->bfer_capable = true; +#endif + + lq_sta->is_vht = true; +} + +static u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwm_softc *mvm, u8 enabled_ants) +{ + if (isset(&mvm->sc_enabled_capa, IWM_UCODE_TLV_CAPA_COEX_SCHEMA_2) && + (mvm->non_shared_ant & enabled_ants)) + return mvm->non_shared_ant; + + return first_antenna(enabled_ants); +} + +/** + * struct ieee80211_rate - bitrate definition + * + * This structure describes a bitrate that an 802.11 PHY can + * operate with. The two values @hw_value and @hw_value_short + * are only for driver use when pointers to this structure are + * passed around. + * + * @flags: rate-specific flags + * @bitrate: bitrate in units of 100 Kbps + * @hw_value: driver/hardware value for this rate + * @hw_value_short: driver/hardware value for this rate when + * short preamble is used + */ +struct ieee80211_rate { + u32 flags; + u16 bitrate; + u16 hw_value, hw_value_short; +}; + +/** + * enum ieee80211_rate_flags - rate flags + * + * Hardware/specification flags for rates. These are structured + * in a way that allows using the same bitrate structure for + * different bands/PHY modes. + * + * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short + * preamble on this bitrate; only relevant in 2.4GHz band and + * with CCK rates. + * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate + * when used with 802.11a (on the 5 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate + * when used with 802.11b (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate + * when used with 802.11g (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. + * @IEEE80211_RATE_SUPPORTS_5MHZ: Rate can be used in 5 MHz mode + * @IEEE80211_RATE_SUPPORTS_10MHZ: Rate can be used in 10 MHz mode + */ +enum ieee80211_rate_flags { + IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, + IEEE80211_RATE_MANDATORY_A = 1<<1, + IEEE80211_RATE_MANDATORY_B = 1<<2, + IEEE80211_RATE_MANDATORY_G = 1<<3, + IEEE80211_RATE_ERP_G = 1<<4, + IEEE80211_RATE_SUPPORTS_5MHZ = 1<<5, + IEEE80211_RATE_SUPPORTS_10MHZ = 1<<6, +}; + +/* + * Called after adding a new station to initialize rate scaling + */ +static void rs_drv_rate_init(struct iwm_softc *mvm, struct ieee80211_node *sta, + enum nl80211_band band) +{ + int i, j; + struct iwl_lq_sta *lq_sta = &mvm->lq_sta.rs_drv; + ItlIwm *that = container_of(mvm, ItlIwm, com); + uint8_t rate; + +// lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock); + + /* clear all non-persistent lq data */ + memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers)); + + lq_sta->lq.sta_id = IWM_STATION_ID; +#if 0 + mvm->amsdu_enabled = 0; + mvm->max_amsdu_len = sta->max_amsdu_len; +#endif + + for (j = 0; j < LQ_SIZE; j++) + rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); + + lq_sta->flush_timer = 0; + lq_sta->last_tx = ticks; + + IWL_DEBUG_RATE(mvm, + "LQ: *** rate scale station global init for station %d ***\n", + IWM_STATION_ID); + /* TODO: what is a good starting rate for STA? About middle? Maybe not + * the lowest or the highest rate.. Could consider using RSSI from + * previous packets? Need to have IEEE 802.1X auth succeed immediately + * after assoc.. */ + + lq_sta->missed_rate_counter = IWL_MVM_RS_MISSED_RATE_MAX; + lq_sta->band = band; + /* + * active legacy rates as per supported rates bitmap + */ + lq_sta->active_legacy_rate = 0; + for (i = 0; i < ieee80211_std_rateset_11g.rs_nrates; i++) { + for (j = 0; j < sta->ni_rates.rs_nrates; j++) { + if (ieee80211_std_rateset_11g.rs_rates[i] == + (sta->ni_rates.rs_rates[j] & IEEE80211_RATE_VAL)) { + lq_sta->active_legacy_rate |= BIT(i); + break; + } + } + } + + /* TODO: should probably account for rx_highest for both HT/VHT */ + if ((sta->ni_flags & IEEE80211_NODE_VHT) == 0) + rs_ht_init(mvm, sta, lq_sta); + else + rs_vht_init(mvm, sta, lq_sta); + + lq_sta->max_legacy_rate_idx = + rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); + lq_sta->max_siso_rate_idx = + rs_get_max_rate_from_mask(lq_sta->active_siso_rate); + lq_sta->max_mimo2_rate_idx = + rs_get_max_rate_from_mask(lq_sta->active_mimo2_rate); + + XYLog("LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC=%d BFER=%d\n", + lq_sta->active_legacy_rate, + lq_sta->active_siso_rate, + lq_sta->active_mimo2_rate, + lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc_capable, + lq_sta->bfer_capable); + XYLog("MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", + lq_sta->max_legacy_rate_idx, + lq_sta->max_siso_rate_idx, + lq_sta->max_mimo2_rate_idx); + + /* These values will be overridden later */ + lq_sta->lq.single_stream_ant_msk = + iwl_mvm_bt_coex_get_single_ant_msk(mvm, that->iwm_fw_valid_tx_ant(mvm)); + lq_sta->lq.dual_stream_ant_msk = ANT_AB; + + /* as default allow aggregation for all tids */ + lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; + lq_sta->is_agg = 0; + rs_initialize_lq(mvm, sta, lq_sta, band); +} + +void rs_drv_rate_update(struct iwm_softc *mvm, + struct ieee80211_node *sta, + enum nl80211_band band, u32 changed) +{ + /* Stop any ongoing aggregations as rs starts off assuming no agg */ + ieee80211_stop_ampdu_tx(&mvm->sc_ic, sta, 0); + + iwl_mvm_rs_rate_init(mvm, sta, band, true); +} + +static void __iwl_mvm_rs_tx_status(struct iwm_softc *mvm, + struct ieee80211_node *sta, + int tid, struct ieee80211_tx_info *info, + bool ndp) +{ + int legacy_success; + int retries; + int i; + struct iwm_lq_cmd *table; + u32 lq_hwrate; + uint32_t last_rate; + struct rs_rate lq_rate, tx_resp_rate; + struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; + u32 tlc_info = (u32)(uintptr_t)info->status.status_driver_data[0]; + u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK; + u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info); + u32 tx_resp_hwrate = (u32)(uintptr_t)info->status.status_driver_data[1]; + struct iwl_lq_sta *lq_sta = &mvm->lq_sta.rs_drv; + char pretty_rate[100]; + + if (!lq_sta->pers.drv) { + IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n"); + return; + } + + /* This packet was aggregated but doesn't carry status info */ + if ((info->flags & IEEE80211_TX_CTL_AMPDU) && + !(info->flags & IEEE80211_TX_STAT_AMPDU)) + return; + + if (rs_rate_from_ucode_rate(tx_resp_hwrate, (enum nl80211_band)info->band, + &tx_resp_rate)) { + WARN_ON_ONCE(1); + return; + } + + if (time_after(ticks, + (unsigned long)(lq_sta->last_tx + + (IWL_MVM_RS_IDLE_TIMEOUT * hz)))) { + IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); + /* reach here only in case of driver RS, call directly + * the unlocked version + */ + rs_drv_rate_init(mvm, sta, (nl80211_band)info->band); + return; + } + lq_sta->last_tx = ticks; + + /* Ignore this Tx frame response if its initial rate doesn't match + * that of latest Link Quality command. There may be stragglers + * from a previous Link Quality command, but we're no longer interested + * in those; they're either from the "active" mode while we're trying + * to check "search" mode, or a prior "search" mode after we've moved + * to a new "search" mode (which might become the new "active" mode). + */ + table = &lq_sta->lq; + lq_hwrate = le32_to_cpu(table->rs_table[0]); + if (rs_rate_from_ucode_rate(lq_hwrate, (enum nl80211_band)info->band, &lq_rate)) { + WARN_ON_ONCE(1); + return; + } + + /* Here we actually compare this rate to the latest LQ command */ + if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) { + IWL_DEBUG_RATE(mvm, + "tx resp color 0x%x does not match 0x%x\n", + lq_color, LQ_FLAG_COLOR_GET(table->flags)); + + /* Since rates mis-match, the last LQ command may have failed. + * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with + * ... driver. + */ + lq_sta->missed_rate_counter++; + if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) { + lq_sta->missed_rate_counter = 0; + IWL_DEBUG_RATE(mvm, + "Too many rates mismatch. Send sync LQ. rs_state %d\n", + lq_sta->rs_state); + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq); + } + /* Regardless, ignore this status info for outdated rate */ + return; + } + + /* Rate did match, so reset the missed_rate_counter */ + lq_sta->missed_rate_counter = 0; + + if (!lq_sta->search_better_tbl) { + curr_tbl = &lq_sta->lq_info[lq_sta->active_tbl]; + other_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; + } else { + curr_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; + other_tbl = &lq_sta->lq_info[lq_sta->active_tbl]; + } + + if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) { + IWL_DEBUG_RATE(mvm, + "Neither active nor search matches tx rate\n"); + tmp_tbl = &lq_sta->lq_info[lq_sta->active_tbl]; + rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE"); + tmp_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; + rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH"); + rs_dump_rate(mvm, &lq_rate, "ACTUAL"); + + /* no matching table found, let's by-pass the data collection + * and continue to perform rate scale to find the rate table + */ + rs_stay_in_table(lq_sta, true); + goto done; + } + + /* Updating the frame history depends on whether packets were + * aggregated. + * + * For aggregation, all packets were transmitted at the same rate, the + * first index into rate scale table. + */ + if (info->flags & IEEE80211_TX_STAT_AMPDU) { + rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index, + info->status.ampdu_len, + info->status.ampdu_ack_len, + reduced_txp); + + /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat + * it as a single frame loss as we don't want the success ratio + * to dip too quickly because a BA wasn't received. + * For TPC, there's no need for this optimisation since we want + * to recover very quickly from a bad power reduction and, + * therefore we'd like the success ratio to get an immediate hit + * when failing to get a BA, so we'd switch back to a lower or + * zero power reduction. When FW transmits agg with a rate + * different from the initial rate, it will not use reduced txp + * and will send BA notification twice (one empty with reduced + * txp equal to the value from LQ and one with reduced txp 0). + * We need to update counters for each txp level accordingly. + */ + if (info->status.ampdu_ack_len == 0) + info->status.ampdu_len = 1; + + rs_collect_tlc_data(mvm, tid, curr_tbl, + tx_resp_rate.index, + info->status.ampdu_len, + info->status.ampdu_ack_len); + + /* Update success/fail counts if not searching for new mode */ + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { + lq_sta->total_success += info->status.ampdu_ack_len; + lq_sta->total_failed += (info->status.ampdu_len - + info->status.ampdu_ack_len); + } + } else { + /* For legacy, update frame history with for each Tx retry. */ + retries = info->status.rates[0].count - 1; + /* HW doesn't send more than 15 retries */ + retries = min(retries, 15); + + /* The last transmission may have been successful */ + legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); + /* Collect data for each rate used during failed TX attempts */ + for (i = 0; i <= retries; ++i) { + lq_hwrate = le32_to_cpu(table->rs_table[i]); + if (rs_rate_from_ucode_rate(lq_hwrate, (enum nl80211_band)info->band, + &lq_rate)) { + WARN_ON_ONCE(1); + return; + } + + /* Only collect stats if retried rate is in the same RS + * table as active/search. + */ + if (rs_rate_column_match(&lq_rate, &curr_tbl->rate)) + tmp_tbl = curr_tbl; + else if (rs_rate_column_match(&lq_rate, + &other_tbl->rate)) + tmp_tbl = other_tbl; + else + continue; + + rs_collect_tpc_data(mvm, lq_sta, tmp_tbl, + tx_resp_rate.index, 1, + i < retries ? 0 : legacy_success, + reduced_txp); + rs_collect_tlc_data(mvm, tid, tmp_tbl, + tx_resp_rate.index, 1, + i < retries ? 0 : legacy_success); + } + + /* Update success/fail counts if not searching for new mode */ + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { + lq_sta->total_success += legacy_success; + lq_sta->total_failed += retries + (1 - legacy_success); + } + } + /* The last TX rate is cached in lq_sta; it's set in if/else above */ + last_rate = lq_sta->last_rate_n_flags; + lq_sta->last_rate_n_flags = lq_hwrate; + if (last_rate != lq_hwrate) { + rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate), lq_sta->last_rate_n_flags); + XYLog("%s new rate: %s\n", __FUNCTION__, pretty_rate); + } + if ((lq_sta->last_rate_n_flags & RATE_MCS_VHT_MSK) || (lq_sta->last_rate_n_flags & RATE_MCS_HE_MSK)) { + sta->ni_txmcs = (lq_sta->last_rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK); + } else if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { + sta->ni_txmcs = (lq_sta->last_rate_n_flags & + (RATE_HT_MCS_RATE_CODE_MSK | + RATE_HT_MCS_NSS_MSK)); + } else { + int index = iwl_mvm_legacy_rate_to_mac80211_idx(lq_sta->last_rate_n_flags, (enum nl80211_band)info->band); + if (index < 0 || index >= ieee80211_std_rateset_11g.rs_nrates) + goto done; + + sta->ni_txrate = ieee80211_std_rateset_11g.rs_rates[index] / 2; + } + IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); +done: + /* See if there's a better rate or modulation mode to try. */ + if (/*sta->supp_rates[info->band]*/ true) + rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp); +} + +void iwl_mvm_rs_tx_status(struct iwm_softc *mvm, struct ieee80211_node *sta, + int tid, struct ieee80211_tx_info *info, bool ndp) +{ + /* If it's locked we are in middle of init flow + * just wait for next tx status to update the lq_sta data + */ + if (!IOSimpleLockTryLock(mvm->lq_sta.rs_drv.pers.lock)) + return; + + __iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp); + IOSimpleLockUnlock(mvm->lq_sta.rs_drv.pers.lock); +} + +static void rs_fill_rates_for_column(struct iwm_softc *mvm, + struct iwl_lq_sta *lq_sta, + struct rs_rate *rate, + __le32 *rs_table, int *rs_table_index, + int num_rates, int num_retries, + u8 valid_tx_ant, bool toggle_ant) +{ + int i, j; + __le32 ucode_rate; + bool bottom_reached = false; + int prev_rate_idx = rate->index; + int end = LINK_QUAL_MAX_RETRY_NUM; + int index = *rs_table_index; + + for (i = 0; i < num_rates && index < end; i++) { + for (j = 0; j < num_retries && index < end; j++, index++) { + ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm, + rate)); + rs_table[index] = ucode_rate; + if (toggle_ant) + rs_toggle_antenna(valid_tx_ant, rate); + } + + prev_rate_idx = rate->index; + bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate); + if (bottom_reached && !is_legacy(rate)) + break; + } + + if (!bottom_reached && !is_legacy(rate)) + rate->index = prev_rate_idx; + + *rs_table_index = index; +} + +/* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI + * column the rate table should look like this: + * + * rate[0] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI + * rate[1] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI + * rate[2] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI + * rate[3] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI + * rate[4] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI + * rate[5] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI + * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI + * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI + * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI + * rate[9] 0x800B Legacy | ANT: B Rate: 36 Mbps + * rate[10] 0x4009 Legacy | ANT: A Rate: 24 Mbps + * rate[11] 0x8007 Legacy | ANT: B Rate: 18 Mbps + * rate[12] 0x4005 Legacy | ANT: A Rate: 12 Mbps + * rate[13] 0x800F Legacy | ANT: B Rate: 9 Mbps + * rate[14] 0x400D Legacy | ANT: A Rate: 6 Mbps + * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps + */ +static void rs_build_rates_table(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta, + const struct rs_rate *initial_rate) +{ + struct rs_rate rate; + int num_rates, num_retries, index = 0; + u8 valid_tx_ant = 0; + struct iwm_lq_cmd *lq_cmd = &lq_sta->lq; + bool toggle_ant = false; + u32 color; + ItlIwm *that = container_of(mvm, ItlIwm, com); + + memcpy(&rate, initial_rate, sizeof(rate)); + + valid_tx_ant = that->iwm_fw_valid_tx_ant(mvm); + + /* TODO: remove old API when min FW API hits 14 */ + if (!isset(&mvm->sc_ucode_api, IWM_UCODE_TLV_API_LQ_SS_PARAMS) && + rs_stbc_allow(mvm, sta, lq_sta)) + rate.stbc = true; + + if (is_siso(&rate)) { + num_rates = IWL_MVM_RS_INITIAL_SISO_NUM_RATES; + num_retries = IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE; + } else if (is_mimo(&rate)) { + num_rates = IWL_MVM_RS_INITIAL_MIMO_NUM_RATES; + num_retries = IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE; + } else { + num_rates = IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES; + num_retries = IWL_MVM_RS_INITIAL_LEGACY_RETRIES; + toggle_ant = true; + } + + rs_fill_rates_for_column(mvm, lq_sta, &rate, (__le32 *)lq_cmd->rs_table, &index, + num_rates, num_retries, valid_tx_ant, + toggle_ant); + + rs_get_lower_rate_down_column(lq_sta, &rate); + + if (is_siso(&rate)) { + num_rates = IWL_MVM_RS_SECONDARY_SISO_NUM_RATES; + num_retries = IWL_MVM_RS_SECONDARY_SISO_RETRIES; + lq_cmd->mimo_delim = index; + } else if (is_legacy(&rate)) { + num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES; + num_retries = IWL_MVM_RS_SECONDARY_LEGACY_RETRIES; + } else { + WARN_ON_ONCE(1); + } + + toggle_ant = true; + + rs_fill_rates_for_column(mvm, lq_sta, &rate, (__le32 *)lq_cmd->rs_table, &index, + num_rates, num_retries, valid_tx_ant, + toggle_ant); + + rs_get_lower_rate_down_column(lq_sta, &rate); + + num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES; + num_retries = IWL_MVM_RS_SECONDARY_LEGACY_RETRIES; + + rs_fill_rates_for_column(mvm, lq_sta, &rate, (__le32 *)lq_cmd->rs_table, &index, + num_rates, num_retries, valid_tx_ant, + toggle_ant); + + /* update the color of the LQ command (as a counter at bits 1-3) */ + color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags)); + lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color); +} + +#if 0 +struct rs_bfer_active_iter_data { + struct ieee80211_node *exclude_sta; + struct ieee80211_node *bfer_mvmsta; +}; + +static void rs_bfer_active_iter(void *_data, + struct ieee80211_node *sta) +{ + struct rs_bfer_active_iter_data *data = (struct rs_bfer_active_iter_data *)_data; + struct iwm_lq_cmd *lq_cmd = &sta->ni_ic->lq_sta.rs_drv.lq; + u32 ss_params = le32_to_cpu(lq_cmd->ss_params); + + if (sta == data->exclude_sta) + return; + + /* The current sta has BFER allowed */ + if (ss_params & LQ_SS_BFER_ALLOWED) { + WARN_ON_ONCE(data->bfer_mvmsta != NULL); + + data->bfer_mvmsta = mvmsta; + } +} + +static int rs_bfer_priority(struct ieee80211_node *sta) +{ + return 1; +} + +/* Returns >0 if sta1 has a higher BFER priority compared to sta2 */ +static int rs_bfer_priority_cmp(struct ieee80211_node *sta1, + struct ieee80211_node *sta2) +{ + int prio1 = rs_bfer_priority(sta1); + int prio2 = rs_bfer_priority(sta2); + + if (prio1 > prio2) + return 1; + if (prio1 < prio2) + return -1; + return 0; +} + +static inline void ieee80211_iterate_stations_atomic(struct iwm_softc *hw, + void (*iterator)(void *data, + struct ieee80211_node *sta), + void *data) +{ + iterator(data, hw->sc_ic.ic_bss); +} + +#endif + +static void rs_set_lq_ss_params(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta, + const struct rs_rate *initial_rate) +{ + struct iwm_lq_cmd *lq_cmd = &lq_sta->lq; +#if 0 + struct rs_bfer_active_iter_data data = { + .exclude_sta = sta, + .bfer_mvmsta = NULL, + }; +#endif + u32 ss_params = LQ_SS_PARAMS_VALID; + + if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) + goto out; + + if (lq_sta->stbc_capable) + ss_params |= LQ_SS_STBC_1SS_ALLOWED; + +#if 0 + if (!lq_sta->bfer_capable) + goto out; + + ieee80211_iterate_stations_atomic(mvm, + rs_bfer_active_iter, + &data); + bfer_mvmsta = data.bfer_mvmsta; + + /* This code is safe as it doesn't run concurrently for different + * stations. This is guaranteed by the fact that calls to + * ieee80211_tx_status wouldn't run concurrently for a single HW. + */ + if (!bfer_mvmsta) { + IWL_DEBUG_RATE(mvm, "No sta with BFER allowed found. Allow\n"); + + ss_params |= LQ_SS_BFER_ALLOWED; + goto out; + } + + IWL_DEBUG_RATE(mvm, "Found existing sta %d with BFER activated\n", + bfer_mvmsta->sta_id); + + /* Disallow BFER on another STA if active and we're a higher priority */ + if (rs_bfer_priority_cmp(mvmsta, bfer_mvmsta) > 0) { + struct iwm_lq_cmd *bfersta_lq_cmd = + &bfer_mvmsta->lq_sta.rs_drv.lq; + u32 bfersta_ss_params = le32_to_cpu(bfersta_lq_cmd->ss_params); + + bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED; + bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params); + iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd); + + ss_params |= LQ_SS_BFER_ALLOWED; + IWL_DEBUG_RATE(mvm, + "Lower priority BFER sta found (%d). Switch BFER\n", + bfer_mvmsta->sta_id); + } +#else + if (lq_sta->bfer_capable) + ss_params |= LQ_SS_BFER_ALLOWED; +#endif +out: + lq_cmd->ss_params = cpu_to_le32(ss_params); +} + +static void rs_fill_lq_cmd(struct iwm_softc *mvm, + struct ieee80211_node *sta, + struct iwl_lq_sta *lq_sta, + const struct rs_rate *initial_rate) +{ + struct iwm_lq_cmd *lq_cmd = &lq_sta->lq; + ItlIwm *that = container_of(mvm, ItlIwm, com); + + lq_cmd->agg_disable_start_th = IWL_MVM_RS_AGG_DISABLE_START; + lq_cmd->agg_time_limit = + cpu_to_le16(IWL_MVM_RS_AGG_TIME_LIMIT); + + if (WARN_ON_ONCE(!sta || !initial_rate)) + return; + + rs_build_rates_table(mvm, sta, lq_sta, initial_rate); + + if (isset(&mvm->sc_ucode_api, IWM_UCODE_TLV_API_LQ_SS_PARAMS)) + rs_set_lq_ss_params(mvm, sta, lq_sta, initial_rate); + + if (!isset(&mvm->sc_enabled_capa, IWM_UCODE_TLV_CAPA_COEX_SCHEMA_2) && + that->iwm_num_of_ant(initial_rate->ant) == 1) + lq_cmd->single_stream_ant_msk = initial_rate->ant; + + lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + +#if 0 + if (mvmsta->vif->p2p) + lq_cmd->flags |= LQ_FLAG_USE_RTS_MSK; +#endif + + lq_cmd->agg_time_limit = + cpu_to_le16(that->iwm_coex_agg_time_limit(mvm, sta)); +} + +int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) +{ + + char *type, *bw; + u8 mcs = 0, nss = 0; + u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS; + + if (!(rate & RATE_MCS_HT_MSK) && + !(rate & RATE_MCS_VHT_MSK) && + !(rate & RATE_MCS_HE_MSK)) { + int index = iwl_hwrate_to_plcp_idx(rate); + + return snprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps", + rs_pretty_ant(ant), + index == IWL_RATE_INVALID ? "BAD" : + iwl_rate_mcs[index].mbps); + } + + if (rate & RATE_MCS_VHT_MSK) { + type = "VHT"; + mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; + nss = ((rate & RATE_VHT_MCS_NSS_MSK) + >> RATE_VHT_MCS_NSS_POS) + 1; + } else if (rate & RATE_MCS_HT_MSK) { + type = "HT"; + mcs = rate & RATE_HT_MCS_INDEX_MSK; + nss = ((rate & RATE_HT_MCS_NSS_MSK) + >> RATE_HT_MCS_NSS_POS) + 1; + } else if (rate & RATE_MCS_HE_MSK) { + type = "HE"; + mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; + nss = ((rate & RATE_VHT_MCS_NSS_MSK) + >> RATE_VHT_MCS_NSS_POS) + 1; + } else { + type = "Unknown"; /* shouldn't happen */ + } + + switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { + case RATE_MCS_CHAN_WIDTH_20: + bw = "20Mhz"; + break; + case RATE_MCS_CHAN_WIDTH_40: + bw = "40Mhz"; + break; + case RATE_MCS_CHAN_WIDTH_80: + bw = "80Mhz"; + break; + case RATE_MCS_CHAN_WIDTH_160: + bw = "160Mhz"; + break; + default: + bw = "BAD BW"; + } + + return snprintf(buf, bufsz, + "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s", + rate, type, rs_pretty_ant(ant), bw, mcs, nss, + (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", + (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", + (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", + (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "", + (rate & RATE_MCS_BF_MSK) ? "BF " : ""); +} + +void iwl_mvm_rs_rate_init(struct iwm_softc *mvm, struct ieee80211_node *sta, + enum nl80211_band band, bool update) +{ + IOSimpleLockLock(mvm->lq_sta.rs_drv.pers.lock); + rs_drv_rate_init(mvm, sta, band); + IOSimpleLockUnlock(mvm->lq_sta.rs_drv.pers.lock); +} + +static int rs_drv_tx_protection(struct iwm_softc *mvm, + bool enable) +{ + struct iwm_lq_cmd *lq = &mvm->lq_sta.rs_drv.lq; + + if (enable) { + if (mvm->tx_protection == 0) + lq->flags |= LQ_FLAG_USE_RTS_MSK; + mvm->tx_protection++; + } else { + mvm->tx_protection--; + if (mvm->tx_protection == 0) + lq->flags &= ~LQ_FLAG_USE_RTS_MSK; + } + + return iwl_mvm_send_lq_cmd(mvm, lq); +} + +/** + * iwl_mvm_tx_protection - ask FW to enable RTS/CTS protection + * @mvm: The mvm component + * @mvmsta: The station + * @enable: Enable Tx protection? + */ +int iwl_mvm_tx_protection(struct iwm_softc *mvm, + bool enable) +{ + return rs_drv_tx_protection(mvm, enable); +} + +void +iwm_rs_alloc(struct iwm_softc *sc) +{ + sc->lq_sta.rs_drv.pers.lock = IOSimpleLockAlloc(); +} + +void iwm_rs_free(struct iwm_softc *sc) +{ + if (sc->lq_sta.rs_drv.pers.lock) { + IOSimpleLockFree(sc->lq_sta.rs_drv.pers.lock); + sc->lq_sta.rs_drv.pers.lock = NULL; + } +} diff --git a/itlwm/hal_iwm/rs.h b/itlwm/hal_iwm/rs.h new file mode 100644 index 000000000..19e032a9a --- /dev/null +++ b/itlwm/hal_iwm/rs.h @@ -0,0 +1,1515 @@ +// +// rs.hpp +// itlwm +// +// Created by zxystd on 2021/8/27. +// Copyright © 2021 钟先耀. All rights reserved. +// + +#ifndef rs_hpp +#define rs_hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define IWL_DEBUG_RATE(sc, fmt, x...) +//#define IWL_DEBUG_RATE(sc, fmt, x...)\ +//do\ +//{\ +//XYLog("%s: " fmt, "RATE", ##x);\ +//}while(0) + +#define IWL_ERR(sc, fmt, x...)\ +do\ +{\ +XYLog("RS %s: " fmt, "ERR", ##x);\ +}while(0) + +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +enum nl80211_band { + NL80211_BAND_2GHZ, + NL80211_BAND_5GHZ, + + NUM_NL80211_BANDS, +}; + +/** + * enum mac80211_tx_info_flags - flags to describe transmission information/status + * + * These flags are used with the @flags member of &ieee80211_tx_info. + * + * @IEEE80211_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame. + * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence + * number to this frame, taking care of not overwriting the fragment + * number and increasing the sequence number only when the + * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly + * assign sequence numbers to QoS-data frames but cannot do so correctly + * for non-QoS-data and management frames because beacons need them from + * that counter as well and mac80211 cannot guarantee proper sequencing. + * If this flag is set, the driver should instruct the hardware to + * assign a sequence number to the frame or assign one itself. Cf. IEEE + * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for + * beacons and always be clear for frames without a sequence number field. + * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack + * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination + * station + * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame + * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon + * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU + * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. + * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted + * because the destination STA was in powersave mode. Note that to + * avoid race conditions, the filter must be set by the hardware or + * firmware upon receiving a frame that indicates that the station + * went to sleep (must be done on device to filter frames already on + * the queue) and may only be unset after mac80211 gives the OK for + * that by setting the IEEE80211_TX_CTL_CLEAR_PS_FILT (see above), + * since only then is it guaranteed that no more frames are in the + * hardware queue. + * @IEEE80211_TX_STAT_ACK: Frame was acknowledged + * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status + * is for the whole aggregation. + * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, + * so consider using block ack request (BAR). + * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be + * set by rate control algorithms to indicate probe rate, will + * be cleared for fragmented frames (except on the last fragment) + * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate + * that a frame can be transmitted while the queues are stopped for + * off-channel operation. + * @IEEE80211_TX_CTL_HW_80211_ENCAP: This frame uses hardware encapsulation + * (header conversion) + * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211, + * used to indicate that a frame was already retried due to PS + * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211, + * used to indicate frame should not be encrypted + * @IEEE80211_TX_CTL_NO_PS_BUFFER: This frame is a response to a poll + * frame (PS-Poll or uAPSD) or a non-bufferable MMPDU and must + * be sent although the station is in powersave mode. + * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the + * transmit function after the current frame, this can be used + * by drivers to kick the DMA queue only if unset or when the + * queue gets full. + * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted + * after TX status because the destination was asleep, it must not + * be modified again (no seqno assignment, crypto, etc.) + * @IEEE80211_TX_INTFL_MLME_CONN_TX: This frame was transmitted by the MLME + * code for connection establishment, this indicates that its status + * should kick the MLME state machine. + * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 + * MLME command (internal to mac80211 to figure out whether to send TX + * status to user space) + * @IEEE80211_TX_CTL_LDPC: tells the driver to use LDPC for this frame + * @IEEE80211_TX_CTL_STBC: Enables Space-Time Block Coding (STBC) for this + * frame and selects the maximum number of streams that it can use. + * @IEEE80211_TX_CTL_TX_OFFCHAN: Marks this packet to be transmitted on + * the off-channel channel when a remain-on-channel offload is done + * in hardware -- normal packets still flow and are expected to be + * handled properly by the device. + * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP + * testing. It will be sent out with incorrect Michael MIC key to allow + * TKIP countermeasures to be tested. + * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate. + * This flag is actually used for management frame especially for P2P + * frames not being sent at CCK rate in 2GHz band. + * @IEEE80211_TX_STATUS_EOSP: This packet marks the end of service period, + * when its status is reported the service period ends. For frames in + * an SP that mac80211 transmits, it is already set; for driver frames + * the driver may set this flag. It is also used to do the same for + * PS-Poll responses. + * @IEEE80211_TX_CTL_USE_MINRATE: This frame will be sent at lowest rate. + * This flag is used to send nullfunc frame at minimum rate when + * the nullfunc is used for connection monitoring purpose. + * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it + * would be fragmented by size (this is optional, only used for + * monitor injection). + * @IEEE80211_TX_STAT_NOACK_TRANSMITTED: A frame that was marked with + * IEEE80211_TX_CTL_NO_ACK has been successfully transmitted without + * any errors (like issues specific to the driver/HW). + * This flag must not be set for frames that don't request no-ack + * behaviour with IEEE80211_TX_CTL_NO_ACK. + * + * Note: If you have to add new flags to the enumeration, then don't + * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. + */ +enum mac80211_tx_info_flags { + IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), + IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), + IEEE80211_TX_CTL_NO_ACK = BIT(2), + IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), + IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), + IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), + IEEE80211_TX_CTL_AMPDU = BIT(6), + IEEE80211_TX_CTL_INJECTED = BIT(7), + IEEE80211_TX_STAT_TX_FILTERED = BIT(8), + IEEE80211_TX_STAT_ACK = BIT(9), + IEEE80211_TX_STAT_AMPDU = BIT(10), + IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), + IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), + IEEE80211_TX_INTFL_OFFCHAN_TX_OK = BIT(13), + IEEE80211_TX_CTL_HW_80211_ENCAP = BIT(14), + IEEE80211_TX_INTFL_RETRIED = BIT(15), + IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), + IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17), + IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), + IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), + IEEE80211_TX_INTFL_MLME_CONN_TX = BIT(20), + IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), + IEEE80211_TX_CTL_LDPC = BIT(22), + IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), + IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), + IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26), + IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27), + IEEE80211_TX_STATUS_EOSP = BIT(28), + IEEE80211_TX_CTL_USE_MINRATE = BIT(29), + IEEE80211_TX_CTL_DONTFRAG = BIT(30), + IEEE80211_TX_STAT_NOACK_TRANSMITTED = BIT(31), +}; + +/** + * enum mac80211_rate_control_flags - per-rate flags set by the + * Rate Control algorithm. + * + * These flags are set by the Rate control algorithm for each rate during tx, + * in the @flags member of struct ieee80211_tx_rate. + * + * @IEEE80211_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate. + * @IEEE80211_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required. + * This is set if the current BSS requires ERP protection. + * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble. + * @IEEE80211_TX_RC_MCS: HT rate. + * @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split + * into a higher 4 bits (Nss) and lower 4 bits (MCS number) + * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in + * Greenfield mode. + * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz. + * @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission + * @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission + * (80+80 isn't supported yet) + * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the + * adjacent 20 MHz channels, if the current channel type is + * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS. + * @IEEE80211_TX_RC_SHORT_GI: Short Guard interval should be used for this rate. + */ +enum mac80211_rate_control_flags { + IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), + IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), + IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), + + /* rate index is an HT/VHT MCS instead of an index */ + IEEE80211_TX_RC_MCS = BIT(3), + IEEE80211_TX_RC_GREEN_FIELD = BIT(4), + IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), + IEEE80211_TX_RC_DUP_DATA = BIT(6), + IEEE80211_TX_RC_SHORT_GI = BIT(7), + IEEE80211_TX_RC_VHT_MCS = BIT(8), + IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(9), + IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(10), +}; + +/** + * struct ieee80211_rx_status - receive status + * + * The low-level driver should provide this information (the subset + * supported by hardware) to the 802.11 code with each received + * frame, in the skb's control buffer (cb). + * + * @mactime: value in microseconds of the 64-bit Time Synchronization Function + * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. + * @boottime_ns: CLOCK_BOOTTIME timestamp the frame was received at, this is + * needed only for beacons and probe responses that update the scan cache. + * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use + * it but can store it and pass it back to the driver for synchronisation + * @band: the active band when this frame was received + * @freq: frequency the radio was tuned to when receiving this frame, in MHz + * This field must be set for management frames, but isn't strictly needed + * for data (other) frames - for those it only affects radiotap reporting. + * @freq_offset: @freq has a positive offset of 500Khz. + * @signal: signal strength when receiving this frame, either in dBm, in dB or + * unspecified depending on the hardware capabilities flags + * @IEEE80211_HW_SIGNAL_* + * @chains: bitmask of receive chains for which separate signal strength + * values were filled. + * @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't + * support dB or unspecified units) + * @antenna: antenna used + * @rate_idx: index of data rate into band's supported rates or MCS index if + * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT) + * @nss: number of streams (VHT and HE only) + * @flag: %RX_FLAG_\* + * @encoding: &enum mac80211_rx_encoding + * @bw: &enum rate_info_bw + * @enc_flags: uses bits from &enum mac80211_rx_encoding_flags + * @he_ru: HE RU, from &enum nl80211_he_ru_alloc + * @he_gi: HE GI, from &enum nl80211_he_gi + * @he_dcm: HE DCM value + * @rx_flags: internal RX flags for mac80211 + * @ampdu_reference: A-MPDU reference number, must be a different value for + * each A-MPDU but the same for each subframe within one A-MPDU + * @ampdu_delimiter_crc: A-MPDU delimiter CRC + * @zero_length_psdu_type: radiotap type of the 0-length PSDU + */ +struct ieee80211_rx_status { +// u64 mactime; +// u64 boottime_ns; +// u32 device_timestamp; +// u32 ampdu_reference; +// u32 flag; +// u16 freq: 13, freq_offset: 1; +// u8 enc_flags; +// u8 encoding:2, bw:3, he_ru:3; +// u8 he_gi:2, he_dcm:1; +// u8 rate_idx; +// u8 nss; +// u8 rx_flags; +// u8 band; +// u8 antenna; + s8 signal; + u8 chains; + s8 chain_signal[4]; +// u8 ampdu_delimiter_crc; +// u8 zero_length_psdu_type; +}; + +/** + * struct ieee80211_tx_rate - rate selection/status + * + * @idx: rate index to attempt to send with + * @flags: rate control flags (&enum mac80211_rate_control_flags) + * @count: number of tries in this rate before going to the next rate + * + * A value of -1 for @idx indicates an invalid rate and, if used + * in an array of retry rates, that no more rates should be tried. + * + * When used for transmit status reporting, the driver should + * always report the rate along with the flags it used. + * + * &struct ieee80211_tx_info contains an array of these structs + * in the control information, and it will be filled by the rate + * control algorithm according to what should be sent. For example, + * if this array contains, in the format { , } the + * information:: + * + * { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 } + * + * then this means that the frame should be transmitted + * up to twice at rate 3, up to twice at rate 2, and up to four + * times at rate 1 if it doesn't get acknowledged. Say it gets + * acknowledged by the peer after the fifth attempt, the status + * information should then contain:: + * + * { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ... + * + * since it was transmitted twice at rate 3, twice at rate 2 + * and once at rate 1 after which we received an acknowledgement. + */ +struct ieee80211_tx_rate { + s8 idx; + u16 count:5, + flags:11; +} __packed; + +struct ieee80211_tx_info { + /* common information */ + u32 flags; + u32 band:3, + ack_frame_id:13, + hw_queue:4, + tx_time_est:10; + /* 2 free bits */ + + union { + struct { + struct ieee80211_tx_rate rates[4]; + s32 ack_signal; + u8 ampdu_ack_len; + u8 ampdu_len; + u8 antenna; + u16 tx_time; + bool is_valid_ack_signal; + void *status_driver_data[19 / sizeof(void *)]; + } status; + }; +}; + +/** + * struct ieee80211_mcs_info - MCS information + * @rx_mask: RX mask + * @rx_highest: highest supported RX rate. If set represents + * the highest supported RX data rate in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_params: TX parameters + */ +struct ieee80211_mcs_info { + u8 rx_mask[10]; + __le16 rx_highest; + u8 tx_params; + u8 reserved[3]; +} __packed; + +/** + * struct ieee80211_sta_ht_cap - STA's HT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11n HT capabilities for an STA. + * + * @ht_supported: is HT supported by the STA + * @cap: HT capabilities map as described in 802.11n spec + * @ampdu_factor: Maximum A-MPDU length factor + * @ampdu_density: Minimum A-MPDU spacing + * @mcs: Supported MCS rates + */ +struct ieee80211_sta_ht_cap { + u16 cap; /* use IEEE80211_HT_CAP_ */ + bool ht_supported; + u8 ampdu_factor; + u8 ampdu_density; + struct ieee80211_mcs_info mcs; +}; + +/** + * struct ieee80211_sta_vht_cap - STA's VHT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11ac VHT capabilities for an STA. + * + * @vht_supported: is VHT supported by the STA + * @cap: VHT capabilities map as described in 802.11ac spec + * @vht_mcs: Supported VHT MCS rates + */ +struct ieee80211_sta_vht_cap { + bool vht_supported; + u32 cap; /* use IEEE80211_VHT_CAP_ */ + struct ieee80211_vht_mcs_info vht_mcs; +}; + +/** + * struct ieee80211_vht_cap - VHT capabilities + * + * This structure is the "VHT capabilities element" as + * described in 802.11ac D3.0 8.4.2.160 + * @vht_cap_info: VHT capability info + * @supp_mcs: VHT MCS supported rates + */ +struct ieee80211_vht_cap { + __le32 vht_cap_info; + struct ieee80211_vht_mcs_info supp_mcs; +} __packed; + +static inline int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, + int bw, + int mcs, bool ext_nss_bw_capable, + unsigned int max_vht_nss) +{ + u16 map = le16_to_cpu(cap->supp_mcs.rx_mcs_map); + int ext_nss_bw; + int supp_width; + int i, mcs_encoding; + + if (map == 0xffff) + return 0; + + if (WARN_ON(mcs > 9 || max_vht_nss > 8)) + return 0; + if (mcs <= 7) + mcs_encoding = 0; + else if (mcs == 8) + mcs_encoding = 1; + else + mcs_encoding = 2; + + if (!max_vht_nss) { + /* find max_vht_nss for the given MCS */ + for (i = 7; i >= 0; i--) { + int supp = (map >> (2 * i)) & 3; + + if (supp == 3) + continue; + + if (supp >= mcs_encoding) { + max_vht_nss = i + 1; + break; + } + } + } + + if (!(cap->supp_mcs.tx_mcs_map & + cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE))) + return max_vht_nss; + + ext_nss_bw = le32_get_bits(cap->vht_cap_info, + IEEE80211_VHTCAP_EXT_NSS_BW_MASK); + supp_width = le32_get_bits(cap->vht_cap_info, + IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK); + + /* if not capable, treat ext_nss_bw as 0 */ + if (!ext_nss_bw_capable) + ext_nss_bw = 0; + + /* This is invalid */ + if (supp_width == 3) + return 0; + + /* This is an invalid combination so pretend nothing is supported */ + if (supp_width == 2 && (ext_nss_bw == 1 || ext_nss_bw == 2)) + return 0; + + /* + * Cover all the special cases according to IEEE 802.11-2016 + * Table 9-250. All other cases are either factor of 1 or not + * valid/supported. + */ + switch (bw) { + case IEEE80211_VHT_CHANWIDTH_USE_HT: + case IEEE80211_VHT_CHANWIDTH_80MHZ: + if ((supp_width == 1 || supp_width == 2) && + ext_nss_bw == 3) + return 2 * max_vht_nss; + break; + case IEEE80211_VHT_CHANWIDTH_160MHZ: + if (supp_width == 0 && + (ext_nss_bw == 1 || ext_nss_bw == 2)) + return max_vht_nss / 2; + if (supp_width == 0 && + ext_nss_bw == 3) + return (3 * max_vht_nss) / 4; + if (supp_width == 1 && + ext_nss_bw == 3) + return 2 * max_vht_nss; + break; + case IEEE80211_VHT_CHANWIDTH_80P80MHZ: + if (supp_width == 0 && ext_nss_bw == 1) + return 0; /* not possible */ + if (supp_width == 0 && + ext_nss_bw == 2) + return max_vht_nss / 2; + if (supp_width == 0 && + ext_nss_bw == 3) + return (3 * max_vht_nss) / 4; + if (supp_width == 1 && + ext_nss_bw == 0) + return 0; /* not possible */ + if (supp_width == 1 && + ext_nss_bw == 1) + return max_vht_nss / 2; + if (supp_width == 1 && + ext_nss_bw == 2) + return (3 * max_vht_nss) / 4; + break; + } + + /* not covered or invalid combination received */ + return max_vht_nss; +} + +#define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20 + +#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC) +#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) +#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) +#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) +#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ +#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ +#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 +#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) +#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) +#define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ + IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\ + IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\ + IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) +#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20 +#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 8 +#define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30 +#define IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20 +#define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50 +#define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50 +#define IWL_MVM_PS_SNOOZE_INTERVAL 25 +#define IWL_MVM_PS_SNOOZE_WINDOW 50 +#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 +#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64 +#define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH 62 +#define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH 65 +#define IWL_MVM_BT_COEX_SYNC2SCO 1 +#define IWL_MVM_BT_COEX_MPLUT 1 +#define IWL_MVM_BT_COEX_RRC 1 +#define IWL_MVM_BT_COEX_TTC 1 +#define IWL_MVM_BT_COEX_MPLUT_REG0 0x22002200 +#define IWL_MVM_BT_COEX_MPLUT_REG1 0x11118451 +#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 +#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 +#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 +#define IWL_MVM_QUOTA_THRESHOLD 4 +#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 +#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 +#define IWL_MVM_TOF_IS_RESPONDER 0 +#define IWL_MVM_HW_CSUM_DISABLE 0 +#define IWL_MVM_PARSE_NVM 0 +#define IWL_MVM_ADWELL_ENABLE 1 +#define IWL_MVM_ADWELL_MAX_BUDGET 0 +#define IWL_MVM_TCM_LOAD_MEDIUM_THRESH 10 /* percentage */ +#define IWL_MVM_TCM_LOAD_HIGH_THRESH 50 /* percentage */ +#define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH 100 /* packets/10 seconds */ +#define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */ +#define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM +#define IWL_MVM_NON_TRANSMITTING_AP 0 +#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 +#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 +#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 +#define IWL_MVM_RS_INITIAL_MIMO_NUM_RATES 3 +#define IWL_MVM_RS_INITIAL_SISO_NUM_RATES 3 +#define IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES 2 +#define IWL_MVM_RS_INITIAL_LEGACY_RETRIES 2 +#define IWL_MVM_RS_SECONDARY_LEGACY_RETRIES 1 +#define IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES 16 +#define IWL_MVM_RS_SECONDARY_SISO_NUM_RATES 3 +#define IWL_MVM_RS_SECONDARY_SISO_RETRIES 1 +#define IWL_MVM_RS_RATE_MIN_FAILURE_TH 3 +#define IWL_MVM_RS_RATE_MIN_SUCCESS_TH 8 +#define IWL_MVM_RS_STAY_IN_COLUMN_TIMEOUT 5 /* Seconds */ +#define IWL_MVM_RS_IDLE_TIMEOUT 5 /* Seconds */ +#define IWL_MVM_RS_MISSED_RATE_MAX 15 +#define IWL_MVM_RS_LEGACY_FAILURE_LIMIT 160 +#define IWL_MVM_RS_LEGACY_SUCCESS_LIMIT 480 +#define IWL_MVM_RS_LEGACY_TABLE_COUNT 160 +#define IWL_MVM_RS_NON_LEGACY_FAILURE_LIMIT 400 +#define IWL_MVM_RS_NON_LEGACY_SUCCESS_LIMIT 4500 +#define IWL_MVM_RS_NON_LEGACY_TABLE_COUNT 1500 +#define IWL_MVM_RS_SR_FORCE_DECREASE 15 /* percent */ +#define IWL_MVM_RS_SR_NO_DECREASE 85 /* percent */ +#define IWL_MVM_RS_AGG_TIME_LIMIT 4000 /* 4 msecs. valid 100-8000 */ +#define IWL_MVM_RS_AGG_DISABLE_START 3 +#define IWL_MVM_RS_AGG_START_THRESHOLD 10 /* num frames per second */ +#define IWL_MVM_RS_TPC_SR_FORCE_INCREASE 75 /* percent */ +#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */ +#define IWL_MVM_RS_TPC_TX_POWER_STEP 3 +#define IWL_MVM_ENABLE_EBS 1 +#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE +#define IWL_MVM_FTM_INITIATOR_DYNACK true +#define IWL_MVM_FTM_R2I_MAX_REP 7 +#define IWL_MVM_FTM_I2R_MAX_REP 7 +#define IWL_MVM_FTM_R2I_MAX_STS 1 +#define IWL_MVM_FTM_I2R_MAX_STS 1 +#define IWL_MVM_FTM_R2I_MAX_TOTAL_LTF 3 +#define IWL_MVM_FTM_I2R_MAX_TOTAL_LTF 3 +#define IWL_MVM_FTM_INITIATOR_SECURE_LTF false +#define IWL_MVM_FTM_RESP_NDP_SUPPORT true +#define IWL_MVM_FTM_RESP_LMR_FEEDBACK_SUPPORT true +#define IWL_MVM_D3_DEBUG false +#define IWL_MVM_USE_TWT true +#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10 +#define IWL_MVM_USE_NSSN_SYNC 0 +#define IWL_MVM_PHY_FILTER_CHAIN_A 0 +#define IWL_MVM_PHY_FILTER_CHAIN_B 0 +#define IWL_MVM_PHY_FILTER_CHAIN_C 0 +#define IWL_MVM_PHY_FILTER_CHAIN_D 0 +#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false +#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40 +/* 20016 pSec is 6 meter RTT, meaning 3 meter range */ +#define IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT 20016 +#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016 +#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2 +#define IWL_MVM_DISABLE_AP_FILS false +#define IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT 3000 /* in seconds */ +#define IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT 60 /* in seconds */ + +#define IWL_MAX_TID_COUNT 8 +#define IWL_MGMT_TID 15 +#define IWL_FRAME_LIMIT 64 +#define IWL_MAX_RX_HW_QUEUES 16 +#define IWL_9000_MAX_RX_HW_QUEUES 6 + +/* Antenna presence definitions */ +#define ANT_NONE 0x0 +#define ANT_INVALID 0xff +#define ANT_A BIT(0) +#define ANT_B BIT(1) +#define ANT_C BIT(2) +#define ANT_AB (ANT_A | ANT_B) +#define ANT_AC (ANT_A | ANT_C) +#define ANT_BC (ANT_B | ANT_C) +#define ANT_ABC (ANT_A | ANT_B | ANT_C) +#define MAX_ANT_NUM 3 + +#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) + +/* fw API values for legacy bit rates, both OFDM and CCK */ +enum { + IWL_RATE_6M_PLCP = 13, + IWL_RATE_9M_PLCP = 15, + IWL_RATE_12M_PLCP = 5, + IWL_RATE_18M_PLCP = 7, + IWL_RATE_24M_PLCP = 9, + IWL_RATE_36M_PLCP = 11, + IWL_RATE_48M_PLCP = 1, + IWL_RATE_54M_PLCP = 3, + IWL_RATE_1M_PLCP = 10, + IWL_RATE_2M_PLCP = 20, + IWL_RATE_5M_PLCP = 55, + IWL_RATE_11M_PLCP = 110, + IWL_RATE_INVM_PLCP = 0xff, +}; + +/* + * Returns the first antenna as ANT_[ABC], as defined in iwl-config.h. + * The parameter should also be a combination of ANT_[ABC]. + */ +static inline u8 first_antenna(u8 mask) +{ + BUILD_BUG_ON(ANT_A != BIT(0)); /* using ffs is wrong if not */ + if (WARN_ON_ONCE(!mask)) /* ffs will return 0 if mask is zeroed */ + return BIT(0); + return BIT(ffs(mask) - 1); +} + +/* + * These serve as indexes into + * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; + * TODO: avoid overlap between legacy and HT rates + */ +enum { + IWL_RATE_1M_INDEX = 0, + IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, + IWL_RATE_2M_INDEX, + IWL_RATE_5M_INDEX, + IWL_RATE_11M_INDEX, + IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, + IWL_RATE_6M_INDEX, + IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, + IWL_RATE_MCS_0_INDEX = IWL_RATE_6M_INDEX, + IWL_FIRST_HT_RATE = IWL_RATE_MCS_0_INDEX, + IWL_FIRST_VHT_RATE = IWL_RATE_MCS_0_INDEX, + IWL_RATE_9M_INDEX, + IWL_RATE_12M_INDEX, + IWL_RATE_MCS_1_INDEX = IWL_RATE_12M_INDEX, + IWL_RATE_18M_INDEX, + IWL_RATE_MCS_2_INDEX = IWL_RATE_18M_INDEX, + IWL_RATE_24M_INDEX, + IWL_RATE_MCS_3_INDEX = IWL_RATE_24M_INDEX, + IWL_RATE_36M_INDEX, + IWL_RATE_MCS_4_INDEX = IWL_RATE_36M_INDEX, + IWL_RATE_48M_INDEX, + IWL_RATE_MCS_5_INDEX = IWL_RATE_48M_INDEX, + IWL_RATE_54M_INDEX, + IWL_RATE_MCS_6_INDEX = IWL_RATE_54M_INDEX, + IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX, + IWL_RATE_60M_INDEX, + IWL_RATE_MCS_7_INDEX = IWL_RATE_60M_INDEX, + IWL_LAST_HT_RATE = IWL_RATE_MCS_7_INDEX, + IWL_RATE_MCS_8_INDEX, + IWL_RATE_MCS_9_INDEX, + IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX, + IWL_RATE_MCS_10_INDEX, + IWL_RATE_MCS_11_INDEX, + IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX, + IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1, + IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1, +}; + +/* + * rate_n_flags bit fields + * + * The 32-bit value has different layouts in the low 8 bites depending on the + * format. There are three formats, HT, VHT and legacy (11abg, with subformats + * for CCK and OFDM). + * + * High-throughput (HT) rate format + * bit 8 is 1, bit 26 is 0, bit 9 is 0 (OFDM) + * Very High-throughput (VHT) rate format + * bit 8 is 0, bit 26 is 1, bit 9 is 0 (OFDM) + * Legacy OFDM rate format for bits 7:0 + * bit 8 is 0, bit 26 is 0, bit 9 is 0 (OFDM) + * Legacy CCK rate format for bits 7:0: + * bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK) + */ + +/* Bit 8: (1) HT format, (0) legacy or VHT format */ +#define RATE_MCS_HT_POS 8 +#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS) + +/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ +#define RATE_MCS_CCK_POS 9 +#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS) + +/* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */ +#define RATE_MCS_VHT_POS 26 +#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS) + + +/* + * High-throughput (HT) rate format for bits 7:0 + * + * 2-0: MCS rate base + * 0) 6 Mbps + * 1) 12 Mbps + * 2) 18 Mbps + * 3) 24 Mbps + * 4) 36 Mbps + * 5) 48 Mbps + * 6) 54 Mbps + * 7) 60 Mbps + * 4-3: 0) Single stream (SISO) + * 1) Dual stream (MIMO) + * 2) Triple stream (MIMO) + * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data + * (bits 7-6 are zero) + * + * Together the low 5 bits work out to the MCS index because we don't + * support MCSes above 15/23, and 0-7 have one stream, 8-15 have two + * streams and 16-23 have three streams. We could also support MCS 32 + * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) + */ +#define RATE_HT_MCS_RATE_CODE_MSK 0x7 +#define RATE_HT_MCS_NSS_POS 3 +#define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS) + +/* Bit 10: (1) Use Green Field preamble */ +#define RATE_HT_MCS_GF_POS 10 +#define RATE_HT_MCS_GF_MSK (1 << RATE_HT_MCS_GF_POS) + +#define RATE_HT_MCS_INDEX_MSK 0x3f + +/* + * Very High-throughput (VHT) rate format for bits 7:0 + * + * 3-0: VHT MCS (0-9) + * 5-4: number of streams - 1: + * 0) Single stream (SISO) + * 1) Dual stream (MIMO) + * 2) Triple stream (MIMO) + */ + +/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */ +#define RATE_VHT_MCS_RATE_CODE_MSK 0xf +#define RATE_VHT_MCS_NSS_POS 4 +#define RATE_VHT_MCS_NSS_MSK (3 << RATE_VHT_MCS_NSS_POS) + +/* + * Legacy OFDM rate format for bits 7:0 + * + * 3-0: 0xD) 6 Mbps + * 0xF) 9 Mbps + * 0x5) 12 Mbps + * 0x7) 18 Mbps + * 0x9) 24 Mbps + * 0xB) 36 Mbps + * 0x1) 48 Mbps + * 0x3) 54 Mbps + * (bits 7-4 are 0) + * + * Legacy CCK rate format for bits 7:0: + * bit 8 is 0, bit 26 is 0, bit 9 is 1 (CCK): + * + * 6-0: 10) 1 Mbps + * 20) 2 Mbps + * 55) 5.5 Mbps + * 110) 11 Mbps + * (bit 7 is 0) + */ +#define RATE_LEGACY_RATE_MSK 0xff + +/* Bit 10 - OFDM HE */ +#define RATE_MCS_HE_POS 10 +#define RATE_MCS_HE_MSK BIT(RATE_MCS_HE_POS) + +/* + * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz + * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT + */ +#define RATE_MCS_CHAN_WIDTH_POS 11 +#define RATE_MCS_CHAN_WIDTH_MSK (3 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_20 (0 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_40 (1 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_80 (2 << RATE_MCS_CHAN_WIDTH_POS) +#define RATE_MCS_CHAN_WIDTH_160 (3 << RATE_MCS_CHAN_WIDTH_POS) + +/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ +#define RATE_MCS_SGI_POS 13 +#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS) + +/* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */ +#define RATE_MCS_ANT_POS 14 +#define RATE_MCS_ANT_A_MSK (1 << RATE_MCS_ANT_POS) +#define RATE_MCS_ANT_B_MSK (2 << RATE_MCS_ANT_POS) +#define RATE_MCS_ANT_C_MSK (4 << RATE_MCS_ANT_POS) +#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | \ + RATE_MCS_ANT_B_MSK) +#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | \ + RATE_MCS_ANT_C_MSK) +#define RATE_MCS_ANT_MSK RATE_MCS_ANT_ABC_MSK + +/* Bit 17: (0) SS, (1) SS*2 */ +#define RATE_MCS_STBC_POS 17 +#define RATE_MCS_STBC_MSK BIT(RATE_MCS_STBC_POS) + +/* Bit 18: OFDM-HE dual carrier mode */ +#define RATE_HE_DUAL_CARRIER_MODE 18 +#define RATE_HE_DUAL_CARRIER_MODE_MSK BIT(RATE_HE_DUAL_CARRIER_MODE) + +/* Bit 19: (0) Beamforming is off, (1) Beamforming is on */ +#define RATE_MCS_BF_POS 19 +#define RATE_MCS_BF_MSK (1 << RATE_MCS_BF_POS) + +/* + * Bit 20-21: HE LTF type and guard interval + * HE (ext) SU: + * 0 1xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 & SGI (bit 13) clear 4xLTF+3.2us + * 3 & SGI (bit 13) set 4xLTF+0.8us + * HE MU: + * 0 4xLTF+0.8us + * 1 2xLTF+0.8us + * 2 2xLTF+1.6us + * 3 4xLTF+3.2us + * HE TRIG: + * 0 1xLTF+1.6us + * 1 2xLTF+1.6us + * 2 4xLTF+3.2us + * 3 (does not occur) + */ +#define RATE_MCS_HE_GI_LTF_POS 20 +#define RATE_MCS_HE_GI_LTF_MSK (3 << RATE_MCS_HE_GI_LTF_POS) + +/* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */ +#define RATE_MCS_HE_TYPE_POS 22 +#define RATE_MCS_HE_TYPE_SU (0 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_EXT_SU (1 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_MU (2 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_TRIG (3 << RATE_MCS_HE_TYPE_POS) +#define RATE_MCS_HE_TYPE_MSK (3 << RATE_MCS_HE_TYPE_POS) + +/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */ +#define RATE_MCS_DUP_POS 24 +#define RATE_MCS_DUP_MSK (3 << RATE_MCS_DUP_POS) + +/* Bit 27: (1) LDPC enabled, (0) LDPC disabled */ +#define RATE_MCS_LDPC_POS 27 +#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS) + +/* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */ +#define RATE_MCS_HE_106T_POS 28 +#define RATE_MCS_HE_106T_MSK (1 << RATE_MCS_HE_106T_POS) + +/* Bit 30-31: (1) RTS, (2) CTS */ +#define RATE_MCS_RTS_REQUIRED_POS (30) +#define RATE_MCS_RTS_REQUIRED_MSK (0x1 << RATE_MCS_RTS_REQUIRED_POS) + +#define RATE_MCS_CTS_REQUIRED_POS (31) +#define RATE_MCS_CTS_REQUIRED_MSK (0x1 << RATE_MCS_CTS_REQUIRED_POS) + +/* Link Quality definitions */ + +/* Link quality command flags bit fields */ + +/* Bit 0: (0) Don't use RTS (1) Use RTS */ +#define LQ_FLAG_USE_RTS_POS 0 +#define LQ_FLAG_USE_RTS_MSK (1 << LQ_FLAG_USE_RTS_POS) + +/* Bit 1-3: LQ command color. Used to match responses to LQ commands */ +#define LQ_FLAG_COLOR_POS 1 +#define LQ_FLAG_COLOR_MSK (7 << LQ_FLAG_COLOR_POS) +#define LQ_FLAG_COLOR_GET(_f) (((_f) & LQ_FLAG_COLOR_MSK) >>\ + LQ_FLAG_COLOR_POS) +#define LQ_FLAGS_COLOR_INC(_c) ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\ + LQ_FLAG_COLOR_MSK) +#define LQ_FLAG_COLOR_SET(_f, _c) ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK)) + +/* Bit 4-5: Tx RTS BW Signalling + * (0) No RTS BW signalling + * (1) Static BW signalling + * (2) Dynamic BW signalling + */ +#define LQ_FLAG_RTS_BW_SIG_POS 4 +#define LQ_FLAG_RTS_BW_SIG_NONE (0 << LQ_FLAG_RTS_BW_SIG_POS) +#define LQ_FLAG_RTS_BW_SIG_STATIC (1 << LQ_FLAG_RTS_BW_SIG_POS) +#define LQ_FLAG_RTS_BW_SIG_DYNAMIC (2 << LQ_FLAG_RTS_BW_SIG_POS) + +/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection + * Dyanmic BW selection allows Tx with narrower BW then requested in rates + */ +#define LQ_FLAG_DYNAMIC_BW_POS 6 +#define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS) + +/* Single Stream Tx Parameters (lq_cmd->ss_params) + * Flags to control a smart FW decision about whether BFER/STBC/SISO will be + * used for single stream Tx. + */ + +/* Bit 0-1: Max STBC streams allowed. Can be 0-3. + * (0) - No STBC allowed + * (1) - 2x1 STBC allowed (HT/VHT) + * (2) - 4x2 STBC allowed (HT/VHT) + * (3) - 3x2 STBC allowed (HT only) + * All our chips are at most 2 antennas so only (1) is valid for now. + */ +#define LQ_SS_STBC_ALLOWED_POS 0 +#define LQ_SS_STBC_ALLOWED_MSK (3 << LQ_SS_STBC_ALLOWED_MSK) + +/* 2x1 STBC is allowed */ +#define LQ_SS_STBC_1SS_ALLOWED (1 << LQ_SS_STBC_ALLOWED_POS) + +/* Bit 2: Beamformer (VHT only) is allowed */ +#define LQ_SS_BFER_ALLOWED_POS 2 +#define LQ_SS_BFER_ALLOWED (1 << LQ_SS_BFER_ALLOWED_POS) + +/* Bit 3: Force BFER or STBC for testing + * If this is set: + * If BFER is allowed then force the ucode to choose BFER else + * If STBC is allowed then force the ucode to choose STBC over SISO + */ +#define LQ_SS_FORCE_POS 3 +#define LQ_SS_FORCE (1 << LQ_SS_FORCE_POS) + +/* Bit 31: ss_params field is valid. Used for FW backward compatibility + * with other drivers which don't support the ss_params API yet + */ +#define LQ_SS_PARAMS_VALID_POS 31 +#define LQ_SS_PARAMS_VALID (1 << LQ_SS_PARAMS_VALID_POS) + +struct iwl_rs_rate_info { + u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ + u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ + u8 plcp_ht_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ + u8 plcp_vht_siso; + u8 plcp_vht_mimo2; + u8 prev_rs; /* previous rate used in rs algo */ + u8 next_rs; /* next rate used in rs algo */ +}; + +extern struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT]; + +#define IWL_RATE_60M_PLCP 3 + +enum { + IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, + IWL_RATE_INVALID = IWL_RATE_COUNT, +}; + +#define LINK_QUAL_MAX_RETRY_NUM 16 + +enum { + IWL_RATE_6M_INDEX_TABLE = 0, + IWL_RATE_9M_INDEX_TABLE, + IWL_RATE_12M_INDEX_TABLE, + IWL_RATE_18M_INDEX_TABLE, + IWL_RATE_24M_INDEX_TABLE, + IWL_RATE_36M_INDEX_TABLE, + IWL_RATE_48M_INDEX_TABLE, + IWL_RATE_54M_INDEX_TABLE, + IWL_RATE_1M_INDEX_TABLE, + IWL_RATE_2M_INDEX_TABLE, + IWL_RATE_5M_INDEX_TABLE, + IWL_RATE_11M_INDEX_TABLE, + IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1, +}; + +/* #define vs. enum to keep from defaulting to 'large integer' */ +#define IWL_RATE_6M_MASK (1 << IWL_RATE_6M_INDEX) +#define IWL_RATE_9M_MASK (1 << IWL_RATE_9M_INDEX) +#define IWL_RATE_12M_MASK (1 << IWL_RATE_12M_INDEX) +#define IWL_RATE_18M_MASK (1 << IWL_RATE_18M_INDEX) +#define IWL_RATE_24M_MASK (1 << IWL_RATE_24M_INDEX) +#define IWL_RATE_36M_MASK (1 << IWL_RATE_36M_INDEX) +#define IWL_RATE_48M_MASK (1 << IWL_RATE_48M_INDEX) +#define IWL_RATE_54M_MASK (1 << IWL_RATE_54M_INDEX) +#define IWL_RATE_60M_MASK (1 << IWL_RATE_60M_INDEX) +#define IWL_RATE_1M_MASK (1 << IWL_RATE_1M_INDEX) +#define IWL_RATE_2M_MASK (1 << IWL_RATE_2M_INDEX) +#define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX) +#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) + + +/* uCode API values for HT/VHT bit rates */ +enum { + IWL_RATE_HT_SISO_MCS_0_PLCP = 0, + IWL_RATE_HT_SISO_MCS_1_PLCP = 1, + IWL_RATE_HT_SISO_MCS_2_PLCP = 2, + IWL_RATE_HT_SISO_MCS_3_PLCP = 3, + IWL_RATE_HT_SISO_MCS_4_PLCP = 4, + IWL_RATE_HT_SISO_MCS_5_PLCP = 5, + IWL_RATE_HT_SISO_MCS_6_PLCP = 6, + IWL_RATE_HT_SISO_MCS_7_PLCP = 7, + IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8, + IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9, + IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA, + IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB, + IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC, + IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD, + IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE, + IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF, + IWL_RATE_VHT_SISO_MCS_0_PLCP = 0, + IWL_RATE_VHT_SISO_MCS_1_PLCP = 1, + IWL_RATE_VHT_SISO_MCS_2_PLCP = 2, + IWL_RATE_VHT_SISO_MCS_3_PLCP = 3, + IWL_RATE_VHT_SISO_MCS_4_PLCP = 4, + IWL_RATE_VHT_SISO_MCS_5_PLCP = 5, + IWL_RATE_VHT_SISO_MCS_6_PLCP = 6, + IWL_RATE_VHT_SISO_MCS_7_PLCP = 7, + IWL_RATE_VHT_SISO_MCS_8_PLCP = 8, + IWL_RATE_VHT_SISO_MCS_9_PLCP = 9, + IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10, + IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11, + IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12, + IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13, + IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14, + IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15, + IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16, + IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17, + IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18, + IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19, + IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, + IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, +}; + +#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) + +#define IWL_INVALID_VALUE 0xff + +#define TPC_MAX_REDUCTION 15 +#define TPC_NO_REDUCTION 0 +#define TPC_INVALID 0xff + +#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63) +#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) +/* + * FIXME - various places in firmware API still use u8, + * e.g. LQ command and SCD config command. + * This should be 256 instead. + */ +#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (255) +#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (255) +#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0) + +#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */ + +/* load per tid defines for A-MPDU activation */ +#define IWL_AGG_TPT_THREHOLD 0 +#define IWL_AGG_ALL_TID 0xff + +enum iwl_table_type { + LQ_NONE, + LQ_LEGACY_G, /* legacy types */ + LQ_LEGACY_A, + LQ_HT_SISO, /* HT types */ + LQ_HT_MIMO2, + LQ_VHT_SISO, /* VHT types */ + LQ_VHT_MIMO2, + LQ_HE_SISO, /* HE types */ + LQ_HE_MIMO2, + LQ_MAX, +}; + +struct rs_rate { + int index; + enum iwl_table_type type; + u8 ant; + u32 bw; + bool sgi; + bool ldpc; + bool stbc; + bool bfer; +}; + +#define is_type_legacy(type) (((type) == LQ_LEGACY_G) || \ + ((type) == LQ_LEGACY_A)) +#define is_type_ht_siso(type) ((type) == LQ_HT_SISO) +#define is_type_ht_mimo2(type) ((type) == LQ_HT_MIMO2) +#define is_type_vht_siso(type) ((type) == LQ_VHT_SISO) +#define is_type_vht_mimo2(type) ((type) == LQ_VHT_MIMO2) +#define is_type_he_siso(type) ((type) == LQ_HE_SISO) +#define is_type_he_mimo2(type) ((type) == LQ_HE_MIMO2) +#define is_type_siso(type) (is_type_ht_siso(type) || is_type_vht_siso(type) || \ + is_type_he_siso(type)) +#define is_type_mimo2(type) (is_type_ht_mimo2(type) || \ + is_type_vht_mimo2(type) || is_type_he_mimo2(type)) +#define is_type_mimo(type) (is_type_mimo2(type)) +#define is_type_ht(type) (is_type_ht_siso(type) || is_type_ht_mimo2(type)) +#define is_type_vht(type) (is_type_vht_siso(type) || is_type_vht_mimo2(type)) +#define is_type_he(type) (is_type_he_siso(type) || is_type_he_mimo2(type)) +#define is_type_a_band(type) ((type) == LQ_LEGACY_A) +#define is_type_g_band(type) ((type) == LQ_LEGACY_G) + +#define is_legacy(rate) is_type_legacy((rate)->type) +#define is_ht_siso(rate) is_type_ht_siso((rate)->type) +#define is_ht_mimo2(rate) is_type_ht_mimo2((rate)->type) +#define is_vht_siso(rate) is_type_vht_siso((rate)->type) +#define is_vht_mimo2(rate) is_type_vht_mimo2((rate)->type) +#define is_siso(rate) is_type_siso((rate)->type) +#define is_mimo2(rate) is_type_mimo2((rate)->type) +#define is_mimo(rate) is_type_mimo((rate)->type) +#define is_ht(rate) is_type_ht((rate)->type) +#define is_vht(rate) is_type_vht((rate)->type) +#define is_he(rate) is_type_he((rate)->type) +#define is_a_band(rate) is_type_a_band((rate)->type) +#define is_g_band(rate) is_type_g_band((rate)->type) + +#define is_ht20(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_20) +#define is_ht40(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_40) +#define is_ht80(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_80) +#define is_ht160(rate) ((rate)->bw == RATE_MCS_CHAN_WIDTH_160) + +#define IWL_MAX_MCS_DISPLAY_SIZE 12 + +struct iwl_rate_mcs_info { + char mbps[IWL_MAX_MCS_DISPLAY_SIZE]; + char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; +}; + +/** + * struct iwl_lq_sta_rs_fw - rate and related statistics for RS in FW + * @last_rate_n_flags: last rate reported by FW + * @sta_id: the id of the station +#ifdef CONFIG_MAC80211_DEBUGFS + * @dbg_fixed_rate: for debug, use fixed rate if not 0 + * @dbg_agg_frame_count_lim: for debug, max number of frames in A-MPDU +#endif + * @chains: bitmask of chains reported in %chain_signal + * @chain_signal: per chain signal strength + * @last_rssi: last rssi reported + * @drv: pointer back to the driver data + */ + +struct iwl_lq_sta_rs_fw { + /* last tx rate_n_flags */ + u32 last_rate_n_flags; + + /* persistent fields - initialized only once - keep last! */ + struct lq_sta_pers_rs_fw { + u32 sta_id; + u8 chains; + s8 chain_signal[4]; + s8 last_rssi; + struct iwm_softc *drv; + } pers; +}; + +/** + * struct iwl_rate_scale_data -- tx success history for one rate + */ +struct iwl_rate_scale_data { + u64 data; /* bitmap of successful frames */ + s32 success_counter; /* number of frames successful */ + s32 success_ratio; /* per-cent * 128 */ + s32 counter; /* number of frames attempted */ + s32 average_tpt; /* success ratio * expected throughput */ +}; + +/* Possible Tx columns + * Tx Column = a combo of legacy/siso/mimo x antenna x SGI + */ +enum rs_column { + RS_COLUMN_LEGACY_ANT_A = 0, + RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_SISO_ANT_A, + RS_COLUMN_SISO_ANT_B, + RS_COLUMN_SISO_ANT_A_SGI, + RS_COLUMN_SISO_ANT_B_SGI, + RS_COLUMN_MIMO2, + RS_COLUMN_MIMO2_SGI, + + RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI, + RS_COLUMN_COUNT = RS_COLUMN_LAST + 1, + RS_COLUMN_INVALID, +}; + +enum rs_ss_force_opt { + RS_SS_FORCE_NONE = 0, + RS_SS_FORCE_STBC, + RS_SS_FORCE_BFER, + RS_SS_FORCE_SISO, +}; + +/* Packet stats per rate */ +struct rs_rate_stats { + u64 success; + u64 total; +}; + +/** + * struct iwl_scale_tbl_info -- tx params and success history for all rates + * + * There are two of these in struct iwl_lq_sta, + * one for "active", and one for "search". + */ +struct iwl_scale_tbl_info { + struct rs_rate rate; + enum rs_column column; + const u16 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ + struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ + /* per txpower-reduction history */ + struct iwl_rate_scale_data tpc_win[TPC_MAX_REDUCTION + 1]; +}; + +enum { + RS_STATE_SEARCH_CYCLE_STARTED, + RS_STATE_SEARCH_CYCLE_ENDED, + RS_STATE_STAY_IN_COLUMN, +}; + +struct lq_sta_pers { + u8 chains; + s8 chain_signal[4]; + s8 last_rssi; + struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT]; + struct iwm_softc *drv; + IOSimpleLock *lock; /* for races in reinit/update table */ +}; + +/** + * struct iwl_lq_sta -- driver's rate scaling private structure + * + * Pointer to this gets passed back and forth between driver and mac80211. + */ +struct iwl_lq_sta { + u8 active_tbl; /* index of active table, range 0-1 */ + u8 rs_state; /* RS_STATE_* */ + u8 search_better_tbl; /* 1: currently trying alternate mode */ + s32 last_tpt; + + /* The following determine when to search for a new mode */ + u32 table_count_limit; + u32 max_failure_limit; /* # failed frames before new search */ + u32 max_success_limit; /* # successful frames before new search */ + u32 table_count; + u32 total_failed; /* total failed frames, any/all rates */ + u32 total_success; /* total successful frames, any/all rates */ + u64 flush_timer; /* time staying in mode before new search */ + + u32 visited_columns; /* Bitmask marking which Tx columns were + * explored during a search cycle + */ + u64 last_tx; + bool is_vht; + bool ldpc; /* LDPC Rx is supported by the STA */ + bool stbc_capable; /* Tx STBC is supported by chip and Rx by STA */ + bool bfer_capable; /* Remote supports beamformee and we BFer */ + + enum nl80211_band band; + + /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ + unsigned long active_legacy_rate; + unsigned long active_siso_rate; + unsigned long active_mimo2_rate; + + /* Highest rate per Tx mode */ + u8 max_legacy_rate_idx; + u8 max_siso_rate_idx; + u8 max_mimo2_rate_idx; + + /* Optimal rate based on RSSI and STA caps. + * Used only to reflect link speed to userspace. + */ + struct rs_rate optimal_rate; + unsigned long optimal_rate_mask; + const struct rs_init_rate_info *optimal_rates; + int optimal_nentries; + + u8 missed_rate_counter; + + struct iwm_lq_cmd lq; + struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ + u8 tx_agg_tid_en; + + /* last tx rate_n_flags */ + u32 last_rate_n_flags; + /* packets destined for this STA are aggregated */ + u8 is_agg; + + /* tx power reduce for this sta */ + int tpc_reduce; + + /* persistent fields - initialized only once - keep last! */ + struct lq_sta_pers pers; +}; + +/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp + * Note, it's iwlmvm <-> mac80211 interface. + * bits 0-7: reduced tx power + * bits 8-10: LQ command's color + */ +#define RS_DRV_DATA_TXP_MSK 0xff +#define RS_DRV_DATA_LQ_COLOR_POS 8 +#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS) +#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\ + RS_DRV_DATA_LQ_COLOR_POS) +#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\ + (((uintptr_t)_p) |\ + ((_c) << RS_DRV_DATA_LQ_COLOR_POS))) + +#define IWL_DECLARE_RATE_INFO(r) \ + [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP + +/* + * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP + */ +static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = { + IWL_DECLARE_RATE_INFO(1), + IWL_DECLARE_RATE_INFO(2), + IWL_DECLARE_RATE_INFO(5), + IWL_DECLARE_RATE_INFO(11), + IWL_DECLARE_RATE_INFO(6), + IWL_DECLARE_RATE_INFO(9), + IWL_DECLARE_RATE_INFO(12), + IWL_DECLARE_RATE_INFO(18), + IWL_DECLARE_RATE_INFO(24), + IWL_DECLARE_RATE_INFO(36), + IWL_DECLARE_RATE_INFO(48), + IWL_DECLARE_RATE_INFO(54), +}; + +#undef IWL_DECLARE_RATE_INFO + +/* Convert an MCS index into an iwm_rates[] index. */ +const int iwm_mcs2ridx[] = { + IWL_RATE_6M_INDEX, + IWL_RATE_12M_INDEX, + IWL_RATE_12M_INDEX, + IWL_RATE_18M_INDEX, + IWL_RATE_24M_INDEX, + IWL_RATE_36M_INDEX, + IWL_RATE_48M_INDEX, + IWL_RATE_54M_INDEX, + IWL_RATE_54M_INDEX, + IWL_RATE_54M_INDEX, +}; + +static inline int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, + enum nl80211_band band) +{ + int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; + int idx; + int band_offset = 0; + + /* Legacy rate format, search for match in table */ + if (band != NL80211_BAND_2GHZ) + band_offset = IWL_FIRST_OFDM_RATE; + for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) + if (fw_rate_idx_to_plcp[idx] == rate) + return idx - band_offset; + + return -1; +} + +static inline u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx) +{ + /* Get PLCP rate for tx_cmd->rate_n_flags */ + return fw_rate_idx_to_plcp[rate_idx]; +} + +static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate, + u8 mcs, u8 nss) +{ + WARN_ON(mcs & ~0xF); + WARN_ON((nss - 1) & ~0x7); + rate->idx = ((nss - 1) << 4) | mcs; +} + +static inline void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, + enum nl80211_band band, + struct ieee80211_tx_rate *r) +{ + if (rate_n_flags & RATE_HT_MCS_GF_MSK) + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; + switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { + case RATE_MCS_CHAN_WIDTH_20: + break; + case RATE_MCS_CHAN_WIDTH_40: + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + break; + case RATE_MCS_CHAN_WIDTH_80: + r->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; + break; + case RATE_MCS_CHAN_WIDTH_160: + r->flags |= IEEE80211_TX_RC_160_MHZ_WIDTH; + break; + } + if (rate_n_flags & RATE_MCS_SGI_MSK) + r->flags |= IEEE80211_TX_RC_SHORT_GI; + if (rate_n_flags & RATE_MCS_HT_MSK) { + r->flags |= IEEE80211_TX_RC_MCS; + r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; + } else if (rate_n_flags & RATE_MCS_VHT_MSK) { + ieee80211_rate_set_vht( + r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK, + ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> + RATE_VHT_MCS_NSS_POS) + 1); + r->flags |= IEEE80211_TX_RC_VHT_MCS; + } else { + r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, + band); + } +} + +/* + * translate ucode response to mac80211 tx status control values + */ +static inline void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, + struct ieee80211_tx_info *info) +{ + struct ieee80211_tx_rate *r = &info->status.rates[0]; + + info->status.antenna = + ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); + iwl_mvm_hwrate_to_tx_rate(rate_n_flags, (enum nl80211_band)info->band, r); +} + +int iwl_mvm_send_lq_cmd(struct iwm_softc *sc, struct iwm_lq_cmd *lq); + +/* Initialize station's rate scaling information after adding station */ +void iwl_mvm_rs_rate_init(struct iwm_softc *mvm, struct ieee80211_node *sta, + enum nl80211_band band, bool init); + +/* Notify RS about Tx status */ +void iwl_mvm_rs_tx_status(struct iwm_softc *mvm, struct ieee80211_node *sta, + int tid, struct ieee80211_tx_info *info, bool ndp); + +void rs_drv_mac80211_tx_status(struct iwm_softc *sc, + struct ieee80211_node *sta, + struct ieee80211_tx_info *info, int tid, uint16_t fc, int ssn); + +void rs_update_last_rssi(struct iwm_softc *mvm, + struct ieee80211_rx_status *rx_status); + +int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate); + +void rs_drv_rate_update(struct iwm_softc *mvm, + struct ieee80211_node *sta, + enum nl80211_band band, u32 changed); + +void *rs_drv_alloc_sta(iwm_softc *sc, struct ieee80211_node *ni); + +void rs_drv_free_sta(iwm_softc *sc, struct ieee80211_node *ni); + +void iwm_rs_alloc(struct iwm_softc *sc); + +void iwm_rs_free(struct iwm_softc *sc); + +#endif /* rs_hpp */ diff --git a/itlwm/hal_iwm/rx.cpp b/itlwm/hal_iwm/rx.cpp index 775771511..2b3e1c7e1 100644 --- a/itlwm/hal_iwm/rx.cpp +++ b/itlwm/hal_iwm/rx.cpp @@ -354,6 +354,7 @@ iwm_rx_mpdu(struct iwm_softc *sc, mbuf_t m, void *pktdata, { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_rxinfo rxi; + struct ieee80211_rx_status rx_status; struct iwm_rx_phy_info *phy_info; struct iwm_rx_mpdu_res_start *rx_res; int device_timestamp; @@ -363,6 +364,7 @@ iwm_rx_mpdu(struct iwm_softc *sc, mbuf_t m, void *pktdata, int rssi, chanidx, rate_n_flags; memset(&rxi, 0, sizeof(rxi)); + memset(&rx_status, 0, sizeof(struct ieee80211_rx_status)); phy_info = &sc->sc_last_phy_info; rx_res = (struct iwm_rx_mpdu_res_start *)pktdata; @@ -415,7 +417,8 @@ iwm_rx_mpdu(struct iwm_softc *sc, mbuf_t m, void *pktdata, phy_flags = letoh16(phy_info->phy_flags); rate_n_flags = le32toh(phy_info->rate_n_flags); - rssi = iwm_get_signal_strength(sc, phy_info); + rssi = iwm_get_signal_strength(sc, &rx_status, phy_info); + rs_update_last_rssi(sc, &rx_status); rssi = (0 - IWM_MIN_DBM) + rssi; /* normalize */ rssi = MIN(rssi, ic->ic_max_rssi); /* clip to max. 100% */ @@ -823,6 +826,7 @@ iwm_rx_mpdu_mq(struct iwm_softc *sc, mbuf_t m, void *pktdata, { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_rxinfo rxi; + struct ieee80211_rx_status rx_status; struct iwm_rx_mpdu_desc *desc; uint32_t len, hdrlen, rate_n_flags, device_timestamp; int rssi; @@ -830,6 +834,7 @@ iwm_rx_mpdu_mq(struct iwm_softc *sc, mbuf_t m, void *pktdata, uint16_t phy_info; memset(&rxi, 0, sizeof(rxi)); + memset(&rx_status, 0, sizeof(struct ieee80211_rx_status)); desc = (struct iwm_rx_mpdu_desc *)pktdata; @@ -950,7 +955,8 @@ iwm_rx_mpdu_mq(struct iwm_softc *sc, mbuf_t m, void *pktdata, chanidx = desc->v1.channel; device_timestamp = desc->v1.gp2_on_air_rise; - rssi = iwm_rxmq_get_signal_strength(sc, desc); + rssi = iwm_rxmq_get_signal_strength(sc, &rx_status, rate_n_flags, desc); + rs_update_last_rssi(sc, &rx_status); rssi = (0 - IWM_MIN_DBM) + rssi; /* normalize */ rssi = MIN(rssi, ic->ic_max_rssi); /* clip to max. 100% */ diff --git a/itlwm/hal_iwm/scan.cpp b/itlwm/hal_iwm/scan.cpp index 7342aaff0..78e85ddf2 100644 --- a/itlwm/hal_iwm/scan.cpp +++ b/itlwm/hal_iwm/scan.cpp @@ -120,6 +120,7 @@ */ #include "ItlIwm.hpp" +#include "rs.h" uint16_t ItlIwm:: iwm_scan_rx_chain(struct iwm_softc *sc) @@ -152,10 +153,10 @@ iwm_scan_rate_n_flags(struct iwm_softc *sc, int flags, int no_cck) tx_ant = (1 << sc->sc_scan_last_antenna) << IWM_RATE_MCS_ANT_POS; if ((flags & IEEE80211_CHAN_2GHZ) && !no_cck) - return htole32(IWM_RATE_1M_PLCP | IWM_RATE_MCS_CCK_MSK | + return htole32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK | tx_ant); else - return htole32(IWM_RATE_6M_PLCP | tx_ant); + return htole32(IWL_RATE_6M_PLCP | tx_ant); } uint8_t ItlIwm:: @@ -763,28 +764,13 @@ iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx) for (i = 0; i < rs->rs_nrates; i++) { rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL); - if (rval == iwm_rates[ridx].rate) + if (rval == ieee80211_std_rateset_11g.rs_rates[ridx]) return rs->rs_rates[i]; } return 0; } -int ItlIwm:: -iwm_rval2ridx(int rval) -{ - int ridx; - - for (ridx = 0; ridx < nitems(iwm_rates); ridx++) { - if (iwm_rates[ridx].plcp == IWM_RATE_INVM_PLCP) - continue; - if (rval == iwm_rates[ridx].rate) - break; - } - - return ridx; -} - void ItlIwm:: iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates, int *ofdm_rates) @@ -799,7 +785,7 @@ iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates, if (ni->ni_chan == IEEE80211_CHAN_ANYC || IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { - for (i = IWM_FIRST_CCK_RATE; i < IWM_FIRST_OFDM_RATE; i++) { + for (i = IWL_FIRST_CCK_RATE; i < IWL_FIRST_OFDM_RATE; i++) { if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0) continue; cck |= (1 << i); @@ -807,10 +793,10 @@ iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates, lowest_present_cck = i; } } - for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) { + for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_NON_HT_RATE; i++) { if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0) continue; - ofdm |= (1 << (i - IWM_FIRST_OFDM_RATE)); + ofdm |= (1 << (i - IWL_FIRST_OFDM_RATE)); if (lowest_present_ofdm == -1 || lowest_present_ofdm > i) lowest_present_ofdm = i; } @@ -838,12 +824,12 @@ iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates, * lower than all of the basic rates to these bitmaps. */ - if (IWM_RATE_24M_INDEX < lowest_present_ofdm) - ofdm |= IWM_RATE_BIT_MSK(24) >> IWM_FIRST_OFDM_RATE; - if (IWM_RATE_12M_INDEX < lowest_present_ofdm) - ofdm |= IWM_RATE_BIT_MSK(12) >> IWM_FIRST_OFDM_RATE; + if (IWL_RATE_24M_INDEX < lowest_present_ofdm) + ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE; + if (IWL_RATE_12M_INDEX < lowest_present_ofdm) + ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE; /* 6M already there or needed so always add */ - ofdm |= IWM_RATE_BIT_MSK(6) >> IWM_FIRST_OFDM_RATE; + ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE; /* * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP. @@ -858,14 +844,14 @@ iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates, * As a consequence, it's not as complicated as it sounds, just add * any lower rates to the ACK rate bitmap. */ - if (IWM_RATE_11M_INDEX < lowest_present_cck) - cck |= IWM_RATE_BIT_MSK(11) >> IWM_FIRST_CCK_RATE; - if (IWM_RATE_5M_INDEX < lowest_present_cck) - cck |= IWM_RATE_BIT_MSK(5) >> IWM_FIRST_CCK_RATE; - if (IWM_RATE_2M_INDEX < lowest_present_cck) - cck |= IWM_RATE_BIT_MSK(2) >> IWM_FIRST_CCK_RATE; + if (IWL_RATE_11M_INDEX < lowest_present_cck) + cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE; + if (IWL_RATE_5M_INDEX < lowest_present_cck) + cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE; + if (IWL_RATE_2M_INDEX < lowest_present_cck) + cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE; /* 1M already there or needed so always add */ - cck |= IWM_RATE_BIT_MSK(1) >> IWM_FIRST_CCK_RATE; + cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE; *cck_rates = cck; *ofdm_rates = ofdm; diff --git a/itlwm/hal_iwm/tx.cpp b/itlwm/hal_iwm/tx.cpp index 02c85454b..2ed600e61 100644 --- a/itlwm/hal_iwm/tx.cpp +++ b/itlwm/hal_iwm/tx.cpp @@ -295,6 +295,10 @@ iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo, int ssn, int struct iwm_tx_ring *ring = &sc->txq[qid]; bool scd_bug = false; + if (agg && + (sc->agg_queue_mask & (1 << qid))) + return 0; + iwm_nic_assert_locked(sc); /* diff --git a/itlwm/hal_iwn/ItlIwn.cpp b/itlwm/hal_iwn/ItlIwn.cpp index e24e66e8e..8da07e73d 100644 --- a/itlwm/hal_iwn/ItlIwn.cpp +++ b/itlwm/hal_iwn/ItlIwn.cpp @@ -166,6 +166,10 @@ IOReturn ItlIwn::disable(IONetworkInterface *netif) { XYLog("%s\n", __FUNCTION__); struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if; + if (!(ifp->if_flags & IFF_UP)) { + XYLog("%s already in diactivating state\n", __FUNCTION__); + return kIOReturnSuccess; + } ifp->if_flags &= ~IFF_UP; iwn_activate(&com, DVACT_QUIESCE); return kIOReturnSuccess; @@ -343,8 +347,6 @@ iwn_attach(struct iwn_softc *sc, struct pci_attach_args *pa) { struct ieee80211com *ic = &sc->sc_ic; struct _ifnet *ifp = &ic->ic_if; - const char *intrstr; - pci_intr_handle_t ih; pcireg_t memtype, reg; int i, error; @@ -391,7 +393,7 @@ iwn_attach(struct iwn_softc *sc, struct pci_attach_args *pa) return false; } - int msiIntrIndex = 0; + int msiIntrIndex = -1; for (int index = 0; ; index++) { int interruptType; @@ -404,12 +406,16 @@ iwn_attach(struct iwn_softc *sc, struct pci_attach_args *pa) break; } } + if (msiIntrIndex == -1) { + XYLog("%s: can't find MSI interrupt controller\n", DEVNAME(sc)); + return false; + } sc->sc_ih = IOFilterInterruptEventSource::filterInterruptEventSource(this, (IOInterruptEventSource::Action)&ItlIwn::iwn_intr, &ItlIwn::intrFilter ,pa->pa_tag, msiIntrIndex); if (sc->sc_ih == NULL || pa->workloop->addEventSource(sc->sc_ih) != kIOReturnSuccess) { - XYLog("%s: can't establish interrupt", DEVNAME(sc)); + XYLog("%s: can't establish interrupt\n", DEVNAME(sc)); return false; } sc->sc_ih->enable(); @@ -544,12 +550,12 @@ iwn_attach(struct iwn_softc *sc, struct pci_attach_args *pa) ieee80211_std_rateset_11a; } if (sc->sc_flags & IWN_FLAG_HAS_11N) { - int ntxstreams = sc->ntxchains; - int nrxstreams = sc->nrxchains; - /* Set supported HT rates. */ if (ic->ic_userflags & IEEE80211_F_NOMIMO) - ntxstreams = nrxstreams = 1; + sc->ntxchains = sc->nrxchains = 1; + + int ntxstreams = sc->ntxchains; + int nrxstreams = sc->nrxchains; ic->ic_sup_mcs[0] = 0xff; /* MCS 0-7 */ if (nrxstreams > 1) @@ -1749,7 +1755,7 @@ iwn_read_eeprom_enhinfo(struct iwn_softc *sc) memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr); for (i = 0; i < nitems(enhinfo); i++) { - if (enhinfo[i].chan == 0 || enhinfo[i].reserved != 0) + if ((enhinfo[i].flags & IWN_TXP_VALID) == 0) continue; /* Skip invalid entries. */ maxpwr = 0; @@ -2204,7 +2210,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, } ni = ieee80211_find_rxnode(ic, wh); - rxi.rxi_flags = 0; + memset(&rxi, 0, sizeof(rxi)); if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) && !IEEE80211_IS_MULTICAST(wh->i_addr1) && @@ -2293,7 +2299,6 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, /* Send the frame to the 802.11 layer. */ rxi.rxi_rssi = rssi; - rxi.rxi_tstamp = 0; /* unused */ rxi.rxi_chan = chan; ieee80211_inputm(ifp, m, ni, &rxi, ml); @@ -3592,7 +3597,10 @@ iwn_tx(struct iwn_softc *sc, mbuf_t m, struct ieee80211_node *ni) } } - if (IEEE80211_IS_MULTICAST(wh->i_addr1) || + if (type == IEEE80211_FC0_TYPE_CTL && + subtype == IEEE80211_FC0_SUBTYPE_BAR) + tx->id = wn->id; + else if (IEEE80211_IS_MULTICAST(wh->i_addr1) || type != IEEE80211_FC0_TYPE_DATA) tx->id = sc->broadcast_id; else @@ -4039,7 +4047,7 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni) struct iwn_cmd_link_quality linkq; struct ieee80211_rateset *rs = &ni->ni_rates; uint8_t txant; - int i, ridx, ridx_min, ridx_max, j, sgi_ok = 0, is_40mhz = 0, mimo, tab = 0, rflags = 0; + int i, ridx, ridx_min, ridx_max, j, mimo, tab = 0, rflags = 0; /* Use the first valid TX antenna. */ txant = IWN_LSB(sc->txchainmask); @@ -4052,22 +4060,17 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni) linkq.ampdu_threshold = 3; linkq.ampdu_limit = htole16(4000); /* 4ms */ - if (ic->ic_flags & IEEE80211_F_USEPROT) - if (sc->hw_type != IWN_HW_REV_TYPE_4965) +#if 0 // RTS/CTS protection not yet tested + if (ni->ni_flags & IEEE80211_NODE_HT && + sc->agg_queue_mask > 0 && + ic->ic_flags & IEEE80211_F_USEPROT) + if (sc->hw_type != IWN_HW_REV_TYPE_4965 && + sc->hw_type != IWN_HW_REV_TYPE_5300 && + sc->hw_type != IWN_HW_REV_TYPE_5150 && + sc->hw_type != IWN_HW_REV_TYPE_5350 && + sc->hw_type != IWN_HW_REV_TYPE_5100) linkq.flags |= IWN_LINK_QUAL_FLAGS_SET_STA_TLC_RTS; - - if (ieee80211_node_supports_ht_sgi20(ni)) { - sgi_ok = 1; - } - - if (ni->ni_chw == IEEE80211_CHAN_WIDTH_40) { - is_40mhz = 1; - if (ieee80211_node_supports_ht_sgi40(ni)) { - sgi_ok = 1; - } else { - sgi_ok = 0; - } - } +#endif /* * Fill the LQ rate selection table with legacy and/or HT rates @@ -4098,17 +4101,20 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni) (!mimo && iwn_is_mimo_ht_plcp(ht_plcp))) continue; for (i = ni->ni_txmcs; i >= 0; i--) { - if (isclr(ni->ni_rxmcs, i)) + if (ic->ic_tx_mcs_set == IEEE80211_TX_MCS_SET_DEFINED && + isclr(ni->ni_rxmcs, i)) + continue; + if (ridx != iwn_mcs2ridx[i]) continue; - if (ridx == iwn_mcs2ridx[i]) { - tab = ht_plcp; - rflags |= IWN_RFLAG_MCS; - if (sgi_ok) - rflags |= IWN_RFLAG_SGI; - if (is_40mhz) - rflags |= IWN_RFLAG_HT40; + tab = ht_plcp; + rflags |= IWN_RFLAG_MCS; + /* First two Tx attempts may use 40MHz/SGI. */ + if (j > 1) break; - } + if (iwn_rxon_ht40_enabled(sc)) + rflags |= IWN_RFLAG_HT40; + if (ieee80211_ra_use_ht_sgi(ni)) + rflags |= IWN_RFLAG_SGI; } } else if (plcp != IWN_RATE_INVM_PLCP) { for (i = ni->ni_txrate; i >= 0; i--) { diff --git a/itlwm/hal_iwn/if_iwnreg.h b/itlwm/hal_iwn/if_iwnreg.h index c1942249c..f89a392c0 100644 --- a/itlwm/hal_iwn/if_iwnreg.h +++ b/itlwm/hal_iwn/if_iwnreg.h @@ -1727,9 +1727,18 @@ struct iwn_eeprom_chan { } __packed; struct iwn_eeprom_enhinfo { - uint16_t chan; + uint8_t flags; +#define IWN_TXP_VALID (1 << 0) +#define IWN_TXP_BAND_52G (1 << 1) +#define IWN_TXP_OFDM (1 << 2) +#define IWN_TXP_40MHZ (1 << 3) +#define IWN_TXP_HT_AP (1 << 4) +#define IWN_TXP_RES1 (1 << 5) +#define IWN_TXP_RES2 (1 << 6) +#define IWN_TXP_COMMON_TYPE (1 << 7) + uint8_t chan; int8_t chain[3]; /* max power in half-dBm */ - uint8_t reserved; + uint8_t delta_20_in_40; int8_t mimo2; /* max power in half-dBm */ int8_t mimo3; /* max power in half-dBm */ } __packed; diff --git a/itlwm/hal_iwx/ItlIwx.cpp b/itlwm/hal_iwx/ItlIwx.cpp index e98448737..32b59180f 100644 --- a/itlwm/hal_iwx/ItlIwx.cpp +++ b/itlwm/hal_iwx/ItlIwx.cpp @@ -227,6 +227,10 @@ IOReturn ItlIwx::disable(IONetworkInterface *netif) { XYLog("%s\n", __FUNCTION__); struct _ifnet *ifp = &com.sc_ic.ic_ac.ac_if; + if (!(ifp->if_flags & IFF_UP)) { + XYLog("%s already in diactivating state\n", __FUNCTION__); + return kIOReturnSuccess; + } ifp->if_flags &= ~IFF_UP; iwx_activate(&com, DVACT_QUIESCE); return kIOReturnSuccess; @@ -4072,10 +4076,6 @@ iwx_setup_he_rates(struct iwx_softc *sc) IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU | IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS | IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX, - .phy_cap_info[0] = - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G, .phy_cap_info[1] = IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | @@ -4452,6 +4452,9 @@ iwx_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, tid >= IWX_MAX_TID_COUNT) return ENOSPC; + if (ic->ic_state != IEEE80211_S_RUN) + return ENOSPC; + if (sc->ba_rx.start_tidmask & (1 << tid)) return EBUSY; @@ -4475,6 +4478,9 @@ iwx_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, if (tid >= IWX_MAX_TID_COUNT || sc->ba_rx.stop_tidmask & (1 << tid)) return; + if (ic->ic_state != IEEE80211_S_RUN) + return; + sc->ba_rx.stop_tidmask |= (1 << tid); that->iwx_add_task(sc, systq, &sc->ba_task); } @@ -8636,7 +8642,7 @@ iwx_scan_abort(struct iwx_softc *sc) } int ItlIwx:: -iwx_enable_data_tx_queues(struct iwx_softc *sc) +iwx_enable_mgmt_queue(struct iwx_softc *sc) { int err; int cmdver; @@ -8728,7 +8734,7 @@ iwx_rs_fw_get_config_flags(struct iwx_softc *sc) } if (iwx_num_of_ant(iwx_fw_valid_tx_ant(sc)) > 1) { - if (ic->ic_flags & IEEE80211_F_HEON && + if ((ni->ni_flags & IEEE80211_NODE_HE) && ni->ni_he_cap_elem.phy_cap_info[2] & IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) { flags |= IWX_TLC_MNG_CFG_FLAGS_STBC_MSK; @@ -8743,17 +8749,17 @@ iwx_rs_fw_get_config_flags(struct iwx_softc *sc) flags |= IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK; /* consider LDPC support in case of HE */ - if ((ic->ic_flags & IEEE80211_F_HEON) && + if ((ni->ni_flags & IEEE80211_NODE_HE) && (ni->ni_he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) flags |= IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK; - if ((ic->ic_flags & IEEE80211_F_HEON) && + if ((ni->ni_flags & IEEE80211_NODE_HE) && !(ni->ni_he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) flags &= ~IWX_TLC_MNG_CFG_FLAGS_LDPC_MSK; - if ((ic->ic_flags & IEEE80211_F_HEON) && + if ((ni->ni_flags & IEEE80211_NODE_HE) && (ni->ni_he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK)) flags |= IWX_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK; @@ -9213,7 +9219,7 @@ iwx_auth(struct iwx_softc *sc) return 0; } - err = iwx_enable_data_tx_queues(sc); + err = iwx_enable_mgmt_queue(sc); if (err) goto rm_sta; @@ -11752,6 +11758,7 @@ static const struct pci_matchid iwx_devices[] = { {IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)}, {IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, + {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)}, {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)}, @@ -12122,6 +12129,15 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name), IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name), IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name), + IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x51F1, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), /* Qu with Hr */ IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), @@ -12565,7 +12581,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, @@ -12582,7 +12598,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, - IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, iwl_cfg_so_a0_hr_a0, iwl_ax101_name), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, @@ -12776,7 +12792,6 @@ intrFilter(OSObject *object, IOFilterInterruptEventSource *src) bool ItlIwx:: iwx_attach(struct iwx_softc *sc, struct pci_attach_args *pa) { - pci_intr_handle_t ih; pcireg_t reg, memtype; struct ieee80211com *ic = &sc->sc_ic; struct _ifnet *ifp = &ic->ic_if; @@ -12835,7 +12850,7 @@ iwx_attach(struct iwx_softc *sc, struct pci_attach_args *pa) PCI_COMMAND_STATUS_REG, reg); } - int msiIntrIndex = 0; + int msiIntrIndex = -1; for (int index = 0; ; index++) { int interruptType; @@ -12848,6 +12863,11 @@ iwx_attach(struct iwx_softc *sc, struct pci_attach_args *pa) break; } } + if (msiIntrIndex == -1) { + XYLog("%s: can't find MSI interrupt controller\n", DEVNAME(sc)); + return false; + } + if (sc->sc_msix) sc->sc_ih = IOFilterInterruptEventSource::filterInterruptEventSource(this, @@ -12859,7 +12879,7 @@ iwx_attach(struct iwx_softc *sc, struct pci_attach_args *pa) (IOInterruptEventSource::Action)&ItlIwx::iwx_intr, &ItlIwx::intrFilter ,pa->pa_tag, msiIntrIndex); if (sc->sc_ih == NULL || pa->workloop->addEventSource(sc->sc_ih) != kIOReturnSuccess) { - XYLog("%s: can't establish interrupt", DEVNAME(sc)); + XYLog("%s: can't establish interrupt\n", DEVNAME(sc)); return false; } sc->sc_ih->enable(); diff --git a/itlwm/hal_iwx/ItlIwx.hpp b/itlwm/hal_iwx/ItlIwx.hpp index 1868067fe..c1f048a8a 100644 --- a/itlwm/hal_iwx/ItlIwx.hpp +++ b/itlwm/hal_iwx/ItlIwx.hpp @@ -420,7 +420,7 @@ class ItlIwx : public ItlHalService, ItlDriverInfo, ItlDriverController { uint16_t iwx_rs_fw_get_config_flags(struct iwx_softc *sc); int iwx_rs_init(struct iwx_softc *, struct iwx_node *, bool update); void iwx_rs_update(struct iwx_softc *sc, struct iwx_tlc_update_notif *notif); - int iwx_enable_data_tx_queues(struct iwx_softc *); + int iwx_enable_mgmt_queue(struct iwx_softc *); int iwx_phy_ctxt_update(struct iwx_softc *, struct iwx_phy_ctxt *, struct ieee80211_channel *, uint8_t, uint8_t, uint32_t); int iwx_auth(struct iwx_softc *); diff --git a/iwlwifi-firmware-license b/iwlwifi-firmware-license index 497ee18b1..6bdd16d92 100644 --- a/iwlwifi-firmware-license +++ b/iwlwifi-firmware-license @@ -1,4 +1,4 @@ -Copyright (c) 2019, Intel Corporation. +Copyright (c) 2006-2021, Intel Corporation. All rights reserved. Redistribution. Redistribution and use in binary form, without